Decompiled source of RPGSkillsMod v0.2.0

plugins/RPGSkillsMod.dll

Decompiled 20 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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 TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("RPGSkillsMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RPGSkillsMod")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("25df85b1-0101-469c-b93b-aa6ed3e7dbb0")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.2.0.0")]
[HarmonyPatch(typeof(StatsManager), "SaveFileCreate")]
internal static class SaveFileCreatePatch
{
	[HarmonyPostfix]
	private static void ResetClass()
	{
		Plugin.SelectedClass = PlayerClass.None;
		Plugin.Log.LogInfo((object)"New save created. Class reset.");
	}
}
[HarmonyPatch(typeof(StatsManager), "LoadGame")]
internal static class LoadGamePatch
{
	[HarmonyPostfix]
	private static void LoadClass(string fileName, List<string> backupList)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Expected O, but got Unknown
		ES3Settings val = new ES3Settings(Path.Combine(Application.persistentDataPath, "saves", fileName, fileName + ".es3"), (EncryptionType)1, "Why would you want to cheat?... :o It's no fun. :') :'D", (ES3Settings)null);
		if (!ES3.KeyExists("selectedClass", val))
		{
			Plugin.SelectedClass = PlayerClass.None;
			Plugin.Log.LogInfo((object)"No saved class found.");
			return;
		}
		string text = ES3.Load<string>("selectedClass", val);
		if (Enum.TryParse<PlayerClass>(text, out var result))
		{
			Plugin.SelectedClass = result;
			Plugin.Log.LogInfo((object)$"Loaded class: {result}");
		}
		else
		{
			Plugin.SelectedClass = PlayerClass.None;
			Plugin.Log.LogWarning((object)("Invalid saved class: " + text));
		}
	}
}
[HarmonyPatch(typeof(StatsManager), "SaveGame")]
internal static class SaveGamePatch
{
	[HarmonyPostfix]
	private static void SaveClass(string fileName)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Expected O, but got Unknown
		if (!string.IsNullOrEmpty(fileName))
		{
			ES3Settings val = new ES3Settings(Path.Combine(Application.persistentDataPath, "saves", fileName, fileName + ".es3"), (EncryptionType)1, "Why would you want to cheat?... :o It's no fun. :') :'D", (ES3Settings)null);
			ES3.Save<string>("selectedClass", Plugin.SelectedClass.ToString(), val);
			Plugin.Log.LogInfo((object)$"Saved class: {Plugin.SelectedClass}");
		}
	}
}
[HarmonyPatch(typeof(RunManager), "Update")]
internal static class SkillPatch
{
	private static void Postfix()
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		if (!Plugin.EnableMod.Value || (Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
		{
			return;
		}
		if (SemiFunc.RunIsLevel())
		{
			SkillManager.Update();
			if (Input.GetKeyDown(Plugin.SkillKey.Value))
			{
				SkillManager.TryUseSkill();
			}
		}
		else
		{
			SkillManager.ResetCooldown();
		}
	}
}
internal static class SkillManager
{
	private static float remainingCooldown;

	public static bool IsReady => remainingCooldown <= 0f;

	public static float RemainingCooldown => Mathf.Max(0f, remainingCooldown);

	public static void Update()
	{
		if (remainingCooldown > 0f)
		{
			remainingCooldown -= Time.deltaTime;
			if (remainingCooldown < 0f)
			{
				remainingCooldown = 0f;
			}
		}
	}

	public static bool TryUseSkill()
	{
		if (!IsReady)
		{
			return false;
		}
		Skill skill = SkillDatabase.Get(Plugin.SelectedClass);
		Plugin.Log.LogInfo((object)("Using skill : " + skill.Name));
		remainingCooldown = skill.Cooldown;
		return true;
	}

	public static void ResetCooldown()
	{
		remainingCooldown = 0f;
	}
}
[HarmonyPatch(typeof(RunManager), "Update")]
internal static class SkillUI
{
	private static GameObject skillUI;

	private static TextMeshProUGUI skillText;

	private static TextMeshProUGUI lobbyDescription;

	private static TextMeshProUGUI lobbyProperties;

	private static TextMeshProUGUI levelCooldown;

	private static TextMeshProUGUI levelKey;

