Decompiled source of HUDdleUP v1.0.3

plugins/HUDdleUP/HUDdleUP.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using EntityStates.Railgunner.Reload;
using EntityStates.Railgunner.Weapon;
using HUDdleUP.Behaviours;
using HUDdleUP.Loot;
using HUDdleUP.Railgunner;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using Rewired;
using RoR2;
using RoR2.UI;
using RoR2.UI.SkinControllers;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("HUDdleUP")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3+b05def0c7017b91238a5d0ef0b2339b433d46f67")]
[assembly: AssemblyProduct("HUDdleUP")]
[assembly: AssemblyTitle("HUDdleUP")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HUDdleUP
{
	public sealed class Config
	{
		private readonly ConfigFile file;

		private readonly ConfigEntry<bool> fullerItemDescriptions;

		private readonly ConfigEntry<bool> fullerEquipmentDescriptions;

		private readonly ConfigEntry<bool> equipmentIconCooldownVisual;

		private readonly ConfigEntry<bool> commandMenuItemTooltips;

		private readonly ConfigEntry<bool> renameEquipmentDrones;

		private readonly ConfigEntry<bool> runDifficultyTooltip;

		private readonly ConfigEntry<bool> scoreboardShowChat;

		private readonly ConfigEntry<bool> lootPanel;

		private readonly ConfigEntry<bool> railgunnerAccuracyPanel;

		public bool FullerItemDescriptions => fullerItemDescriptions.Value;

		public bool FullerEquipmentDescriptions => fullerEquipmentDescriptions.Value;

		public bool EquipmentIconCooldownVisual => equipmentIconCooldownVisual.Value;

		public bool CommandMenuItemTooltips => commandMenuItemTooltips.Value;

		public bool RenameEquipmentDrones => renameEquipmentDrones.Value;

		public bool RunDifficultyTooltip => runDifficultyTooltip.Value;

		public bool ScoreboardShowChat => scoreboardShowChat.Value;

		public bool LootPanel => lootPanel.Value;

		public bool RailgunnerAccuracyPanel => railgunnerAccuracyPanel.Value;

		internal void Reload()
		{
			Plugin.Logger.LogDebug((object)("Reloading " + file.ConfigFilePath.Substring(file.ConfigFilePath.LastIndexOf(Path.DirectorySeparatorChar) + 1)));
			file.Reload();
		}

		public Config(ConfigFile config)
		{
			file = config;
			fullerItemDescriptions = config.Bind<bool>("", "fullerItemDescriptions", true, "Replace the default short (pickup) descriptions in item tooltips with a combination of the short and detailed descriptions.\n\nNote that this mod currently does not provide calculated item stack stats.");
			fullerEquipmentDescriptions = config.Bind<bool>("", "fullerEquipmentDescriptions", true, "Replace the default short (pickup) descriptions in equipment tooltips with a combination of the short and detailed descriptions, as well as the equipment cooldown.\n\nNote that this mod currently does not provide calculated item stack stats.");
			equipmentIconCooldownVisual = config.Bind<bool>("", "equipmentIconCooldownVisual", true, "Add the cooldown progress visual from skill icons to the equipment icon.");
			commandMenuItemTooltips = config.Bind<bool>("", "commandMenuItemTooltips", true, "Add tooltips to items and equipment in pickup picker menus (e.g. command cubes, void potentials) that show the (fuller) description of the item.");
			renameEquipmentDrones = config.Bind<bool>("", "renameEquipmentDrones", true, "Replace the names of equipment drones in ally cards with the name of its held equipment.");
			runDifficultyTooltip = config.Bind<bool>("", "runDifficultyTooltip", true, "Add a tooltip to the difficulty icon in the HUD that shows the description of the run's difficulty.");
			scoreboardShowChat = config.Bind<bool>("", "scoreboardShowChat", true, "Show the chat history when the scoreboard is open.");
			lootPanel = config.Bind<bool>("HUD Panels", "lootPanel", true, "Add a Loot panel to the HUD to track how much loot is left on a stage.\n\nOnly visible when the scoreboard is open.");
			railgunnerAccuracyPanel = config.Bind<bool>("HUD Panels", "railgunnerAccuracyPanel", true, "Add an Accuracy panel to the HUD to track your accuracy with landing perfect reloads and hitting weak points.");
		}
	}
	public sealed class HUDPanel
	{
		public readonly GameObject gameObject;

		public readonly TextMeshProUGUI label;

		private readonly GameObject stripContainer;

		private HUDPanel(GameObject panel, TextMeshProUGUI label, GameObject stripContainer)
		{
			gameObject = panel;
			this.label = label;
			this.stripContainer = stripContainer;
		}

		public TextMeshProUGUI AddTextComponent(string name)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI obj = Object.Instantiate<TextMeshProUGUI>(label, stripContainer.transform);
			((Object)obj).name = name;
			LayoutElement component = ((Component)obj).GetComponent<LayoutElement>();
			if (Object.op_Implicit((Object)(object)component))
			{
				Object.Destroy((Object)(object)component);
			}
			LabelSkinController val = default(LabelSkinController);
			if (((Component)obj).TryGetComponent<LabelSkinController>(ref val))
			{
				val.labelType = (LabelType)0;
			}
			((TMP_Text)obj).fontSize = 12f;
			((TMP_Text)obj).fontSizeMax = 12f;
			((TMP_Text)obj).fontSizeMin = 6f;
			((TMP_Text)obj).alignment = (TextAlignmentOptions)257;
			((TMP_Text)obj).text = "hello world.";
			return obj;
		}

		public static HUDPanel ClonePanel(ObjectivePanelController objectivePanel, string name)
		{
			ObjectivePanelController val = Object.Instantiate<ObjectivePanelController>(objectivePanel, ((Component)objectivePanel).transform.parent);
			GameObject val2 = ((Component)((Component)val).transform.GetChild(((Component)val).transform.childCount - 1)).gameObject;
			GameObject val3 = ((Component)val).gameObject;
			((Object)val3).name = name;
			Object.Destroy((Object)(object)val);
			TextMeshProUGUI val4 = (TextMeshProUGUI)(((object)val3.GetComponentInChildren<HGTextMeshProUGUI>()) ?? ((object)val3.GetComponentInChildren<TextMeshProUGUI>()));
			HudObjectiveTargetSetter val5 = default(HudObjectiveTargetSetter);
			if (val3.TryGetComponent<HudObjectiveTargetSetter>(ref val5))
			{
				Object.Destroy((Object)(object)val5);
			}
			LanguageTextMeshController val6 = default(LanguageTextMeshController);
			if (((Component)val4).TryGetComponent<LanguageTextMeshController>(ref val6))
			{
				Object.DestroyImmediate((Object)(object)val6);
			}
			return new HUDPanel(val3, val4, val2);
		}
	}
	[HarmonyPatch]
	[BepInPlugin("itsschwer.HUDdleUP", "HUDdleUP", "1.0.3")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string GUID = "itsschwer.HUDdleUP";

		public const string Author = "itsschwer";

		public const string Name = "HUDdleUP";

		public const string Version = "1.0.3";

		internal static ManualLogSource Logger { get; private set; }

		public static Config Config { get; private set; }

		private void Awake()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			Logger.Sources.Remove((ILogSource)(object)((BaseUnityPlugin)this).Logger);
			Logger = Logger.CreateLogSource("itsschwer.HUDdleUP");
			Config = new Config(((BaseUnityPlugin)this).Config);
			new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID).PatchAll();
			Logger.LogMessage((object)"~awake.");
		}

		private void OnEnable()
		{
			Run.onRunStartGlobal += OnRunStart;
			Run.onRunDestroyGlobal += OnRunDestroy;
			Logger.LogMessage((object)"~enabled.");
		}

		private void OnDisable()
		{
			Run.onRunStartGlobal -= OnRunStart;
			Run.onRunDestroyGlobal -= OnRunDestroy;
			Logger.LogMessage((object)"~disabled.");
		}

		private void OnRunStart(Run _)
		{
			LootPanel.Hook();
			RailgunnerAccuracyPanel.Hook();
		}

		private void OnRunDestroy(Run _)
		{
			LootPanel.Unhook();
			RailgunnerAccuracyPanel.Unhook();
		}
	}
	public static class TooltipHelper
	{
		public static TooltipProvider AddTooltipProvider(Graphic target, bool suppressLogs = false)
		{
			if ((Object)(object)target == (Object)null)
			{
				return null;
			}
			((Component)(object)target).AddGraphicRaycasterToParentCanvas(!suppressLogs);
			target.raycastTarget = true;
			return ((Component)target).gameObject.AddComponentIfMissing<TooltipProvider>(!suppressLogs);
		}

		private static bool AddGraphicRaycasterToParentCanvas(this Component child, bool emitLog)
		{
			GameObject gameObject = ((Component)child.GetComponentInParent<Canvas>()).gameObject;
			if (emitLog)
			{
				Plugin.Logger.LogDebug((object)("Found parent canvas " + ((Object)gameObject).name + " for " + ((Object)child).name));
			}
			return Object.op_Implicit((Object)(object)gameObject.AddComponentIfMissing<GraphicRaycaster>(emitLog));
		}

		private static T AddComponentIfMissing<T>(this GameObject target, bool emitLog) where T : Component
		{
			T val = target.GetComponent<T>();
			if ((Object)(object)val == (Object)null)
			{
				val = target.AddComponent<T>();
				if (emitLog)
				{
					Plugin.Logger.LogDebug((object)("Added " + typeof(T).FullName + " to " + ((Object)target).name));
				}
			}
			return val;
		}
	}
}
namespace HUDdleUP.Patches
{
	[HarmonyPatch]
	internal static class EquipmentCooldownProgressVisual
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(HUD), "Awake")]
		private static void HUD_Awake(HUD __instance)
		{
			if (!Plugin.Config.EquipmentIconCooldownVisual || __instance.skillIcons.Length == 0 || !Object.op_Implicit((Object)(object)__instance.skillIcons[0]))
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)__instance.skillIcons[0].cooldownRemapPanel) || !Object.op_Implicit((Object)(object)((Component)__instance.skillIcons[0].cooldownRemapPanel).gameObject))
			{
				Plugin.Logger.LogWarning((object)"EquipmentCooldownProgressVisual> Could not initialize — missing cooldownRemapPanel. This warning can safely be ignored if RiskUI is installed.");
				return;
			}
			GameObject gameObject = ((Component)__instance.skillIcons[0].cooldownRemapPanel).gameObject;
			EquipmentIcon[] equipmentIcons = __instance.equipmentIcons;
			for (int i = 0; i < equipmentIcons.Length; i++)
			{
				EquipmentCooldownPanel.Init(equipmentIcons[i], gameObject);
			}
		}
	}
	[HarmonyPatch]
	internal static class EquipmentDroneUseHeldEquipmentNameInAllyCard
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(AllyCardController), "LateUpdate")]
		private static void AllyCardController_LateUpdate(AllyCardController __instance)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Config.RenameEquipmentDrones || !Object.op_Implicit((Object)(object)__instance.sourceMaster) || !Object.op_Implicit((Object)(object)__instance.sourceMaster.inventory))
			{
				return;
			}
			EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(__instance.sourceMaster.inventory.currentEquipmentIndex);
			if ((Object)(object)equipmentDef == (Object)null)
			{
				return;
			}
			string @string = Language.GetString(equipmentDef.nameToken);
			if (!(((TMP_Text)__instance.nameLabel).text == @string))
			{
				CharacterBody body = __instance.sourceMaster.GetBody();
				if (!((Object)(object)body == (Object)null) && !(body.baseNameToken != "EQUIPMENTDRONE_BODY_NAME"))
				{
					((TMP_Text)__instance.nameLabel).text = Language.GetString(equipmentDef.nameToken);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class FullerDescriptions
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(ItemIcon), "SetItemIndex")]
		private static void ItemIcon_SetItemIndex(ItemIcon __instance)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Config.FullerItemDescriptions)
			{
				ItemDef itemDef = ItemCatalog.GetItemDef(__instance.itemIndex);
				if (!((Object)(object)itemDef == (Object)null) && !((Object)(object)__instance.tooltipProvider == (Object)null))
				{
					__instance.tooltipProvider.overrideBodyText = GetCombinedDescription(itemDef.descriptionToken, itemDef.pickupToken);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(EquipmentIcon), "SetDisplayData")]
		private static void EquipmentIcon_SetDisplayData(EquipmentIcon __instance)
		{
			if (Plugin.Config.FullerEquipmentDescriptions)
			{
				EquipmentDef equipmentDef = __instance.currentDisplayData.equipmentDef;
				if (!((Object)(object)equipmentDef == (Object)null) && !((Object)(object)__instance.tooltipProvider == (Object)null))
				{
					StringBuilder stringBuilder = new StringBuilder(GetCombinedDescription(equipmentDef.descriptionToken, equipmentDef.pickupToken));
					stringBuilder.AppendLine().AppendLine().Append(GetEquipmentCooldown(equipmentDef, __instance.targetInventory));
					__instance.tooltipProvider.overrideBodyText = stringBuilder.ToString();
				}
			}
		}

		internal static string GetCombinedDescription(string descriptionToken, string pickupToken)
		{
			StringBuilder stringBuilder = new StringBuilder();
			string @string = Language.GetString(descriptionToken);
			string string2 = Language.GetString(pickupToken);
			if (@string != descriptionToken && @string != string2)
			{
				stringBuilder.AppendLine("<style=cStack>" + string2 + "</style>");
				stringBuilder.AppendLine();
				stringBuilder.Append(@string);
			}
			else
			{
				stringBuilder.Append(string2);
			}
			return stringBuilder.ToString();
		}

		internal static string GetEquipmentCooldown(EquipmentDef equipment, Inventory inventory)
		{
			if ((Object)(object)inventory == (Object)null)
			{
				return $"Cooldown: <style=cIsDamage>{equipment.cooldown:0.###}s</style>";
			}
			StringBuilder stringBuilder = new StringBuilder();
			float num = inventory.CalculateEquipmentCooldownScale();
			stringBuilder.Append($"Cooldown: <style=cIsDamage>{equipment.cooldown * num:0.###}s</style>");
			if (num < 1f)
			{
				stringBuilder.Append($" <style=cStack>({equipment.cooldown}×<style=cIsUtility>{num:0.###%}</style>)</style>");
			}
			return stringBuilder.ToString();
		}
	}
	[HarmonyPatch]
	internal static class PickupPickerTooltips
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(PickupPickerPanel), "SetPickupOptions")]
		private static void PickupPickerPanel_SetPickupOptions(PickupPickerPanel __instance, Option[] options)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Config.CommandMenuItemTooltips)
			{
				return;
			}
			for (int i = 0; i < options.Length; i++)
			{
				TooltipProvider val = TooltipHelper.AddTooltipProvider(((Component)__instance.buttonAllocator.elements[i]).GetComponent<Graphic>(), suppressLogs: true);
				PickupDef pickupDef = PickupCatalog.GetPickupDef(options[i].pickupIndex);
				ItemDef itemDef = ItemCatalog.GetItemDef(pickupDef.itemIndex);
				EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(pickupDef.equipmentIndex);
				bool flag = (Object)(object)itemDef != (Object)null;
				val.titleColor = pickupDef.darkColor;
				val.titleToken = (flag ? itemDef.nameToken : equipmentDef.nameToken);
				val.bodyToken = (flag ? itemDef.descriptionToken : equipmentDef.descriptionToken);
				if (flag)
				{
					val.overrideBodyText = FullerDescriptions.GetCombinedDescription(val.bodyToken, itemDef.pickupToken);
				}
				else
				{
					val.overrideBodyText = FullerDescriptions.GetCombinedDescription(val.bodyToken, equipmentDef.pickupToken) + "\n\n" + FullerDescriptions.GetEquipmentCooldown(equipmentDef, null);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class RunDifficultyTooltip
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(CurrentDifficultyIconController), "Start")]
		private static void CurrentDifficultyIconController_Start(CurrentDifficultyIconController __instance)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Config.RunDifficultyTooltip && (Object)(object)Run.instance != (Object)null)
			{
				TooltipProvider obj = TooltipHelper.AddTooltipProvider(((Component)__instance).GetComponent<Graphic>());
				DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(Run.instance.selectedDifficulty);
				obj.titleColor = difficultyDef.color;
				obj.titleToken = difficultyDef.nameToken;
				obj.bodyToken = difficultyDef.descriptionToken;
			}
		}
	}
	[HarmonyPatch]
	internal static class ScoreboardShowChat
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(ChatBox), "UpdateFade")]
		private static void ChatBox_UpdateFade(ChatBox __instance)
		{
			if (Plugin.Config.ScoreboardShowChat && (Object)(object)__instance.fadeGroup != (Object)null)
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				Player val = ((firstLocalUser != null) ? firstLocalUser.inputPlayer : null);
				if (val != null && val.GetButton("info"))
				{
					__instance.fadeGroup.alpha = 1f;
				}
			}
		}
	}
}
namespace HUDdleUP.Railgunner
{
	internal sealed class RailgunnerAccuracyPanel : MonoBehaviour
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static ShouldHudDisplayDelegate <0>__Init;
		}

		private static HUD hud;

		private static ReloadAccuracy reloadAccuracy;

		private static WeakPointAccuracy weakPointAccuracy;

		private HUDPanel panel;

		private TextMeshProUGUI display;

		public static void Hook()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__Init;
			if (obj == null)
			{
				ShouldHudDisplayDelegate val = Init;
				<>O.<0>__Init = val;
				obj = (object)val;
			}
			HUD.shouldHudDisplay += (ShouldHudDisplayDelegate)obj;
		}

		public static void Unhook()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__Init;
			if (obj == null)
			{
				ShouldHudDisplayDelegate val = Init;
				<>O.<0>__Init = val;
				obj = (object)val;
			}
			HUD.shouldHudDisplay -= (ShouldHudDisplayDelegate)obj;
			if (reloadAccuracy != null)
			{
				reloadAccuracy.Unhook();
				reloadAccuracy = null;
			}
			if (weakPointAccuracy != null)
			{
				weakPointAccuracy.Unhook();
				weakPointAccuracy = null;
			}
		}

		public static void Init(HUD hud, ref bool _)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Config.RailgunnerAccuracyPanel || (Object)(object)RailgunnerAccuracyPanel.hud != (Object)null)
			{
				return;
			}
			ObjectivePanelController componentInChildren = ((Component)hud).GetComponentInChildren<ObjectivePanelController>();
			if (!Object.op_Implicit((Object)(object)componentInChildren))
			{
				return;
			}
			RailgunnerAccuracyPanel.hud = hud;
			if (hud.localUserViewer.cachedBody.bodyIndex != BodyCatalog.FindBodyIndex("RailgunnerBody"))
			{
				Plugin.Logger.LogDebug((object)"Local user is not Railgunner, skipping RailgunnerAccuracyPanel initialization.");
				return;
			}
			if (reloadAccuracy == null)
			{
				reloadAccuracy = new ReloadAccuracy();
				reloadAccuracy.Hook();
			}
			if (weakPointAccuracy == null)
			{
				weakPointAccuracy = new WeakPointAccuracy();
				weakPointAccuracy.Hook();
			}
			HUDPanel hUDPanel = HUDPanel.ClonePanel(componentInChildren, "RailgunnerAccuracyPanel");
			((Component)hud).gameObject.AddComponent<RailgunnerAccuracyPanel>().panel = hUDPanel;
			Plugin.Logger.LogDebug((object)"Initialized RailgunnerAccuracyPanel.");
		}

		private void Start()
		{
			((TMP_Text)panel.label).text = "Accuracy:";
			display = panel.AddTextComponent("Accuracy Tracker");
		}

		private void Update()
		{
			if (reloadAccuracy != null)
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine(reloadAccuracy.ToString());
				stringBuilder.AppendLine();
				stringBuilder.AppendLine(weakPointAccuracy.ToString());
				((TMP_Text)display).text = stringBuilder.ToString();
			}
		}
	}
	internal sealed class ReloadAccuracy
	{
		private static readonly MethodInfo AttemptBoost = typeof(Reloading).GetMethod("AttemptBoost", BindingFlags.Instance | BindingFlags.Public);

		private readonly string labelColor = "#" + ColorUtility.ToHtmlStringRGB(DamageColor.FindColor((DamageColorIndex)12));

		private int totalReloads;

		private int perfectReloads;

		private int totalReloadsStage;

		private int perfectReloadsStage;

		private int consecutive;

		private int consecutiveBest;

		private Hook OnReloadAttemptBoost;

		public void Hook()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			MethodInfo method = typeof(ReloadAccuracy).GetMethod("RecordReload", BindingFlags.Instance | BindingFlags.NonPublic);
			OnReloadAttemptBoost = new Hook((MethodBase)AttemptBoost, method, (object)this);
			Stage.onStageStartGlobal += OnStageStart;
		}

		public void Unhook()
		{
			OnReloadAttemptBoost.Dispose();
			Stage.onStageStartGlobal -= OnStageStart;
		}

		private bool RecordReload(Func<Reloading, bool> orig, Reloading self)
		{
			bool num = orig(self);
			if (num)
			{
				perfectReloads++;
				perfectReloadsStage++;
				consecutive++;
			}
			else
			{
				if (consecutive > consecutiveBest)
				{
					consecutiveBest = consecutive;
				}
				consecutive = 0;
			}
			totalReloads++;
			totalReloadsStage++;
			return num;
		}

		private void OnStageStart(Stage _)
		{
			totalReloadsStage = 0;
			perfectReloadsStage = 0;
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("<style=cStack>> </style><color=" + labelColor + ">Perfect Reloads</color><style=cStack>: </style>");
			if (totalReloads == 0)
			{
				stringBuilder.Append("<style=cStack>-.--%</style>");
			}
			else
			{
				stringBuilder.Append($"{(float)perfectReloads / (float)totalReloads:0.00%}");
			}
			stringBuilder.AppendLine();
			stringBuilder.Append("<style=cStack>   > this stage: </style>");
			if (totalReloadsStage == 0)
			{
				stringBuilder.Append("<style=cStack>-.--%</style>");
			}
			else
			{
				stringBuilder.Append($"{(float)perfectReloadsStage / (float)totalReloadsStage:0.00%}");
			}
			stringBuilder.AppendLine($"<style=cStack> ({perfectReloadsStage}/{totalReloadsStage})</style>");
			stringBuilder.Append($"<style=cStack>   > consecutive: </style>{consecutive}<style=cStack> ({consecutiveBest})</style>");
			return stringBuilder.ToString();
		}
	}
	internal sealed class WeakPointAccuracy
	{
		private readonly string labelColor = "#" + ColorUtility.ToHtmlStringRGB(DamageColor.FindColor((DamageColorIndex)5));

		private int shots;

		private int weakPointHits;

		private int consecutive;

		private int consecutiveBest;

		public void Hook()
		{
			BaseFireSnipe.onFireSnipe += Snipe_onFireSnipe;
			BaseFireSnipe.onWeakPointHit += Snipe_onWeakPointHit;
			BaseFireSnipe.onWeakPointMissed += Snipe_onWeakPointMissed;
			Stage.onStageStartGlobal += OnStageStart;
		}

		public void Unhook()
		{
			BaseFireSnipe.onFireSnipe -= Snipe_onFireSnipe;
			BaseFireSnipe.onWeakPointHit -= Snipe_onWeakPointHit;
			BaseFireSnipe.onWeakPointMissed -= Snipe_onWeakPointMissed;
			Stage.onStageStartGlobal -= OnStageStart;
		}

		private void Snipe_onFireSnipe(BaseFireSnipe snipe)
		{
			if (((EntityState)snipe).isAuthority)
			{
				shots++;
			}
		}

		private void Snipe_onWeakPointHit(DamageInfo _)
		{
			weakPointHits++;
			consecutive++;
		}

		private void Snipe_onWeakPointMissed()
		{
			if (consecutive > consecutiveBest)
			{
				consecutiveBest = consecutive;
			}
			consecutive = 0;
		}

		private void OnStageStart(Stage _)
		{
			shots = 0;
			weakPointHits = 0;
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("<style=cStack>> </style><color=" + labelColor + ">Weak Points Hit</color><style=cStack>: </style>");
			stringBuilder.AppendLine($"{weakPointHits}<style=cStack> : {shots}</style>");
			stringBuilder.Append($"<style=cStack>   > consecutive: </style>{consecutive}<style=cStack> ({consecutiveBest})</style>");
			return stringBuilder.ToString();
		}
	}
}
namespace HUDdleUP.Loot
{
	public sealed record Interactables
	{
		public readonly int chests;

