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 v1.1.0
plugins/RPGSkillsMod.dll
Decompiled a day agousing 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<string> 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<string>("selectedClass", val2); if (Enum.TryParse<PlayerClass>(text, out var result)) { Plugin.SelectedClass = result; ES3.Save<string>("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<string>("selectedClass", val); if (Enum.TryParse<PlayerClass>(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<string>("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<PhysGrabObject>(); if ((Object)(object)component == (Object)null) { return false; } if (!SemiFunc.IsMultiplayer()) { component.OverrideIndestructible(999999f); } else { ((Component)component).GetComponent<PhotonView>().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<PlayerAvatar> list = new List<PlayerAvatar> { 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<PlayerAvatar> list2 = new List<PlayerAvatar>(); Dictionary<PlayerAvatar, int> dictionary = new Dictionary<PlayerAvatar, int>(); 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<PlayerAvatar, int> dictionary2 = new Dictionary<PlayerAvatar, int>(); while (num > 0 && list2.Count > 0) { int num2 = num / list2.Count; if (num2 <= 0) { break; } List<PlayerAvatar> list3 = new List<PlayerAvatar>(); 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<PlayerAvatar, int> 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>(); int value2 = obj.Field("maxHealth").GetValue<int>(); 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<Enemy>(); 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<EnemyStateStunned>(); if ((Object)(object)component != (Object)null) { component.Set(5f); } Rigidbody component2 = ((Component)val).GetComponent<Rigidbody>(); if ((Object)(object)component2 != (Object)null) { component2.AddExplosionForce(35f, ((Component)caster).transform.position, 10f, 5f, (ForceMode)1); } } else { ((Component)((Component)val).GetComponentInParent<EnemyParent>()).GetComponent<PhotonView>().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<bool>()) { return caster; } Transform grabbedObjectTransform = caster.physGrabber.grabbedObjectTransform; if ((Object)(object)grabbedObjectTransform == (Object)null) { return null; } PlayerDeathHead component = ((Component)grabbedObjectTransform).GetComponent<PlayerDeathHead>(); if (!((Object)(object)component != (Object)null)) { return null; } return component.playerAvatar; } } internal class NecromancerReviveRelay : MonoBehaviour { internal static readonly Dictionary<PlayerAvatar, Vector3> LastDeathPosition = new Dictionary<PlayerAvatar, Vector3>(); [PunRPC] public void RequestReviveRPC(bool revivedByTruck) { PlayerAvatar component = ((Component)this).GetComponent<PlayerAvatar>(); if ((Object)(object)component != (Object)null) { ReviveWithCorrectPosition(component, revivedByTruck); } } [PunRPC] public void SetVisionFreezeRPC(float duration) { PlayerAvatar component = ((Component)this).GetComponent<PlayerAvatar>(); 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<PlayerDeathHead>(); PhysGrabObject val = (((Object)(object)value2 != (Object)null) ? Traverse.Create((object)value2).Field("physGrabObject").GetValue<PhysGrabObject>() : 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<NecromancerReviveRelay>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<NecromancerReviveRelay>(); } } } [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<KonamiCheatRelay>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<KonamiCheatRelay>(); } } } [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<KonamiCheatRelay>() == (Object)null) { ((Component)instance).gameObject.AddComponent<KonamiCheatRelay>(); } 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<Enemy>(); 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<EnemyParent>()).GetComponent<PhotonView>().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<Enemy>(); foreach (Enemy val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.CenterTransform == (Object)null)) { EnemyParent componentInParent = ((Component)val).GetComponentInParent<EnemyParent>(); 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<EnemyMapReveal>().RevealRPC(20f); return; } ((Component)enemyParent).GetComponent<PhotonView>().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<PlayerAvatar>() : null); Enemy componentInChildren = ((Component)this).GetComponentInChildren<Enemy>(); 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<Enemy>(); if (!((Object)(object)componentInChildren == (Object)null)) { EnemyStateStunned component = ((Component)componentInChildren).GetComponent<EnemyStateStunned>(); if ((Object)(object)component != (Object)null) { component.Set(stunDuration); } Rigidbody component2 = ((Component)componentInChildren).GetComponent<Rigidbody>(); 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<Enemy>(); 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<MapCustom>(); 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<EnemyMapReveal>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<EnemyMapReveal>(); } } } internal class PhysGrabObjectRelay : MonoBehaviour { [PunRPC] public void OverrideIndestructibleRPC(float duration) { PhysGrabObject component = ((Component)this).GetComponent<PhysGrabObject>(); 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<PhysGrabObjectRelay>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<PhysGrabObjectRelay>(); } } } 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<ValuableObject>(); 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<PlayerClass, Color> LightColors = new Dictionary<PlayerClass, Color> { { 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<ParticleSystem>(); if ((Object)(object)componentInChildren == (Object)null) { return; } ParticleSystem val2 = Object.Instantiate<ParticleSystem>(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<ParticleSystem>(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<Light>(((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<ParticleSystem>(); 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<ParticleSystem>(); if ((Object)(object)componentInChildren == (Object)null) { return; } ParticleSystem val2 = Object.Instantiate<ParticleSystem>(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<ParticleSystem>(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<Light>(((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<GameObject>(((Component)EnergyUI.instance).gameObject, ((Component)EnergyUI.instance).transform.parent); skillUI2 = Object.Instantiate<GameObject>(((Component)EnergyUI.instance).gameObject, ((Component)EnergyUI.instance).transform.parent); ((Object)skillUI).name = "SkillUI"; ((Object)skillUI2).name = "SkillUI"; Object.Destroy((Object)(object)skillUI.GetComponent<EnergyUI>()); Object.Destroy((Object)(object)skillUI2.GetComponent<EnergyUI>()); DestroyAllChildren(skillUI); DestroyAllChildren(skillUI2); skillText = skillUI.GetComponent<TextMeshProUGUI>(); ((TMP_Text)skillText).fontSize = 28f; ((Graphic)skillText).color = Color.yellow; skillText2 = skillUI2.GetComponent<TextMeshProUGUI>(); ((TMP_Text)skillText2).fontSize = 28f; ((Graphic)skillText2).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, 130f); component.sizeDelta = new Vector2(260f, 160f); RectTransform component2 = skillUI2.GetComponent<RectTransform>(); 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<string> list = new List<string>(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<string> list2 = new List<string>(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<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; ((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<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); 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<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", "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<bool> EnableMod; public static ConfigEntry<KeyCode> PreviousClassKey; public static ConfigEntry<KeyCode> NextClassKey; public static ConfigEntry<KeyCode> SkillKey; public static ConfigEntry<KeyCode> SkillKey2; public static ConfigEntry<KeyCode> 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<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 primary skill."); SkillKey2 = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "SkillKey2", (KeyCode)103, "Key used to activate the secondary skill."); ToggleSkillUIKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("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<string> Properties { get; set; } public float Cooldown { get; set; } public float ActiveDuration { get; protected set; } = 2f; public Skill() { Name = "No skill"; Description = ""; Properties = new List<string>(); 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<PlayerClass, ClassSkills> Skills = new Dictionary<PlayerClass, ClassSkills> { { 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; } }