	private static void Postfix()
	{
		if (Plugin.EnableMod.Value && !((Object)(object)LevelGenerator.Instance == (Object)null) && LevelGenerator.Instance.Generated)
		{
			if ((Object)(object)skillUI == (Object)null)
			{
				CreateUI();
			}
			if (Plugin.SelectedClass == PlayerClass.None)
			{
				skillUI.SetActive(false);
			}
			else if (SemiFunc.RunIsLobby() || SemiFunc.RunIsShop())
			{
				skillUI.SetActive(true);
				((Component)lobbyDescription).gameObject.SetActive(true);
				((Component)lobbyProperties).gameObject.SetActive(true);
				((Component)levelCooldown).gameObject.SetActive(false);
				((Component)levelKey).gameObject.SetActive(false);
				RefreshLobbyShop();
			}
			else if (SemiFunc.RunIsLevel())
			{
				skillUI.SetActive(true);
				((Component)lobbyDescription).gameObject.SetActive(false);
				((Component)lobbyProperties).gameObject.SetActive(false);
				((Component)levelCooldown).gameObject.SetActive(true);
				RefreshLevel();
			}
			else
			{
				skillUI.SetActive(false);
			}
		}
	}

	private static void CreateUI()
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		skillUI = Object.Instantiate<GameObject>(((Component)EnergyUI.instance).gameObject, ((Component)EnergyUI.instance).transform.parent);
		((Object)skillUI).name = "SkillUI";
		Object.Destroy((Object)(object)skillUI.GetComponent<EnergyUI>());
		DestroyChild("EnergyMax");
		DestroyChild("Zap");
		DestroyChild("Scanlines");
		skillText = skillUI.GetComponent<TextMeshProUGUI>();
		((TMP_Text)skillText).fontSize = 32f;
		((Graphic)skillText).color = Color.yellow;
		RectTransform component = skillUI.GetComponent<RectTransform>();
		component.anchorMin = new Vector2(0f, 0f);
		component.anchorMax = new Vector2(0f, 0f);
		component.pivot = new Vector2(0f, 0f);
		component.anchoredPosition = new Vector2(0f, 50f);
		component.sizeDelta = new Vector2(260f, 160f);
		lobbyDescription = CreateText("Description", "", new Vector2(0f, -85f), 18f, Color.white);
		lobbyProperties = CreateText("Properties", "", new Vector2(0f, -120f), 18f, Color.green);
		levelCooldown = CreateText("Cooldown", "", new Vector2(0f, -85f), 18f, Color.white);
		levelKey = CreateText("Key", ((object)Plugin.SkillKey.Value/*cast due to .constrained prefix*/).ToString() + " to use", new Vector2(0f, -105f), 18f, Color.grey);
		RefreshLevel();
	}

	private static void RefreshLobbyShop()
	{
		Skill skill = SkillDatabase.Get(Plugin.SelectedClass);
		((TMP_Text)skillText).text = skill.Name;
		((TMP_Text)lobbyDescription).text = skill.Description;
		((TMP_Text)lobbyProperties).text = string.Join("\n", skill.Properties.ConvertAll((string p) => "• " + p));
	}

	private static void RefreshLevel()
	{
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		Skill skill = SkillDatabase.Get(Plugin.SelectedClass);
		((TMP_Text)skillText).text = skill.Name;
		if (SkillManager.IsReady)
		{
			((Component)levelKey).gameObject.SetActive(true);
			((Graphic)levelCooldown).color = Color.green;
			((TMP_Text)levelCooldown).text = "READY";
		}
		else
		{
			((Component)levelKey).gameObject.SetActive(false);
			((Graphic)levelCooldown).color = Color.white;
			((TMP_Text)levelCooldown).text = $"{SkillManager.RemainingCooldown:0}s remaining...";
		}
	}

	private static TextMeshProUGUI CreateText(string name, string text, Vector2 position, float size, Color color)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: 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_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: 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_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name);
		val.transform.SetParent(skillUI.transform, false);
		RectTransform obj = val.AddComponent<RectTransform>();
		obj.anchorMin = new Vector2(0f, 1f);
		obj.anchorMax = new Vector2(0f, 1f);
		obj.pivot = new Vector2(0f, 1f);
		obj.anchoredPosition = position;
		obj.sizeDelta = new Vector2(480f, 50f);
		TextMeshProUGUI obj2 = val.AddComponent<TextMeshProUGUI>();
		((TMP_Text)obj2).font = ((TMP_Text)skillText).font;
		((TMP_Text)obj2).fontSharedMaterial = ((TMP_Text)skillText).fontSharedMaterial;
		((TMP_Text)obj2).fontSize = size;
		((Graphic)obj2).color = color;
		((TMP_Text)obj2).text = text;
		((TMP_Text)obj2).alignment = (TextAlignmentOptions)257;
		return obj2;
	}

	private static void DestroyChild(string child)
	{
		Transform val = skillUI.transform.Find(child);
		if ((Object)(object)val != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)val).gameObject);
		}
	}
}
public enum PlayerClass
{
	None,
	Assassin,
	Alchemist,
	Druid,
	Guardian,
	Necromancer,
	Scout,
	Warrior
}
[HarmonyPatch(typeof(RunManager), "Update")]
internal static class ClassUI
{
	public static GameObject classUI;

