using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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 LocalHudControl
{
[BepInPlugin("local.howtofish.hudcontrol", "HUD Control", "1.0.0")]
[DefaultExecutionOrder(30000)]
public sealed class HudControl : BaseUnityPlugin
{
public const string Id = "local.howtofish.hudcontrol";
public static HudControl Instance;
private static readonly FieldInfo UiInstance = AccessTools.Field(typeof(PlayerUI), "_instance");
private static readonly string[] GroupNames = new string[3] { "_mainCanvas", "_fxCanvas", "_bossCanvas" };
private readonly List<HudGroup> groups = new List<HudGroup>();
private ConfigEntry<float> scaleSetting;
private ConfigEntry<float> opacitySetting;
private ConfigEntry<bool> hideSetting;
private Harmony harmony;
private PlayerUI boundUi;
private bool open;
private bool dirty;
private float nextScan;
private float saveAt;
private Rect window = new Rect(32f, 80f, 400f, 300f);
private CursorLockMode oldLock;
private bool oldVisible;
private GUIStyle heading;
private GUIStyle label;
private GUIStyle button;
private GUIStyle checkbox;
public static bool IsOpen
{
get
{
if ((Object)(object)Instance != (Object)null)
{
return Instance.open;
}
return false;
}
}
private void Awake()
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Expected O, but got Unknown
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Expected O, but got Unknown
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_0113: Expected O, but got Unknown
Instance = this;
((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
scaleSetting = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Scale", 1f, new ConfigDescription("Base HUD scale: 0.5 (50%) to 1 (default).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 1f), Array.Empty<object>()));
opacitySetting = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Opacity", 1f, new ConfigDescription("Base HUD opacity: 0 (transparent) to 1 (opaque).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
hideSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "HideHUD", false, "Hide the base HUD. The F1 settings panel remains accessible.");
scaleSetting.Value = HudValues.Clamp(scaleSetting.Value, 0.5f, 1f, 1f);
opacitySetting.Value = HudValues.Clamp(opacitySetting.Value, 0f, 1f, 1f);
harmony = new Harmony("local.howtofish.hudcontrol");
harmony.PatchAll(typeof(HudControl).Assembly);
((BaseUnityPlugin)this).Config.Save();
((BaseUnityPlugin)this).Logger.LogInfo((object)"HUD Control loaded. F1 opens scale, visibility and opacity settings.");
}
private void Update()
{
Keyboard current = Keyboard.current;
if (current != null && ((ButtonControl)current.f1Key).wasPressedThisFrame)
{
SetOpen(!open);
}
if (Time.unscaledTime >= nextScan)
{
nextScan = Time.unscaledTime + 0.5f;
object? value = UiInstance.GetValue(null);
PlayerUI val = (PlayerUI)((value is PlayerUI) ? value : null);
if ((Object)(object)val != (Object)(object)boundUi || ((Object)(object)val != (Object)null && groups.Count == 0) || ((Object)(object)val == (Object)null && groups.Count > 0))
{
Bind(val);
}
}
}
private void Bind(PlayerUI ui)
{
foreach (HudGroup group in groups)
{
group.Restore();
}
groups.Clear();
boundUi = ui;
if ((Object)(object)ui == (Object)null)
{
return;
}
List<CanvasGroup> list = new List<CanvasGroup>();
string[] groupNames = GroupNames;
foreach (string text in groupNames)
{
object? value = AccessTools.Field(typeof(PlayerUI), text).GetValue(ui);
CanvasGroup val = (CanvasGroup)((value is CanvasGroup) ? value : null);
if ((Object)(object)val != (Object)null && !list.Contains(val))
{
list.Add(val);
}
}
foreach (CanvasGroup item in list)
{
bool flag = false;
foreach (CanvasGroup item2 in list)
{
if ((Object)(object)item2 != (Object)(object)item && ((Component)item).transform.IsChildOf(((Component)item2).transform))
{
flag = true;
}
}
if (!flag)
{
groups.Add(new HudGroup(item));
((BaseUnityPlugin)this).Logger.LogInfo((object)("Controlling base HUD group: " + ((Object)item).name));
}
}
}
private void LateUpdate()
{
foreach (HudGroup group in groups)
{
group.Apply(scaleSetting.Value, hideSetting.Value ? 0f : opacitySetting.Value);
}
if (open)
{
Cursor.lockState = (CursorLockMode)0;
Cursor.visible = true;
}
if (dirty && Time.unscaledTime >= saveAt)
{
Save();
}
}
public void CaptureGameAlpha(MethodBase method)
{
string text = ((method.Name == "ToggleMainCanvas") ? "_mainCanvas" : ((method.Name == "ToggleFXCanvas") ? "_fxCanvas" : "_bossCanvas"));
object? value = UiInstance.GetValue(null);
PlayerUI val = (PlayerUI)((value is PlayerUI) ? value : null);
if ((Object)(object)val == (Object)null)
{
return;
}
object? value2 = AccessTools.Field(typeof(PlayerUI), text).GetValue(val);
CanvasGroup val2 = (CanvasGroup)((value2 is CanvasGroup) ? value2 : null);
foreach (HudGroup group in groups)
{
if ((Object)(object)group.Group == (Object)(object)val2)
{
group.CaptureAlpha();
}
}
}
public void CaptureCanvasScale(CanvasScaler scaler, float value)
{
foreach (HudGroup group in groups)
{
group.CaptureCanvasScale(scaler, value);
}
}
public void SetOpen(bool value)
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Invalid comparison between Unknown and I4
if (open == value)
{
return;
}
if (value)
{
oldLock = Cursor.lockState;
oldVisible = Cursor.visible;
open = true;
try
{
PlayerCamera.ToggleMouse(true);
}
catch
{
}
Cursor.lockState = (CursorLockMode)0;
Cursor.visible = true;
}
else
{
open = false;
try
{
PlayerCamera.ToggleMouse((int)oldLock != 1);
}
catch
{
Cursor.lockState = oldLock;
Cursor.visible = oldVisible;
}
Save();
}
}
private void Changed()
{
dirty = true;
saveAt = Time.unscaledTime + 0.4f;
}
private void Save()
{
if (dirty)
{
((BaseUnityPlugin)this).Config.Save();
dirty = false;
}
}
private void OnGUI()
{
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
//IL_0157: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Expected O, but got Unknown
//IL_0161: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Expected O, but got Unknown
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Expected O, but got Unknown
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Expected O, but got Unknown
if (open)
{
if (heading == null)
{
heading = new GUIStyle(GUI.skin.label)
{
fontSize = 21,
fontStyle = (FontStyle)1
};
label = new GUIStyle(GUI.skin.label)
{
fontSize = 15
};
button = new GUIStyle(GUI.skin.button)
{
fontSize = 14
};
checkbox = new GUIStyle(GUI.skin.toggle)
{
fontSize = 16
};
}
GUI.depth = -10000;
((Rect)(ref window)).width = Mathf.Min(400, Screen.width);
((Rect)(ref window)).height = Mathf.Min(300, Screen.height);
((Rect)(ref window)).x = Mathf.Clamp(((Rect)(ref window)).x, 0f, Mathf.Max(0f, (float)Screen.width - ((Rect)(ref window)).width));
((Rect)(ref window)).y = Mathf.Clamp(((Rect)(ref window)).y, 0f, Mathf.Max(0f, (float)Screen.height - ((Rect)(ref window)).height));
window = GUI.Window(4740420, window, new WindowFunction(DrawWindow), "");
}
}
private void DrawWindow(int id)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
//IL_0208: Unknown result type (might be due to invalid IL or missing references)
//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
//IL_030a: Unknown result type (might be due to invalid IL or missing references)
//IL_0353: Unknown result type (might be due to invalid IL or missing references)
GUI.Label(new Rect(18f, 12f, 290f, 32f), "HUD settings", heading);
if (GUI.Button(new Rect(((Rect)(ref window)).width - 45f, 12f, 28f, 27f), "X", button))
{
SetOpen(value: false);
}
GUI.Label(new Rect(18f, 51f, ((Rect)(ref window)).width - 36f, 24f), "Scale " + Mathf.RoundToInt(scaleSetting.Value * 100f) + "%", label);
float num = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 81f, ((Rect)(ref window)).width - 40f, 22f), scaleSetting.Value, 0.5f, 1f) * 100f) / 100f;
GUI.Label(new Rect(18f, 101f, ((Rect)(ref window)).width - 36f, 23f), "50% 100% (default)", label);
bool flag = GUI.Toggle(new Rect(20f, 133f, ((Rect)(ref window)).width - 40f, 26f), hideSetting.Value, " Hide HUD", checkbox);
GUI.Label(new Rect(18f, 171f, ((Rect)(ref window)).width - 36f, 24f), "Opacity " + Mathf.RoundToInt(opacitySetting.Value * 100f) + "%", label);
float num2 = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 202f, ((Rect)(ref window)).width - 40f, 22f), opacitySetting.Value, 0f, 1f) * 100f) / 100f;
if (num != scaleSetting.Value || num2 != opacitySetting.Value || flag != hideSetting.Value)
{
scaleSetting.Value = num;
opacitySetting.Value = num2;
hideSetting.Value = flag;
Changed();
}
if (GUI.Button(new Rect(18f, 246f, 128f, 30f), "Reset defaults", button))
{
ConfigEntry<float> obj = scaleSetting;
float value = (opacitySetting.Value = 1f);
obj.Value = value;
hideSetting.Value = false;
Changed();
}
GUI.Label(new Rect(163f, 249f, ((Rect)(ref window)).width - 170f, 25f), (groups.Count == 0) ? "Load a game to preview" : "F1 / Esc to close", label);
GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref window)).width - 52f, 45f));
}
private void OnDestroy()
{
SetOpen(value: false);
Save();
foreach (HudGroup group in groups)
{
group.Restore();
}
if (harmony != null)
{
harmony.UnpatchSelf();
}
Instance = null;
}
}
public sealed class HudGroup
{
private readonly RectTransform rect;
private readonly Canvas rootCanvas;
private readonly Vector3 originalScale;
private readonly Vector2 originalSize;
private readonly bool originalRaycasts;
private readonly bool originalInteractable;
private readonly MultiplierState alpha;
private readonly MultiplierState canvasScale;
public CanvasGroup Group { get; private set; }
public HudGroup(CanvasGroup group)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: 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)
Group = group;
ref RectTransform reference = ref rect;
Transform transform = ((Component)group).transform;
reference = (RectTransform)(object)((transform is RectTransform) ? transform : null);
originalScale = ((Transform)rect).localScale;
originalSize = rect.sizeDelta;
originalRaycasts = group.blocksRaycasts;
originalInteractable = group.interactable;
alpha = new MultiplierState(group.alpha);
Canvas component = ((Component)group).GetComponent<Canvas>();
if ((Object)(object)component != (Object)null && component.isRootCanvas)
{
rootCanvas = component;
canvasScale = new MultiplierState(component.scaleFactor);
}
}
public void CaptureAlpha()
{
if ((Object)(object)Group != (Object)null)
{
alpha.SetBaseline(Group.alpha);
}
}
public void CaptureCanvasScale(CanvasScaler scaler, float value)
{
if ((Object)(object)rootCanvas != (Object)null && (Object)(object)((Component)scaler).gameObject == (Object)(object)((Component)rootCanvas).gameObject)
{
canvasScale.SetBaseline(value);
}
}
public void Apply(float scale, float opacity)
{
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: 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_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Group == (Object)null)
{
return;
}
alpha.Observe(Group.alpha);
Group.alpha = alpha.Apply(opacity);
Group.blocksRaycasts = opacity > 0f && originalRaycasts;
Group.interactable = opacity > 0f && originalInteractable;
if ((Object)(object)rootCanvas != (Object)null)
{
canvasScale.Observe(rootCanvas.scaleFactor);
rootCanvas.scaleFactor = canvasScale.Apply(scale);
}
else if ((Object)(object)rect != (Object)null)
{
Transform parent = ((Transform)rect).parent;
RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
if ((Object)(object)val != (Object)null)
{
Rect val2 = val.rect;
Vector2 val3 = Vector2.Scale(((Rect)(ref val2)).size, rect.anchorMax - rect.anchorMin);
rect.sizeDelta = new Vector2(HudValues.CompensatedSize(val3.x, originalSize.x, scale), HudValues.CompensatedSize(val3.y, originalSize.y, scale));
}
((Transform)rect).localScale = originalScale * scale;
}
}
public void Restore()
{
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)Group == (Object)null))
{
Group.alpha = alpha.Baseline;
Group.blocksRaycasts = originalRaycasts;
Group.interactable = originalInteractable;
if ((Object)(object)rootCanvas != (Object)null)
{
rootCanvas.scaleFactor = canvasScale.Baseline;
}
else if ((Object)(object)rect != (Object)null)
{
((Transform)rect).localScale = originalScale;
rect.sizeDelta = originalSize;
}
}
}
}
[HarmonyPatch(typeof(Player), "get_BlockInputs")]
internal static class BlockPlayerInput
{
private static void Postfix(Player __instance, ref bool __result)
{
if (HudControl.IsOpen && (Object)(object)__instance == (Object)(object)Player.LocalPlayer)
{
__result = true;
}
}
}
[HarmonyPatch]
internal static class BlockCameraInput
{
private static IEnumerable<MethodBase> TargetMethods()
{
string[] array = new string[4] { "MouseClick", "MouseInput", "ControllerRotation", "ApplyAimAssist" };
foreach (string text in array)
{
yield return AccessTools.Method(typeof(PlayerCamera), text, (Type[])null, (Type[])null);
}
}
private static bool Prefix()
{
return !HudControl.IsOpen;
}
}
[HarmonyPatch(typeof(PauseManager), "PauseInput")]
internal static class CloseOnEscape
{
private static bool Prefix(CallbackContext context)
{
if (!HudControl.IsOpen)
{
return true;
}
if (((CallbackContext)(ref context)).performed)
{
HudControl.Instance.SetOpen(value: false);
}
return false;
}
}
[HarmonyPatch]
internal static class RespectGameVisibility
{
private static IEnumerable<MethodBase> TargetMethods()
{
string[] array = new string[3] { "ToggleMainCanvas", "ToggleFXCanvas", "ToggleBossCanvas" };
foreach (string text in array)
{
yield return AccessTools.Method(typeof(PlayerUI), text, (Type[])null, (Type[])null);
}
}
private static void Postfix(MethodBase __originalMethod)
{
if ((Object)(object)HudControl.Instance != (Object)null)
{
HudControl.Instance.CaptureGameAlpha(__originalMethod);
}
}
}
[HarmonyPatch(typeof(CanvasScaler), "SetScaleFactor")]
internal static class RespectResolutionScale
{
private static void Postfix(CanvasScaler __instance, float __0)
{
if ((Object)(object)HudControl.Instance != (Object)null)
{
HudControl.Instance.CaptureCanvasScale(__instance, __0);
}
}
}
public static class HudValues
{
public static float Clamp(float value, float minimum, float maximum, float fallback)
{
if (float.IsNaN(value) || float.IsInfinity(value))
{
return fallback;
}
return Math.Max(minimum, Math.Min(maximum, value));
}
public static float CompensatedSize(float parentSpan, float originalDelta, float scale)
{
return (parentSpan + originalDelta) / scale - parentSpan;
}
}
public sealed class MultiplierState
{
private float applied;
private bool hasApplied;
public float Baseline { get; private set; }
public MultiplierState(float initial)
{
Baseline = initial;
}
public void Observe(float current)
{
if (!hasApplied || Math.Abs(current - applied) > 1E-05f)
{
Baseline = current;
}
}
public void SetBaseline(float value)
{
Baseline = value;
}
public float Apply(float multiplier)
{
hasApplied = true;
return applied = Baseline * multiplier;
}
}
}