Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RPGSkillsMod v0.2.0
plugins/RPGSkillsMod.dll
Decompiled 20 hours agousing 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]; } }