	private static TextMeshProUGUI classText;

	private static TextMeshProUGUI leftArrow;

	private static TextMeshProUGUI rightArrow;

	private static TextMeshProUGUI leftKey;

	private static TextMeshProUGUI rightKey;

	private static void Postfix()
	{
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		if (!Plugin.EnableMod.Value || (Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
		{
			return;
		}
		if ((Object)(object)classUI == (Object)null)
		{
			CreateUI();
		}
		if (SemiFunc.RunIsLobby() || SemiFunc.RunIsShop())
		{
			classUI.SetActive(true);
			((Component)leftArrow).gameObject.SetActive(true);
			((Component)rightArrow).gameObject.SetActive(true);
			((Component)leftKey).gameObject.SetActive(true);
			((Component)rightKey).gameObject.SetActive(true);
			if (Input.GetKeyDown(Plugin.PreviousClassKey.Value))
			{
				PreviousClass();
				Refresh();
			}
			if (Input.GetKeyDown(Plugin.NextClassKey.Value))
			{
				NextClass();
				Refresh();
			}
		}
		else if (SemiFunc.RunIsLevel())
		{
			classUI.SetActive(true);
			((Component)leftArrow).gameObject.SetActive(false);
			((Component)rightArrow).gameObject.SetActive(false);
			((Component)leftKey).gameObject.SetActive(false);
			((Component)rightKey).gameObject.SetActive(false);
		}
		else
		{
			classUI.SetActive(false);
		}
	}

	private static void CreateUI()
	{
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: 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_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		classUI = Object.Instantiate<GameObject>(((Component)EnergyUI.instance).gameObject, ((Component)EnergyUI.instance).transform.parent);
		((Object)classUI).name = "ClassUI";
		Object.Destroy((Object)(object)classUI.GetComponent<EnergyUI>());
		DestroyIfExists(classUI.transform, "EnergyMax");
		DestroyIfExists(classUI.transform, "Zap");
		DestroyIfExists(classUI.transform, "Scanlines");
		classText = classUI.GetComponent<TextMeshProUGUI>();
		((TMP_Text)classText).fontSize = 32f;
		((Graphic)classText).color = Color.white;
		((TMP_Text)classText).alignment = (TextAlignmentOptions)4097;
		RectTransform component = classUI.GetComponent<RectTransform>();
		component.sizeDelta = new Vector2(260f, 30f);
		component.anchoredPosition = new Vector2(0f, -62f);
		leftArrow = CreateText("LeftArrow", "◀", new Vector2(-120f, -25f), 24f, Color.yellow);
		rightArrow = CreateText("RightArrow", "▶", new Vector2(-90f, -25f), 24f, Color.yellow);
		leftKey = CreateText("LeftKey", ((object)Plugin.PreviousClassKey.Value/*cast due to .constrained prefix*/).ToString(), new Vector2(-120f, -50f), 18f, Color.grey);
		rightKey = CreateText("RightKey", ((object)Plugin.NextClassKey.Value/*cast due to .constrained prefix*/).ToString(), new Vector2(-90f, -50f), 18f, Color.grey);
		Refresh();
	}

	private static TextMeshProUGUI CreateText(string name, string text, Vector2 position, float size, Color color)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: 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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name);
		val.transform.SetParent(classUI.transform, false);
		val.AddComponent<RectTransform>().anchoredPosition = position;
		TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
		((TMP_Text)obj).font = ((TMP_Text)classText).font;
		((TMP_Text)obj).fontSharedMaterial = ((TMP_Text)classText).fontSharedMaterial;
		((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
		((TMP_Text)obj).fontSize = size;
		((Graphic)obj).color = color;
		((TMP_Text)obj).text = text;
		return obj;
	}

	private static void Refresh()
	{
		if (!((Object)(object)classText == (Object)null))
		{
			((TMP_Text)classText).text = Plugin.SelectedClass.ToString();
		}
	}

	private static void PreviousClass()
	{
		int length = Enum.GetValues(typeof(PlayerClass)).Length;
		Plugin.SelectedClass = (PlayerClass)((int)(Plugin.SelectedClass - 1 + length) % length);
	}

	private static void NextClass()
	{
		int length = Enum.GetValues(typeof(PlayerClass)).Length;
		Plugin.SelectedClass = (PlayerClass)((int)(Plugin.SelectedClass + 1) % length);
	}

	private static void DestroyIfExists(Transform parent, string name)
	{
		Transform val = parent.Find(name);
		if ((Object)(object)val != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)val).gameObject);
		}
	}
}
[BepInPlugin("com.spefire.rpgskillsmod", "RPGSkillsMod", "0.0.1")]
public class Plugin : BaseUnityPlugin
{
	public const string ModGUID = "com.spefire.rpgskillsmod";

