Decompiled source of HexSkillBarOverlay v1.0.0

Plugins/HexSkillBarOverlay.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HexSkillBarOverlay.UI;
using HexSkillBarOverlay.UI.Models;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("HexSkillVarOverlay")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HexSkillVarOverlay")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("5a4e3281-7d6a-4cf5-8a43-477471bebb33")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HexSkillBarOverlay
{
	[BepInPlugin("com.hex.skillbaroverlay", "HexSkillBarOverlay", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private const string PluginGuid = "com.hex.skillbaroverlay";

		private const string PluginName = "HexSkillBarOverlay";

		private const string PluginVersion = "1.0.0";

		private Harmony _harmonyInstance;

		private GameObject _controllerObject;

		internal static ManualLogSource Log;

		internal static Plugin Instance;

		internal static readonly FieldRef<Skills, Player> SkillsPlayerField = AccessTools.FieldRefAccess<Skills, Player>("m_player");

		internal static readonly FieldRef<Skill, SkillDef> SkillInfoField = AccessTools.FieldRefAccess<Skill, SkillDef>("m_info");

		internal static readonly FieldRef<Skill, float> SkillLevelField = AccessTools.FieldRefAccess<Skill, float>("m_level");

		internal static readonly FieldRef<SkillDef, Sprite> SkillIconField = AccessTools.FieldRefAccess<SkillDef, Sprite>("m_icon");

		internal static readonly FieldRef<SkillDef, float> SkillIncreaseStepField = AccessTools.FieldRefAccess<SkillDef, float>("m_increseStep");

		internal static readonly FastInvokeHandler SkillsGetSkillMethod = MethodInvoker.GetHandler(AccessTools.Method(typeof(Skills), "GetSkill", (Type[])null, (Type[])null), false);

		internal static readonly FastInvokeHandler SkillGetLevelPercentageMethod = MethodInvoker.GetHandler(AccessTools.Method(typeof(Skill), "GetLevelPercentage", (Type[])null, (Type[])null), false);

		internal static AssetBundle Bundle;

		internal static GameObject SkillBarPrefab;

		internal static ConfigEntry<bool> EnableDragging { get; private set; }

		internal static ConfigEntry<float> OverlayPositionX { get; private set; }

		internal static ConfigEntry<float> OverlayPositionY { get; private set; }

		private void Awake()
		{
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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;
			Log = ((BaseUnityPlugin)this).Logger;
			EnableDragging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable Dragging", false, "Allows the skill bar overlay to be repositioned by dragging it. The game must be paused while moving the overlay.");
			OverlayPositionX = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Overlay Position X", 40f, "Saved horizontal position of the skill bar overlay.");
			OverlayPositionY = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Overlay Position Y", 0f, "Saved vertical position of the skill bar overlay.");
			Bundle = GetAssetBundleFromResources("skill-bar-overlay");
			if ((Object)(object)Bundle == (Object)null)
			{
				Log.LogError((object)"Failed to load skill bar AssetBundle.");
				return;
			}
			SkillBarPrefab = Bundle.LoadAsset<GameObject>("SkillBars");
			if ((Object)(object)SkillBarPrefab == (Object)null)
			{
				Log.LogError((object)"Failed to load SkillBars prefab from AssetBundle.");
				return;
			}
			_controllerObject = new GameObject("HexSkillBarOverlayController");
			Object.DontDestroyOnLoad((Object)(object)_controllerObject);
			_controllerObject.AddComponent<SkillBarPrefabController>();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmonyInstance = new Harmony("com.hex.skillbaroverlay");
			_harmonyInstance.PatchAll(executingAssembly);
		}

		private void OnDestroy()
		{
			Harmony harmonyInstance = _harmonyInstance;
			if (harmonyInstance != null)
			{
				harmonyInstance.UnpatchSelf();
			}
			_harmonyInstance = null;
			if ((Object)(object)_controllerObject != (Object)null)
			{
				Object.Destroy((Object)(object)_controllerObject);
				_controllerObject = null;
			}
			Instance = null;
			Log = null;
		}

		private static AssetBundle GetAssetBundleFromResources(string fileName)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string text = executingAssembly.GetManifestResourceNames().SingleOrDefault((string resourceName) => resourceName.EndsWith(fileName));
			if (text == null)
			{
				Log.LogError((object)("Could not find embedded resource ending with '" + fileName + "'."));
				return null;
			}
			using Stream stream = executingAssembly.GetManifestResourceStream(text);
			if (stream == null)
			{
				Log.LogError((object)("Failed to open embedded resource stream: " + text));
				return null;
			}
			return AssetBundle.LoadFromStream(stream);
		}
	}
}
namespace HexSkillBarOverlay.UI
{
	internal sealed class SkillBarDragHandler : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		private RectTransform _rectTransform;

