using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("NMCrosshair")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NMCrosshair")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2e32abd0-8b35-45d5-a142-462ec5858869")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace NMCrosshair;
[BepInPlugin("Swaggies.NMCrosshair", "NMCrosshair", "1.1.2")]
public class Plugin : BaseUnityPlugin
{
private const string _guid = "Swaggies.NMCrosshair";
private const string _name = "NMCrosshair";
private const string _ver = "1.1.2";
private readonly Harmony harmony = new Harmony("Swaggies.NMCrosshair");
private static Plugin Instance;
public static ManualLogSource loggywoggy;
public static ConfigEntry<bool> ModifyTooltips;
public static ConfigEntry<bool> ClientSideAdvantage;
private static Sprite ui = null;
private static readonly int interactableObjectsMask = 832;
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
loggywoggy = Logger.CreateLogSource("Swaggies.NMCrosshair");
harmony.PatchAll(typeof(Plugin));
loggywoggy.LogInfo((object)"NMCrosshair up and running.");
ModifyTooltips = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UseCustomTooltips", false, "Adds custom tooltips such as showing an enemies name when you look at them, and colors tooltips based on context. Can degrade performance a lil.");
ClientSideAdvantage = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable CSA Tooltips", true, "If custom tooltips is enabled, this will enable client-side advantages such as showing enemy HP, the ship timer, the scrap value & battery of items, etc. Disable this if you'd like a more fair experience with vanilla players.");
}
[HarmonyPatch(typeof(PlayerControllerB), "Start")]
[HarmonyPostfix]
private static void InitiateCursor(ref PlayerControllerB __instance)
{
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)ui == (Object)null)
{
ui = ((IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()).FirstOrDefault((Func<Sprite, bool>)((Sprite img) => ((Object)img).name == "UISprite"));
}
__instance.cursorIcon.sprite = ui;
((Component)__instance.cursorIcon).transform.localScale = new Vector3(0.031f, 0.031f, 0.031f);
}
[HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")]
[HarmonyPostfix]
private static void ChangeCursor(ref PlayerControllerB __instance)
{
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance.localPlayerController))
{
if (__instance.isPlayerDead || __instance.inTerminalMenu)
{
Tooltips.SetTooltip("");
((Behaviour)__instance.cursorIcon).enabled = false;
}
else
{
((Behaviour)__instance.cursorIcon).enabled = true;
__instance.cursorIcon.sprite = ui;
((Graphic)__instance.cursorIcon).color = SetCrosshairIconBasedOnConditions(__instance);
}
}
}
public static Color SetCrosshairIconBasedOnConditions(PlayerControllerB self)
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_027c: Unknown result type (might be due to invalid IL or missing references)
//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
//IL_0235: Unknown result type (might be due to invalid IL or missing references)
//IL_021f: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Unknown result type (might be due to invalid IL or missing references)
//IL_023a: Unknown result type (might be due to invalid IL or missing references)
//IL_0270: Unknown result type (might be due to invalid IL or missing references)
//IL_0275: Unknown result type (might be due to invalid IL or missing references)
if (self.jetpackControls)
{
return new Color(0.3f, 0.3f, 0.3f, 0.3f);
}
Ray val = default(Ray);
((Ray)(ref val))..ctor(((Component)self.gameplayCamera).transform.position, ((Component)self.gameplayCamera).transform.forward);
RaycastHit val2 = default(RaycastHit);
if (Physics.Raycast(val, ref val2, self.grabDistance, interactableObjectsMask) && ((Component)((RaycastHit)(ref val2)).collider).gameObject.layer != 8)
{
if (((Component)((RaycastHit)(ref val2)).collider).tag == "InteractTrigger")
{
InteractTrigger component = ((Component)((RaycastHit)(ref val2)).transform).gameObject.GetComponent<InteractTrigger>();
if ((Object)(object)component != (Object)null)
{
Tooltips.LookAtInteractTrigger(component);
return component.interactable ? new Color(0f, 1f, 1f) : new Color(0f, 0.33f, 0.33f);
}
}
if (((Component)((RaycastHit)(ref val2)).collider).tag == "PhysicsProp")
{
GrabbableObject component2 = ((Component)((RaycastHit)(ref val2)).transform).gameObject.GetComponent<GrabbableObject>();
if ((Object)(object)component2 != (Object)null && !component2.isHeld && !component2.isHeldByEnemy)
{
Tooltips.LookAtGrabbableObject(component2);
return new Color(0f, 1f, 0f);
}
}
}
if (Physics.Raycast(val, ref val2, self.grabDistance, 524288))
{
EnemyAICollisionDetect component3 = ((Component)((RaycastHit)(ref val2)).transform).GetComponent<EnemyAICollisionDetect>();
IHittable val3 = default(IHittable);
if ((Object)(object)component3 != (Object)null && (Object)(object)component3.mainScript != (Object)null && !component3.mainScript.isEnemyDead && ((Component)((RaycastHit)(ref val2)).transform).TryGetComponent<IHittable>(ref val3))
{
Tooltips.LookAtEnemyAI(component3.mainScript);
return component3.mainScript.enemyType.canDie ? new Color(1f, 0f, 0f) : new Color(0.4f, 0f, 0f);
}
if ((Object)(object)component3 != (Object)null && (Object)(object)component3.mainScript == (Object)null)
{
return new Color(0.4f, 0f, 0f);
}
}
if (Physics.Raycast(val, ref val2, self.grabDistance, StartOfRound.Instance.collidersAndRoomMaskAndDefault) && (((Component)((RaycastHit)(ref val2)).transform).gameObject.layer == 8 || ((Component)((RaycastHit)(ref val2)).transform).gameObject.layer == 11))
{
return new Color(0.6f, 0.6f, 0.6f);
}
return new Color(1f, 1f, 1f);
}
}
internal class Tooltips
{
private static float lastNearbyEnemyCheck;
private static bool nearbyActivity;
private static bool CheckForNearbyEnemies(EntranceTeleport teleport)
{
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
if (Time.realtimeSinceStartup - lastNearbyEnemyCheck < 1f)
{
return nearbyActivity;
}
lastNearbyEnemyCheck = Time.realtimeSinceStartup;
EnemyAI[] array = Object.FindObjectsOfType<EnemyAI>();
EnemyAI[] array2 = array;
foreach (EnemyAI val in array2)
{
if (!((Object)(object)val == (Object)null) && !val.isEnemyDead && !(Vector3.Distance(((Component)val).transform.position, ((Component)teleport.exitPoint).transform.position) >= 7.7f))
{
return true;
}
}
return false;
}
public static void LookAtInteractTrigger(InteractTrigger trigger)
{
//IL_018e: Unknown result type (might be due to invalid IL or missing references)
//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
if (!Plugin.ModifyTooltips.Value)
{
return;
}
if ((Object)(object)((Component)trigger).GetComponent<StartMatchLever>() != (Object)null && trigger.interactable)
{
if (StartOfRound.Instance.inShipPhase)
{
SetTooltip("Land on " + StartOfRound.Instance.currentLevel.PlanetName + " : [E]", "#00ffff");
return;
}
string text = "Start ship";
if (Plugin.ClientSideAdvantage.Value && StartOfRound.Instance.currentLevel.planetHasTime)
{
text = text + " • " + GetShipTimer();
}
SetTooltip(text, "#00ffff");
return;
}
Terminal val = default(Terminal);
if (((Component)trigger).TryGetComponent<Terminal>(ref val) && trigger.interactable && !val.terminalInUse)
{
string text2 = "Terminal";
if (Plugin.ClientSideAdvantage.Value)
{
text2 += $" • ${val.groupCredits}";
}
SetTooltip(text2, "#00ffff");
}
EntranceTeleport val2 = default(EntranceTeleport);
if (((Component)trigger).TryGetComponent<EntranceTeleport>(ref val2) && trigger.interactable)
{
nearbyActivity = CheckForNearbyEnemies(val2);
if (nearbyActivity && (Plugin.ClientSideAdvantage.Value || val2.isEntranceToBuilding))
{
string text3 = ColorUtility.ToHtmlStringRGB(Color.Lerp(new Color(1f, 0f, 0f), new Color(1f, 1f, 0f), 1f - Math.Abs(2f * (Time.realtimeSinceStartup % 1f - 0.5f))));
SetTooltip("[Near activity detected]", "#" + text3);
}
else
{
SetTooltip(val2.isEntranceToBuilding ? "Enter building : [E]" : "Exit building : [E]", "#00ffff");
}
}
else
{
SetTooltip(null, trigger.interactable ? "#00ffff" : "#008686");
}
}
public static void LookAtGrabbableObject(GrabbableObject obj)
{
if (!Plugin.ModifyTooltips.Value)
{
return;
}
string text = obj.itemProperties.itemName;
if (obj.itemProperties.isScrap && Plugin.ClientSideAdvantage.Value)
{
text += $" • ${obj.scrapValue}";
}
if (obj.itemProperties.requiresBattery && Plugin.ClientSideAdvantage.Value)
{
string arg = "#868686";
if (obj.insertedBattery.charge > 0f)
{
arg = "#ff0000";
}
if (obj.insertedBattery.charge > 0.2f)
{
arg = "#ff6900";
}
if (obj.insertedBattery.charge > 0.4f)
{
arg = "#ffff00";
}
if (obj.insertedBattery.charge > 0.65f)
{
arg = "#00ff00";
}
text += $" • <color={arg}>{(int)Math.Ceiling(obj.insertedBattery.charge * 100f)}%</color>";
}
ShotgunItem val = default(ShotgunItem);
if (Plugin.ClientSideAdvantage.Value && ((Component)obj).TryGetComponent<ShotgunItem>(ref val))
{
text += $" • {val.shellsLoaded} ammo";
}
SetTooltip(text, (obj.grabbable && !obj.isHeldByEnemy) ? "#00ff00" : "#008600");
}
public static void LookAtEnemyAI(EnemyAI enemy)
{
if (!Plugin.ModifyTooltips.Value)
{
return;
}
ScanNodeProperties componentInChildren = ((Component)enemy).GetComponentInChildren<ScanNodeProperties>();
if (!((Object)(object)componentInChildren == (Object)null))
{
string text = componentInChildren.headerText;
if (enemy.enemyType.canDie && Plugin.ClientSideAdvantage.Value)
{
text += $" • {enemy.enemyHP} HP";
}
SetTooltip(text, "#ff0000");
}
}
public static void SetTooltip(string text, string color = null)
{
if (text == null)
{
text = ((TMP_Text)GameNetworkManager.Instance.localPlayerController.cursorTip).text;
}
if (color == null)
{
((TMP_Text)GameNetworkManager.Instance.localPlayerController.cursorTip).text = text;
return;
}
((TMP_Text)GameNetworkManager.Instance.localPlayerController.cursorTip).text = "<color=" + color + ">" + text + "</color>";
}
private static string GetShipTimer()
{
float num = TimeOfDay.Instance.shipLeaveAutomaticallyTime - TimeOfDay.Instance.normalizedTimeOfDay;
float num2 = Mathf.Clamp((float)Math.Ceiling(num * 60f * (float)TimeOfDay.Instance.numberOfHours / TimeOfDay.Instance.globalTimeSpeedMultiplier), 0f, 5999f);
int num3 = (int)Math.Floor(num2 % 60f);
int num4 = (int)Math.Floor(num2 / 60f);
return $"{num4:00}:{num3:00}";
}
}