Please disclose if your mod was created primarily 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 KillableEnemies v0.1.2
KillableEnemies.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using KillableEnemies.hooks; using KillableEnemies.managers; using KillableEnemies.models; using KillableEnemies.network; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using RuntimeNetcodeRPCValidator; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("KillableEnemies")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("KillableEnemies")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("cf12050d-f455-47a2-a2c4-ca884f582b30")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace KillableEnemies { [BepInPlugin("Ovchinikov.KillableEnemies.Main", "KillableEnemies", "0.1.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class KillableEnemies : BaseUnityPlugin { private const string modGUID = "Ovchinikov.KillableEnemies.Main"; private const string modName = "KillableEnemies"; private const string modVersion = "0.1.2"; private readonly Harmony harmony = new Harmony("Ovchinikov.KillableEnemies.Main"); private static KillableEnemies instance; private NetcodeValidator netcodeValidator; internal ManualLogSource mls; private void Awake() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown if ((Object)(object)instance == (Object)null) { instance = this; } mls = Logger.CreateLogSource("Ovchinikov.KillableEnemies.Main"); mls.LogInfo((object)"Enabling KillableEnemies"); InitializeConfigValues(); harmony.PatchAll(typeof(VanillaHook)); netcodeValidator = new NetcodeValidator("Ovchinikov.KillableEnemies.Main"); netcodeValidator.PatchAll(); netcodeValidator.BindToPreExistingObjectByBehaviour<KillableEnemyEmitter, PlayerControllerB>(); mls.LogInfo((object)"Finished Enabling KillableEnemies"); } private void InitializeConfigValues() { //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Expected O, but got Unknown //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Expected O, but got Unknown //IL_0189: Expected O, but got Unknown //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Expected O, but got Unknown //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Expected O, but got Unknown //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Expected O, but got Unknown //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Expected O, but got Unknown //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Expected O, but got Unknown //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Expected O, but got Unknown //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Expected O, but got Unknown mls.LogInfo((object)"Parsing KillableEnemies config"); ConfigEntry<bool> killableJesterEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("Killable Enemies", "Killable Jester", false, "Should Jesters be killable?"); ConfigEntry<bool> killableGhostGirlEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("Killable Enemies", "Killable Ghost Girl", false, "Should Ghost Girls be killable?"); ConfigEntry<bool> killableGiantEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("Killable Enemies", "Killable Giant", false, "Should Giants be killable?"); ConfigEntry<bool> killableCoilHeadEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("Killable Enemies", "Killable Coil Head", false, "Should Coil Heads be killable?"); ConfigEntry<bool> killableSporeLizardEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("Killable Enemies", "Killable Spore Lizard", false, "Should Spore Lizards be killable?"); ConfigEntry<int> jesterHPEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Enemy Health", "Jester Health", 100, "Health points for Jesters."); ConfigEntry<int> ghostGirlHPEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Enemy Health", "Ghost Girl Health", 100, "Health points for Ghost Girls."); ConfigEntry<int> giantHPEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Enemy Health", "Giant Health", 100, "Health points for Giants."); ConfigEntry<int> coilHeadHPEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Enemy Health", "Coil Head Health", 100, "Health points for Coil Heads."); ConfigEntry<int> sporeLizardHPEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Enemy Health", "Spore Lizard Health", 100, "Health points for Spore Lizards."); IntSliderOptions val = new IntSliderOptions { RequiresRestart = false }; ((BaseRangeOptions<int>)val).Min = 1; ((BaseRangeOptions<int>)val).Max = 1000; IntSliderOptions val2 = val; BoolCheckBoxConfigItem val3 = new BoolCheckBoxConfigItem(killableJesterEntry); BoolCheckBoxConfigItem val4 = new BoolCheckBoxConfigItem(killableGhostGirlEntry); BoolCheckBoxConfigItem val5 = new BoolCheckBoxConfigItem(killableGiantEntry); BoolCheckBoxConfigItem val6 = new BoolCheckBoxConfigItem(killableCoilHeadEntry); BoolCheckBoxConfigItem val7 = new BoolCheckBoxConfigItem(killableSporeLizardEntry); IntSliderConfigItem val8 = new IntSliderConfigItem(jesterHPEntry, val2); IntSliderConfigItem val9 = new IntSliderConfigItem(ghostGirlHPEntry, val2); IntSliderConfigItem val10 = new IntSliderConfigItem(giantHPEntry, val2); IntSliderConfigItem val11 = new IntSliderConfigItem(coilHeadHPEntry, val2); IntSliderConfigItem val12 = new IntSliderConfigItem(sporeLizardHPEntry, val2); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val8); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val9); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val10); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val11); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val12); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val3); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val4); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val5); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val6); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val7); KillableEnemyManager.Instance.DoJesterKill = killableJesterEntry.Value; KillableEnemyManager.Instance.DoGhostGirlKill = killableGhostGirlEntry.Value; KillableEnemyManager.Instance.DoGiantKill = killableGiantEntry.Value; KillableEnemyManager.Instance.DoCoilHeadKill = killableCoilHeadEntry.Value; KillableEnemyManager.Instance.DoSporeLizardKill = killableSporeLizardEntry.Value; KillableEnemyManager.Instance.JesterHP = jesterHPEntry.Value; KillableEnemyManager.Instance.GhostGirlHP = ghostGirlHPEntry.Value; KillableEnemyManager.Instance.GiantHP = giantHPEntry.Value; KillableEnemyManager.Instance.CoilHeadHP = coilHeadHPEntry.Value; KillableEnemyManager.Instance.SporeLizardHP = sporeLizardHPEntry.Value; killableJesterEntry.SettingChanged += delegate { if (((NetworkBehaviour)HUDManager.Instance).IsHost || ((NetworkBehaviour)HUDManager.Instance).IsServer) { KillableEnemyManager.Instance.DoJesterKill = killableJesterEntry.Value; } }; killableGhostGirlEntry.SettingChanged += delegate { if (((NetworkBehaviour)HUDManager.Instance).IsHost || ((NetworkBehaviour)HUDManager.Instance).IsServer) { KillableEnemyManager.Instance.DoGhostGirlKill = killableGhostGirlEntry.Value; } }; killableGiantEntry.SettingChanged += delegate { if (((NetworkBehaviour)HUDManager.Instance).IsHost || ((NetworkBehaviour)HUDManager.Instance).IsServer) { KillableEnemyManager.Instance.DoGiantKill = killableGiantEntry.Value; } }; killableCoilHeadEntry.SettingChanged += delegate { if (((NetworkBehaviour)HUDManager.Instance).IsHost || ((NetworkBehaviour)HUDManager.Instance).IsServer) { KillableEnemyManager.Instance.DoCoilHeadKill = killableCoilHeadEntry.Value; } }; killableSporeLizardEntry.SettingChanged += delegate { if (((NetworkBehaviour)HUDManager.Instance).IsHost || ((NetworkBehaviour)HUDManager.Instance).IsServer) { KillableEnemyManager.Instance.DoSporeLizardKill = killableSporeLizardEntry.Value; } }; jesterHPEntry.SettingChanged += delegate { if (((NetworkBehaviour)HUDManager.Instance).IsHost || ((NetworkBehaviour)HUDManager.Instance).IsServer) { KillableEnemyManager.Instance.JesterHP = jesterHPEntry.Value; } }; ghostGirlHPEntry.SettingChanged += delegate { if (((NetworkBehaviour)HUDManager.Instance).IsHost || ((NetworkBehaviour)HUDManager.Instance).IsServer) { KillableEnemyManager.Instance.GhostGirlHP = ghostGirlHPEntry.Value; } }; giantHPEntry.SettingChanged += delegate { if (((NetworkBehaviour)HUDManager.Instance).IsHost || ((NetworkBehaviour)HUDManager.Instance).IsServer) { KillableEnemyManager.Instance.GiantHP = giantHPEntry.Value; } }; coilHeadHPEntry.SettingChanged += delegate { if (((NetworkBehaviour)HUDManager.Instance).IsHost || ((NetworkBehaviour)HUDManager.Instance).IsServer) { KillableEnemyManager.Instance.CoilHeadHP = coilHeadHPEntry.Value; } }; sporeLizardHPEntry.SettingChanged += delegate { if (((NetworkBehaviour)HUDManager.Instance).IsHost || ((NetworkBehaviour)HUDManager.Instance).IsServer) { KillableEnemyManager.Instance.SporeLizardHP = sporeLizardHPEntry.Value; } }; mls.LogInfo((object)"Config finished parsing"); } } } namespace KillableEnemies.network { public class KillableEnemyEmitter : NetworkBehaviour { [ServerRpc(RequireOwnership = false)] public void DoDamageServerRpc(ulong objectId, int damage) { DoDamageClientRpc(objectId, damage); } [ServerRpc(RequireOwnership = false)] public void DoKillServerRpc(ulong objectId) { DoKillClientRpc(objectId); } [ClientRpc] public void DoDamageClientRpc(ulong objectId, int damage) { EnemyAI valueSafe = GeneralExtensions.GetValueSafe<ulong, EnemyAI>(KillableEnemyManager.Instance.NetworkObjectIDToEnemyAI, objectId); KillableEnemy component = ((Component)valueSafe).gameObject.GetComponent<KillableEnemy>(); if ((Object)(object)component != (Object)null) { ((Component)valueSafe).gameObject.GetComponent<KillableEnemy>().DoDamage(damage); } } [ClientRpc] public void DoKillClientRpc(ulong objectId) { EnemyAI valueSafe = GeneralExtensions.GetValueSafe<ulong, EnemyAI>(KillableEnemyManager.Instance.NetworkObjectIDToEnemyAI, objectId); KillableEnemy component = ((Component)valueSafe).gameObject.GetComponent<KillableEnemy>(); if ((Object)(object)component != (Object)null) { ((Component)valueSafe).gameObject.GetComponent<KillableEnemy>().DoDeath(); } } } } namespace KillableEnemies.models { public class KillableEnemy : MonoBehaviour { public delegate void DeathEventHandler(KillableEnemy sender, DeathEventArgs e); public delegate void HitEventHandler(KillableEnemy sender, HitEventArgs e); private int startingHealth = 0; private int currentHealth = 0; private ulong networkObjectId; private EnemyType enemyType; private EnemyAI enemyAI; public EnemyType EnemyType { get { return enemyType; } set { enemyType = value; } } public EnemyAI EnemyAI { get { return enemyAI; } set { enemyAI = value; } } public ulong NetworkObjectId { get { return networkObjectId; } set { networkObjectId = value; } } public int CurrentHealth { get { return currentHealth; } set { currentHealth = value; } } public int StartingHealth { get { return startingHealth; } set { startingHealth = value; } } public event DeathEventHandler DeathEvent; public event HitEventHandler HitEvent; public void DoDamage(int amount, PlayerControllerB whoHit = null) { HitEventArgs hitEventArgs = new HitEventArgs(this, amount); OnHitEvent(hitEventArgs); if (!hitEventArgs.Cancel) { currentHealth -= amount; if (currentHealth < 0) { currentHealth = 0; } if (currentHealth == 0 && (((NetworkBehaviour)enemyAI).IsHost || ((NetworkBehaviour)enemyAI).IsServer)) { ((Component)StartOfRound.Instance.allPlayerScripts[0]).gameObject.GetComponent<KillableEnemyEmitter>().DoKillServerRpc(((NetworkBehaviour)enemyAI).NetworkObjectId); } } } public void DoDeath() { if (!((NetworkBehaviour)enemyAI).IsHost && !((NetworkBehaviour)enemyAI).IsServer) { return; } DeathEventArgs deathEventArgs = new DeathEventArgs(this, currentHealth); OnDeathEvent(deathEventArgs); if (!deathEventArgs.Cancel) { EnemyAI.isEnemyDead = true; if (((NetworkBehaviour)enemyAI).IsServer || ((NetworkBehaviour)enemyAI).IsHost) { ((NetworkBehaviour)EnemyAI).NetworkObject.Despawn(true); } } } protected virtual void OnDeathEvent(DeathEventArgs e) { this.DeathEvent?.Invoke(this, e); } protected virtual void OnHitEvent(HitEventArgs e) { this.HitEvent?.Invoke(this, e); } } public class DeathEventArgs : EventArgs { public KillableEnemy Enemy { get; private set; } public bool Cancel { get; set; } = false; public DeathEventArgs(KillableEnemy enemy, int remainingHealth) { Enemy = enemy; } } public class HitEventArgs : EventArgs { public KillableEnemy Enemy { get; private set; } public int DamageDealt { get; private set; } public bool Cancel { get; set; } = false; public HitEventArgs(KillableEnemy enemy, int damageDealt) { Enemy = enemy; DamageDealt = damageDealt; } } public enum EnemyType { COIL_HEAD, GHOST_GIRL, GIANT, SPORE_LIZARD, JESTER } } namespace KillableEnemies.managers { internal class KillableEnemyManager { private static KillableEnemyManager _instance; public static KillableEnemyManager Instance => _instance ?? (_instance = new KillableEnemyManager()); public Dictionary<ulong, EnemyAI> NetworkObjectIDToEnemyAI { get; } = new Dictionary<ulong, EnemyAI>(); public Dictionary<EnemyAI, ulong> EnemyAIToNetworkObjectID { get; } = new Dictionary<EnemyAI, ulong>(); public bool DoJesterKill { get; set; } public bool DoGhostGirlKill { get; set; } public bool DoGiantKill { get; set; } public bool DoCoilHeadKill { get; set; } public bool DoSporeLizardKill { get; set; } public int JesterHP { get; set; } public int GhostGirlHP { get; set; } public int GiantHP { get; set; } public int CoilHeadHP { get; set; } public int SporeLizardHP { get; set; } } } namespace KillableEnemies.hooks { internal class LethalThingsHook { } internal class UnityHook { private const string modGUID = "Ovchinikov.KillableEnemies.Unity"; private static ManualLogSource mls; static UnityHook() { mls = Logger.CreateLogSource("Ovchinikov.KillableEnemies.Unity"); } [HarmonyPrefix] [HarmonyPatch(typeof(NetworkManager), "DespawnObject")] private static void PrefixDespawn(NetworkSpawnManager __instance, NetworkObject networkObject, bool destroyObject) { EnemyAI component = ((Component)networkObject).GetComponent<EnemyAI>(); if ((Object)(object)component != (Object)null) { KillableEnemyManager.Instance.EnemyAIToNetworkObjectID.Remove(component); KillableEnemyManager.Instance.NetworkObjectIDToEnemyAI.Remove(((NetworkBehaviour)component).NetworkObjectId); mls.LogInfo((object)"Monster removed from map"); } } } internal class VanillaHook { private const string modGUID = "Ovchinikov.KillableEnemies.Vanilla"; private static ManualLogSource mls; static VanillaHook() { mls = Logger.CreateLogSource("Ovchinikov.KillableEnemies.Vanilla"); } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyAI), "Start")] private static void PostfixStartEnemy(EnemyAI __instance) { ForestGiantAI val = (ForestGiantAI)(object)((__instance is ForestGiantAI) ? __instance : null); if (val == null) { DressGirlAI val2 = (DressGirlAI)(object)((__instance is DressGirlAI) ? __instance : null); if (val2 == null) { PufferAI val3 = (PufferAI)(object)((__instance is PufferAI) ? __instance : null); if (val3 == null) { SpringManAI val4 = (SpringManAI)(object)((__instance is SpringManAI) ? __instance : null); if (val4 == null) { JesterAI val5 = (JesterAI)(object)((__instance is JesterAI) ? __instance : null); if (val5 != null && KillableEnemyManager.Instance.DoJesterKill) { InitializeKillableData(__instance); KillableEnemy component = ((Component)val5).gameObject.GetComponent<KillableEnemy>(); component.StartingHealth = KillableEnemyManager.Instance.CoilHeadHP; component.CurrentHealth = KillableEnemyManager.Instance.CoilHeadHP; component.EnemyAI = (EnemyAI)(object)val5; component.EnemyType = EnemyType.JESTER; component.NetworkObjectId = ((NetworkBehaviour)val5).NetworkObjectId; mls.LogInfo((object)"Found a Jester. Registering killable data."); } } else if (KillableEnemyManager.Instance.DoCoilHeadKill) { InitializeKillableData(__instance); KillableEnemy component2 = ((Component)val4).gameObject.GetComponent<KillableEnemy>(); component2.StartingHealth = KillableEnemyManager.Instance.CoilHeadHP; component2.CurrentHealth = KillableEnemyManager.Instance.CoilHeadHP; component2.EnemyAI = (EnemyAI)(object)val4; component2.EnemyType = EnemyType.COIL_HEAD; component2.NetworkObjectId = ((NetworkBehaviour)val4).NetworkObjectId; mls.LogInfo((object)"Found a Coilhead. Registering killable data."); } } else if (KillableEnemyManager.Instance.DoSporeLizardKill) { InitializeKillableData(__instance); KillableEnemy component3 = ((Component)val3).gameObject.GetComponent<KillableEnemy>(); component3.StartingHealth = KillableEnemyManager.Instance.SporeLizardHP; component3.CurrentHealth = KillableEnemyManager.Instance.SporeLizardHP; component3.EnemyAI = (EnemyAI)(object)val3; component3.EnemyType = EnemyType.SPORE_LIZARD; component3.NetworkObjectId = ((NetworkBehaviour)val3).NetworkObjectId; mls.LogInfo((object)"Found a Spore Lizard. Registering killable data."); } } else if (KillableEnemyManager.Instance.DoGhostGirlKill) { InitializeKillableData(__instance); KillableEnemy component4 = ((Component)val2).gameObject.GetComponent<KillableEnemy>(); component4.StartingHealth = KillableEnemyManager.Instance.GhostGirlHP; component4.CurrentHealth = KillableEnemyManager.Instance.GhostGirlHP; component4.EnemyAI = (EnemyAI)(object)val2; component4.EnemyType = EnemyType.GHOST_GIRL; component4.NetworkObjectId = ((NetworkBehaviour)val2).NetworkObjectId; mls.LogInfo((object)"Found a Ghost Girl. Registering killable data."); } } else if (KillableEnemyManager.Instance.DoGiantKill) { InitializeKillableData(__instance); KillableEnemy component5 = ((Component)val).gameObject.GetComponent<KillableEnemy>(); component5.StartingHealth = KillableEnemyManager.Instance.GiantHP; component5.CurrentHealth = KillableEnemyManager.Instance.GiantHP; component5.EnemyAI = (EnemyAI)(object)val; component5.EnemyType = EnemyType.GIANT; component5.NetworkObjectId = ((NetworkBehaviour)val).NetworkObjectId; mls.LogInfo((object)"Found a Forest Giant. Registering killable data."); } } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyAI), "HitEnemy")] private static void HitPostfix(EnemyAI __instance, int force = 1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false) { if (((NetworkBehaviour)__instance).IsHost || ((NetworkBehaviour)__instance).IsServer) { KillableEnemy component = ((Component)__instance).gameObject.GetComponent<KillableEnemy>(); if (Object.op_Implicit((Object)(object)component)) { ((Component)StartOfRound.Instance.allPlayerScripts[0]).GetComponent<KillableEnemyEmitter>().DoDamageServerRpc(((NetworkBehaviour)__instance).NetworkObjectId, force); } } } private static void InitializeKillableData(EnemyAI enemyAI) { ((Component)enemyAI).gameObject.AddComponent<KillableEnemy>(); KillableEnemyManager.Instance.EnemyAIToNetworkObjectID[enemyAI] = ((NetworkBehaviour)enemyAI).NetworkObjectId; KillableEnemyManager.Instance.NetworkObjectIDToEnemyAI[((NetworkBehaviour)enemyAI).NetworkObjectId] = enemyAI; } } }