		private Vector2 _startPosition;

		private Vector2 _startPointerPosition;

		internal Action<Vector2> DragEnded { get; set; }

		private void Awake()
		{
			_rectTransform = ((Component)this).GetComponent<RectTransform>();
		}

		public void OnBeginDrag(PointerEventData eventData)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_rectTransform == (Object)null))
			{
				_startPosition = _rectTransform.anchoredPosition;
				_startPointerPosition = eventData.position;
			}
		}

		public void OnDrag(PointerEventData eventData)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_rectTransform == (Object)null))
			{
				Vector2 val = eventData.position - _startPointerPosition;
				_rectTransform.anchoredPosition = _startPosition + val;
			}
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_rectTransform == (Object)null))
			{
				DragEnded?.Invoke(_rectTransform.anchoredPosition);
			}
		}
	}
	internal sealed class SkillBarPrefabController : MonoBehaviour
	{
		private const float DisplayDuration = 2f;

		private const float GainPulseScale = 1.5f;

		private const float GainPulseDuration = 0.25f;

		private readonly Dictionary<SkillType, SkillBarViewModel> _skillBars = new Dictionary<SkillType, SkillBarViewModel>();

		private readonly List<SkillType> _activeSkills = new List<SkillType>();

		private readonly Dictionary<SkillType, float> _gainPulseTimes = new Dictionary<SkillType, float>();

		private GameObject _canvasObject;

		private GameObject _skillBarsObject;

		private RectTransform _container;

		private GameObject _skillBarTemplate;

		private SkillBarDragHandler _dragHandler;

		private GameObject _dragArea;

		private TextMeshProUGUI _dragText;

		internal static SkillBarPrefabController Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			Plugin.EnableDragging.SettingChanged += OnEnableDraggingChanged;
		}

		private void Update()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (_activeSkills.Count == 0)
			{
				return;
			}
			for (int num = _activeSkills.Count - 1; num >= 0; num--)
			{
				SkillType val = _activeSkills[num];
				SkillBarViewModel skillBarViewModel = _skillBars[val];
				UpdateGainPulse(val, skillBarViewModel);
				if (!(Time.time < skillBarViewModel.HideTime))
				{
					skillBarViewModel.GameObject.SetActive(false);
					skillBarViewModel.IsVisible = false;
					((Transform)((TMP_Text)skillBarViewModel.GainText).rectTransform).localScale = Vector3.one;
					((TMP_Text)skillBarViewModel.GainText).fontStyle = (FontStyles)0;
					_gainPulseTimes.Remove(val);
					_activeSkills.RemoveAt(num);
				}
			}
		}

		internal void CreateUi()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0084: 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)
			if (!((Object)(object)_canvasObject != (Object)null) && !((Object)(object)Plugin.SkillBarPrefab == (Object)null))
			{
				_canvasObject = new GameObject("HexSkillBarPrefabCanvas");
				_canvasObject.transform.SetParent(((Component)this).transform, false);
				Canvas obj = _canvasObject.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.overrideSorting = true;
				obj.sortingOrder = 400;
				CanvasScaler obj2 = _canvasObject.AddComponent<CanvasScaler>();
				obj2.uiScaleMode = (ScaleMode)1;
				obj2.referenceResolution = new Vector2(1920f, 1080f);
				obj2.matchWidthOrHeight = 0.5f;
				_canvasObject.AddComponent<GraphicRaycaster>();
				_skillBarsObject = Object.Instantiate<GameObject>(Plugin.SkillBarPrefab, _canvasObject.transform, false);
				((Object)_skillBarsObject).name = "HexSkillBarsRuntime";
				_container = _skillBarsObject.GetComponent<RectTransform>();
				if ((Object)(object)_container != (Object)null)
				{
					_container.anchoredPosition = new Vector2(Plugin.OverlayPositionX.Value, Plugin.OverlayPositionY.Value);
				}
				Transform obj3 = _skillBarsObject.transform.Find("SkillBar");
				_skillBarTemplate = ((obj3 != null) ? ((Component)obj3).gameObject : null);
				Transform obj4 = _skillBarsObject.transform.Find("DragArea");
				_dragArea = ((obj4 != null) ? ((Component)obj4).gameObject : null);
				GameObject dragArea = _dragArea;
				object dragText;
				if (dragArea == null)
				{
					dragText = null;
				}
				else
				{
					Transform obj5 = dragArea.transform.Find("DragText");
					dragText = ((obj5 != null) ? ((Component)obj5).GetComponent<TextMeshProUGUI>() : null);
				}
				_dragText = (TextMeshProUGUI)dragText;
				if (!((Object)(object)_container == (Object)null) && !((Object)(object)_skillBarTemplate == (Object)null) && !((Object)(object)_dragArea == (Object)null) && !((Object)(object)_dragText == (Object)null) && ConfigureText(_dragText))
				{
					_dragHandler = _skillBarsObject.AddComponent<SkillBarDragHandler>();
					_dragHandler.DragEnded = OnDragEnded;
					((Behaviour)_dragHandler).enabled = Plugin.EnableDragging.Value;
					_dragArea.SetActive(Plugin.EnableDragging.Value);
					_skillBarTemplate.SetActive(false);
				}
			}
		}

		private void OnEnableDraggingChanged(object sender, EventArgs eventArgs)
		{
			bool value = Plugin.EnableDragging.Value;
			if ((Object)(object)_dragHandler != (Object)null)
			{
				((Behaviour)_dragHandler).enabled = value;
			}
			if ((Object)(object)_dragArea != (Object)null)
			{
				_dragArea.SetActive(value);
			}
		}

		private void OnDestroy()
		{
			if (Plugin.EnableDragging != null)
			{
				Plugin.EnableDragging.SettingChanged -= OnEnableDraggingChanged;
			}
			if ((Object)(object)_canvasObject != (Object)null)
			{
				Object.Destroy((Object)(object)_canvasObject);
				_canvasObject = null;
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		internal unsafe void ShowSkill(SkillType skillType, Sprite icon, float level, float progress, float gain)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (!_skillBars.TryGetValue(skillType, out var value))
			{
				value = CreateSkillBar(skillType);
				if (value == null)
				{
					return;
				}
				_skillBars.Add(skillType, value);
			}
			value.SkillIcon.sprite = icon;
			((Behaviour)value.SkillIcon).enabled = (Object)(object)icon != (Object)null;
			((TMP_Text)value.LevelText).text = ((int)level).ToString();
			((TMP_Text)value.SkillNameText).text = ((object)(*(SkillType*)(&skillType))/*cast due to .constrained prefix*/).ToString();
			((TMP_Text)value.GainText).text = $"+{gain:0.##}";
			((TMP_Text)value.GainText).fontStyle = (FontStyles)1;
			((Transform)((TMP_Text)value.GainText).rectTransform).localScale = Vector3.one * 1.5f;
			float num = Mathf.Clamp01(progress);
			value.ProgressFillRect.anchorMax = new Vector2(num, 1f);
			value.HideTime = Time.time + 2f;
			_gainPulseTimes[skillType] = Time.time;
			if (!value.IsVisible)
			{
				value.GameObject.SetActive(true);
				value.IsVisible = true;
				_activeSkills.Add(skillType);
			}
		}

		private SkillBarViewModel CreateSkillBar(SkillType skillType)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_skillBarTemplate == (Object)null || (Object)(object)_container == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(_skillBarTemplate, (Transform)(object)_container, false);
			((Object)val).name = $"SkillBar_{skillType}";
			RectTransform component = val.GetComponent<RectTransform>();
			Transform obj = val.transform.Find("SkillIcon");
			Image val2 = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null);
			Transform obj2 = val.transform.Find("Background/Fill");
			Image val3 = ((obj2 != null) ? ((Component)obj2).GetComponent<Image>() : null);
			Transform obj3 = val.transform.Find("Background/Level");
			TextMeshProUGUI val4 = ((obj3 != null) ? ((Component)obj3).GetComponent<TextMeshProUGUI>() : null);
			Transform obj4 = val.transform.Find("Background/SkillName");
			TextMeshProUGUI val5 = ((obj4 != null) ? ((Component)obj4).GetComponent<TextMeshProUGUI>() : null);
			Transform obj5 = val.transform.Find("Gain");
			TextMeshProUGUI val6 = ((obj5 != null) ? ((Component)obj5).GetComponent<TextMeshProUGUI>() : null);
			if ((Object)(object)component == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)val5 == (Object)null || (Object)(object)val6 == (Object)null)
			{
				Plugin.Log.LogError((object)$"SkillBar prefab hierarchy is invalid for {skillType}.");
				Object.Destroy((Object)(object)val);
				return null;
			}
			if (!ConfigureText(val4) || !ConfigureText(val5) || !ConfigureText(val6))
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			val.SetActive(false);
			return new SkillBarViewModel(val, component, val2, val3, ((Graphic)val3).rectTransform, val4, val5, val6);
		}

		private void UpdateGainPulse(SkillType skillType, SkillBarViewModel skillBar)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (_gainPulseTimes.TryGetValue(skillType, out var value))
			{
				float num = Time.time - value;
				if (num >= 0.25f)
				{
					((Transform)((TMP_Text)skillBar.GainText).rectTransform).localScale = Vector3.one;
					_gainPulseTimes.Remove(skillType);
				}
				else
				{
					float num2 = num / 0.25f;
					float num3 = Mathf.Lerp(1.5f, 1f, num2);
					((Transform)((TMP_Text)skillBar.GainText).rectTransform).localScale = Vector3.one * num3;
				}
			}
		}

		private static bool ConfigureText(TextMeshProUGUI text)
		{
			if ((Object)(object)Hud.instance == (Object)null || (Object)(object)Hud.instance.m_healthText == (Object)null)
			{
				return false;
			}
			((TMP_Text)text).font = Hud.instance.m_healthText.font;
			((TMP_Text)text).fontSharedMaterial = Hud.instance.m_healthText.fontSharedMaterial;
			((Graphic)text).raycastTarget = false;
			return true;
		}

		private static void OnDragEnded(Vector2 position)
		{
			//IL_0005: 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)
			Plugin.OverlayPositionX.Value = position.x;
			Plugin.OverlayPositionY.Value = position.y;
		}
	}
}
namespace HexSkillBarOverlay.UI.Models
{
	internal sealed class SkillBarViewModel
	{
		internal GameObject GameObject { get; }

