Decompiled source of BuffWindow ClickOff v1.0.1

BuffClickOff.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("BuffClickOff")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BuffClickOff")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("7f6e3433-2753-41bf-a02d-3ba713d12866")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BuffClickOff;

[BepInPlugin("com.erenshor.buffclickoff", "Buff Click Off", "1.29.0")]
public class Plugin : BaseUnityPlugin
{
	private class BuffInfo
	{
		public int Index;

		public string Name;

		public Spell Spell;

		public StatusEffect StatusEffect;
	}

	internal static ManualLogSource Log;

	private static bool showWindow = false;

	private static Rect windowRect = new Rect(40f, 120f, 340f, 420f);

	private static Vector2 scrollPos;

	private static float autoOpenTimer = 12f;

	private static bool hasAutoOpened = false;

	private static FieldInfo effectField;

	private static PropertyInfo statusEffectsProp;

	private static ConstructorInfo emptyStatusEffectCtor;

	private static string hoverText = null;

	private static Rect hoverRect;

	private static GUIStyle buttonStyle;

	private static GUIStyle labelStyle;

	private static GUIStyle windowStyle;

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		CacheReflection();
		Log.LogInfo((object)"Buff Click Off 1.29.0 loaded – modern GUI + 1.7.0 style click-off");
	}

	private void CacheReflection()
	{
		statusEffectsProp = typeof(Stats).GetProperty("StatusEffects", BindingFlags.Instance | BindingFlags.Public);
		Type typeFromHandle = typeof(StatusEffect);
		effectField = AccessTools.Field(typeFromHandle, "Effect") ?? AccessTools.Field(typeFromHandle, "MySpell") ?? AccessTools.Field(typeFromHandle, "spell");
		emptyStatusEffectCtor = AccessTools.Constructor(typeFromHandle, new Type[4]
		{
			typeof(Spell),
			typeof(bool),
			typeof(bool),
			typeof(Character)
		}, false);
		if (emptyStatusEffectCtor == null)
		{
			emptyStatusEffectCtor = AccessTools.Constructor(typeFromHandle, new Type[4]
			{
				typeof(Spell),
				typeof(bool),
				typeof(bool),
				typeof(object)
			}, false);
		}
	}

	private void Update()
	{
		//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)
		if ((Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)) && Input.GetKeyDown((KeyCode)98))
		{
			showWindow = !showWindow;
		}
		if (Input.GetKeyDown((KeyCode)289))
		{
			showWindow = true;
			windowRect = new Rect(40f, 120f, 340f, 420f);
		}
		if (!hasAutoOpened && (Object)(object)GameData.PlayerStats != (Object)null)
		{
			autoOpenTimer -= Time.deltaTime;
			if (autoOpenTimer <= 0f)
			{
				showWindow = true;
				hasAutoOpened = true;
				Log.LogInfo((object)"Buff window auto-opened (delayed)");
			}
		}
	}

	private void OnGUI()
	{
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Expected O, but got Unknown
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: 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_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Expected O, but got Unknown
		//IL_0062: 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_008e: Expected O, but got Unknown
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Expected O, but got Unknown
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		if (showWindow)
		{
			if (buttonStyle == null)
			{
				buttonStyle = new GUIStyle(GUI.skin.button)
				{
					fontSize = Mathf.RoundToInt((float)GUI.skin.button.fontSize * 1.1f)
				};
				labelStyle = new GUIStyle(GUI.skin.label)
				{
					fontSize = Mathf.RoundToInt((float)GUI.skin.label.fontSize * 1.1f)
				};
				windowStyle = new GUIStyle(GUI.skin.window)
				{
					fontSize = Mathf.RoundToInt((float)GUI.skin.window.fontSize * 1.1f)
				};
			}
			windowRect = SanitizeRect(windowRect);
			windowRect = GUI.Window(987654, windowRect, new WindowFunction(DrawWindow), "Buffs (Left-click = Remove) Press Shift + B to Toggle", windowStyle);
			if (!string.IsNullOrEmpty(hoverText))
			{
				GUI.Box(hoverRect, hoverText);
			}
		}
	}

	private void DrawWindow(int id)
	{
		//IL_015c: 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_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		//IL_026e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("Close", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
		{
			showWindow = false;
		}
		GUILayout.FlexibleSpace();
		if (GUILayout.Button("Small", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
		{
			((Rect)(ref windowRect)).width = 280f;
			((Rect)(ref windowRect)).height = 320f;
		}
		if (GUILayout.Button("Medium", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
		{
			((Rect)(ref windowRect)).width = 340f;
			((Rect)(ref windowRect)).height = 420f;
		}
		if (GUILayout.Button("Large", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
		{
			((Rect)(ref windowRect)).width = 420f;
			((Rect)(ref windowRect)).height = 560f;
		}
		GUILayout.EndHorizontal();
		GUILayout.Space(8f);
		List<BuffInfo> activeBuffs = GetActiveBuffs();
		if (activeBuffs.Count == 0)
		{
			GUILayout.Label("No active buffs", labelStyle, Array.Empty<GUILayoutOption>());
		}
		else
		{
			scrollPos = GUILayout.BeginScrollView(scrollPos, Array.Empty<GUILayoutOption>());
			List<BuffInfo> list = new List<BuffInfo>(activeBuffs);
			foreach (BuffInfo item in list)
			{
				if (GUILayout.Button(item.Name, buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
				{
					if (RemoveEffect(item))
					{
						Log.LogInfo((object)("[BuffClickOff] Removed: " + item.Name));
					}
					else
					{
						Log.LogWarning((object)("[BuffClickOff] Failed to remove: " + item.Name));
					}
				}
				Rect lastRect = GUILayoutUtility.GetLastRect();
				if (((Rect)(ref lastRect)).Contains(Event.current.mousePosition))
				{
					hoverText = BuildTooltip(item);
					hoverRect = new Rect(((Rect)(ref windowRect)).x + ((Rect)(ref windowRect)).width + 10f, ((Rect)(ref windowRect)).y + ((Rect)(ref lastRect)).y + 30f, 320f, 180f);
				}
			}
			GUILayout.EndScrollView();
		}
		GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f));
	}

	private List<BuffInfo> GetActiveBuffs()
	{
		List<BuffInfo> list = new List<BuffInfo>();
		if ((Object)(object)GameData.PlayerStats == (Object)null)
		{
			return list;
		}
		try
		{
			if (!(statusEffectsProp?.GetValue(GameData.PlayerStats) is StatusEffect[] array))
			{
				return list;
			}
			for (int i = 0; i < array.Length; i++)
			{
				StatusEffect val = array[i];
				if (val == null)
				{
					continue;
				}
				object? obj = effectField?.GetValue(val);
				Spell val2 = (Spell)((obj is Spell) ? obj : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					string spellName = val2.SpellName;
					if (!string.IsNullOrEmpty(spellName) && !(spellName == "Unknown") && !(spellName == "StatusEffect"))
					{
						list.Add(new BuffInfo
						{
							Index = i,
							Name = spellName,
							Spell = val2,
							StatusEffect = val
						});
					}
				}
			}
		}
		catch
		{
		}
		return list;
	}

	private string BuildTooltip(BuffInfo buff)
	{
		if ((Object)(object)buff.Spell == (Object)null)
		{
			return buff.Name;
		}
		List<string> list = new List<string>
		{
			"<b>" + buff.Name + "</b>",
			""
		};
		if (!string.IsNullOrEmpty(buff.Spell.SpellDesc))
		{
			list.Add(buff.Spell.SpellDesc);
		}
		if (!string.IsNullOrEmpty(buff.Spell.SpecialDescriptor))
		{
			list.Add(buff.Spell.SpecialDescriptor);
		}
		if (buff.Spell.HP != 0)
		{
			list.Add($"HP: {buff.Spell.HP}");
		}
		if (buff.Spell.AC != 0)
		{
			list.Add($"AC: {buff.Spell.AC}");
		}
		if (buff.Spell.Mana != 0)
		{
			list.Add($"Mana: {buff.Spell.Mana}");
		}
		if (buff.Spell.Str != 0)
		{
			list.Add($"Str: {buff.Spell.Str}");
		}
		if (buff.Spell.End != 0)
		{
			list.Add($"End: {buff.Spell.End}");
		}
		if (buff.Spell.Dex != 0)
		{
			list.Add($"Dex: {buff.Spell.Dex}");
		}
		if (buff.Spell.Agi != 0)
		{
			list.Add($"Agi: {buff.Spell.Agi}");
		}
		if (buff.Spell.Int != 0)
		{
			list.Add($"Int: {buff.Spell.Int}");
		}
		if (buff.Spell.Wis != 0)
		{
			list.Add($"Wis: {buff.Spell.Wis}");
		}
		if (buff.Spell.Cha != 0)
		{
			list.Add($"Cha: {buff.Spell.Cha}");
		}
		if (buff.Spell.Haste != 0f)
		{
			list.Add($"Haste: {buff.Spell.Haste}");
		}
		if (buff.Spell.MovementSpeed != 0f)
		{
			list.Add($"Movement: {buff.Spell.MovementSpeed}");
		}
		if (buff.Spell.SpellDurationInTicks > 0)
		{
			list.Add($"Duration: {buff.Spell.SpellDurationInTicks} ticks");
		}
		return string.Join("\n", list);
	}

	private bool RemoveEffect(BuffInfo buff)
	{
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Expected O, but got Unknown
		if ((Object)(object)GameData.PlayerStats == (Object)null || buff.StatusEffect == null)
		{
			return false;
		}
		try
		{
			if (emptyStatusEffectCtor != null)
			{
				object obj = emptyStatusEffectCtor.Invoke(new object[4] { null, false, false, null });
				if (statusEffectsProp?.GetValue(GameData.PlayerStats) is StatusEffect[] array && buff.Index >= 0 && buff.Index < array.Length)
				{
					array[buff.Index] = (StatusEffect)obj;
					ForceCalcStats();
					return true;
				}
			}
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("[BuffClickOff] Remove failed: " + ex.Message));
		}
		return false;
	}

	private void ForceCalcStats()
	{
		try
		{
			AccessTools.Method(typeof(Stats), "CalcStats", (Type[])null, (Type[])null)?.Invoke(GameData.PlayerStats, null);
		}
		catch
		{
		}
	}

	private static Rect SanitizeRect(Rect r)
	{
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		((Rect)(ref r)).width = Mathf.Clamp(((Rect)(ref r)).width, 260f, (float)(Screen.width - 20));
		((Rect)(ref r)).height = Mathf.Clamp(((Rect)(ref r)).height, 200f, (float)(Screen.height - 20));
		((Rect)(ref r)).x = Mathf.Clamp(((Rect)(ref r)).x, 0f, (float)Screen.width - ((Rect)(ref r)).width);
		((Rect)(ref r)).y = Mathf.Clamp(((Rect)(ref r)).y, 0f, (float)Screen.height - ((Rect)(ref r)).height);
		return r;
	}
}