		public readonly int chestsAvailable;

		public readonly int terminals;

		public readonly int terminalsAvailable;

		public readonly int chanceShrines;

		public readonly int chanceShrinesAvailable;

		public readonly int shrineChances;

		public readonly int shrineChancesAvailable;

		public readonly int lockboxes;

		public readonly int lockboxesAvailable;

		public readonly int adaptiveChests;

		public readonly int adaptiveChestsAvailable;

		public readonly int voids;

		public readonly int voidsAvailable;

		public readonly int cloakedChests;

		public readonly int cloakedChestsAvailable;

		public readonly int equipment;

		public readonly int equipmentAvailable;

		public readonly int lunarPods;

		public readonly int lunarPodsAvailable;

		public readonly bool cleansingPoolPresent;

		public readonly bool scrapperPresent;

		public readonly int whiteTakers;

		public readonly int greenTakers;

		public readonly int redTakers;

		public readonly int yellowTakers;

		public Interactables(List<PurchaseInteraction> interactions, bool scrapperPresent)
		{
			//IL_0579: Unknown result type (might be due to invalid IL or missing references)
			//IL_057e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0580: Unknown result type (might be due to invalid IL or missing references)
			//IL_0583: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a5: Expected I4, but got Unknown
			this.scrapperPresent = scrapperPresent;
			for (int i = 0; i < interactions.Count; i++)
			{
				switch (interactions[i].displayNameToken)
				{
				case "CHEST1_NAME":
				case "CHEST2_NAME":
				case "CATEGORYCHEST_HEALING_NAME":
				case "CATEGORYCHEST_UTILITY_NAME":
				case "CATEGORYCHEST2_DAMAGE_NAME":
				case "CATEGORYCHEST2_HEALING_NAME":
				case "CATEGORYCHEST2_UTILITY_NAME":
				case "GOLDCHEST_NAME":
				case "CATEGORYCHEST_DAMAGE_NAME":
					chests++;
					if (interactions[i].available)
					{
						chestsAvailable++;
					}
					break;
				case "EQUIPMENTBARREL_NAME":
					equipment++;
					if (interactions[i].available)
					{
						equipmentAvailable++;
					}
					break;
				case "MULTISHOP_TERMINAL_NAME":
					if (((Object)interactions[i]).name.Contains("Equipment"))
					{
						equipment++;
						if (interactions[i].available)
						{
							equipmentAvailable++;
						}
					}
					else
					{
						terminals++;
						if (interactions[i].available)
						{
							terminalsAvailable++;
						}
					}
					break;
				case "SHRINE_CHANCE_NAME":
					chanceShrines++;
					if (interactions[i].available)
					{
						chanceShrinesAvailable++;
					}
					if (NetworkServer.active)
					{
						ShrineChanceBehavior component = ((Component)interactions[i]).GetComponent<ShrineChanceBehavior>();
						shrineChances += component.maxPurchaseCount;
						shrineChancesAvailable += component.maxPurchaseCount - component.successfulPurchaseCount;
					}
					break;
				case "VOIDLOCKBOX_NAME":
				case "LOCKBOX_NAME":
					lockboxes++;
					if (interactions[i].available)
					{
						lockboxesAvailable++;
					}
					break;
				case "CASINOCHEST_NAME":
					adaptiveChests++;
					if (interactions[i].available)
					{
						adaptiveChestsAvailable++;
					}
					break;
				case "VOID_TRIPLE_NAME":
				case "VOID_CHEST_NAME":
					voids++;
					if (interactions[i].available)
					{
						voidsAvailable++;
					}
					break;
				case "CHEST1_STEALTHED_NAME":
					cloakedChests++;
					if (interactions[i].available)
					{
						cloakedChestsAvailable++;
					}
					break;
				case "DUPLICATOR_WILD_NAME":
				case "BAZAAR_CAULDRON_NAME":
				case "DUPLICATOR_NAME":
				case "DUPLICATOR_MILITARY_NAME":
				{
					CostTypeIndex costType = interactions[i].costType;
					switch (costType - 4)
					{
					case 0:
						whiteTakers++;
						break;
					case 1:
						greenTakers++;
						break;
					case 2:
						redTakers++;
						break;
					case 6:
						yellowTakers++;
						break;
					}
					break;
				}
				case "SHRINE_CLEANSE_NAME":
					cleansingPoolPresent = true;
					break;
				case "LUNAR_CHEST_NAME":
					lunarPods++;
					if (interactions[i].available)
					{
						lunarPodsAvailable++;
					}
					break;
				}
			}
		}
	}
	internal sealed class LootPanel : MonoBehaviour
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static ShouldHudDisplayDelegate <0>__Init;
		}

		private static HUD hud;

		private HUDPanel panel;

		private TextMeshProUGUI display;

		private Interactables interactables;

		public static void Hook()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__Init;
			if (obj == null)
			{
				ShouldHudDisplayDelegate val = Init;
				<>O.<0>__Init = val;
				obj = (object)val;
			}
			HUD.shouldHudDisplay += (ShouldHudDisplayDelegate)obj;
		}

		public static void Unhook()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__Init;
			if (obj == null)
			{
				ShouldHudDisplayDelegate val = Init;
				<>O.<0>__Init = val;
				obj = (object)val;
			}
			HUD.shouldHudDisplay -= (ShouldHudDisplayDelegate)obj;
		}

		public static void Init(HUD hud, ref bool _)
		{
			if (Plugin.Config.LootPanel && !((Object)(object)LootPanel.hud != (Object)null))
			{
				ObjectivePanelController componentInChildren = ((Component)hud).GetComponentInChildren<ObjectivePanelController>();
				if (Object.op_Implicit((Object)(object)componentInChildren))
				{
					LootPanel.hud = hud;
					HUDPanel hUDPanel = HUDPanel.ClonePanel(componentInChildren, "LootPanel");
					((Component)hud).gameObject.AddComponent<LootPanel>().panel = hUDPanel;
					Plugin.Logger.LogDebug((object)"Initialized LootPanel.");
				}
			}
		}

		private void Start()
		{
			((TMP_Text)panel.label).text = "Loot:";
			display = panel.AddTextComponent("Loot Tracker");
		}

		private void Update()
		{
			LocalUser localUserViewer = hud.localUserViewer;
			bool flag = ((localUserViewer != null) ? localUserViewer.inputPlayer : null) != null && hud.localUserViewer.inputPlayer.GetButton("info");
			panel.gameObject.SetActive(flag);
			if (flag)
			{
				interactables = new Interactables(InstanceTracker.GetInstancesList<PurchaseInteraction>(), (Object)(object)Object.FindObjectOfType<ScrapperController>() != (Object)null);
				((TMP_Text)display).text = GenerateText();
			}
		}

		public string GenerateText()
		{
			string tagValue = "#" + ColorCatalog.GetColorHexString((ColorIndex)5);
			StringBuilder stringBuilder = new StringBuilder();
			if (interactables.terminals > 0)
			{
				stringBuilder.AppendLine(FormatLine("style", "cIsUtility", "MULTISHOP_TERMINAL_NAME", interactables.terminalsAvailable, interactables.terminals));
			}
			if (interactables.chests > 0)
			{
				stringBuilder.AppendLine(FormatLine("style", "cIsDamage", "CHEST1_NAME", interactables.chestsAvailable, interactables.chests));
			}
			if (interactables.adaptiveChests > 0)
			{
				stringBuilder.AppendLine(FormatLine("style", "cArtifact", "CASINOCHEST_NAME", interactables.adaptiveChestsAvailable, interactables.adaptiveChests));
			}
			if (interactables.chanceShrines > 0)
			{
				stringBuilder.AppendLine(NetworkServer.active ? FormatLine("style", "cShrine", "SHRINE_CHANCE_NAME", interactables.shrineChancesAvailable, interactables.shrineChances, interactables.chanceShrinesAvailable) : FormatLine("style", "cShrine", "SHRINE_CHANCE_NAME", interactables.chanceShrinesAvailable, interactables.chanceShrines));
			}
			if (interactables.equipment > 0)
			{
				stringBuilder.AppendLine(FormatLine("color", tagValue, "EQUIPMENTBARREL_NAME", interactables.equipmentAvailable, interactables.equipment));
			}
			if (interactables.lockboxes > 0)
			{
				stringBuilder.AppendLine(FormatLine("style", "cHumanObjective", "LOCKBOX_NAME", interactables.lockboxesAvailable, interactables.lockboxes));
			}
			if ((Object)(object)TeleporterInteraction.instance != (Object)null)
			{
				if (TeleporterInteraction.instance.monstersCleared)
				{
					string text = (interactables.cleansingPoolPresent ? " · <style=cLunarObjective>@</style>" : "");
					stringBuilder.AppendLine().AppendLine(FormatLabel("<style=cSub>" + Language.GetString("SCRAPPER_NAME") + "</style>") + (interactables.scrapperPresent ? "@" : "×") + text);
					AppendFabricators(interactables, stringBuilder);
					if (interactables.voids > 0)
					{
						stringBuilder.AppendLine(FormatLine("style", "cIsVoid", "VOID_CHEST_NAME", interactables.voidsAvailable, interactables.voids));
					}
					if (interactables.lunarPods > 0)
					{
						stringBuilder.AppendLine(FormatLine("style", "cLunarObjective", "LUNAR_CHEST_NAME", interactables.lunarPodsAvailable, interactables.lunarPods));
					}
				}
				if (TeleporterInteraction.instance.isCharged && interactables.cloakedChests > 0)
				{
					stringBuilder.AppendLine().AppendLine(FormatLine("style", "cLunarObjective", "CHEST1_STEALTHED_NAME", interactables.cloakedChestsAvailable, interactables.cloakedChests));
				}
			}
			stringBuilder.AppendLine().AppendLine(FormatEnemies());
			if ((Object)(object)TeleporterInteraction.instance != (Object)null && TeleporterInteraction.instance.shrineBonusStacks > 0)
			{
				stringBuilder.AppendLine($"<style=cStack>Invitations: <style=cIsUtility>{TeleporterInteraction.instance.shrineBonusStacks}</style></style>");
			}
			return stringBuilder.ToString();
		}

		private static StringBuilder AppendFabricators(Interactables interactables, StringBuilder sb)
		{
			//IL_001f: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			if (interactables.whiteTakers > 0)
			{
				int whiteTakers = interactables.whiteTakers;
				list.Add(Util.GenerateColoredString(whiteTakers.ToString(), ColorCatalog.GetColor((ColorIndex)1)));
			}
			if (interactables.greenTakers > 0)
			{
				int whiteTakers = interactables.greenTakers;
				list.Add(Util.GenerateColoredString(whiteTakers.ToString(), ColorCatalog.GetColor((ColorIndex)2)));
			}
			if (interactables.redTakers > 0)
			{
				int whiteTakers = interactables.redTakers;
				list.Add(Util.GenerateColoredString(whiteTakers.ToString(), ColorCatalog.GetColor((ColorIndex)3)));
			}
			if (interactables.yellowTakers > 0)
			{
				int whiteTakers = interactables.yellowTakers;
				list.Add(Util.GenerateColoredString(whiteTakers.ToString(), ColorCatalog.GetColor((ColorIndex)13)));
			}
			string text = string.Join(" · ", list);
			if (!string.IsNullOrEmpty(text))
			{
				sb.AppendLine(FormatToken("DUPLICATOR_NAME", "style", "cStack") + "<style=cStack>" + text + "</style>");
			}
			return sb;
		}

		private static string FormatEnemies()
		{
			int count = TeamComponent.GetTeamMembers((TeamIndex)2).Count;
			int count2 = TeamComponent.GetTeamMembers((TeamIndex)3).Count;
			int count3 = TeamComponent.GetTeamMembers((TeamIndex)4).Count;
			List<string> list = new List<string>();
			if (count > 0)
			{
				list.Add($"<style=cSub>{count}</style>");
			}
			if (count2 > 0)
			{
				list.Add($"<style=cLunarObjective>{count2}</style>");
			}
			if (count3 > 0)
			{
				list.Add($"<style=cIsVoid>{count3}</style>");
			}
			string text = string.Join(" · ", list);
			return "<style=cStack>Enemies: " + (string.IsNullOrEmpty(text) ? "0" : text) + "</style>";
		}

		private static string FormatLine(string tagKey, string tagValue, string token, int available, int total, int meta)
		{
			return FormatToken(token, tagKey, tagValue) + FormatCounter(available, total, meta);
		}

		private static string FormatLine(string tagKey, string tagValue, string token, int available, int total)
		{
			return FormatToken(token, tagKey, tagValue) + FormatCounter(available, total);
		}

		private static string FormatToken(string token, string tagKey, string tagValue)
		{
			return FormatLabel("<" + tagKey + "=" + tagValue + ">" + Language.GetString(token) + "</" + tagKey + ">");
		}

		private static string FormatLabel(string label)
		{
			return "<style=cStack>> </style>" + label + "<style=cStack>:</style> ";
		}

		private static string FormatCounter(int available, int total, int meta)
		{
			return $"{FormatCounter(available, total)}<style=cStack><size=90%> ({meta})</size></style>";
		}

		private static string FormatCounter(int available, int total)
		{
			if (available != 0)
			{
				return $"{available}<style=cStack>/{total}</style>";
			}
			return $"<style=cSub>{available}</style><style=cStack>/{total}</style>";
		}
	}
}
namespace HUDdleUP.Behaviours
{
	internal class EquipmentCooldownPanel : MonoBehaviour
	{
		private static float LastLogTime;