		internal RectTransform RectTransform { get; }

		internal Image SkillIcon { get; }

		internal Image ProgressFill { get; }

		internal RectTransform ProgressFillRect { get; }

		internal TextMeshProUGUI LevelText { get; }

		internal TextMeshProUGUI SkillNameText { get; }

		internal TextMeshProUGUI GainText { get; }

		internal float HideTime { get; set; }

		internal bool IsVisible { get; set; }

		internal SkillBarViewModel(GameObject gameObject, RectTransform rectTransform, Image skillIcon, Image progressFill, RectTransform progressFillRect, TextMeshProUGUI levelText, TextMeshProUGUI skillNameText, TextMeshProUGUI gainText)
		{
			GameObject = gameObject;
			RectTransform = rectTransform;
			SkillIcon = skillIcon;
			ProgressFill = progressFill;
			ProgressFillRect = progressFillRect;
			LevelText = levelText;
			SkillNameText = skillNameText;
			GainText = gainText;
		}
	}
}
namespace HexSkillBarOverlay.Patches
{
	[HarmonyPatch(typeof(Player), "SetLocalPlayer")]
	internal static class PlayerSetLocalPlayerPatch
	{
		private static void Postfix()
		{
			SkillBarPrefabController.Instance?.CreateUi();
		}
	}
	[HarmonyPatch(typeof(Skills), "RaiseSkill")]
	internal static class SkillsRaiseSkillPatch
	{
		private struct SkillProgressState
		{
			internal float Level;