	public const string ModName = "RPGSkillsMod";

	public const string ModVersion = "0.0.1";

	public const string totallyNormalString = "Why would you want to cheat?... :o It's no fun. :') :'D";

	public static ConfigEntry<bool> EnableMod;

	public static ConfigEntry<KeyCode> PreviousClassKey;

	public static ConfigEntry<KeyCode> NextClassKey;

	public static ConfigEntry<KeyCode> SkillKey;

	internal static ManualLogSource Log;

	public static PlayerClass SelectedClass;

	private void Awake()
	{
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMod", true, "Enable or disable the mod.");
		PreviousClassKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "PreviousClassKey", (KeyCode)287, "Key used to select the previous class.");
		NextClassKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "NextClassKey", (KeyCode)289, "Key used to select the next class.");
		SkillKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "SkillKey", (KeyCode)102, "Key used to activate the skill.");
		Log.LogInfo((object)"RPGSkillsMod loaded...");
		new Harmony("com.spefire.rpgskillsmod").PatchAll();
		Log.LogInfo((object)"...with Harmony patched !");
	}
}
public class Skill
{
	public string Name { get; }

	public string Description { get; }

	public List<string> Properties { get; }

	public float Cooldown { get; }

	public Skill(string name, string description, List<string> properties, float cooldown)
	{
		Name = name;
		Description = description;
		Properties = properties;
		Cooldown = cooldown;
	}
}
public static class SkillDatabase
{
	private static readonly Dictionary<PlayerClass, Skill> Skills = new Dictionary<PlayerClass, Skill>
	{
		{
			PlayerClass.None,
			new Skill("No Skill", "", new List<string>(), 0f)
		},
		{
			PlayerClass.Necromancer,
			new Skill("Resurrection", "Revive a fallen ally by sacrificing part of your own health.", new List<string> { "Health Cost: 50 HP", "Target: Dead Ally", "Cooldown: 60 s" }, 60f)
		},
		{
			PlayerClass.Druid,
			new Skill("Nature's Blessing", "Heal nearby allies within a small radius.", new List<string> { "Heal Radius: 8 m", "Affects nearby allies", "Cooldown: 25 s" }, 25f)
		},
		{
			PlayerClass.Assassin,
			new Skill("Shadow Veil", "Become invisible and undetectable for a short duration.", new List<string> { "Duration: 8 s", "Breaks on attack", "Cooldown: 45 s" }, 45f)
		},
		{
			PlayerClass.Scout,
			new Skill("Adrenaline Rush", "Gain unlimited stamina for a short duration.", new List<string> { "Infinite Stamina", "Duration: 12 s", "Cooldown: 30 s" }, 30f)
		},
		{
			PlayerClass.Warrior,
			new Skill("Battle Rage", "Greatly increase your strength for a short duration.", new List<string> { "Increased Strength", "Duration: 15 s", "Cooldown: 45 s" }, 45f)
		},
		{
			PlayerClass.Alchemist,
			new Skill("Transmutation", "Duplicate the item currently held in your hands.", new List<string> { "Duplicates held item", "Single use per activation", "Cooldown: 60 s" }, 60f)
		},
		{
			PlayerClass.Guardian,
			new Skill("Taunt", "Force nearby enemies to focus their attention on you.", new List<string> { "Taunt Radius: 15 m", "Duration: 8 s", "Cooldown: 35 s" }, 35f)
		}
	};

	public static Skill Get(PlayerClass playerClass)
	{
		return Skills[playerClass];
	}
}