		private EquipmentIcon parent;

		private RawImage cooldownRemapPanel;

		private float cooldownEndTime;

		private float cooldownTimerMax;

		internal static void Init(EquipmentIcon parent, GameObject target)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(target, ((Component)parent).transform);
			EquipmentCooldownPanel equipmentCooldownPanel = val.AddComponent<EquipmentCooldownPanel>();
			equipmentCooldownPanel.parent = parent;
			equipmentCooldownPanel.cooldownRemapPanel = val.GetComponent<RawImage>();
			((RectTransform)((Component)equipmentCooldownPanel.cooldownRemapPanel).transform).sizeDelta = ((RectTransform)((Component)parent).transform).sizeDelta;
		}

		private void Update()
		{
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)parent == (Object)null)
			{
				float time = Time.time;
				if (!Mathf.Approximately(LastLogTime, time))
				{
					Plugin.Logger.LogWarning((object)"EquipmentCooldownPanel> Component instantiated but parent became null, removing self. This warning can safely be ignored if Starstorm 2 is installed.");
					LastLogTime = time;
				}
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			float num = 1f;
			if (Object.op_Implicit((Object)(object)parent.targetInventory))
			{
				EquipmentState val = (parent.displayAlternateEquipment ? parent.targetInventory.alternateEquipmentState : parent.targetInventory.currentEquipmentState);
				float timeUntilClamped = ((FixedTimeStamp)(ref val.chargeFinishTime)).timeUntilClamped;
				if (cooldownEndTime != val.chargeFinishTime.t)
				{
					cooldownTimerMax = timeUntilClamped;
					cooldownEndTime = val.chargeFinishTime.t;
				}
				if (cooldownTimerMax > 0f)
				{
					num = 1f - timeUntilClamped / cooldownTimerMax;
				}
			}
			((Behaviour)cooldownRemapPanel).enabled = num < 1f;
			((Graphic)cooldownRemapPanel).color = new Color(1f, 1f, 1f, num);
		}
	}
}