			internal float Progress;
		}

		private static void Prefix(Skills __instance, SkillType skillType, out SkillProgressState __state)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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)
			//IL_0043: Expected O, but got Unknown
			__state = default(SkillProgressState);
			if (!((Object)(object)Plugin.SkillsPlayerField.Invoke(__instance) != (Object)(object)Player.m_localPlayer) && (int)skillType != 0)
			{
				Skill val = (Skill)Plugin.SkillsGetSkillMethod.Invoke((object)__instance, new object[1] { skillType });
				if (val != null)
				{
					__state.Level = Plugin.SkillLevelField.Invoke(val);
					__state.Progress = (float)Plugin.SkillGetLevelPercentageMethod.Invoke((object)val, Array.Empty<object>());
				}
			}
		}

		private static void Postfix(Skills __instance, SkillType skillType, SkillProgressState __state)
		{
			//IL_0018: 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_003c: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Plugin.SkillsPlayerField.Invoke(__instance) != (Object)(object)Player.m_localPlayer || (int)skillType == 0)
			{
				return;
			}
			Skill val = (Skill)Plugin.SkillsGetSkillMethod.Invoke((object)__instance, new object[1] { skillType });
			if (val != null)
			{
				SkillDef val2 = Plugin.SkillInfoField.Invoke(val);
				if (val2 != null)
				{
					float num = Plugin.SkillLevelField.Invoke(val);
					float num2 = (float)Plugin.SkillGetLevelPercentageMethod.Invoke((object)val, Array.Empty<object>());
					float gain = (Mathf.Floor(num) - Mathf.Floor(__state.Level)) * 100f + (num2 - __state.Progress) * 100f;
					Sprite icon = Plugin.SkillIconField.Invoke(val2);
					SkillBarPrefabController.Instance?.ShowSkill(skillType, icon, num, num2, gain);
				}
			}
		}
	}
}