Decompiled source of EverythingCanDieAlternative v1.1.59
nwnt.EverythingCanDieAlternative.dll
Decompiled 20 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EverythingCanDieAlternative.ModCompatibility; using EverythingCanDieAlternative.ModCompatibility.Handlers; using EverythingCanDieAlternative.UI; using GameNetcodeStuff; using HarmonyLib; using LethalNetworkAPI; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("EverythingCanDieAlternative")] [assembly: AssemblyFileVersion("1.1.59")] [assembly: AssemblyDescription("A mod that makes everything in Lethal Company damageable")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.1.59.0")] namespace EverythingCanDieAlternative { public class DespawnConfiguration { private static DespawnConfiguration _instance; private ConfigFile _configFile; private readonly Dictionary<string, bool> _enemyDespawnEnabled = new Dictionary<string, bool>(); private readonly string[] _enemiesWithProperDeathAnimations = new string[22] { "DOGDAY", "DOGDAYCRITTER", "PICKYCRITTER", "CATNAPCRITTER", "BOBBYCRITTER", "CRAFTYCRITTER", "HOPPYCRITTER", "BUBBACRITTER", "KICKINCRITTER", "BABOONHAWK", "MANEATER", "CENTIPEDE", "CRAWLER", "TULIPSNAKE", "FLOWERMAN", "FORESTGIANT", "HOARDINGBUG", "MASKED", "MOUTHDOG", "NUTCRACKER", "BUNKERSPIDER", "BUSHWOLF" }; public static DespawnConfiguration Instance => _instance ?? (_instance = new DespawnConfiguration()); public ConfigEntry<bool> EnableDespawnFeature { get; private set; } private DespawnConfiguration() { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown string text = Path.Combine(Paths.ConfigPath, "nwnt.EverythingCanDieAlternative_Despawn_Rules.cfg"); _configFile = new ConfigFile(text, true); EnableDespawnFeature = _configFile.Bind<bool>("General", "EnableDespawnFeature", true, new ConfigDescription("If true, dead enemies can despawn based on other settings", (AcceptableValueBase)null, Array.Empty<object>())); PreCreateEnemyConfigEntries(); } public void ReloadConfig() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown try { _configFile.Reload(); _enemyDespawnEnabled.Clear(); EnableDespawnFeature = _configFile.Bind<bool>("General", "EnableDespawnFeature", true, new ConfigDescription("If true, dead enemies can despawn based on other settings", (AcceptableValueBase)null, Array.Empty<object>())); Plugin.LogInfo("Despawn configuration reloaded from disk"); } catch (Exception ex) { Plugin.Log.LogError((object)("Error reloading despawn config: " + ex.Message)); } } private void PreCreateEnemyConfigEntries() { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown if (Plugin.enemies == null || Plugin.enemies.Count <= 0) { return; } foreach (EnemyType enemy in Plugin.enemies) { string text = Plugin.RemoveInvalidCharacters(enemy.enemyName).ToUpper(); bool flag = !_enemiesWithProperDeathAnimations.Contains(text); _configFile.Bind<bool>("Enemies", text + ".Despawn", flag, new ConfigDescription("If true, " + enemy.enemyName + " will despawn after death", (AcceptableValueBase)null, Array.Empty<object>())); } } public bool ShouldDespawnEnemy(string enemyName) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown if (!EnableDespawnFeature.Value) { return false; } string text = Plugin.RemoveInvalidCharacters(enemyName).ToUpper(); if (_enemyDespawnEnabled.TryGetValue(text, out var value)) { return value; } bool flag = true; string[] enemiesWithProperDeathAnimations = _enemiesWithProperDeathAnimations; foreach (string text2 in enemiesWithProperDeathAnimations) { if (text == text2) { flag = false; break; } } ConfigEntry<bool> val = _configFile.Bind<bool>("Enemies", text + ".Despawn", flag, new ConfigDescription("If true, " + enemyName + " will despawn after death", (AcceptableValueBase)null, Array.Empty<object>())); _enemyDespawnEnabled[text] = val.Value; return val.Value; } public void ClearCache() { _enemyDespawnEnabled.Clear(); Plugin.Log.LogInfo((object)"Despawn cache cleared"); } } public class EnemyControlConfiguration { private static EnemyControlConfiguration _instance; private ConfigFile _configFile; private readonly Dictionary<string, bool> _enemyModEnabled = new Dictionary<string, bool>(); private bool _configEntriesCreated = false; public static EnemyControlConfiguration Instance => _instance ?? (_instance = new EnemyControlConfiguration()); private EnemyControlConfiguration() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown string text = Path.Combine(Paths.ConfigPath, "nwnt.EverythingCanDieAlternative_Enemy_Control.cfg"); _configFile = new ConfigFile(text, true); _configFile.Bind<string>("Enemies", "_INFO", "Control which enemies are affected by this mod", new ConfigDescription("This is an Experimental Feature: If you set an enemy's value to 'false', it will not be affected by the EverythingCanDieAlternative mod. The health and hit synconization, and the despawn feature will not take effect for the configured enemy. This can be useful if specific enemies have built-in hit/health/death mechanisms that you want to preserve, but that ECDA overwrites. Now you can preserve them by setting the enemy to false.", (AcceptableValueBase)null, Array.Empty<object>())); } public void ReloadConfig() { try { _configFile.Reload(); _enemyModEnabled.Clear(); Plugin.LogInfo("Enemy control configuration reloaded from disk"); } catch (Exception ex) { Plugin.Log.LogError((object)("Error reloading enemy control config: " + ex.Message)); } } public void PreCreateEnemyConfigEntries() { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown if (_configEntriesCreated || Plugin.enemies == null || Plugin.enemies.Count <= 0) { return; } Plugin.LogInfo($"Creating control entries for {Plugin.enemies.Count} enemy types"); foreach (EnemyType enemy in Plugin.enemies) { if (!((Object)(object)enemy == (Object)null) && !string.IsNullOrEmpty(enemy.enemyName)) { string text = Plugin.RemoveInvalidCharacters(enemy.enemyName).ToUpper(); _configFile.Bind<bool>("Enemies", text + ".Enabled", true, new ConfigDescription("If set to false, " + enemy.enemyName + " will not be affected by this mod", (AcceptableValueBase)null, Array.Empty<object>())); } } _configEntriesCreated = true; } public bool IsModEnabledForEnemy(string enemyName) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown string text = Plugin.RemoveInvalidCharacters(enemyName).ToUpper(); if (_enemyModEnabled.TryGetValue(text, out var value)) { return value; } try { ConfigEntry<bool> val = _configFile.Bind<bool>("Enemies", text + ".Enabled", true, new ConfigDescription("If set to false, " + enemyName + " will not be affected by this mod", (AcceptableValueBase)null, Array.Empty<object>())); _enemyModEnabled[text] = val.Value; return val.Value; } catch (Exception ex) { Plugin.Log.LogError((object)("Error checking if mod is enabled for " + enemyName + ": " + ex.Message + " - defaulting to true")); return true; } } public void ClearCache() { _enemyModEnabled.Clear(); Plugin.LogInfo("Enemy control cache cleared"); } } public static class HealthManager { [Serializable] public struct HitData { public int EnemyInstanceId; public ulong EnemyNetworkId; public int EnemyIndex; public string EnemyName; public int Damage; public ulong PlayerClientId; public override string ToString() { return $"HitData(EnemyId={EnemyInstanceId}, NetworkId={EnemyNetworkId}, Index={EnemyIndex}, Name={EnemyName}, Damage={Damage}, PlayerClientId={PlayerClientId})"; } } private static int networkVarCounter = 0; private static readonly Dictionary<int, LNetworkVariable<int>> enemyHealthVars = new Dictionary<int, LNetworkVariable<int>>(); private static readonly Dictionary<int, int> enemyMaxHealth = new Dictionary<int, int>(); private static readonly Dictionary<int, bool> processedEnemies = new Dictionary<int, bool>(); private static readonly Dictionary<int, ulong> enemyNetworkIds = new Dictionary<int, ulong>(); private static readonly Dictionary<int, string> enemyNetworkVarNames = new Dictionary<int, string>(); private static readonly Dictionary<int, bool> enemiesInDespawnProcess = new Dictionary<int, bool>(); private static readonly Dictionary<int, bool> immortalEnemies = new Dictionary<int, bool>(); private static LNetworkMessage<int> despawnMessage; private static LNetworkMessage<HitData> hitMessage; private static bool networkMessagesCreated = false; public static void Initialize() { enemyHealthVars.Clear(); enemyMaxHealth.Clear(); processedEnemies.Clear(); enemyNetworkIds.Clear(); enemyNetworkVarNames.Clear(); enemiesInDespawnProcess.Clear(); immortalEnemies.Clear(); CreateNetworkMessages(); Plugin.LogInfo("Networked Health Manager initialized"); } private static void CreateNetworkMessages() { try { hitMessage = LNetworkMessage<HitData>.Create("ECDA_HitMessage", (Action<HitData, ulong>)delegate(HitData hitData, ulong clientId) { Plugin.LogInfo($"[HOST] Received hit message from client {clientId}: {hitData}"); if (((NetworkBehaviour)StartOfRound.Instance).IsHost) { EnemyAI val2 = FindEnemyMultiMethod(hitData); PlayerControllerB playerWhoHit = null; if (hitData.PlayerClientId != 0) { PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val3 in allPlayerScripts) { if (val3.actualClientId == hitData.PlayerClientId) { playerWhoHit = val3; break; } } } if ((Object)(object)val2 != (Object)null && !val2.isEnemyDead) { ProcessDamageDirectly(val2, hitData.Damage, playerWhoHit); } else { Plugin.Log.LogWarning((object)$"Could not find enemy: {hitData.EnemyName} (NetworkID: {hitData.EnemyNetworkId}, Index: {hitData.EnemyIndex})"); } } }, (Action<HitData>)null, (Action<HitData, ulong>)null); despawnMessage = LNetworkMessage<int>.Create("ECDA_DespawnMessage", (Action<int, ulong>)delegate(int enemyIndex, ulong clientId) { if (!((NetworkBehaviour)StartOfRound.Instance).IsHost) { EnemyAI val = FindEnemyByIndex(enemyIndex); if ((Object)(object)val != (Object)null) { Plugin.LogInfo($"[CLIENT] Received despawn message for enemy index {enemyIndex}"); Object.Destroy((Object)(object)((Component)val).gameObject); } } }, (Action<int>)null, (Action<int, ulong>)null); Plugin.LogInfo("Network messages created successfully"); } catch (Exception arg) { Plugin.Log.LogError((object)$"Error creating network messages: {arg}"); } } private static EnemyAI FindEnemyByIndex(int index) { EnemyAI[] array = Object.FindObjectsOfType<EnemyAI>(); foreach (EnemyAI val in array) { if (val.thisEnemyIndex == index) { return val; } } return null; } private static EnemyAI FindEnemyMultiMethod(HitData hitData) { if (hitData.EnemyIndex >= 0) { foreach (EnemyAI spawnedEnemy in RoundManager.Instance.SpawnedEnemies) { if (spawnedEnemy.thisEnemyIndex == hitData.EnemyIndex) { Plugin.LogInfo($"Found enemy by index: {hitData.EnemyIndex}"); return spawnedEnemy; } } } if (hitData.EnemyNetworkId != 0) { EnemyAI[] array = Object.FindObjectsOfType<EnemyAI>(); foreach (EnemyAI val in array) { if (((NetworkBehaviour)val).NetworkObjectId == hitData.EnemyNetworkId) { Plugin.LogInfo($"Found enemy by NetworkObjectId: {hitData.EnemyNetworkId}"); return val; } } } if (!string.IsNullOrEmpty(hitData.EnemyName)) { EnemyAI[] array2 = Object.FindObjectsOfType<EnemyAI>(); foreach (EnemyAI val2 in array2) { if (val2.enemyType.enemyName == hitData.EnemyName) { Plugin.LogInfo("Found enemy by name: " + hitData.EnemyName); return val2; } } } Plugin.Log.LogWarning((object)"Could not find enemy. All enemies in scene:"); EnemyAI[] array3 = Object.FindObjectsOfType<EnemyAI>(); foreach (EnemyAI val3 in array3) { Plugin.Log.LogWarning((object)$" - {val3.enemyType.enemyName}, Index: {val3.thisEnemyIndex}, NetworkId: {((NetworkBehaviour)val3).NetworkObjectId}"); } return null; } public static void SetupEnemy(EnemyAI enemy) { if ((Object)(object)enemy == (Object)null || (Object)(object)enemy.enemyType == (Object)null) { return; } try { int instanceId = ((Object)enemy).GetInstanceID(); if ((Object)(object)((NetworkBehaviour)enemy).NetworkObject != (Object)null) { enemyNetworkIds[instanceId] = ((NetworkBehaviour)enemy).NetworkObjectId; } if (processedEnemies.ContainsKey(instanceId) && processedEnemies[instanceId]) { Plugin.LogInfo($"Enemy {enemy.enemyType.enemyName} (ID: {instanceId}) already processed, skipping setup"); return; } string enemyName = enemy.enemyType.enemyName; string mobName = Plugin.RemoveInvalidCharacters(enemyName).ToUpper(); if (!Plugin.IsModEnabledForEnemy(mobName)) { Plugin.LogInfo("Mod disabled for enemy " + enemyName + " via config, using vanilla behavior"); processedEnemies[instanceId] = true; } else if (Plugin.CanMob(".Unimmortal", mobName)) { int num = Plugin.GetMobHealth(mobName, enemy.enemyHP); BrutalCompanyMinusCompatibility handler = ModCompatibilityManager.Instance.GetHandler<BrutalCompanyMinusCompatibility>("SoftDiamond.BrutalCompanyMinusExtraReborn"); if (handler != null && handler.IsInstalled) { num = handler.ApplyBonusHp(num); } string text = $"ECDA_Health_{enemy.thisEnemyIndex}_{networkVarCounter++}"; enemyNetworkVarNames[instanceId] = text; Plugin.LogInfo($"Creating network variable {text} for enemy {enemyName} (ID: {instanceId})"); if (!enemyHealthVars.ContainsKey(instanceId)) { try { LNetworkVariable<int> val = LNetworkVariable<int>.Create(text, num, (LNetworkVariableWritePerms)0, (Action<int, int>)null); val.OnValueChanged += delegate(int oldHealth, int newHealth) { HandleHealthChange(instanceId, newHealth); }; enemyHealthVars[instanceId] = val; } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to create network variable " + text + ": " + ex.Message)); text = $"ECDA_Health_{enemy.thisEnemyIndex}_{networkVarCounter++}_Retry"; Plugin.LogInfo("Retrying with new variable name: " + text); enemyNetworkVarNames[instanceId] = text; LNetworkVariable<int> val = LNetworkVariable<int>.Create(text, num, (LNetworkVariableWritePerms)0, (Action<int, int>)null); val.OnValueChanged += delegate(int oldHealth, int newHealth) { HandleHealthChange(instanceId, newHealth); }; enemyHealthVars[instanceId] = val; } } else { LNetworkVariable<int> val = enemyHealthVars[instanceId]; Plugin.LogInfo($"Using existing health variable for enemy {enemyName} (ID: {instanceId})"); } enemyMaxHealth[instanceId] = num; enemy.enemyType.canDie = true; enemy.enemyType.canBeDestroyed = true; enemy.enemyHP = 999; processedEnemies[instanceId] = true; immortalEnemies[instanceId] = false; Plugin.LogInfo($"Setup enemy {enemyName} (ID: {instanceId}, NetID: {((NetworkBehaviour)enemy).NetworkObjectId}, Index: {enemy.thisEnemyIndex}) with {num} networked health"); } else { Plugin.LogInfo("Enemy " + enemyName + " is configured as immortal (Unimmortal=false, Enabled=true)"); enemy.enemyHP = 999; immortalEnemies[instanceId] = true; processedEnemies[instanceId] = true; Plugin.LogInfo($"Set enemy {enemyName} (ID: {instanceId}) to be immortal with 999 HP"); } } catch (Exception ex2) { Plugin.Log.LogError((object)("Error setting up enemy: " + ex2.Message)); Plugin.Log.LogError((object)("Stack trace: " + ex2.StackTrace)); } } private static void HandleHealthChange(int instanceId, int newHealth) { EnemyAI val = FindEnemyById(instanceId); if ((Object)(object)val == (Object)null) { return; } Plugin.LogInfo($"Health changed for enemy {val.enemyType.enemyName} (ID: {instanceId}): new health = {newHealth}"); if (newHealth <= 0 && !val.isEnemyDead && ((NetworkBehaviour)StartOfRound.Instance).IsHost) { HitmarkerCompatibility handler = ModCompatibilityManager.Instance.GetHandler<HitmarkerCompatibility>("com.github.zehsteam.Hitmarker"); if (handler != null && handler.IsInstalled) { PlayerControllerB lastDamageSource = handler.GetLastDamageSource(instanceId); handler.NotifyEnemyKilled(val, lastDamageSource); } KillEnemy(val); } } private static EnemyAI FindEnemyById(int instanceId) { EnemyAI[] array = Object.FindObjectsOfType<EnemyAI>(); EnemyAI[] array2 = array; foreach (EnemyAI val in array2) { if (((Object)val).GetInstanceID() == instanceId) { return val; } } return null; } public static void ProcessHit(EnemyAI enemy, int damage, PlayerControllerB playerWhoHit) { if ((Object)(object)enemy == (Object)null || enemy.isEnemyDead) { return; } int instanceID = ((Object)enemy).GetInstanceID(); string mobName = Plugin.RemoveInvalidCharacters(enemy.enemyType.enemyName).ToUpper(); if (!Plugin.IsModEnabledForEnemy(mobName)) { Plugin.LogInfo("Mod disabled for enemy " + enemy.enemyType.enemyName + ", not processing hit"); return; } if (immortalEnemies.TryGetValue(instanceID, out var value) && value) { enemy.enemyHP = 999; Plugin.LogInfo("Refreshed immortal enemy " + enemy.enemyType.enemyName + " HP to 999"); return; } LethalHandsCompatibility handler = ModCompatibilityManager.Instance.GetHandler<LethalHandsCompatibility>("SlapitNow.LethalHands"); if (handler != null && handler.IsInstalled && damage == -22) { damage = handler.ConvertPunchForceToDamage(damage); Plugin.LogInfo($"Converted LethalHands punch to damage: {damage}"); } else if (damage < 0) { Plugin.Log.LogWarning((object)$"Received negative damage value: {damage}, setting to 0"); damage = 0; } if (damage <= 0) { return; } if (((NetworkBehaviour)StartOfRound.Instance).IsHost) { Plugin.LogInfo($"Processing hit locally as host: Enemy {enemy.enemyType.enemyName}, Damage {damage}"); ProcessDamageDirectly(enemy, damage, playerWhoHit); return; } HitData hitData = default(HitData); hitData.EnemyInstanceId = instanceID; hitData.EnemyNetworkId = ((NetworkBehaviour)enemy).NetworkObjectId; hitData.EnemyIndex = enemy.thisEnemyIndex; hitData.EnemyName = enemy.enemyType.enemyName; hitData.Damage = damage; hitData.PlayerClientId = (((Object)(object)playerWhoHit != (Object)null) ? playerWhoHit.actualClientId : 0); HitData hitData2 = hitData; try { if (hitMessage == null) { Plugin.Log.LogWarning((object)"Hit message is null, recreating it"); CreateNetworkMessages(); } hitMessage.SendServer(hitData2); Plugin.LogInfo($"Sent hit message to server: Enemy {enemy.enemyType.enemyName}, Damage {damage}, Index {enemy.thisEnemyIndex}, PlayerClientId {hitData2.PlayerClientId}"); } catch (Exception arg) { Plugin.Log.LogError((object)$"Error sending hit message: {arg}"); } } private static void ProcessDamageDirectly(EnemyAI enemy, int damage, PlayerControllerB playerWhoHit = null) { if ((Object)(object)enemy == (Object)null || enemy.isEnemyDead) { return; } int instanceID = ((Object)enemy).GetInstanceID(); string mobName = Plugin.RemoveInvalidCharacters(enemy.enemyType.enemyName).ToUpper(); if (!Plugin.IsModEnabledForEnemy(mobName)) { Plugin.LogInfo("Mod disabled for enemy " + enemy.enemyType.enemyName + ", not processing damage"); return; } if ((Object)(object)playerWhoHit != (Object)null) { HitmarkerCompatibility handler = ModCompatibilityManager.Instance.GetHandler<HitmarkerCompatibility>("com.github.zehsteam.Hitmarker"); if (handler != null && handler.IsInstalled) { handler.TrackDamageSource(instanceID, playerWhoHit); } } if (immortalEnemies.TryGetValue(instanceID, out var value) && value) { enemy.enemyHP = 999; Plugin.LogInfo("Refreshed immortal enemy " + enemy.enemyType.enemyName + " HP to 999"); return; } if (!processedEnemies.ContainsKey(instanceID) || !processedEnemies[instanceID]) { SetupEnemy(enemy); } if (enemyHealthVars.TryGetValue(instanceID, out var value2)) { int value3 = value2.Value; int num = Mathf.Max(0, value3 - damage); Plugin.LogInfo($"Enemy {enemy.enemyType.enemyName} damaged for {damage}: {value3} -> {num}"); value2.Value = num; } else { Plugin.Log.LogWarning((object)$"No health variable found for enemy {enemy.enemyType.enemyName} (ID: {instanceID})"); } } public static void NotifyClientsOfDestroy(int enemyIndex) { if (despawnMessage != null) { despawnMessage.SendClients(enemyIndex); } } private static void KillEnemy(EnemyAI enemy) { if ((Object)(object)enemy == (Object)null || enemy.isEnemyDead) { return; } Plugin.LogInfo("Killing enemy " + enemy.enemyType.enemyName); SellBodiesCompatibility handler = ModCompatibilityManager.Instance.GetHandler<SellBodiesCompatibility>("Entity378.sellbodies"); if (handler != null && handler.IsInstalled && handler.IsProblemEnemy(enemy.enemyType.enemyName)) { handler.HandleProblemEnemyDeath(enemy); } if (!((NetworkBehaviour)enemy).IsOwner) { Plugin.LogInfo("Attempting to take ownership of " + enemy.enemyType.enemyName + " to kill it"); ulong actualClientId = StartOfRound.Instance.allPlayerScripts[0].actualClientId; enemy.ChangeOwnershipOfEnemy(actualClientId); } LastResortKillerCompatibility handler2 = ModCompatibilityManager.Instance.GetHandler<LastResortKillerCompatibility>("nwnt.EverythingCanDieAlternative.LastResortKiller"); if (handler2 != null) { bool allowDespawn = DespawnConfiguration.Instance.ShouldDespawnEnemy(enemy.enemyType.enemyName); handler2.AttemptToKillEnemy(enemy, allowDespawn); } else { enemy.KillEnemyOnOwnerClient(false); if (enemy.enemyType.enemyName.Contains("Spring")) { Plugin.LogInfo("Using fallback kill method for " + enemy.enemyType.enemyName); enemy.KillEnemyOnOwnerClient(true); } } if (DespawnConfiguration.Instance.ShouldDespawnEnemy(enemy.enemyType.enemyName)) { StartDespawnProcess(enemy); } } private static void StartDespawnProcess(EnemyAI enemy) { if ((Object)(object)enemy == (Object)null) { return; } int instanceID = ((Object)enemy).GetInstanceID(); if (!enemiesInDespawnProcess.ContainsKey(instanceID) || !enemiesInDespawnProcess[instanceID]) { enemiesInDespawnProcess[instanceID] = true; Plugin.LogInfo($"Starting despawn process for {enemy.enemyType.enemyName} (Index: {enemy.thisEnemyIndex})"); if ((Object)(object)StartOfRound.Instance != (Object)null) { ((MonoBehaviour)StartOfRound.Instance).StartCoroutine(WaitForDeathAnimationAndDespawn(enemy)); } } } private static IEnumerator WaitForDeathAnimationAndDespawn(EnemyAI enemy) { if ((Object)(object)enemy == (Object)null) { yield break; } int instanceId = ((Object)enemy).GetInstanceID(); int enemyIndex = enemy.thisEnemyIndex; float waitTime = 0.5f; SellBodiesCompatibility sellBodiesHandler = ModCompatibilityManager.Instance.GetHandler<SellBodiesCompatibility>("Entity378.sellbodies"); if (sellBodiesHandler?.IsInstalled ?? false) { waitTime = sellBodiesHandler.GetDespawnDelay(); Plugin.LogInfo($"Using SellBodies compatibility despawn delay: {waitTime}s for {enemy.enemyType.enemyName}"); } yield return (object)new WaitForSeconds(waitTime); if ((Object)(object)enemy != (Object)null && enemy.isEnemyDead) { if (despawnMessage != null) { despawnMessage.SendClients(enemyIndex); } Object.Destroy((Object)(object)((Component)enemy).gameObject); } if (enemiesInDespawnProcess.ContainsKey(instanceId)) { enemiesInDespawnProcess.Remove(instanceId); } } public static int GetEnemyHealth(EnemyAI enemy) { if ((Object)(object)enemy == (Object)null) { return 0; } int instanceID = ((Object)enemy).GetInstanceID(); if (enemyHealthVars.TryGetValue(instanceID, out var value)) { return value.Value; } return 0; } public static int GetEnemyMaxHealth(EnemyAI enemy) { if ((Object)(object)enemy == (Object)null) { return 0; } int instanceID = ((Object)enemy).GetInstanceID(); if (enemyMaxHealth.TryGetValue(instanceID, out var value)) { return value; } return 0; } } public static class Patches { public static void Initialize(Harmony harmony) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(typeof(StartOfRound), "Start", (Type[])null, (Type[])null); if (methodInfo == null) { Plugin.Log.LogError((object)"Could not find StartOfRound.Start method - patches failed!"); return; } MethodInfo methodInfo2 = AccessTools.Method(typeof(Patches), "StartOfRoundPostfix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo3 = AccessTools.Method(typeof(EnemyAI), "Start", (Type[])null, (Type[])null); MethodInfo methodInfo4 = AccessTools.Method(typeof(Patches), "EnemyAIStartPostfix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(methodInfo4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo5 = AccessTools.Method(typeof(EnemyAI), "HitEnemyOnLocalClient", (Type[])null, (Type[])null); MethodInfo methodInfo6 = AccessTools.Method(typeof(Patches), "HitEnemyOnLocalClientPrefix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(methodInfo6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo7 = AccessTools.Method(typeof(EnemyAI), "HitEnemy", (Type[])null, (Type[])null); MethodInfo methodInfo8 = AccessTools.Method(typeof(Patches), "HitEnemyPrefix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo7, new HarmonyMethod(methodInfo8), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo9 = AccessTools.Method(typeof(RoundManager), "FinishGeneratingLevel", (Type[])null, (Type[])null); MethodInfo methodInfo10 = AccessTools.Method(typeof(Patches), "FinishGeneratingLevelPostfix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo9, (HarmonyMethod)null, new HarmonyMethod(methodInfo10), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo11 = AccessTools.Method(typeof(StartOfRound), "ShipLeave", (Type[])null, (Type[])null); MethodInfo methodInfo12 = AccessTools.Method(typeof(Patches), "ShipLeavePostfix", (Type[])null, (Type[])null); harmony.Patch((MethodBase)methodInfo11, (HarmonyMethod)null, new HarmonyMethod(methodInfo12), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.Log.LogInfo((object)"All Harmony patches applied successfully"); } catch (Exception ex) { Plugin.Log.LogError((object)("Error applying Harmony patches: " + ex.Message)); Plugin.Log.LogError((object)("Stack trace: " + ex.StackTrace)); } } public static void StartOfRoundPostfix(StartOfRound __instance) { try { Plugin.Log.LogInfo((object)"Game starting, initializing networked enemy health system..."); ((BaseUnityPlugin)Plugin.Instance).Config.Reload(); EnemyControlConfiguration.Instance.ReloadConfig(); DespawnConfiguration.Instance.ReloadConfig(); Plugin.LogInfo("All configurations reloaded from files"); HealthManager.Initialize(); Plugin.enemies = new List<EnemyType>(Resources.FindObjectsOfTypeAll<EnemyType>()); Plugin.LogInfo($"Found {Plugin.enemies.Count} enemy types"); foreach (EnemyType enemy in Plugin.enemies) { if ((Object)(object)enemy == (Object)null || string.IsNullOrEmpty(enemy.enemyName)) { Plugin.Log.LogWarning((object)"Found null or invalid enemy type, skipping"); continue; } string mobName = Plugin.RemoveInvalidCharacters(enemy.enemyName).ToUpper(); Plugin.LogInfo("Processing enemy type: " + enemy.enemyName); Plugin.CanMob(".Unimmortal", mobName); int num = 3; if ((Object)(object)enemy.enemyPrefab != (Object)null) { EnemyAI componentInChildren = enemy.enemyPrefab.GetComponentInChildren<EnemyAI>(); if ((Object)(object)componentInChildren != (Object)null) { if (componentInChildren.enemyHP <= 0) { num = 1; Plugin.LogInfo("Detected 0 or negative HP for " + enemy.enemyName + ", setting default to 1"); } else { num = Math.Min(componentInChildren.enemyHP, 30); if (componentInChildren.enemyHP > 30) { Plugin.LogInfo($"Capped HP for {enemy.enemyName} from {componentInChildren.enemyHP} to {num}"); } } } } Plugin.GetMobHealth(mobName, num); Plugin.ShouldDespawn(mobName); } EnemyControlConfiguration.Instance.PreCreateEnemyConfigEntries(); ProcessExistingEnemies(); Plugin.Log.LogInfo((object)"StartOfRoundPostfix completed successfully"); } catch (Exception ex) { Plugin.Log.LogError((object)("Error in StartOfRoundPostfix: " + ex.Message)); Plugin.Log.LogError((object)("Stack trace: " + ex.StackTrace)); } } private static void ProcessExistingEnemies() { try { EnemyAI[] array = Object.FindObjectsOfType<EnemyAI>(); Plugin.LogInfo($"Found {array.Length} active enemies"); EnemyAI[] array2 = array; foreach (EnemyAI val in array2) { if (!((Object)(object)val?.enemyType == (Object)null)) { Plugin.LogInfo("Setting up enemy: " + val.enemyType.enemyName); HealthManager.SetupEnemy(val); } } } catch (Exception ex) { Plugin.Log.LogError((object)("Error processing existing enemies: " + ex.Message)); Plugin.Log.LogError((object)("Stack trace: " + ex.StackTrace)); } } public static void EnemyAIStartPostfix(EnemyAI __instance) { try { if (!((Object)(object)__instance?.enemyType == (Object)null)) { HealthManager.SetupEnemy(__instance); } } catch (Exception ex) { Plugin.Log.LogError((object)("Error in EnemyAIStartPostfix: " + ex.Message)); } } public static bool HitEnemyOnLocalClientPrefix(EnemyAI __instance, int force, Vector3 hitDirection, PlayerControllerB playerWhoHit, bool playHitSFX, int hitID) { try { if ((Object)(object)__instance == (Object)null || __instance.isEnemyDead) { return true; } Plugin.LogInfo(string.Format("Local hit detected on {0} from {1} with force {2}", __instance.enemyType.enemyName, playerWhoHit?.playerUsername ?? "unknown", force)); LethalHandsCompatibility handler = ModCompatibilityManager.Instance.GetHandler<LethalHandsCompatibility>("SlapitNow.LethalHands"); bool flag = handler != null && handler.IsInstalled && force == -22; if (flag) { Plugin.LogInfo($"Detected LethalHands punch with force {force}"); } HealthManager.ProcessHit(__instance, force, playerWhoHit); if (flag) { return true; } return true; } catch (Exception ex) { Plugin.Log.LogError((object)("Error in HitEnemyOnLocalClientPrefix: " + ex.Message)); return true; } } public static bool HitEnemyPrefix(EnemyAI __instance, int force, PlayerControllerB playerWhoHit) { try { if ((Object)(object)__instance == (Object)null || __instance.isEnemyDead) { return true; } string enemyName = __instance.enemyType.enemyName; string mobName = Plugin.RemoveInvalidCharacters(enemyName).ToUpper(); if (Plugin.IsModEnabledForEnemy(mobName) && !Plugin.CanMob(".Unimmortal", mobName)) { __instance.enemyHP = 999; Plugin.LogInfo("HitEnemyPrefix: Refreshed immortal enemy " + enemyName + " HP to 999"); return true; } return true; } catch (Exception ex) { Plugin.Log.LogError((object)("Error in HitEnemyPrefix: " + ex.Message)); return true; } } [HarmonyPostfix] public static void ShipLeavePostfix() { try { HitmarkerCompatibility handler = ModCompatibilityManager.Instance.GetHandler<HitmarkerCompatibility>("com.github.zehsteam.Hitmarker"); if (handler != null && handler.IsInstalled) { Plugin.LogInfo("Clearing Hitmarker compatibility data on level unload"); handler.ClearTracking(); } } catch (Exception ex) { Plugin.Log.LogError((object)("Error in ShipLeavePostfix: " + ex.Message)); } } public static void FinishGeneratingLevelPostfix() { try { BrutalCompanyMinusCompatibility handler = ModCompatibilityManager.Instance.GetHandler<BrutalCompanyMinusCompatibility>("SoftDiamond.BrutalCompanyMinusExtraReborn"); if (handler != null && handler.IsInstalled) { Plugin.LogInfo("Refreshing BrutalCompanyMinus compatibility data after level generation"); handler.RefreshBonusHp(); } } catch (Exception ex) { Plugin.Log.LogError((object)("Error in FinishGeneratingLevelPostfix: " + ex.Message)); } } } [BepInPlugin("nwnt.EverythingCanDieAlternative", "EverythingCanDieAlternative", "1.1.59")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public static List<EnemyType> enemies = new List<EnemyType>(); private static bool _infoLogsEnabled = true; public static Plugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } public static Harmony Harmony { get; private set; } public static ConfigEntry<bool> PatchCruiserDamage { get; private set; } public static ConfigEntry<int> CruiserDamageAtHighSpeeds { get; private set; } public bool IsSellBodiesModDetected => IsModInstalled("Entity378.sellbodies"); private void Awake() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Harmony = new Harmony("nwnt.EverythingCanDieAlternative"); try { _ = UIConfiguration.Instance; if (UIConfiguration.Instance != null && UIConfiguration.Instance.IsInitialized) { _infoLogsEnabled = UIConfiguration.Instance.ShouldLogInfo(); } _ = DespawnConfiguration.Instance; _ = EnemyControlConfiguration.Instance; ModCompatibilityManager.Instance.Initialize(); Patches.Initialize(Harmony); if (UIConfiguration.Instance.IsConfigMenuEnabled()) { ConfigMenuPatch.Initialize(Harmony); Log.LogInfo((object)"EverythingCanDieAlternative v1.1.59 is loaded with network support and configuration menu!"); } else { Log.LogInfo((object)"EverythingCanDieAlternative v1.1.59 is loaded with network support (configuration menu disabled)"); } } catch (Exception ex) { Log.LogError((object)("Error initializing EverythingCanDieAlternative: " + ex.Message)); Log.LogError((object)("Stack trace: " + ex.StackTrace)); } } public bool IsModInstalled(string modId) { return ModCompatibilityManager.Instance.IsModInstalled(modId); } public static bool IsModEnabledForEnemy(string mobName) { return EnemyControlConfiguration.Instance.IsModEnabledForEnemy(mobName); } public static string RemoveInvalidCharacters(string source) { if (string.IsNullOrEmpty(source)) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(); foreach (char c in source) { if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { stringBuilder.Append(c); } } return string.Join("", stringBuilder.ToString().Split((string[]?)null, StringSplitOptions.RemoveEmptyEntries)); } public static void LogInfo(string message) { if (_infoLogsEnabled) { Log.LogInfo((object)message); } } public static void LogError(string message) { Log.LogError((object)message); } public static void LogWarning(string message) { Log.LogWarning((object)message); } public static bool CanMob(string identifier, string mobName) { try { string text = RemoveInvalidCharacters(mobName).ToUpper(); string source = text + identifier.ToUpper(); ConfigEntry<bool> val = null; foreach (ConfigDefinition key in ((BaseUnityPlugin)Instance).Config.Keys) { if (RemoveInvalidCharacters(key.Key.ToUpper()).Equals(RemoveInvalidCharacters(source))) { val = (ConfigEntry<bool>)(object)((BaseUnityPlugin)Instance).Config[key]; return val.Value; } } val = ((BaseUnityPlugin)Instance).Config.Bind<bool>("Mobs", text + identifier, true, "If true, " + mobName + " will be damageable"); return val.Value; } catch (Exception ex) { Log.LogError((object)("Error in config check for mob " + mobName + ": " + ex.Message)); return false; } } public static int GetMobHealth(string mobName, int defaultHealth) { try { if (defaultHealth <= 0) { defaultHealth = 1; LogInfo("Enforcing minimum health of 1 for " + mobName); } string text = RemoveInvalidCharacters(mobName).ToUpper(); string value = text + ".HEALTH"; ConfigEntry<int> val = null; foreach (ConfigDefinition key in ((BaseUnityPlugin)Instance).Config.Keys) { if (RemoveInvalidCharacters(key.Key.ToUpper()).Equals(value)) { val = (ConfigEntry<int>)(object)((BaseUnityPlugin)Instance).Config[key]; int num = val.Value; if (num <= 0) { num = 1; LogInfo("Enforcing minimum configured health of 1 for " + mobName); val.Value = 1; } LogInfo($"Enemy {mobName} health from config: {num}"); return num; } } val = ((BaseUnityPlugin)Instance).Config.Bind<int>("Mobs", text + ".Health", defaultHealth, "Health for " + mobName); LogInfo($"Using config for {mobName} health: {val.Value}"); return val.Value; } catch (Exception ex) { Log.LogError((object)("Error getting health for " + mobName + ": " + ex.Message)); return Math.Max(1, defaultHealth); } } public static bool ShouldDespawn(string mobName) { return DespawnConfiguration.Instance.ShouldDespawnEnemy(mobName); } } public static class PluginInfo { public const string PLUGIN_GUID = "nwnt.EverythingCanDieAlternative"; public const string PLUGIN_NAME = "EverythingCanDieAlternative"; public const string PLUGIN_VERSION = "1.1.59"; } } namespace EverythingCanDieAlternative.UI { public class UIConfiguration { public static ConfigEntry<bool> EnableConfigMenu; public static ConfigEntry<bool> EnableInfoLogs; public static ConfigEntry<bool> ShowEnemyImages; private static UIConfiguration _instance; public static UIConfiguration Instance => _instance ?? (_instance = new UIConfiguration()); public bool IsInitialized { get; private set; } private UIConfiguration() { try { EnableConfigMenu = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("General", "EnableConfigMenu", true, "If set to true, the config menu button will be shown in the main menu"); EnableInfoLogs = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("General", "EnableInfoLogs", true, "If set to false, info logs will be suppressed to reduce console spam"); ShowEnemyImages = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("General", "ShowEnemyImages", false, "If set to true, preview images for enemies will be shown in the config menu if available"); IsInitialized = true; } catch (Exception ex) { Plugin.Log.LogError((object)("Error initializing UI configuration: " + ex.Message)); IsInitialized = false; } } public bool IsConfigMenuEnabled() { if (!IsInitialized || EnableConfigMenu == null) { return true; } return EnableConfigMenu.Value; } public bool ShouldLogInfo() { if (!IsInitialized || EnableInfoLogs == null) { return true; } return EnableInfoLogs.Value; } public bool ShouldShowEnemyImages() { if (!IsInitialized || ShowEnemyImages == null) { return false; } return ShowEnemyImages.Value; } public void SetInfoLogsEnabled(bool enabled) { if (IsInitialized && EnableInfoLogs != null) { EnableInfoLogs.Value = enabled; Plugin.Log.LogInfo((object)("Info logs " + (enabled ? "enabled" : "disabled"))); } } public void SetConfigMenuEnabled(bool enabled) { if (IsInitialized && EnableConfigMenu != null) { EnableConfigMenu.Value = enabled; Plugin.Log.LogInfo((object)("Config menu " + (enabled ? "enabled" : "disabled"))); } } public void SetShowEnemyImages(bool enabled) { if (IsInitialized && ShowEnemyImages != null) { ShowEnemyImages.Value = enabled; Plugin.Log.LogInfo((object)("Enemy images " + (enabled ? "enabled" : "disabled"))); } } public void Save() { try { ((BaseUnityPlugin)Plugin.Instance).Config.Save(); ((BaseUnityPlugin)Plugin.Instance).Config.Reload(); EnemyControlConfiguration.Instance.ReloadConfig(); DespawnConfiguration.Instance.ReloadConfig(); Plugin.LogInfo("All UI settings saved and reloaded"); } catch (Exception ex) { Plugin.Log.LogError((object)("Error saving UI settings: " + ex.Message)); } } public void ReloadAllConfigs() { try { ((BaseUnityPlugin)Plugin.Instance).Config.Reload(); EnemyControlConfiguration.Instance.ReloadConfig(); DespawnConfiguration.Instance.ReloadConfig(); Plugin.LogInfo("All configs reloaded from files"); } catch (Exception ex) { Plugin.Log.LogError((object)("Error reloading configs: " + ex.Message)); } } } public static class ConfigBridge { private static string pluginConfigPath = Path.Combine(Paths.ConfigPath, "nwnt.EverythingCanDieAlternative.cfg"); private static string enemyControlConfigPath = Path.Combine(Paths.ConfigPath, "nwnt.EverythingCanDieAlternative_Enemy_Control.cfg"); private static string despawnConfigPath = Path.Combine(Paths.ConfigPath, "nwnt.EverythingCanDieAlternative_Despawn_Rules.cfg"); private static Dictionary<string, Dictionary<string, object>> cachedConfigEntries = new Dictionary<string, Dictionary<string, object>>(); private static bool isLoading = false; public static List<EnemyConfigData> LoadAllEnemyConfigs() { if (isLoading) { return new List<EnemyConfigData>(); } isLoading = true; List<EnemyConfigData> list = new List<EnemyConfigData>(); try { cachedConfigEntries.Clear(); LogFileDetails(pluginConfigPath, "Main plugin config"); LogFileDetails(enemyControlConfigPath, "Enemy control config"); LogFileDetails(despawnConfigPath, "Despawn config"); ReadConfigFileDirectly(pluginConfigPath, "Mobs"); ReadConfigFileDirectly(enemyControlConfigPath, "Enemies"); ReadConfigFileDirectly(despawnConfigPath, "Enemies"); List<string> allConfiguredEnemyNames = GetAllConfiguredEnemyNames(); if (allConfiguredEnemyNames.Count == 0) { Plugin.Log.LogWarning((object)"No configured enemies found in any config files. Start a round to generate configurations."); isLoading = false; return list; } Plugin.LogInfo($"Found {allConfiguredEnemyNames.Count} configured enemies in config files"); foreach (string item in allConfiguredEnemyNames) { bool isEnabled = false; bool canDie = true; bool shouldDespawn = true; int health = 3; if (cachedConfigEntries.TryGetValue(item, out var value)) { if (value.TryGetValue(".ENABLED", out var value2) && value2 is bool flag) { isEnabled = flag; } if (value.TryGetValue(".UNIMMORTAL", out var value3) && value3 is bool flag2) { canDie = flag2; } if (value.TryGetValue(".DESPAWN", out var value4) && value4 is bool flag3) { shouldDespawn = flag3; } if (value.TryGetValue(".HEALTH", out var value5)) { int result; if (value5 is int num) { health = num; } else if (value5 is string s && int.TryParse(s, out result)) { health = result; } } } list.Add(new EnemyConfigData(item, isEnabled, canDie, shouldDespawn, health)); } Plugin.LogInfo($"Loaded {list.Count} enemy configurations successfully"); } catch (Exception arg) { Plugin.Log.LogError((object)$"Error loading enemy configurations: {arg}"); } finally { isLoading = false; } return list; } private static void LogFileDetails(string path, string description) { if (File.Exists(path)) { FileInfo fileInfo = new FileInfo(path); } } private static void ReadConfigFileDirectly(string path, string targetSection) { if (!File.Exists(path)) { return; } try { string[] array = File.ReadAllLines(path); Plugin.LogInfo($"Reading config file {Path.GetFileName(path)} ({array.Length} lines)"); string text = ""; int num = 0; string[] array2 = array; foreach (string text2 in array2) { string text3 = text2.Trim(); if (string.IsNullOrWhiteSpace(text3) || text3.StartsWith("#") || text3.StartsWith("//")) { continue; } Match match = Regex.Match(text3, "^\\[(.*)\\]$"); if (match.Success) { text = match.Groups[1].Value; } else if (!(text != targetSection)) { int num2 = text3.IndexOf('='); if (num2 > 0) { string key = text3.Substring(0, num2).Trim(); string value = text3.Substring(num2 + 1).Trim(); ProcessConfigEntry(text, key, value); num++; } } } Plugin.LogInfo($"Found {num} entries in section [{targetSection}]"); } catch (Exception ex) { Plugin.Log.LogError((object)("Error reading config file " + path + ": " + ex.Message)); } } private static void ProcessConfigEntry(string section, string key, string value) { string text = null; string text2 = null; if (section == "Mobs") { int num = key.LastIndexOf('.'); if (num > 0) { text = key.Substring(0, num).ToUpper(); text2 = key.Substring(num).ToUpper(); } } else if (section == "Enemies") { int num2 = key.LastIndexOf('.'); if (num2 > 0) { text = key.Substring(0, num2).ToUpper(); text2 = key.Substring(num2).ToUpper(); } } if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(text2)) { return; } if (!cachedConfigEntries.ContainsKey(text)) { cachedConfigEntries[text] = new Dictionary<string, object>(); } if (text2 == ".ENABLED" || text2 == ".UNIMMORTAL" || text2 == ".DESPAWN") { if (bool.TryParse(value, out var result)) { cachedConfigEntries[text][text2] = result; } } else if (text2 == ".HEALTH") { if (int.TryParse(value, out var result2)) { cachedConfigEntries[text][text2] = result2; return; } cachedConfigEntries[text][text2] = value; Plugin.Log.LogWarning((object)("Could not parse health value " + value + " for " + text)); } } private static List<string> GetAllConfiguredEnemyNames() { return cachedConfigEntries.Keys.ToList(); } private static bool GetCachedBoolValue(string enemyName, string suffix, bool defaultValue) { if (cachedConfigEntries.TryGetValue(enemyName, out var value) && value.TryGetValue(suffix, out var value2) && value2 is bool result) { return result; } return defaultValue; } private static int GetCachedIntValue(string enemyName, string suffix, int defaultValue) { if (cachedConfigEntries.TryGetValue(enemyName, out var value) && value.TryGetValue(suffix, out var value2)) { if (value2 is int result) { return result; } if (value2 is string s && int.TryParse(s, out var result2)) { return result2; } Plugin.Log.LogWarning((object)string.Format("Invalid health value for {0}: {1} (type: {2})", enemyName, value2, value2?.GetType().Name ?? "null")); } return defaultValue; } public static void SaveEnemyConfig(EnemyConfigData config) { if (config == null) { return; } string sanitizedName = config.SanitizedName; string name = config.Name; if (!cachedConfigEntries.ContainsKey(sanitizedName)) { Plugin.Log.LogWarning((object)("Cannot save config for " + name + " as no existing entries were found")); return; } try { bool flag = false; bool flag2 = false; bool flag3 = false; if (cachedConfigEntries[sanitizedName].ContainsKey(".UNIMMORTAL") || cachedConfigEntries[sanitizedName].ContainsKey(".HEALTH")) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (cachedConfigEntries[sanitizedName].ContainsKey(".UNIMMORTAL")) { dictionary[sanitizedName + ".Unimmortal"] = config.CanDie.ToString().ToLower(); } if (cachedConfigEntries[sanitizedName].ContainsKey(".HEALTH")) { dictionary[sanitizedName + ".Health"] = config.Health.ToString(); } flag = UpdateConfigFileDirectly(pluginConfigPath, "Mobs", dictionary); } if (cachedConfigEntries[sanitizedName].ContainsKey(".ENABLED")) { flag2 = UpdateConfigFileDirectly(enemyControlConfigPath, "Enemies", new Dictionary<string, string> { { sanitizedName + ".Enabled", config.IsEnabled.ToString().ToLower() } }); } if (cachedConfigEntries[sanitizedName].ContainsKey(".DESPAWN")) { flag3 = UpdateConfigFileDirectly(despawnConfigPath, "Enemies", new Dictionary<string, string> { { sanitizedName + ".Despawn", config.ShouldDespawn.ToString().ToLower() } }); } cachedConfigEntries[sanitizedName][".ENABLED"] = config.IsEnabled; cachedConfigEntries[sanitizedName][".UNIMMORTAL"] = config.CanDie; cachedConfigEntries[sanitizedName][".HEALTH"] = config.Health; cachedConfigEntries[sanitizedName][".DESPAWN"] = config.ShouldDespawn; } catch (Exception ex) { Plugin.Log.LogError((object)("Error saving configuration: " + ex.Message)); } } private static bool UpdateConfigFileDirectly(string path, string section, Dictionary<string, string> updates) { if (!File.Exists(path)) { return false; } try { string[] array = File.ReadAllLines(path); List<string> list = new List<string>(); string text = ""; bool flag = false; Dictionary<string, bool> dictionary = new Dictionary<string, bool>(); foreach (string key in updates.Keys) { dictionary[key.ToUpper()] = false; } string[] array2 = array; foreach (string text2 in array2) { string text3 = text2.Trim(); Match match = Regex.Match(text3, "^\\[(.*)\\]$"); if (match.Success) { text = match.Groups[1].Value; list.Add(text2); } else if (text == section) { bool flag2 = false; int num = text3.IndexOf('='); if (num > 0) { string text4 = text3.Substring(0, num).Trim(); foreach (string key2 in updates.Keys) { if (text4.Equals(key2, StringComparison.OrdinalIgnoreCase) || Plugin.RemoveInvalidCharacters(text4.ToUpper()) == Plugin.RemoveInvalidCharacters(key2.ToUpper())) { list.Add(text4 + " = " + updates[key2]); dictionary[key2.ToUpper()] = true; flag = true; flag2 = true; break; } } } if (!flag2) { list.Add(text2); } } else { list.Add(text2); } } bool flag3 = false; foreach (KeyValuePair<string, bool> item in dictionary) { if (!item.Value) { flag3 = true; break; } } if (flag3) { bool flag4 = false; for (int j = 0; j < list.Count; j++) { if (list[j].Trim() == "[" + section + "]") { flag4 = true; break; } } if (!flag4) { if (list.Count > 0 && !string.IsNullOrWhiteSpace(list[list.Count - 1])) { list.Add(""); } list.Add("[" + section + "]"); } foreach (KeyValuePair<string, bool> entry in dictionary) { if (!entry.Value) { string text5 = updates.Keys.First((string k) => k.ToUpper() == entry.Key); string text6 = updates[text5]; list.Add(text5 + " = " + text6); flag = true; } } } if (flag) { File.WriteAllLines(path, list); } return flag; } catch (Exception ex) { Plugin.Log.LogError((object)("Error updating config file " + path + ": " + ex.Message)); return false; } } } public class ConfigMenuManager : MonoBehaviour { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Comparison<EnemyConfigData> <>9__13_0; public static UnityAction <>9__18_0; public static UnityAction<bool> <>9__18_1; public static UnityAction<bool> <>9__18_2; public static UnityAction<bool> <>9__18_3; public static Func<KeyValuePair<string, GameObject>, bool> <>9__20_0; internal int <RefreshEnemyData>b__13_0(EnemyConfigData a, EnemyConfigData b) { return string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase); } internal void <CreateMenuPrefab>b__18_0() { PlayCancelSFX(); menuPrefab.SetActive(false); } internal void <CreateMenuPrefab>b__18_1(bool isHideMenu) { PlayConfirmSFX(); UIConfiguration.Instance.SetConfigMenuEnabled(!isHideMenu); UIConfiguration.Instance.Save(); } internal void <CreateMenuPrefab>b__18_2(bool isLessLogs) { PlayConfirmSFX(); UIConfiguration.Instance.SetInfoLogsEnabled(!isLessLogs); UIConfiguration.Instance.Save(); } internal void <CreateMenuPrefab>b__18_3(bool showImages) { PlayConfirmSFX(); UIConfiguration.Instance.SetShowEnemyImages(showImages); UIConfiguration.Instance.Save(); ConfigMenuManager component = menuPrefab.GetComponent<ConfigMenuManager>(); if ((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.selectedEnemyName)) { component.UpdateConfigPanel(); } } internal bool <FilterEnemyList>b__20_0(KeyValuePair<string, GameObject> e) { return e.Value.activeSelf; } } private static GameObject menuPrefab; private GameObject menuPanel; private RectTransform enemyListContent; private GameObject enemyConfigPanel; private List<EnemyConfigData> enemyConfigs = new List<EnemyConfigData>(); private Dictionary<string, GameObject> enemyEntries = new Dictionary<string, GameObject>(); private string selectedEnemyName; private const float ENTRY_HEIGHT = 35f; private static bool refreshScheduled; private TMP_InputField searchInputField; private string lastSearchText = ""; private void ClearSearch() { if ((Object)(object)searchInputField != (Object)null) { searchInputField.text = ""; lastSearchText = ""; FilterEnemyList(lastSearchText); } } private void ScheduleRefresh() { if (!refreshScheduled) { refreshScheduled = true; ClearSearch(); ((MonoBehaviour)this).StartCoroutine(DelayedRefresh()); } } public void RefreshEnemyData() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown Plugin.LogInfo("RefreshEnemyData called"); foreach (Transform item in (Transform)enemyListContent) { Transform val = item; Object.Destroy((Object)(object)((Component)val).gameObject); } enemyEntries.Clear(); enemyConfigs = ConfigBridge.LoadAllEnemyConfigs(); enemyConfigs.Sort((EnemyConfigData a, EnemyConfigData b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase)); Plugin.LogInfo($"Sorted {enemyConfigs.Count} enemies alphabetically"); foreach (EnemyConfigData enemyConfig in enemyConfigs) { CreateEnemyListEntry(enemyConfig); } FilterEnemyList(lastSearchText); selectedEnemyName = null; UpdateConfigPanel(); Plugin.LogInfo($"Loaded {enemyConfigs.Count} enemy configurations"); } private static void PlayConfirmSFX() { MenuManager val = Object.FindObjectOfType<MenuManager>(); if ((Object)(object)val != (Object)null && (Object)(object)val.MenuAudio != (Object)null) { val.PlayConfirmSFX(); } } private static void PlayCancelSFX() { MenuManager val = Object.FindObjectOfType<MenuManager>(); if ((Object)(object)val != (Object)null && (Object)(object)val.MenuAudio != (Object)null) { val.PlayCancelSFX(); } } public static void ToggleConfigMenu() { if (!UIConfiguration.Instance.IsConfigMenuEnabled()) { Plugin.LogWarning("Attempted to open config menu, but it's disabled in settings"); return; } Plugin.LogInfo("ToggleConfigMenu called"); if ((Object)(object)menuPrefab == (Object)null) { CreateMenuPrefab(); } bool activeSelf = menuPrefab.activeSelf; menuPrefab.SetActive(!activeSelf); if (!activeSelf) { Plugin.LogInfo("Menu opened, scheduling refresh"); ConfigMenuManager component = menuPrefab.GetComponent<ConfigMenuManager>(); component.ScheduleRefresh(); } } private IEnumerator DelayedRefresh() { Plugin.LogInfo("Starting delayed refresh"); yield return (object)new WaitForSeconds(0.1f); RefreshEnemyData(); refreshScheduled = false; Plugin.LogInfo("Delayed refresh completed"); } private static void CreateMenuPrefab() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Expected O, but got Unknown //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0315: 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_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_0400: Unknown result type (might be due to invalid IL or missing references) //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_042e: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_05c3: Unknown result type (might be due to invalid IL or missing references) //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_0516: Unknown result type (might be due to invalid IL or missing references) //IL_052d: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Unknown result type (might be due to invalid IL or missing references) //IL_055b: Unknown result type (might be due to invalid IL or missing references) //IL_0603: Unknown result type (might be due to invalid IL or missing references) //IL_061a: Unknown result type (might be due to invalid IL or missing references) //IL_0631: Unknown result type (might be due to invalid IL or missing references) //IL_0648: Unknown result type (might be due to invalid IL or missing references) //IL_065f: Unknown result type (might be due to invalid IL or missing references) //IL_0680: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_06c0: Unknown result type (might be due to invalid IL or missing references) //IL_06d7: Unknown result type (might be due to invalid IL or missing references) //IL_06ee: Unknown result type (might be due to invalid IL or missing references) //IL_0705: Unknown result type (might be due to invalid IL or missing references) //IL_0822: Unknown result type (might be due to invalid IL or missing references) //IL_0754: Unknown result type (might be due to invalid IL or missing references) //IL_076b: Unknown result type (might be due to invalid IL or missing references) //IL_0782: Unknown result type (might be due to invalid IL or missing references) //IL_0799: Unknown result type (might be due to invalid IL or missing references) //IL_07b0: Unknown result type (might be due to invalid IL or missing references) //IL_05a0: Unknown result type (might be due to invalid IL or missing references) //IL_0862: Unknown result type (might be due to invalid IL or missing references) //IL_0879: Unknown result type (might be due to invalid IL or missing references) //IL_0890: Unknown result type (might be due to invalid IL or missing references) //IL_08a7: Unknown result type (might be due to invalid IL or missing references) //IL_08be: Unknown result type (might be due to invalid IL or missing references) //IL_07ff: Unknown result type (might be due to invalid IL or missing references) //IL_098d: Unknown result type (might be due to invalid IL or missing references) //IL_0994: Expected O, but got Unknown //IL_09be: Unknown result type (might be due to invalid IL or missing references) //IL_09d5: Unknown result type (might be due to invalid IL or missing references) //IL_09ec: Unknown result type (might be due to invalid IL or missing references) //IL_0a03: Unknown result type (might be due to invalid IL or missing references) //IL_0a1a: Unknown result type (might be due to invalid IL or missing references) //IL_0a44: Unknown result type (might be due to invalid IL or missing references) //IL_0a54: Unknown result type (might be due to invalid IL or missing references) //IL_0a5b: Expected O, but got Unknown //IL_0a85: Unknown result type (might be due to invalid IL or missing references) //IL_0a9c: Unknown result type (might be due to invalid IL or missing references) //IL_0ab3: Unknown result type (might be due to invalid IL or missing references) //IL_0aca: Unknown result type (might be due to invalid IL or missing references) //IL_0ae1: Unknown result type (might be due to invalid IL or missing references) //IL_0b25: Unknown result type (might be due to invalid IL or missing references) //IL_0b4b: Unknown result type (might be due to invalid IL or missing references) //IL_0b52: Expected O, but got Unknown //IL_0b7c: Unknown result type (might be due to invalid IL or missing references) //IL_0b93: Unknown result type (might be due to invalid IL or missing references) //IL_0baa: Unknown result type (might be due to invalid IL or missing references) //IL_0bc1: Unknown result type (might be due to invalid IL or missing references) //IL_0bf8: Unknown result type (might be due to invalid IL or missing references) //IL_0c15: Unknown result type (might be due to invalid IL or missing references) //IL_0c1c: Expected O, but got Unknown //IL_0c46: Unknown result type (might be due to invalid IL or missing references) //IL_0c5d: Unknown result type (might be due to invalid IL or missing references) //IL_0c74: Unknown result type (might be due to invalid IL or missing references) //IL_0c8b: Unknown result type (might be due to invalid IL or missing references) //IL_0ccf: Unknown result type (might be due to invalid IL or missing references) //IL_0d3a: Unknown result type (might be due to invalid IL or missing references) //IL_0d51: Unknown result type (might be due to invalid IL or missing references) //IL_0d72: Unknown result type (might be due to invalid IL or missing references) //IL_0db2: Unknown result type (might be due to invalid IL or missing references) //IL_0dc9: Unknown result type (might be due to invalid IL or missing references) //IL_0de0: Unknown result type (might be due to invalid IL or missing references) //IL_0df7: Unknown result type (might be due to invalid IL or missing references) //IL_0ea3: Unknown result type (might be due to invalid IL or missing references) //IL_0e50: Unknown result type (might be due to invalid IL or missing references) //IL_0e67: Unknown result type (might be due to invalid IL or missing references) //IL_0e74: Unknown result type (might be due to invalid IL or missing references) //IL_0e81: Unknown result type (might be due to invalid IL or missing references) //IL_0ed6: Unknown result type (might be due to invalid IL or missing references) //IL_0eed: Unknown result type (might be due to invalid IL or missing references) //IL_0f04: Unknown result type (might be due to invalid IL or missing references) //IL_0f1b: Unknown result type (might be due to invalid IL or missing references) //IL_0f54: Unknown result type (might be due to invalid IL or missing references) //IL_0fc7: Unknown result type (might be due to invalid IL or missing references) try { Plugin.LogInfo("Creating menu prefab"); menuPrefab = new GameObject("ECDAConfigMenu"); ConfigMenuManager menuManager = menuPrefab.AddComponent<ConfigMenuManager>(); menuPrefab.SetActive(false); Object.DontDestroyOnLoad((Object)(object)menuPrefab); Canvas val = menuPrefab.AddComponent<Canvas>(); val.renderMode = (RenderMode)0; val.sortingOrder = 1000; CanvasScaler val2 = menuPrefab.AddComponent<CanvasScaler>(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); menuPrefab.AddComponent<GraphicRaycaster>(); GameObject val3 = UIHelper.CreatePanel(menuPrefab.transform, "Overlay", new Vector2(2000f, 2000f)); if ((Object)(object)val3 == (Object)null) { Plugin.LogError("Failed to create overlay panel"); return; } Image component = val3.GetComponent<Image>(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = new Color(0f, 0f, 0f, 0.7f); } GameObject val4 = UIHelper.CreatePanel(menuPrefab.transform, "MainPanel", new Vector2(800f, 600f)); if ((Object)(object)val4 == (Object)null) { Plugin.LogError("Failed to create main panel"); return; } menuManager.menuPanel = val4; Image component2 = val4.GetComponent<Image>(); if ((Object)(object)component2 != (Object)null) { ((Graphic)component2).color = new Color(0.1f, 0.1f, 0.1f, 0.95f); } Transform transform = val4.transform; object obj = <>c.<>9__18_0; if (obj == null) { UnityAction val5 = delegate { PlayCancelSFX(); menuPrefab.SetActive(false); }; <>c.<>9__18_0 = val5; obj = (object)val5; } GameObject val6 = UIHelper.CreateButton(transform, "CloseButton", "X", (UnityAction)obj); if ((Object)(object)val6 != (Object)null) { RectTransform component3 = val6.GetComponent<RectTransform>(); component3.anchorMin = new Vector2(1f, 1f); component3.anchorMax = new Vector2(1f, 1f); component3.pivot = new Vector2(1f, 1f); component3.sizeDelta = new Vector2(40f, 40f); component3.anchoredPosition = new Vector2(-10f, -10f); } GameObject val7 = UIHelper.CreateYesNoSelector(val4.transform, "HideMenuSelector", "Hide Menu:", !UIConfiguration.Instance.IsConfigMenuEnabled(), delegate(bool isHideMenu) { PlayConfirmSFX(); UIConfiguration.Instance.SetConfigMenuEnabled(!isHideMenu); UIConfiguration.Instance.Save(); }); if ((Object)(object)val7 != (Object)null) { RectTransform component4 = val7.GetComponent<RectTransform>(); component4.anchorMin = new Vector2(0f, 1f); component4.anchorMax = new Vector2(0f, 1f); component4.pivot = new Vector2(0f, 1f); component4.sizeDelta = new Vector2(160f, 30f); component4.anchoredPosition = new Vector2(40f, -15f); Transform obj2 = val7.transform.Find("Label"); RectTransform val8 = ((obj2 != null) ? ((Component)obj2).GetComponent<RectTransform>() : null); if ((Object)(object)val8 != (Object)null) { val8.sizeDelta = new Vector2(80f, 30f); } } GameObject val9 = UIHelper.CreateYesNoSelector(val4.transform, "LessLogsSelector", "Less Logs:", !UIConfiguration.Instance.ShouldLogInfo(), delegate(bool isLessLogs) { PlayConfirmSFX(); UIConfiguration.Instance.SetInfoLogsEnabled(!isLessLogs); UIConfiguration.Instance.Save(); }); if ((Object)(object)val9 != (Object)null) { RectTransform component5 = val9.GetComponent<RectTransform>(); component5.anchorMin = new Vector2(0f, 1f); component5.anchorMax = new Vector2(0f, 1f); component5.pivot = new Vector2(0f, 1f); component5.sizeDelta = new Vector2(150f, 30f); component5.anchoredPosition = new Vector2(260f, -15f); Transform obj3 = val9.transform.Find("Label"); RectTransform val10 = ((obj3 != null) ? ((Component)obj3).GetComponent<RectTransform>() : null); if ((Object)(object)val10 != (Object)null) { val10.sizeDelta = new Vector2(70f, 30f); } } GameObject val11 = UIHelper.CreateYesNoSelector(val4.transform, "ShowImagesSelector", "Show Images:", UIConfiguration.Instance.ShouldShowEnemyImages(), delegate(bool showImages) { PlayConfirmSFX(); UIConfiguration.Instance.SetShowEnemyImages(showImages); UIConfiguration.Instance.Save(); ConfigMenuManager component18 = menuPrefab.GetComponent<ConfigMenuManager>(); if ((Object)(object)component18 != (Object)null && !string.IsNullOrEmpty(component18.selectedEnemyName)) { component18.UpdateConfigPanel(); } }); if ((Object)(object)val11 != (Object)null) { RectTransform component6 = val11.GetComponent<RectTransform>(); component6.anchorMin = new Vector2(0f, 1f); component6.anchorMax = new Vector2(0f, 1f); component6.pivot = new Vector2(0f, 1f); component6.sizeDelta = new Vector2(170f, 30f); component6.anchoredPosition = new Vector2(470f, -15f); Transform obj4 = val11.transform.Find("Label"); RectTransform val12 = ((obj4 != null) ? ((Component)obj4).GetComponent<RectTransform>() : null); if ((Object)(object)val12 != (Object)null) { val12.sizeDelta = new Vector2(100f, 30f); } } GameObject val13 = UIHelper.CreatePanel(val4.transform, "ContentPanel", new Vector2(780f, 520f)); if ((Object)(object)val13 == (Object)null) { Plugin.LogError("Failed to create content panel"); return; } RectTransform component7 = val13.GetComponent<RectTransform>(); component7.anchorMin = new Vector2(0f, 0f); component7.anchorMax = new Vector2(1f, 1f); component7.pivot = new Vector2(0.5f, 0.5f); component7.offsetMin = new Vector2(10f, 60f); component7.offsetMax = new Vector2(-10f, -50f); GameObject val14 = UIHelper.CreatePanel(val13.transform, "EnemyListPanel", new Vector2(250f, 520f)); if ((Object)(object)val14 == (Object)null) { Plugin.LogError("Failed to create enemy list panel"); return; } RectTransform component8 = val14.GetComponent<RectTransform>(); component8.anchorMin = new Vector2(0f, 0f); component8.anchorMax = new Vector2(0f, 1f); component8.pivot = new Vector2(0f, 0.5f); component8.sizeDelta = new Vector2(250f, 0f); GameObject val15 = UIHelper.CreateText(val14.transform, "ListLabel", "ENEMIES", (TextAlignmentOptions)514); if ((Object)(object)val15 != (Object)null) { RectTransform component9 = val15.GetComponent<RectTransform>(); component9.anchorMin = new Vector2(0f, 1f); component9.anchorMax = new Vector2(1f, 1f); component9.pivot = new Vector2(0.5f, 1f); component9.sizeDelta = new Vector2(0f, 30f); component9.anchoredPosition = new Vector2(0f, -5f); TextMeshProUGUI component10 = val15.GetComponent<TextMeshProUGUI>(); if ((Object)(object)component10 != (Object)null) { ((TMP_Text)component10).fontSize = 16f; ((TMP_Text)component10).fontStyle = (FontStyles)1; ((Graphic)component10).color = new Color(1f, 0.9f, 0.5f, 1f); } } GameObject val16 = UIHelper.CreateScrollView(val14.transform, "EnemyScrollView", new Vector2(240f, 450f)); if ((Object)(object)val16 == (Object)null) { Plugin.LogError("Failed to create enemy scroll view"); return; } RectTransform component11 = val16.GetComponent<RectTransform>(); component11.anchorMin = new Vector2(0.5f, 0.5f); component11.anchorMax = new Vector2(0.5f, 0.5f); component11.pivot = new Vector2(0.5f, 0.5f); component11.anchoredPosition = new Vector2(0f, -25f); component11.sizeDelta = new Vector2(240f, 430f); ScrollRect component12 = val16.GetComponent<ScrollRect>(); if ((Object)(object)component12 != (Object)null) { component12.scrollSensitivity = 15f; } Transform val17 = val16.transform.Find("Viewport"); if ((Object)(object)val17 == (Object)null) { Plugin.LogError("Viewport not found in scroll view"); return; } Transform val18 = val17.Find("Content"); if ((Object)(object)val18 == (Object)null) { Plugin.LogError("Content not found in viewport"); return; } menuManager.enemyListContent = ((Component)val18).GetComponent<RectTransform>(); if ((Object)(object)menuManager.enemyListContent == (Object)null) { Plugin.LogError("Failed to get RectTransform for enemyListContent"); return; } GameObject val19 = new GameObject("SearchContainer"); val19.transform.SetParent(val14.transform, false); RectTransform val20 = val19.AddComponent<RectTransform>(); val20.anchorMin = new Vector2(0f, 1f); val20.anchorMax = new Vector2(1f, 1f); val20.pivot = new Vector2(0.5f, 1f); val20.sizeDelta = new Vector2(-20f, 30f); val20.anchoredPosition = new Vector2(0f, -35f); Image val21 = val19.AddComponent<Image>(); ((Graphic)val21).color = new Color(0.12f, 0.12f, 0.12f, 1f); GameObject val22 = new GameObject("SearchIcon"); val22.transform.SetParent(val19.transform, false); RectTransform val23 = val22.AddComponent<RectTransform>(); val23.anchorMin = new Vector2(0f, 0.5f); val23.anchorMax = new Vector2(0f, 0.5f); val23.pivot = new Vector2(0.5f, 0.5f); val23.sizeDelta = new Vector2(20f, 20f); val23.anchoredPosition = new Vector2(15f, 0f); TextMeshProUGUI val24 = val22.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val24).text = ">"; ((TMP_Text)val24).fontSize = 16f; ((Graphic)val24).color = new Color(0.7f, 0.7f, 0.7f, 1f); ((TMP_Text)val24).alignment = (TextAlignmentOptions)514; TMP_InputField val25 = val19.AddComponent<TMP_InputField>(); GameObject val26 = new GameObject("Text"); val26.transform.SetParent(val19.transform, false); RectTransform val27 = val26.AddComponent<RectTransform>(); val27.anchorMin = new Vector2(0f, 0f); val27.anchorMax = new Vector2(1f, 1f); val27.offsetMin = new Vector2(35f, 2f); val27.offsetMax = new Vector2(-5f, -2f); TextMeshProUGUI val28 = val26.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val28).fontSize = 14f; ((Graphic)val28).color = new Color(0.9f, 0.9f, 0.9f, 1f); ((TMP_Text)val28).alignment = (TextAlignmentOptions)513; GameObject val29 = new GameObject("Placeholder"); val29.transform.SetParent(val19.transform, false); RectTransform val30 = val29.AddComponent<RectTransform>(); val30.anchorMin = new Vector2(0f, 0f); val30.anchorMax = new Vector2(1f, 1f); val30.offsetMin = new Vector2(35f, 2f); val30.offsetMax = new Vector2(-5f, -2f); TextMeshProUGUI val31 = val29.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val31).text = "Search enemies..."; ((TMP_Text)val31).fontSize = 14f; ((Graphic)val31).color = new Color(0.5f, 0.5f, 0.5f, 1f); ((TMP_Text)val31).alignment = (TextAlignmentOptions)513; val25.textComponent = (TMP_Text)(object)val28; val25.placeholder = (Graphic)(object)val31; val25.text = ""; menuManager.searchInputField = val25; ((UnityEvent<string>)(object)val25.onValueChanged).AddListener((UnityAction<string>)delegate(string searchText) { menuManager.FilterEnemyList(searchText); }); component11.anchoredPosition = new Vector2(0f, -45f); component11.sizeDelta = new Vector2(240f, 430f); GameObject val32 = UIHelper.CreatePanel(val13.transform, "ConfigPanel", new Vector2(500f, 520f)); if ((Object)(object)val32 == (Object)null) { Plugin.LogError("Failed to create config panel"); return; } RectTransform component13 = val32.GetComponent<RectTransform>(); component13.anchorMin = new Vector2(1f, 0f); component13.anchorMax = new Vector2(1f, 1f); component13.pivot = new Vector2(1f, 0.5f); component13.sizeDelta = new Vector2(500f, 0f); menuManager.enemyConfigPanel = val32; GameObject val33 = UIHelper.CreateText(val32.transform, "NoSelection", "Select an enemy from the list", (TextAlignmentOptions)514); if ((Object)(object)val33 != (Object)null) { RectTransform component14 = val33.GetComponent<RectTransform>(); component14.anchorMin = new Vector2(0f, 0f); component14.anchorMax = new Vector2(1f, 1f); component14.offsetMin = Vector2.zero; component14.offsetMax = Vector2.zero; } GameObject val34 = UIHelper.CreatePanel(val4.transform, "MissingEnemiesMessage", new Vector2(780f, 40f)); if ((Object)(object)val34 != (Object)null) { RectTransform component15 = val34.GetComponent<RectTransform>(); component15.anchorMin = new Vector2(0.5f, 0f); component15.anchorMax = new Vector2(0.5f, 0f); component15.pivot = new Vector2(0.5f, 0f); component15.anchoredPosition = new Vector2(0f, 10f); Image component16 = val34.GetComponent<Image>(); if ((Object)(object)component16 != (Object)null) { ((Graphic)component16).color = new Color(0.2f, 0.2f, 0.2f, 0.8f); } GameObject val35 = UIHelper.CreateText(val34.transform, "Text", "If enemies are missing, start a round to generate their entries.", (TextAlignmentOptions)514); if ((Object)(object)val35 != (Object)null) { TextMeshProUGUI component17 = val35.GetComponent<TextMeshProUGUI>(); if ((Object)(object)component17 != (Object)null) { ((TMP_Text)component17).fontSize = 14f; ((Graphic)component17).color = new Color(1f, 0.9f, 0.5f, 1f); } } } EnemyImageLoader.Initialize(); Plugin.LogInfo("Config menu created successfully"); } catch (Exception ex) { Plugin.LogError("Error creating menu prefab: " + ex.Message + "\nStack trace: " + ex.StackTrace); } } private void CreateEnemyListEntry(EnemyConfigData config) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0134: 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_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) GameObject val = UIHelper.CreatePanel((Transform)(object)enemyListContent, "Enemy_" + config.SanitizedName, new Vector2(230f, 35f)); LayoutElement val2 = val.AddComponent<LayoutElement>(); val2.minHeight = 35f; val2.preferredHeight = 35f; val2.flexibleHeight = 0f; GameObject val3 = UIHelper.CreateButton(val.transform, "Button", config.Name, (UnityAction)delegate { SelectEnemy(config.Name); }); RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = new Vector2(5f, 3f); component.offsetMax = new Vector2(-5f, -3f); GameObject val4 = new GameObject("Status"); val4.transform.SetParent(val3.transform, false); RectTransform val5 = val4.AddComponent<RectTransform>(); val5.anchorMin = new Vector2(0f, 0.5f); val5.anchorMax = new Vector2(0f, 0.5f); val5.pivot = new Vector2(0f, 0.5f); val5.sizeDelta = new Vector2(10f, 10f); val5.anchoredPosition = new Vector2(10f, 0f); Image val6 = val4.AddComponent<Image>(); ((Graphic)val6).color = config.GetStatusColor(); Transform val7 = val3.transform.Find("Text"); if ((Object)(object)val7 != (Object)null) { RectTransform component2 = ((Component)val7).GetComponent<RectTransform>(); component2.offsetMin = new Vector2(25f, 0f); TextMeshProUGUI component3 = ((Component)val7).GetComponent<TextMeshProUGUI>(); ((TMP_Text)component3).fontSize = UITheme.NormalFontSize; ((TMP_Text)component3).alignment = (TextAlignmentOptions)513; } enemyEntries[config.Name] = val; } private void FilterEnemyList(string searchText = "") { //IL_0189: Unknown result type (might be due to invalid IL or missing references) searchText = searchText?.ToLower() ?? ""; lastSearchText = searchText; foreach (KeyValuePair<string, GameObject> entry in enemyEntries) { EnemyConfigData enemyConfigData = enemyConfigs.Find((EnemyConfigData c) => c.Name == entry.Key); if (enemyConfigData != null) { bool active = string.IsNullOrEmpty(searchText) || enemyConfigData.Name.ToLower().Contains(searchText); entry.Value.SetActive(active); } } bool flag = enemyEntries.Any((KeyValuePair<string, GameObject> e) => e.Value.activeSelf); Transform obj = ((Component)enemyListContent).transform.Find("NoResults"); GameObject val = ((obj != null) ? ((Component)obj).gameObject : null); if (!flag && (Object)(object)val == (Object)null && !string.IsNullOrEmpty(searchText)) { val = UIHelper.CreateText(((Component)enemyListContent).transform, "NoResults", "No enemies found matching \"" + searchText + "\"", (TextAlignmentOptions)514); TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>(); if ((Object)(object)component != (Object)null) { ((TMP_Text)component).fontSize = 14f; ((Graphic)component).color = new Color(0.7f, 0.7f, 0.7f, 1f); ((TMP_Text)component).alignment = (TextAlignmentOptions)514; } } else if (flag && (Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } else if ((Object)(object)val != (Object)null && string.IsNullOrEmpty(searchText)) { Object.Destroy((Object)(object)val); } } private void SelectEnemy(string enemyName) { PlayConfirmSFX(); selectedEnemyName = enemyName; UpdateConfigPanel(); } private void UpdateConfigPanel() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Expected O, but got Unknown //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Expected O, but got Unknown //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Expected O, but got Unknown //IL_0465: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_04cf: Unknown result type (might be due to invalid IL or missing references) //IL_053b: Unknown result type (might be due to invalid IL or missing references) //IL_059e: Unknown result type (might be due to invalid IL or missing references) //IL_0601: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)enemyConfigPanel == (Object)null) { Plugin.LogError("enemyConfigPanel is null in UpdateConfigPanel"); return; } foreach (Transform item in enemyConfigPanel.transform) { Transform val = item; if ((Object)(object)val != (Object)null && ((Object)val).name != "NoSelection") { Object.Destroy((Object)(object)((Component)val).gameObject); } } Transform val2 = enemyConfigPanel.transform.Find("NoSelection"); if ((Object)(object)val2 != (Object)null) { ((Component)val2).gameObject.SetActive(string.IsNullOrEmpty(selectedEnemyName)); } if (string.IsNullOrEmpty(selectedEnemyName)) { return; } EnemyConfigData config = enemyConfigs.Find((EnemyConfigData c) => c.Name == selectedEnemyName); if (config == null) { return; } GameObject val3 = UIHelper.CreateText(enemyConfigPanel.transform, "Title", config.Name, (TextAlignmentOptions)514); if ((Object)(object)val3 != (Object)null) { RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 1f); component.sizeDelta = new Vector2(0f, 40f); TextMeshProUGUI component2 = val3.GetComponent<TextMeshProUGUI>(); if ((Object)(object)component2 != (Object)null) { ((TMP_Text)component2).fontSize = 22f; ((Graphic)component2).color = new Color(1f, 0.9f, 0.5f, 1f); ((TMP_Text)component2).fontStyle = (FontStyles)1; } } GameObject controlsPanel = UIHelper.CreatePanel(enemyConfigPanel.transform, "ControlsPanel", new Vector2(480f, 400f)); if ((Object)(object)controlsPanel == (Object)null) { Plugin.LogError("Failed to create controls panel"); return; } RectTransform component3 = controlsPanel.GetComponent<RectTransform>(); component3.anchorMin = new Vector2(0.5f, 0.5f); component3.anchorMax = new Vector2(0.5f, 0.5f); component3.pivot = new Vector2(0.5f, 0.5f); component3.anchoredPosition = new Vector2(0f, 30f); component3.sizeDelta = new Vector2(480f, 380f); Image component4 = controlsPanel.GetComponent<Image>(); if ((Object)(object)component4 != (Object)null) { ((Graphic)component4).color = new Color(0f, 0f, 0f, 0f); } VerticalLayoutGroup val4 = controlsPanel.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)val4).padding = new RectOffset(20, 20, 20, 20); ((HorizontalOrVerticalLayoutGroup)val4).spacing = 15f; ((HorizontalOrVerticalLayoutGroup)val4).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val4).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)val4).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val4).childControlHeight = false; ((LayoutGroup)val4).childAlignment = (TextAnchor)0; GameObject val5 = new GameObject("StatusPanel"); val5.transform.SetParent(controlsPanel.transform, false); RectTransform val6 = val5.AddComponent<RectTransform>(); val6.sizeDelta = new Vector2(0f, 30f); GameObject val7 = UIHelper.CreateText(val5.transform, "StatusText", "Current Status: " + config.GetStatusText(), (TextAlignmentOptions)513); TextMeshProUGUI statusTextComp = ((val7 != null) ? val7.GetComponent<TextMeshProUGUI>() : null); if ((Object)(object)statusTextComp != (Object)null) { ((Graphic)statusTextComp).color = config.GetStatusColor(); } GameObject val8 = new GameObject("AutoSavePanel"); val8.transform.SetParent(controlsPanel.transform, false); RectTransform val9 = val8.AddComponent<RectTransform>(); val9.sizeDelta = new Vector2(0f, 25f); GameObject val10 = UIHelper.CreateText(val8.transform, "AutoSaveText", "All changes are saved immediately", (TextAlignmentOptions)513); TextMeshProUGUI val11 = ((val10 != null) ? val10.GetComponent<TextMeshProUGUI>() : null); if ((Object)(object)val11 != (Object)null) { ((TMP_Text)val11).fontSize = 14f; ((Graphic)val11).color = new Color(0.7f, 0.7f, 0.7f, 1f); ((TMP_Text)val11).fontStyle = (FontStyles)2; } GameObject val12 = UIHelper.CreateYesNoSelector(controlsPanel.transform, "EnabledSelector", "Affected by ECDA mod:", config.IsEnabled, delegate(bool isYes) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) config.IsEnabled = isYes; UpdateSelectorEnablements(controlsPanel, isYes); if ((Object)(object)statusTextComp != (Object)null) { ((TMP_Text)statusTextComp).text = "Current Status: " + config.GetStatusText(); ((Graphic)statusTextComp).color = config.GetStatusColor(); } SaveCurrentEnemyConfig(); PlayConfirmSFX(); }); if ((Object)(object)val12 != (Object)null) { RectTransform component5 = val12.GetComponent<RectTransform>(); component5.sizeDelta = new Vector2(0f, 30f); } GameObject val13 = UIHelper.CreateYesNoSelector(controlsPanel.transform, "CanDieSelector", "Can be damaged and killed:", config.CanDie, delegate(bool isYes) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) config.CanDie = isYes; if ((Object)(object)statusTextComp != (Object)null) { ((TMP_Text)statusTextComp).text = "Current Status: " + config.GetStatusText(); ((Graphic)statusTextComp).color = config.GetStatusColor(); } SaveCurrentEnemyConfig(); PlayConfirmSFX(); }); if ((Object)(object)val13 != (Object)null) { RectTransform component6 = val13.GetComponent<RectTransform>(); component6.sizeDelta = new Vector2(0f, 30f); } GameObject val14 = UIHelper.CreateYesNoSelector(controlsPanel.transform, "DespawnSelector", "Despawn after death:", config.ShouldDespawn, delegate(bool isYes) { config.ShouldDespawn = isYes; SaveCurrentEnemyConfig(); PlayConfirmSFX(); }); if ((Object)(object)val14 != (Object)null) { RectTransform component7 = val14.GetComponent<RectTransform>(); component7.sizeDelta = new Vector2(0f, 30f); } GameObject val15 = UIHelper.CreateNumericInputWithArrows(controlsPanel.transform, "HealthInput", "Health:", config.Health, 1, 100, delegate(int newValue) { config.Health = newValue; SaveCurrentEnemyConfig(); PlayConfirmSFX(); }); if ((Object)(object)val15 != (Object)null) { ((Object)val15).name = "HealthPanel"; } UpdateSelectorEnablements(controlsPanel, config.IsEnabled); UpdateEnemyImageVisibility(controlsPanel, config.Name); } catch (Exception ex) { Plugin.LogError("Error in UpdateConfigPanel: " + ex.Message + "\nStack trace: " + ex.StackTrace); } } private void UpdateSelectorEnablements(GameObject controlsPanel, bool isEnabled) { Transform obj = controlsPanel.transform.Find("CanDieSelector"); UIHelper.StateHolder stateHolder = ((obj != null) ? ((Component)obj).GetComponent<UIHelper.StateHolder>() : null); Transform obj2 = controlsPanel.transform.Find("DespawnSelector"); UIHelper.StateHolder stateHolder2 = ((obj2 != null) ? ((Component)obj2).GetComponent<UIHelper.StateHolder>() : null); Transform obj3 = controlsPanel.transform.Find("HealthPanel"); UIHelper.NumericInputState numericInputState = ((obj3 != null) ? ((Component)obj3).GetComponent<UIHelper.NumericInputState>() : null); if ((Object)(object)stateHolder != (Object)null) { EnemyConfigData enemyConfigData = enemyConfigs.Find((EnemyConfigData c) => c.Name == selectedEnemyName); if (enemyConfigData != null) { stateHolder.SetInteractable(isEnabled); stateHolder.UpdateVisualState(enemyConfigData.CanDie); } } if ((Object)(object)stateHolder2 != (Object)null) { EnemyConfigData enemyConfigData2 = enemyConfigs.Find((EnemyConfigData c) => c.Name == selectedEnemyName); if (enemyConfigData2 != null) { stateHolder2.SetInteractable(isEnabled); stateHolder2.UpdateVisualState(enemyConfigData2.ShouldDespawn); } } if ((Object)(object)numericInputState != (Object)null) { EnemyConfigData enemyConfigData3 = enemyConfigs.Find((EnemyConfigData c) => c.Name == selectedEnemyName); if (enemyConfigData3 != null) { numericInputState.SetInteractable(isEnabled); numericInputState.SetValue(enemyConfigData3.Health); } } } private void UpdateEnemyImageVisibility(GameObject controlsPanel, string enemyName) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_00e4: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) try { Transform obj = controlsPanel.transform.Find("ImageContainer"); GameObject val = ((obj != null) ? ((Component)obj).gameObject : null); if ((Object)(object)val == (Object)null && UIConfiguration.Instance.ShouldShowEnemyImages()) { val = new GameObject("ImageContainer"); val.transform.SetParent(controlsPanel.transform, false); val.transform.SetAsLastSibling(); RectTransform val2 = val.AddComponent<RectTransform>(); val2.sizeDelta = new Vector2(0f, 180f); LayoutElement val3 = val.AddComponent<LayoutElement>(); val3.minHeight = 180f; val3.preferredHeight = 180f; val3.flexibleHeight = 0f; GameObject val4 = new GameObject("EnemyImage"); val4.transform.SetParent(val.transform, false); RectTransform val5 = val4.AddComponent<RectTransform>(); val5.anchorMin = new Vector2(0.5f, 0.5f); val5.anchorMax = new Vector2(0.5f, 0.5f); val5.pivot = new Vector2(0.5f, 0.5f); val5.sizeDelta = new Vector2(170f, 170f); Image val6 = val4.AddComponent<Image>(); val6.preserveAspect = true; } if (!((Object)(object)val != (Object)null)) { return; } if (UIConfiguration.Instance.ShouldShowEnemyImages() && !string.IsNullOrEmpty(enemyName)) { Texture2D enemyTexture = EnemyImageLoader.GetEnemyTexture(enemyName); if ((Object)(object)enemyTexture != (Object)null) { val.SetActive(true); Transform val7 = val.transform.Find("EnemyImage"); if ((Object)(object)val7 != (Object)null) { Image component = ((Component)val7).GetComponent<Image>(); if ((Object)(object)component != (Object)null) { Sprite sprite = Sprite.Create(enemyTexture, new Rect(0f, 0f, (float)((Texture)enemyTexture).width, (float)((Texture)enemyTexture).height), new Vector2(0.5f, 0.5f)); component.sprite = sprite; component.preserveAspect = true; } } } else { val.SetActive(false); } } else { val.SetActive(false); } } catch (Exception ex) { Plugin.Log.LogError((object)("Error updating enemy image visibility: " + ex.Message)); } } private void SaveCurrentEnemyConfig() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (s