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.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+1f79d7e94b8102d4865b1f50c45ae8797ffb54d1")]
[assembly: AssemblyProduct("HUDdleUP")]
[assembly: AssemblyTitle("HUDdleUP")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.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 HGTextMeshProUGUI label;
internal HUDPanel(GameObject panel, HGTextMeshProUGUI label)
{
gameObject = panel;
this.label = label;
}
public HGTextMeshProUGUI AddTextComponent(string name)
{
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
HGTextMeshProUGUI obj = Object.Instantiate<HGTextMeshProUGUI>(label, ((TMP_Text)label).transform.parent);
LayoutElement component = ((Component)obj).GetComponent<LayoutElement>();
if (Object.op_Implicit((Object)(object)component))
{
Object.Destroy((Object)(object)component);
}
((Object)obj).name = name;
((Component)obj).GetComponent<LabelSkinController>().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)
{
GameObject obj = DeleteObjectiveComponents(Object.Instantiate<ObjectivePanelController>(objectivePanel, ((Component)objectivePanel).transform.parent));
HGTextMeshProUGUI componentInChildren = obj.GetComponentInChildren<HGTextMeshProUGUI>();
LanguageTextMeshController component = ((Component)componentInChildren).GetComponent<LanguageTextMeshController>();
if (Object.op_Implicit((Object)(object)component))
{
Object.DestroyImmediate((Object)(object)component);
}
((Object)obj).name = name;
return new HUDPanel(obj, componentInChildren);
}
private static GameObject DeleteObjectiveComponents(ObjectivePanelController objectivePanel)
{
GameObject val = ((Component)((Component)objectivePanel).transform.GetChild(((Component)objectivePanel).transform.childCount - 1)).gameObject;
if (Object.op_Implicit((Object)(object)val))
{
Object.Destroy((Object)(object)val);
}
HudObjectiveTargetSetter component = ((Component)objectivePanel).GetComponent<HudObjectiveTargetSetter>();
if (Object.op_Implicit((Object)(object)component))
{
Object.Destroy((Object)(object)component);
}
GameObject result = ((Component)objectivePanel).gameObject;
Object.Destroy((Object)(object)objectivePanel);
return result;
}
}
[HarmonyPatch]
[BepInPlugin("itsschwer.HUDdleUP", "HUDdleUP", "1.0.2")]
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.2";
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]))
{
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 HGTextMeshProUGUI 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 HGTextMeshProUGUI 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))
{
HUDPanel hUDPanel = HUDPanel.ClonePanel(componentInChildren, "LootPanel");
((Component)hud).gameObject.AddComponent<LootPanel>().panel = hUDPanel;
LootPanel.hud = hud;
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 EquipmentIcon parent;
private RawImage cooldownRemapPanel;
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_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)parent == (Object)null)
{
Plugin.Logger.LogWarning((object)"EquipmentCooldownPanel> Component instantiated but parent became null, removing self. This warning can safely be ignored if Starstorm 2 is installed.");
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 (timeUntilClamped > cooldownTimerMax || float.IsInfinity(cooldownTimerMax))
{
cooldownTimerMax = timeUntilClamped;
}
if (cooldownTimerMax >= Mathf.Epsilon)
{
num = 1f - timeUntilClamped / cooldownTimerMax;
}
}
((Behaviour)cooldownRemapPanel).enabled = num < 1f;
((Graphic)cooldownRemapPanel).color = new Color(1f, 1f, 1f, num);
}
}
}