Decompiled source of NMCrosshair v1.1.2

NMCrosshair.dll

Decompiled 3 weeks ago
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}";
	}
}