using System; using System.Collections; 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 Photon.Pun; 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 backupList) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown ES3Settings val = new ES3Settings(Path.Combine(Application.persistentDataPath, "saves", fileName, fileName + "_rpgSkillsMod.es3"), (EncryptionType)1, "Why would you want to cheat?... :o It's no fun. :') :'D", (ES3Settings)null); if (!ES3.KeyExists("selectedClass", val)) { ES3Settings val2 = 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", val2)) { string text = ES3.Load("selectedClass", val2); if (Enum.TryParse(text, out var result)) { Plugin.SelectedClass = result; ES3.Save("selectedClass", text, val); Plugin.Log.LogInfo((object)$"Migrated legacy saved class: {result}"); return; } } Plugin.SelectedClass = PlayerClass.None; Plugin.Log.LogInfo((object)"No saved class found."); } else { string text2 = ES3.Load("selectedClass", val); if (Enum.TryParse(text2, out var result2)) { Plugin.SelectedClass = result2; Plugin.Log.LogInfo((object)$"Loaded class: {result2}"); } else { Plugin.SelectedClass = PlayerClass.None; Plugin.Log.LogWarning((object)("Invalid saved class: " + text2)); } } } } [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 + "_rpgSkillsMod.es3"), (EncryptionType)1, "Why would you want to cheat?... :o It's no fun. :') :'D", (ES3Settings)null); ES3.Save("selectedClass", Plugin.SelectedClass.ToString(), val); Plugin.Log.LogInfo((object)$"Saved class: {Plugin.SelectedClass}"); } } } internal class AssassinSkill : Skill { private const float Duration = 15f; public AssassinSkill() { base.Name = "Phantom"; base.Description = "Become undetectable by enemies, floating like a ghost."; base.Cooldown = (Plugin.DebugAllow ? 20f : 60f); base.ActiveDuration = 15f; base.Properties.Add($"Duration: {15f}s"); } public override bool Execute() { PlayerAvatar instance = PlayerAvatar.instance; FreezeEnemyVision(instance); PlayerController.instance.AntiGravity(15f); Plugin.Log.LogInfo((object)"Assassin skill used."); return true; } private void FreezeEnemyVision(PlayerAvatar caster) { if (!SemiFunc.IsMultiplayer()) { caster.EnemyVisionFreezeTimerSet(15f); return; } caster.photonView.RPC("SetVisionFreezeRPC", (RpcTarget)2, new object[1] { 15f }); } } internal class BlacksmithSkill : Skill { private const float IndestructibleDuration = 999999f; public BlacksmithSkill() { base.Name = "Reinforce"; base.Description = "Makes the item you're currently holding unbreakable."; base.Cooldown = (Plugin.DebugAllow ? 20f : 90f); } public override bool Execute() { if (!ReinforceHeldItem()) { Plugin.Log.LogInfo((object)"Blacksmith skill failed: no item held."); return false; } Plugin.Log.LogInfo((object)"Blacksmith skill used."); return true; } private bool ReinforceHeldItem() { Transform grabbedObjectTransform = PlayerAvatar.instance.physGrabber.grabbedObjectTransform; if ((Object)(object)grabbedObjectTransform == (Object)null) { return false; } PhysGrabObject component = ((Component)grabbedObjectTransform).GetComponent(); if ((Object)(object)component == (Object)null) { return false; } if (!SemiFunc.IsMultiplayer()) { component.OverrideIndestructible(999999f); } else { ((Component)component).GetComponent().RPC("OverrideIndestructibleRPC", (RpcTarget)2, new object[1] { 999999f }); } return true; } } internal class DruidSkill : Skill { private const int Health = 50; private const float Radius = 5f; public DruidSkill() { base.Name = "Nature's Blessing"; base.Description = "Heal nearby allies within a small radius."; base.Cooldown = (Plugin.DebugAllow ? 20f : 45f); base.Properties.Add($"Radius: {5f}m"); base.Properties.Add($"Total health: {50}"); } public override bool Execute() { bool flag = HealNearbyPlayers(); Plugin.Log.LogInfo((object)(flag ? "Druid skill used." : "Druid skill failed.")); return flag; } private bool HealNearbyPlayers() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar instance = PlayerAvatar.instance; List list = new List { instance }; foreach (PlayerAvatar item in SemiFunc.PlayerGetAll()) { if (!((Object)(object)item == (Object)(object)instance) && Vector3.Distance(((Component)item).transform.position, ((Component)instance).transform.position) <= 5f) { list.Add(item); } } List list2 = new List(); Dictionary dictionary = new Dictionary(); foreach (PlayerAvatar item2 in list) { int missingHealth = GetMissingHealth(item2); if (missingHealth > 0) { list2.Add(item2); dictionary[item2] = missingHealth; } } if (list2.Count == 0) { return false; } int num = 50; Dictionary dictionary2 = new Dictionary(); while (num > 0 && list2.Count > 0) { int num2 = num / list2.Count; if (num2 <= 0) { break; } List list3 = new List(); foreach (PlayerAvatar item3 in list2) { int num3 = Mathf.Min(num2, dictionary[item3]); dictionary2[item3] = (dictionary2.TryGetValue(item3, out var value) ? (value + num3) : num3); num -= num3; dictionary[item3] -= num3; if (dictionary[item3] <= 0) { list3.Add(item3); } } foreach (PlayerAvatar item4 in list3) { list2.Remove(item4); } } if (dictionary2.Count == 0) { return false; } foreach (KeyValuePair item5 in dictionary2) { if ((Object)(object)item5.Key == (Object)(object)instance) { instance.playerHealth.Heal(item5.Value, true); } else { item5.Key.playerHealth.HealOther(item5.Value, true); } } return true; } private static int GetMissingHealth(PlayerAvatar player) { Traverse obj = Traverse.Create((object)player.playerHealth); int value = obj.Field("health").GetValue(); int value2 = obj.Field("maxHealth").GetValue(); return Mathf.Max(0, value2 - value); } } internal class MonkSkill : Skill { private const float Radius = 10f; private const float StunDuration = 5f; private const float ExplosionForce = 35f; private const float UpwardsModifier = 5f; public MonkSkill() { base.Name = "Shockwave"; base.Description = "Releases a powerful shockwave, stunning all nearby enemies."; base.Cooldown = (Plugin.DebugAllow ? 20f : 75f); base.ActiveDuration = 5f; base.Properties.Add($"Radius: {10f}m"); base.Properties.Add($"Stun duration: {5f}s"); } public override bool Execute() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar instance = PlayerAvatar.instance; PushBackNearbyEnemies(instance); try { SkillVfx.PlayShockwaveEffect(((Component)instance).transform.position, Plugin.SelectedClass, 10f); } catch (Exception arg) { Plugin.Log.LogWarning((object)$"Shockwave VFX failed: {arg}"); } Plugin.Log.LogInfo((object)"Monk skill used."); return true; } private void PushBackNearbyEnemies(PlayerAvatar caster) { //IL_0017: 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) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) Enemy[] array = Object.FindObjectsOfType(); foreach (Enemy val in array) { Vector3 val2 = val.CenterTransform.position - ((Component)caster).transform.position; if (((Vector3)(ref val2)).magnitude > 10f) { continue; } if (!SemiFunc.IsMultiplayer()) { EnemyStateStunned component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { component.Set(5f); } Rigidbody component2 = ((Component)val).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.AddExplosionForce(35f, ((Component)caster).transform.position, 10f, 5f, (ForceMode)1); } } else { ((Component)((Component)val).GetComponentInParent()).GetComponent().RPC("StunAndPushRPC", (RpcTarget)2, new object[5] { ((Component)caster).transform.position, 5f, 35f, 10f, 5f }); } } } } internal class NecromancerSkill : Skill { private const int HealthSacrifice = 25; public NecromancerSkill() { base.Name = "Raise Dead"; base.Description = "Sacrifice your own health to revive yourself, or a fallen ally."; base.Cooldown = (Plugin.DebugAllow ? 20f : 120f); base.Properties.Add($"Health sacrificed: {25}"); } public override bool Execute() { bool flag = ReviveSelfOrHeldAlly(); Plugin.Log.LogInfo((object)(flag ? "Necromancer skill used." : "Necromancer skill failed: not downed and not holding a dead ally's head.")); return flag; } private bool ReviveSelfOrHeldAlly() { PlayerAvatar instance = PlayerAvatar.instance; PlayerAvatar val = FindReviveTarget(instance); if ((Object)(object)val == (Object)null) { return false; } instance.playerHealth.Hurt(25, false, -1, false); ReviveTarget(val); return true; } private void ReviveTarget(PlayerAvatar target) { if (!SemiFunc.IsMultiplayer()) { NecromancerReviveRelay.ReviveWithCorrectPosition(target, revivedByTruck: false); return; } target.photonView.RPC("RequestReviveRPC", (RpcTarget)2, new object[1] { false }); } private PlayerAvatar FindReviveTarget(PlayerAvatar caster) { if (Traverse.Create((object)caster).Field("isDisabled").GetValue()) { return caster; } Transform grabbedObjectTransform = caster.physGrabber.grabbedObjectTransform; if ((Object)(object)grabbedObjectTransform == (Object)null) { return null; } PlayerDeathHead component = ((Component)grabbedObjectTransform).GetComponent(); if (!((Object)(object)component != (Object)null)) { return null; } return component.playerAvatar; } } internal class NecromancerReviveRelay : MonoBehaviour { internal static readonly Dictionary LastDeathPosition = new Dictionary(); [PunRPC] public void RequestReviveRPC(bool revivedByTruck) { PlayerAvatar component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null) { ReviveWithCorrectPosition(component, revivedByTruck); } } [PunRPC] public void SetVisionFreezeRPC(float duration) { PlayerAvatar component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null) { component.EnemyVisionFreezeTimerSet(duration); } } internal static void ReviveWithCorrectPosition(PlayerAvatar target, bool revivedByTruck) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (LastDeathPosition.TryGetValue(target, out var value)) { PlayerDeathHead value2 = Traverse.Create((object)target).Field("playerDeathHead").GetValue(); PhysGrabObject val = (((Object)(object)value2 != (Object)null) ? Traverse.Create((object)value2).Field("physGrabObject").GetValue() : null); if ((Object)(object)val != (Object)null) { val.Teleport(value, ((Component)val).transform.rotation); } } target.Revive(revivedByTruck); } } [HarmonyPatch(typeof(PlayerAvatar), "Awake")] internal static class NecromancerRevivePatch { private static void Postfix(PlayerAvatar __instance) { if ((Object)(object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } } } [HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathDone")] internal static class NecromancerDeathPositionPatch { [HarmonyPrefix] private static void Prefix(PlayerAvatar __instance) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) NecromancerReviveRelay.LastDeathPosition[__instance] = ((Component)__instance).transform.position; } } internal class KonamiCheatRelay : MonoBehaviour { public static bool FreeClassChangeUnlocked; [PunRPC] public void SetFreeClassChangeRPC(bool unlocked) { FreeClassChangeUnlocked = unlocked; } } [HarmonyPatch(typeof(PlayerAvatar), "Awake")] internal static class KonamiCheatPatch { private static void Postfix(PlayerAvatar __instance) { if ((Object)(object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } } } [HarmonyPatch(typeof(RunManager), "Update")] internal static class KonamiCheatDetector { private static readonly KeyCode[][] Sequence = new KeyCode[10][] { (KeyCode[])(object)new KeyCode[1] { (KeyCode)273 }, (KeyCode[])(object)new KeyCode[1] { (KeyCode)273 }, (KeyCode[])(object)new KeyCode[1] { (KeyCode)274 }, (KeyCode[])(object)new KeyCode[1] { (KeyCode)274 }, (KeyCode[])(object)new KeyCode[1] { (KeyCode)276 }, (KeyCode[])(object)new KeyCode[1] { (KeyCode)275 }, (KeyCode[])(object)new KeyCode[1] { (KeyCode)276 }, (KeyCode[])(object)new KeyCode[1] { (KeyCode)275 }, (KeyCode[])(object)new KeyCode[1] { (KeyCode)98 }, (KeyCode[])(object)new KeyCode[2] { (KeyCode)97, (KeyCode)113 } }; private static readonly KeyCode[] RelevantKeys; private static int progress; private static void Postfix() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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 (!Plugin.EnableMod.Value) { return; } if (IsAnyKeyDown(Sequence[progress])) { progress++; if (progress >= Sequence.Length) { progress = 0; ToggleFreeClassChange(); } return; } KeyCode[] relevantKeys = RelevantKeys; foreach (KeyCode val in relevantKeys) { if (Input.GetKeyDown(val)) { progress = ((Array.IndexOf(Sequence[0], val) >= 0) ? 1 : 0); break; } } } private static bool IsAnyKeyDown(KeyCode[] keys) { for (int i = 0; i < keys.Length; i++) { if (Input.GetKeyDown(keys[i])) { return true; } } return false; } private static void ToggleFreeClassChange() { bool flag = !KonamiCheatRelay.FreeClassChangeUnlocked; PlayerAvatar instance = PlayerAvatar.instance; if (SemiFunc.IsMultiplayer() && (Object)(object)instance != (Object)null && (Object)(object)instance.photonView != (Object)null) { if ((Object)(object)((Component)instance).GetComponent() == (Object)null) { ((Component)instance).gameObject.AddComponent(); } instance.photonView.RPC("SetFreeClassChangeRPC", (RpcTarget)0, new object[1] { flag }); } else { KonamiCheatRelay.FreeClassChangeUnlocked = flag; } if ((Object)(object)ChatManager.instance != (Object)null) { ChatManager.instance.ForceSendMessage(flag ? "Konami Code activated" : "Konami Code deactivated"); } } static KonamiCheatDetector() { KeyCode[] array = new KeyCode[7]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); RelevantKeys = (KeyCode[])(object)array; progress = 0; } } internal class PaladinSkill : Skill { private const float Radius = 15f; private const float Duration = 10f; public PaladinSkill() { base.Name = "Divine Taunt"; base.Description = "Grants invulnerability, but forces nearby enemies to focus you."; base.Cooldown = (Plugin.DebugAllow ? 20f : 60f); base.ActiveDuration = 10f; base.Properties.Add($"Duration: {10f}s"); base.Properties.Add($"Radius: {15f}m"); } public override bool Execute() { PlayerAvatar.instance.playerHealth.InvincibleSet(10f); TauntNearbyEnemies(); Plugin.Log.LogInfo((object)"Paladin skill used."); return true; } private void TauntNearbyEnemies() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar instance = PlayerAvatar.instance; Enemy[] array = Object.FindObjectsOfType(); foreach (Enemy val in array) { if (!(Vector3.Distance(val.CenterTransform.position, ((Component)instance).transform.position) > 15f)) { if (!SemiFunc.IsMultiplayer()) { val.SetChaseTarget(instance); continue; } ((Component)((Component)val).GetComponentInParent()).GetComponent().RPC("SetChaseTargetRPC", (RpcTarget)2, new object[1] { instance.photonView.ViewID }); } } } } internal class RangerSkill : Skill { private const float Radius = 30f; private const float Duration = 20f; public RangerSkill() { base.Name = "Predator Sense"; base.Description = "Marks nearby enemies on the map, revealing them to every player."; base.Cooldown = (Plugin.DebugAllow ? 20f : 60f); base.ActiveDuration = 20f; base.Properties.Add($"Radius: {30f}m"); base.Properties.Add($"Duration: {20f}s"); } public override bool Execute() { int num = RevealNearbyEnemies(); Plugin.Log.LogInfo((object)$"Ranger skill used, revealed {num} enemies."); return true; } private int RevealNearbyEnemies() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar instance = PlayerAvatar.instance; int num = 0; Enemy[] array = Object.FindObjectsOfType(); foreach (Enemy val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.CenterTransform == (Object)null)) { EnemyParent componentInParent = ((Component)val).GetComponentInParent(); if (!((Object)(object)componentInParent == (Object)null) && !(Vector3.Distance(val.CenterTransform.position, ((Component)instance).transform.position) > 30f)) { RevealEnemy(componentInParent); num++; } } } return num; } private void RevealEnemy(EnemyParent enemyParent) { if (!SemiFunc.IsMultiplayer()) { ((Component)enemyParent).GetComponent().RevealRPC(20f); return; } ((Component)enemyParent).GetComponent().RPC("RevealRPC", (RpcTarget)0, new object[1] { 20f }); } } internal class EnemyMapReveal : MonoBehaviour { private const string MarkerName = "RPG_EnemyReveal"; private static readonly Color MapMarkerColor = new Color(1f, 0f, 0f); private static Sprite markerSprite; private Coroutine activeCoroutine; [PunRPC] public void SetChaseTargetRPC(int casterViewId) { PhotonView val = PhotonView.Find(casterViewId); PlayerAvatar val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent() : null); Enemy componentInChildren = ((Component)this).GetComponentInChildren(); if ((Object)(object)val2 != (Object)null && (Object)(object)componentInChildren != (Object)null) { componentInChildren.SetChaseTarget(val2); } } [PunRPC] public void StunAndPushRPC(Vector3 casterPosition, float stunDuration, float explosionForce, float radius, float upwardsModifier) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) Enemy componentInChildren = ((Component)this).GetComponentInChildren(); if (!((Object)(object)componentInChildren == (Object)null)) { EnemyStateStunned component = ((Component)componentInChildren).GetComponent(); if ((Object)(object)component != (Object)null) { component.Set(stunDuration); } Rigidbody component2 = ((Component)componentInChildren).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.AddExplosionForce(explosionForce, casterPosition, radius, upwardsModifier, (ForceMode)1); } } } [PunRPC] public void RevealRPC(float duration) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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) Enemy componentInChildren = ((Component)this).GetComponentInChildren(); if (!((Object)(object)componentInChildren == (Object)null) && !((Object)(object)componentInChildren.CenterTransform == (Object)null)) { Transform val = componentInChildren.CenterTransform.Find("RPG_EnemyReveal"); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } GameObject val2 = new GameObject("RPG_EnemyReveal"); val2.transform.SetParent(componentInChildren.CenterTransform, false); val2.transform.localPosition = Vector3.zero; if ((Object)(object)Map.Instance != (Object)null) { MapCustom obj = val2.AddComponent(); obj.sprite = GetMarkerSprite(); obj.color = MapMarkerColor; } if (activeCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(activeCoroutine); } activeCoroutine = ((MonoBehaviour)this).StartCoroutine(DestroyAfter(val2, duration)); } } private IEnumerator DestroyAfter(GameObject marker, float duration) { yield return (object)new WaitForSeconds(duration); if ((Object)(object)marker != (Object)null) { Object.Destroy((Object)(object)marker); } activeCoroutine = null; } private static Sprite GetMarkerSprite() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_00c0: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)markerSprite != (Object)null) { return markerSprite; } Texture2D val = new Texture2D(40, 40, (TextureFormat)4, false); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(20f, 20f); float num = 20f; for (int i = 0; i < 40; i++) { for (int j = 0; j < 40; j++) { bool flag = Vector2.Distance(new Vector2((float)i + 0.5f, (float)j + 0.5f), val2) <= num; val.SetPixel(i, j, new Color(1f, 1f, 1f, flag ? 1f : 0f)); } } val.Apply(); markerSprite = Sprite.Create(val, new Rect(0f, 0f, 40f, 40f), new Vector2(0.5f, 0.5f), 200f); return markerSprite; } } [HarmonyPatch(typeof(EnemyParent), "Awake")] internal static class EnemyRevealPatch { private static void Postfix(EnemyParent __instance) { if ((Object)(object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } } } internal class PhysGrabObjectRelay : MonoBehaviour { [PunRPC] public void OverrideIndestructibleRPC(float duration) { PhysGrabObject component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null) { component.OverrideIndestructible(duration); } } } [HarmonyPatch(typeof(PhysGrabObject), "Awake")] internal static class PhysGrabObjectRelayPatch { private static void Postfix(PhysGrabObject __instance) { if ((Object)(object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } } } internal class ScoutSkill : Skill { private bool active; private float timer; private const float Duration = 15f; public ScoutSkill() { base.Name = "Best Runner"; base.Description = "Grants infinite stamina."; base.Cooldown = (Plugin.DebugAllow ? 20f : 60f); base.ActiveDuration = 15f; base.Properties.Add($"Duration: {15f}s"); } public override bool Execute() { if (!ActivateInfiniteStamina()) { return false; } Plugin.Log.LogInfo((object)"Scout skill activated."); return true; } public override void Update() { if (active) { PlayerController.instance.EnergyCurrent = PlayerController.instance.EnergyStart; timer -= Time.deltaTime; if (timer <= 0f) { DeactivateInfiniteStamina(); } } } private bool ActivateInfiniteStamina() { if (active) { return false; } active = true; timer = 15f; return true; } private void DeactivateInfiniteStamina() { active = false; Plugin.Log.LogInfo((object)"Scout skill ended."); } } internal class TreasureHunterSkill : Skill { private const float Radius = 15f; public TreasureHunterSkill() { base.Name = "Treasure Sense"; base.Description = "Reveals valuable items around you."; base.Cooldown = (Plugin.DebugAllow ? 20f : 60f); base.Properties.Add($"Radius: {15f}m"); } public override bool Execute() { RevealNearbyValuables(); Plugin.Log.LogInfo((object)"Treasure Hunter skill used."); return true; } private void RevealNearbyValuables() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar instance = PlayerAvatar.instance; ValuableObject[] array = Object.FindObjectsOfType(); foreach (ValuableObject val in array) { if (!(Vector3.Distance(((Component)val).transform.position, ((Component)instance).transform.position) > 15f)) { val.Discover((State)0); } } } } internal class WarriorSkill : Skill { private bool active; private float timer; private const int StrengthLevels = 20; private const float Duration = 15f; public WarriorSkill() { base.Name = "Berserk"; base.Description = "Increases your strength."; base.Cooldown = (Plugin.DebugAllow ? 20f : 90f); base.ActiveDuration = 15f; base.Properties.Add($"Strength levels: +{20}"); base.Properties.Add($"Duration: {15f}s"); } public override bool Execute() { if (!ActivateBerserk()) { return false; } Plugin.Log.LogInfo((object)"Warrior skill activated."); return true; } public override void Update() { if (active) { timer -= Time.deltaTime; if (timer <= 0f) { DeactivateBerserk(); } } } private bool ActivateBerserk() { if (active) { return false; } active = true; timer = 15f; string text = SemiFunc.PlayerGetSteamID(PlayerAvatar.instance); PunManager.instance.UpgradePlayerGrabStrength(text, 20); PunManager.instance.UpgradePlayerThrowStrength(text, 20); return true; } private void DeactivateBerserk() { active = false; string text = SemiFunc.PlayerGetSteamID(PlayerAvatar.instance); PunManager.instance.UpgradePlayerGrabStrength(text, -20); PunManager.instance.UpgradePlayerThrowStrength(text, -20); Plugin.Log.LogInfo((object)"Warrior skill ended."); } } [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) //IL_0051: 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(SkillSlot.Primary); } if (Input.GetKeyDown(Plugin.SkillKey2.Value)) { SkillManager.TryUseSkill(SkillSlot.Secondary); } } else { SkillManager.ResetCooldown(); } } } internal static class SkillManager { private static float remainingCooldownPrimary; private static float remainingCooldownSecondary; public static bool IsReady(SkillSlot slot) { return RemainingCooldown(slot) <= 0f; } public static float RemainingCooldown(SkillSlot slot) { return Mathf.Max(0f, (slot == SkillSlot.Primary) ? remainingCooldownPrimary : remainingCooldownSecondary); } public static void Update() { if (remainingCooldownPrimary > 0f) { remainingCooldownPrimary -= Time.deltaTime; if (remainingCooldownPrimary < 0f) { remainingCooldownPrimary = 0f; } } if (remainingCooldownSecondary > 0f) { remainingCooldownSecondary -= Time.deltaTime; if (remainingCooldownSecondary < 0f) { remainingCooldownSecondary = 0f; } } SkillDatabase.Get(Plugin.SelectedClass, SkillSlot.Primary).Update(); SkillDatabase.Get(Plugin.SelectedClass, SkillSlot.Secondary).Update(); } public static bool TryUseSkill(SkillSlot slot) { if (!IsReady(slot)) { return false; } Skill skill = SkillDatabase.Get(Plugin.SelectedClass, slot); if (!skill.Execute()) { return false; } Plugin.Log.LogInfo((object)("Using skill : " + skill.Name)); AnnounceSkillInChat(skill); if (slot == SkillSlot.Primary) { remainingCooldownPrimary = skill.Cooldown; } else { remainingCooldownSecondary = skill.Cooldown; } try { SkillVfx.PlayCastEffect(PlayerAvatar.instance, Plugin.SelectedClass, skill.ActiveDuration); } catch (Exception arg) { Plugin.Log.LogWarning((object)$"SkillVfx failed: {arg}"); } return true; } private static void AnnounceSkillInChat(Skill skill) { if ((Object)(object)ChatManager.instance != (Object)null) { ChatManager.instance.ForceSendMessage(skill.Name.ToUpper() ?? ""); } } public static void ResetCooldown() { remainingCooldownPrimary = 0f; remainingCooldownSecondary = 0f; } } internal static class SkillVfx { private const float FadeOutBuffer = 1f; private const string CastEffectName = "RPG_Particles"; private static readonly Color DefaultLightColor = Color.white; private static readonly Dictionary LightColors = new Dictionary { { PlayerClass.Warrior, new Color(0.9f, 0.1f, 0.1f) }, { PlayerClass.Paladin, new Color(0.1f, 0.2f, 0.9f) }, { PlayerClass.Scout, new Color(0.9f, 0.9f, 0.1f) }, { PlayerClass.Druid, new Color(0.25f, 0.85f, 0.25f) }, { PlayerClass.Mage, new Color(0.6f, 0.1f, 0.9f) } }; public static void PlayCastEffect(PlayerAvatar caster, PlayerClass playerClass, float duration) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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_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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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_014b: 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_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)caster == (Object)null || playerClass == PlayerClass.None) { return; } GameObject val = (((Object)(object)AssetManager.instance != (Object)null) ? AssetManager.instance.prefabTeleportEffect : null); if ((Object)(object)val == (Object)null) { return; } ParticleSystem componentInChildren = val.GetComponentInChildren(); if ((Object)(object)componentInChildren == (Object)null) { return; } ParticleSystem val2 = Object.Instantiate(componentInChildren, ((Component)caster).transform); ((Object)((Component)val2).gameObject).name = "RPG_Particles"; ((Component)val2).transform.localPosition = new Vector3(0f, 1.1f, 0f); ((Component)val2).transform.localRotation = Quaternion.identity; Color value; Color color = (LightColors.TryGetValue(playerClass, out value) ? value : DefaultLightColor); ShapeModule shape = val2.shape; ((ShapeModule)(ref shape)).scale = new Vector3(0.1f, 0.1f, 0.1f); EmissionModule emission = val2.emission; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(10f); ParticleSystem[] componentsInChildren = ((Component)val2).GetComponentsInChildren(true); foreach (ParticleSystem obj in componentsInChildren) { MainModule main = obj.main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(Color.white); ((MainModule)(ref main)).loop = true; ((MainModule)(ref main)).startLifetime = new MinMaxCurve(0.2f, 1f); ColorOverLifetimeModule colorOverLifetime = obj.colorOverLifetime; if (((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled) { ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = false; } ColorBySpeedModule colorBySpeed = obj.colorBySpeed; if (((ColorBySpeedModule)(ref colorBySpeed)).enabled) { ((ColorBySpeedModule)(ref colorBySpeed)).enabled = false; } LightsModule lights = obj.lights; if (((LightsModule)(ref lights)).enabled && (Object)(object)((LightsModule)(ref lights)).light != (Object)null) { Light val3 = Object.Instantiate(((LightsModule)(ref lights)).light, ((Component)val2).transform); ((Object)((Component)val3).gameObject).name = "RPG_LightTemplate"; val3.color = color; ((Behaviour)val3).enabled = false; ((LightsModule)(ref lights)).light = val3; ((LightsModule)(ref lights)).useParticleColor = false; } } val2.Play(true); ((MonoBehaviour)caster).StartCoroutine(StopAndDestroy(val2, duration)); } private static IEnumerator StopAndDestroy(ParticleSystem effect, float duration) { yield return (object)new WaitForSeconds(duration); if (!((Object)(object)effect == (Object)null)) { effect.Stop(true, (ParticleSystemStopBehavior)1); yield return (object)new WaitForSeconds(1f); if ((Object)(object)effect != (Object)null) { Object.Destroy((Object)(object)((Component)effect).gameObject); } } } public static void ClearActiveEffects(PlayerAvatar avatar) { if ((Object)(object)avatar == (Object)null) { return; } Transform val = ((Component)avatar).transform.Find("RPG_Particles"); if (!((Object)(object)val == (Object)null)) { ParticleSystem component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { component.Stop(true, (ParticleSystemStopBehavior)0); } Object.Destroy((Object)(object)((Component)val).gameObject); } } public static void PlayShockwaveEffect(Vector3 position, PlayerClass playerClass, float radius, float duration = 1.2f) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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) //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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_010d: 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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_023d: 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) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) GameObject val = (((Object)(object)AssetManager.instance != (Object)null) ? AssetManager.instance.prefabTeleportEffect : null); if ((Object)(object)val == (Object)null) { return; } ParticleSystem componentInChildren = val.GetComponentInChildren(); if ((Object)(object)componentInChildren == (Object)null) { return; } ParticleSystem val2 = Object.Instantiate(componentInChildren, position, Quaternion.identity); ((Object)((Component)val2).gameObject).name = "RPG_Shockwave"; Color value; Color color = (LightColors.TryGetValue(playerClass, out value) ? value : DefaultLightColor); float num = Mathf.Max(0.2f, radius / 5f); ShapeModule shape = val2.shape; ((ShapeModule)(ref shape)).scale = Vector3.one * num; EmissionModule emission = val2.emission; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(80f); ParticleSystem[] componentsInChildren = ((Component)val2).GetComponentsInChildren(true); foreach (ParticleSystem obj in componentsInChildren) { MainModule main = obj.main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(Color.white); ((MainModule)(ref main)).loop = false; ((MainModule)(ref main)).startLifetime = new MinMaxCurve(0.4f, duration); ((MainModule)(ref main)).startSpeedMultiplier = ((MainModule)(ref main)).startSpeedMultiplier * num; ColorOverLifetimeModule colorOverLifetime = obj.colorOverLifetime; if (((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled) { ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = false; } ColorBySpeedModule colorBySpeed = obj.colorBySpeed; if (((ColorBySpeedModule)(ref colorBySpeed)).enabled) { ((ColorBySpeedModule)(ref colorBySpeed)).enabled = false; } LightsModule lights = obj.lights; if (((LightsModule)(ref lights)).enabled && (Object)(object)((LightsModule)(ref lights)).light != (Object)null) { Light val3 = Object.Instantiate(((LightsModule)(ref lights)).light, ((Component)val2).transform); ((Object)((Component)val3).gameObject).name = "RPG_ShockwaveLight"; val3.color = color; val3.range = Mathf.Max(val3.range, radius * 2f); val3.intensity *= 4f; ((Behaviour)val3).enabled = false; ((LightsModule)(ref lights)).light = val3; ((LightsModule)(ref lights)).useParticleColor = false; } } val2.Play(true); if ((Object)(object)GameDirector.instance != (Object)null) { GameDirector.instance.CameraShake.ShakeDistance(6f, radius * 0.4f, radius * 1.5f, position, 0.2f); GameDirector.instance.CameraImpact.ShakeDistance(14f, radius * 0.4f, radius * 1.5f, position, 0.2f); } Object.Destroy((Object)(object)((Component)val2).gameObject, duration + 1f); } } [HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathDone")] internal static class SkillVfxDeathPatch { [HarmonyPrefix] private static void Prefix(PlayerAvatar __instance) { SkillVfx.ClearActiveEffects(__instance); } } [HarmonyPatch(typeof(RunManager), "Update")] internal static class SkillUI { private static GameObject skillUI; private static GameObject skillUI2; private static TextMeshProUGUI skillText; private static TextMeshProUGUI lobbyDescription; private static TextMeshProUGUI lobbyProperties; private static TextMeshProUGUI levelCooldown; private static TextMeshProUGUI levelKey; private static TextMeshProUGUI skillText2; private static TextMeshProUGUI lobbyDescription2; private static TextMeshProUGUI lobbyProperties2; private static TextMeshProUGUI levelCooldown2; private static TextMeshProUGUI levelKey2; private static bool visible = true; private static void Postfix() { //IL_004c: 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) { if ((Object)(object)skillUI == (Object)null && (Object)(object)skillUI2 == (Object)null) { CreateUI(); } if (Input.GetKeyDown(Plugin.ToggleSkillUIKey.Value)) { visible = !visible; } if (!visible || Plugin.SelectedClass == PlayerClass.None) { skillUI.SetActive(false); skillUI2.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); skillUI2.SetActive(true); ((Component)lobbyDescription2).gameObject.SetActive(true); ((Component)lobbyProperties2).gameObject.SetActive(true); ((Component)levelCooldown2).gameObject.SetActive(false); ((Component)levelKey2).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); skillUI2.SetActive(true); ((Component)lobbyDescription2).gameObject.SetActive(false); ((Component)lobbyProperties2).gameObject.SetActive(false); ((Component)levelCooldown2).gameObject.SetActive(true); RefreshLevel(); } else { skillUI.SetActive(false); skillUI2.SetActive(false); } } } private static void CreateUI() { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0158: 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_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: 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_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Unknown result type (might be due to invalid IL or missing references) skillUI = Object.Instantiate(((Component)EnergyUI.instance).gameObject, ((Component)EnergyUI.instance).transform.parent); skillUI2 = Object.Instantiate(((Component)EnergyUI.instance).gameObject, ((Component)EnergyUI.instance).transform.parent); ((Object)skillUI).name = "SkillUI"; ((Object)skillUI2).name = "SkillUI"; Object.Destroy((Object)(object)skillUI.GetComponent()); Object.Destroy((Object)(object)skillUI2.GetComponent()); DestroyAllChildren(skillUI); DestroyAllChildren(skillUI2); skillText = skillUI.GetComponent(); ((TMP_Text)skillText).fontSize = 28f; ((Graphic)skillText).color = Color.yellow; skillText2 = skillUI2.GetComponent(); ((TMP_Text)skillText2).fontSize = 28f; ((Graphic)skillText2).color = Color.yellow; RectTransform component = skillUI.GetComponent(); component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(0f, 0f); component.pivot = new Vector2(0f, 0f); component.anchoredPosition = new Vector2(0f, 130f); component.sizeDelta = new Vector2(260f, 160f); RectTransform component2 = skillUI2.GetComponent(); component2.anchorMin = new Vector2(0f, 0f); component2.anchorMax = new Vector2(0f, 0f); component2.pivot = new Vector2(0f, 0f); component2.anchoredPosition = new Vector2(0f, 20f); component2.sizeDelta = new Vector2(260f, 160f); lobbyDescription = CreateText(skillUI.transform, "Description", "", new Vector2(0f, -85f), 18f, Color.white); lobbyProperties = CreateText(skillUI.transform, "Properties", "", new Vector2(0f, -110f), 12f, Color.green); levelCooldown = CreateText(skillUI.transform, "Cooldown", "", new Vector2(0f, -85f), 18f, Color.white); levelKey = CreateText(skillUI.transform, "Key", ((object)Plugin.SkillKey.Value/*cast due to .constrained prefix*/).ToString() + " to use", new Vector2(0f, -105f), 18f, Color.grey); lobbyDescription2 = CreateText(skillUI2.transform, "Description", "", new Vector2(0f, -85f), 18f, Color.white); lobbyProperties2 = CreateText(skillUI2.transform, "Properties", "", new Vector2(0f, -110f), 12f, Color.green); levelCooldown2 = CreateText(skillUI2.transform, "Cooldown", "", new Vector2(0f, -85f), 18f, Color.white); levelKey2 = CreateText(skillUI2.transform, "Key", ((object)Plugin.SkillKey2.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, SkillSlot.Primary); ((TMP_Text)skillText).text = skill.Name; ((TMP_Text)lobbyDescription).text = skill.Description; List list = new List(skill.Properties) { $"Cooldown: {skill.Cooldown:0}s" }; ((TMP_Text)lobbyProperties).text = string.Join("\n", list.ConvertAll((string p) => "• " + p)); Skill skill2 = SkillDatabase.Get(Plugin.SelectedClass, SkillSlot.Secondary); ((TMP_Text)skillText2).text = skill2.Name; ((TMP_Text)lobbyDescription2).text = skill2.Description; List list2 = new List(skill2.Properties) { $"Cooldown: {skill2.Cooldown:0}s" }; ((TMP_Text)lobbyProperties2).text = string.Join("\n", list2.ConvertAll((string p) => "• " + p)); } private static void RefreshLevel() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_00cb: Unknown result type (might be due to invalid IL or missing references) Skill skill = SkillDatabase.Get(Plugin.SelectedClass, SkillSlot.Primary); ((TMP_Text)skillText).text = skill.Name; if (SkillManager.IsReady(SkillSlot.Primary)) { ((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(SkillSlot.Primary):0}s remaining..."; } Skill skill2 = SkillDatabase.Get(Plugin.SelectedClass, SkillSlot.Secondary); ((TMP_Text)skillText2).text = skill2.Name; if (SkillManager.IsReady(SkillSlot.Secondary)) { ((Component)levelKey2).gameObject.SetActive(true); ((Graphic)levelCooldown2).color = Color.green; ((TMP_Text)levelCooldown2).text = "READY"; } else { ((Component)levelKey2).gameObject.SetActive(false); ((Graphic)levelCooldown2).color = Color.white; ((TMP_Text)levelCooldown2).text = $"{SkillManager.RemainingCooldown(SkillSlot.Secondary):0}s remaining..."; } } private static TextMeshProUGUI CreateText(Transform uiParent, 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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(uiParent, false); RectTransform obj = val.AddComponent(); 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(); ((TMP_Text)obj2).font = ((TMP_Text)skillText).font; ((TMP_Text)obj2).fontSharedMaterial = ((TMP_Text)skillText).fontSharedMaterial; ((TMP_Text)obj2).fontSize = size; ((TMP_Text)obj2).fontSizeMin = size; ((Graphic)obj2).color = color; ((TMP_Text)obj2).text = text; ((TMP_Text)obj2).alignment = (TextAlignmentOptions)257; return obj2; } private static void DestroyAllChildren(GameObject parent) { for (int num = parent.transform.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)parent.transform.GetChild(num)).gameObject); } } } public enum PlayerClass { None, Warrior, Paladin, Scout, Druid, Mage } public enum SkillSlot { Primary, Secondary } [HarmonyPatch(typeof(RunManager), "Update")] internal static class ClassUI { public static GameObject classUI; private static TextMeshProUGUI classText; private static TextMeshProUGUI helpIcon; private static TextMeshProUGUI helpKey; private static TextMeshProUGUI leftArrow; private static TextMeshProUGUI rightArrow; private static TextMeshProUGUI leftKey; private static TextMeshProUGUI rightKey; private static void Postfix() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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(); } bool flag = Plugin.DebugAllow || KonamiCheatRelay.FreeClassChangeUnlocked; if (SemiFunc.RunIsLobby() || SemiFunc.RunIsShop() || (flag && SemiFunc.RunIsLevel())) { if (Input.GetKeyDown(Plugin.PreviousClassKey.Value)) { PreviousClass(); Refresh(); } if (Input.GetKeyDown(Plugin.NextClassKey.Value)) { NextClass(); Refresh(); } } if (SemiFunc.RunIsLobby() || SemiFunc.RunIsShop() || flag) { classUI.SetActive(true); ((Component)helpIcon).gameObject.SetActive(true); ((Component)helpKey).gameObject.SetActive(true); ((Component)leftArrow).gameObject.SetActive(true); ((Component)rightArrow).gameObject.SetActive(true); ((Component)leftKey).gameObject.SetActive(true); ((Component)rightKey).gameObject.SetActive(true); } else if (SemiFunc.RunIsLevel()) { classUI.SetActive(true); ((Component)helpIcon).gameObject.SetActive(true); ((Component)helpKey).gameObject.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_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) classUI = Object.Instantiate(((Component)EnergyUI.instance).gameObject, ((Component)EnergyUI.instance).transform.parent); ((Object)classUI).name = "ClassUI"; Object.Destroy((Object)(object)classUI.GetComponent()); DestroyIfExists(classUI.transform, "EnergyMax"); DestroyIfExists(classUI.transform, "Zap"); DestroyIfExists(classUI.transform, "Scanlines"); classText = classUI.GetComponent(); ((TMP_Text)classText).fontSize = 32f; ((Graphic)classText).color = Color.white; ((TMP_Text)classText).alignment = (TextAlignmentOptions)4097; RectTransform component = classUI.GetComponent(); component.sizeDelta = new Vector2(260f, 30f); component.anchoredPosition = new Vector2(0f, -62f); helpIcon = CreateText("HelpIcon", "◩", new Vector2(-120f, -25f), 24f, Color.yellow); leftArrow = CreateText("LeftArrow", "◀", new Vector2(-90f, -25f), 24f, Color.yellow); rightArrow = CreateText("RightArrow", "▶", new Vector2(-60f, -25f), 24f, Color.yellow); helpKey = CreateText("HelpKey", ((object)Plugin.ToggleSkillUIKey.Value/*cast due to .constrained prefix*/).ToString(), new Vector2(-120f, -50f), 18f, Color.grey); leftKey = CreateText("LeftKey", ((object)Plugin.PreviousClassKey.Value/*cast due to .constrained prefix*/).ToString(), new Vector2(-90f, -50f), 18f, Color.grey); rightKey = CreateText("RightKey", ((object)Plugin.NextClassKey.Value/*cast due to .constrained prefix*/).ToString(), new Vector2(-60f, -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().anchoredPosition = position; TextMeshProUGUI obj = val.AddComponent(); ((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", "1.1.0")] public class Plugin : BaseUnityPlugin { public const string ModGUID = "com.spefire.rpgskillsmod"; public const string ModName = "RPGSkillsMod"; public const string ModVersion = "1.1.0"; public const string totallyNormalString = "Why would you want to cheat?... :o It's no fun. :') :'D"; public static ConfigEntry EnableMod; public static ConfigEntry PreviousClassKey; public static ConfigEntry NextClassKey; public static ConfigEntry SkillKey; public static ConfigEntry SkillKey2; public static ConfigEntry ToggleSkillUIKey; internal static ManualLogSource Log; public static PlayerClass SelectedClass; public static bool DebugAllow; private void Awake() { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; EnableMod = ((BaseUnityPlugin)this).Config.Bind("General", "EnableMod", true, "Enable or disable the mod."); PreviousClassKey = ((BaseUnityPlugin)this).Config.Bind("Controls", "PreviousClassKey", (KeyCode)287, "Key used to select the previous class."); NextClassKey = ((BaseUnityPlugin)this).Config.Bind("Controls", "NextClassKey", (KeyCode)289, "Key used to select the next class."); SkillKey = ((BaseUnityPlugin)this).Config.Bind("Controls", "SkillKey", (KeyCode)102, "Key used to activate the primary skill."); SkillKey2 = ((BaseUnityPlugin)this).Config.Bind("Controls", "SkillKey2", (KeyCode)103, "Key used to activate the secondary skill."); ToggleSkillUIKey = ((BaseUnityPlugin)this).Config.Bind("Controls", "ToggleSkillUIKey", (KeyCode)104, "Key used to show or hide the skill UI."); Log.LogInfo((object)"RPGSkillsMod loaded..."); new Harmony("com.spefire.rpgskillsmod").PatchAll(); Log.LogInfo((object)"...with Harmony patched !"); } } public class Skill { public string Name { get; set; } public string Description { get; set; } public List Properties { get; set; } public float Cooldown { get; set; } public float ActiveDuration { get; protected set; } = 2f; public Skill() { Name = "No skill"; Description = ""; Properties = new List(); Cooldown = 0f; } public virtual bool Execute() { return true; } public virtual void Update() { } } public static class SkillDatabase { private class ClassSkills { public readonly Skill Primary; public readonly Skill Secondary; public ClassSkills(Skill primary, Skill secondary) { Primary = primary; Secondary = secondary; } } private static readonly Dictionary Skills = new Dictionary { { PlayerClass.None, new ClassSkills(new Skill(), new Skill()) }, { PlayerClass.Druid, new ClassSkills(new DruidSkill(), new NecromancerSkill()) }, { PlayerClass.Warrior, new ClassSkills(new WarriorSkill(), new RangerSkill()) }, { PlayerClass.Scout, new ClassSkills(new ScoutSkill(), new TreasureHunterSkill()) }, { PlayerClass.Paladin, new ClassSkills(new PaladinSkill(), new MonkSkill()) }, { PlayerClass.Mage, new ClassSkills(new AssassinSkill(), new BlacksmithSkill()) } }; public static Skill Get(PlayerClass playerClass, SkillSlot slot) { ClassSkills classSkills = Skills[playerClass]; if (slot != SkillSlot.Primary) { return classSkills.Secondary; } return classSkills.Primary; } }