Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MonsterLabZBalance v0.1.2
MonsterLabZBalance.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("MonsterLabZBalance")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: AssemblyInformationalVersion("0.1.2")] [assembly: AssemblyProduct("MonsterLabZBalance")] [assembly: AssemblyTitle("MonsterLabZBalance")] [assembly: AssemblyVersion("0.1.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MonsterLabZBalance { [BepInPlugin("xnolde.monsterlabzbalance", "MonsterLabZ Balance", "0.1.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "xnolde.monsterlabzbalance"; public const string PluginName = "MonsterLabZ Balance"; public const string PluginVersion = "0.1.2"; internal static ManualLogSource Log; private static readonly WaitForSeconds ScenePollDelay = new WaitForSeconds(1f); private Harmony _harmony; private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("xnolde.monsterlabzbalance"); _harmony.PatchAll(); ((MonoBehaviour)this).StartCoroutine(SceneWatcher()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"MonsterLabZ Balance 0.1.2 loaded. Runtime world-spawn guard installed."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private IEnumerator SceneWatcher() { ZNetScene configuredScene = null; bool draugrCargoConfigured = false; while (true) { Balance.EnsureLocalization(); ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { configuredScene = null; draugrCargoConfigured = false; Balance.ResetRuntimeGuardLog(); yield return ScenePollDelay; continue; } if ((Object)(object)configuredScene != (Object)(object)instance && Balance.IsReady(instance)) { Balance.ApplyPrefabChanges(instance); configuredScene = instance; draugrCargoConfigured = false; Balance.ResetRuntimeGuardLog(); } if ((Object)(object)configuredScene == (Object)(object)instance && !draugrCargoConfigured) { draugrCargoConfigured = Balance.ConfigureDraugrCargo(instance); } yield return ScenePollDelay; } } } internal static class Balance { private sealed class ContainerDropSpec { internal readonly string Prefab; internal readonly int Min; internal readonly int Max; internal readonly float Weight; internal ContainerDropSpec(string prefab, int min, int max, float weight = 1f) { Prefab = prefab; Min = min; Max = max; Weight = weight; } } private sealed class SpawnSystemState { } private const string PurpleNameKey = "mlzb_mycotic_greydwarf"; private static readonly ConditionalWeakTable<SpawnSystem, SpawnSystemState> ConfiguredSpawnSystems = new ConditionalWeakTable<SpawnSystem, SpawnSystemState>(); private static readonly string[] RequiredScenePrefabs = new string[7] { "Greydwarf_Purple_Shroom", "DwarfGoblin", "DwarfGoblinShaman", "DwarfGoblinLoot", "ML_GoblinShip", "ML_DraugrShip", "DeepSea_Serpent" }; private static readonly string[] RequiredItemPrefabs = new string[11] { "Greydwarf_elite_attack", "DeepSea_Serpent_Cast", "MushroomBlue", "Mushroom", "Coins", "Amber", "Ruby", "SerpentMeat", "SerpentScale", "FishRaw", "TrophyDeepSeaSerpent" }; private static readonly ContainerDropSpec[] DraugrCargoSpecs = new ContainerDropSpec[4] { new ContainerDropSpec("BoarJerky", 3, 6), new ContainerDropSpec("IronScrap", 3, 6), new ContainerDropSpec("AmberPearl", 4, 6), new ContainerDropSpec("RottenMeat", 2, 4) }; private static Type LocalizationType; private static FieldInfo LocalizationInstanceField; private static PropertyInfo LocalizationInstanceProperty; private static MethodInfo LocalizationAddWordMethod; private static MethodInfo LocalizationLanguageMethod; private static object LocalizedInstance; private static string LocalizedLanguage; private static bool RuntimeGuardCorrectionLogged; private static readonly HashSet<string> MonsterLabZCreaturePrefabs = new HashSet<string>(StringComparer.Ordinal) { "BlackSpider", "BrownSpider", "BrownSpider_Spawn", "ChaosSkeletonWarrior", "ChaosSkeletonWarriorNoFX", "DeepSea_Serpent", "DeepSea_Serpent_Flying", "DwarfGoblin", "DwarfGoblinLoot", "DwarfGoblinShaman", "DwarfGoblinShaman_Boat", "DwarfGoblin_Boat", "DwarfGoblin_NoAttack", "DwarfGoblin_Spawn", "EvilShadow", "FireGolem", "FireSkeletonWarrior", "FireSkeletonWarriorNoFx", "ForestSpider", "FrigidSpider", "FrostSpider", "GhostWarrior", "GreenSpider", "Green_Butterfly", "Greydwarf_Purple", "Greydwarf_Purple_Shroom", "IceGolem", "IceSkeletonWarrior", "IceSkeletonWarriorNoFx", "IceSkeletonWarriorT6", "KrakenLD", "Kraken_Blob", "MLabz1_DummyTest", "MLNPC_Female0", "MLNPC_Female1", "MLNPC_Male0", "MLNPC_Male1", "MLNPC_Male2", "MLNPC_Male3", "MLNPC_Svartalfar0", "ML_AshHatchling", "ML_AshHuldra", "ML_AshHuldraQueen1", "ML_AshHuldraQueen2", "ML_AshHuldraQueen3", "ML_BlueMistile_Aggressive", "ML_BlueMistile_Passive", "ML_DraugrBomber_Boat", "ML_DraugrShip", "ML_Draugr_Boat", "ML_Draugr_Spawn", "ML_FrostHatchling", "ML_FrostHatchling_Spawn", "ML_GoblinShip", "ML_HailStorm", "ML_JellyFish0", "ML_LavaRoot", "ML_LightningStorm", "ML_MeteorShower", "ML_RedMistile_Aggressive", "ML_RedMistile_Passive", "ML_Surtling", "ML_Sword_Frigga_Spider_1", "ML_Sword_Frigga_Spider_2", "ML_Sword_Frigga_Spider_3_Cold", "ML_Sword_Frigga_Spider_3_Fire", "ML_Sword_Frigga_Spider_3_Light", "Molluscan", "MolluscanLand", "NightmareDragon", "NightmareDragonEV", "NormalGhostWarrior", "NormalSkeletonWarrior", "ObsidianGolem", "PoisonSkeletonWarrior", "PoisonSkeletonWarriorNoFx", "Rainbow_Butterfly", "Silkworm_Butterfly", "SpiderBoss_Egg", "Spider_Boss", "Spider_Hatchling", "Surtling_Spawn", "Surtr", "TanSpider", "TreeSpider", "TreeSpider_Spawn" }; internal static bool IsReady(ZNetScene scene) { if ((Object)(object)scene == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) { return false; } string[] requiredScenePrefabs = RequiredScenePrefabs; foreach (string text in requiredScenePrefabs) { if ((Object)(object)scene.GetPrefab(text) == (Object)null) { return false; } } requiredScenePrefabs = RequiredItemPrefabs; foreach (string prefabName in requiredScenePrefabs) { if ((Object)(object)FindPrefab(scene, prefabName) == (Object)null) { return false; } } return true; } internal static void ApplyPrefabChanges(ZNetScene scene) { ConfigurePurple(scene); ConfigureDwarfGoblin(scene); ConfigureDwarfGoblinShaman(scene); ConfigureDwarfGoblinLoot(scene); ConfigureGoblinShip(scene); ConfigureDraugrShip(scene); ConfigureDeepSeaSerpent(scene); Plugin.Log.LogInfo((object)"MonsterLabZ curated prefab balance applied."); } internal static void EnsureLocalization() { object localizationInstance = GetLocalizationInstance(); if (localizationInstance == null) { return; } string selectedLanguage = GetSelectedLanguage(localizationInstance); if (localizationInstance == LocalizedInstance && string.Equals(selectedLanguage, LocalizedLanguage, StringComparison.OrdinalIgnoreCase)) { return; } string text = ((selectedLanguage.IndexOf("Spanish", StringComparison.OrdinalIgnoreCase) >= 0) ? "Grisucio micótico" : "Mycotic Greydwarf"); try { LocalizationAddWordMethod?.Invoke(localizationInstance, new object[2] { "mlzb_mycotic_greydwarf", text }); LocalizedInstance = localizationInstance; LocalizedLanguage = selectedLanguage; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not register Purple Shroom localization: " + ex.Message)); } } private static object GetLocalizationInstance() { try { if (LocalizationType == null) { ResolveLocalizationMetadata(); } if (LocalizationType == null) { return null; } object obj = LocalizationInstanceField?.GetValue(null); if (obj != null) { return obj; } return LocalizationInstanceProperty?.GetValue(null, null); } catch { return null; } } private static void ResolveLocalizationMetadata() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("Localization", throwOnError: false); if (!(type == null)) { LocalizationType = type; LocalizationInstanceField = type.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); LocalizationInstanceProperty = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); LocalizationAddWordMethod = type.GetMethod("AddWord", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(string), typeof(string) }, null); LocalizationLanguageMethod = type.GetMethod("GetSelectedLanguage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); break; } } } private static string GetSelectedLanguage(object localization) { try { return (LocalizationLanguageMethod?.Invoke(localization, null) as string) ?? "English"; } catch { return "English"; } } private static GameObject FindPrefab(ZNetScene scene, string prefabName) { if ((Object)(object)ObjectDB.instance != (Object)null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName); if ((Object)(object)itemPrefab != (Object)null) { return itemPrefab; } } if (!((Object)(object)scene != (Object)null)) { return null; } return scene.GetPrefab(prefabName); } private static Character GetCharacter(ZNetScene scene, string prefabName) { GameObject prefab = scene.GetPrefab(prefabName); if ((Object)(object)prefab == (Object)null) { Plugin.Log.LogWarning((object)("Prefab '" + prefabName + "' not found.")); return null; } Character component = prefab.GetComponent<Character>(); if ((Object)(object)component == (Object)null) { Plugin.Log.LogWarning((object)("Prefab '" + prefabName + "' has no Character component.")); } return component; } private static void SetHealth(ZNetScene scene, string prefabName, float health) { Character character = GetCharacter(scene, prefabName); if ((Object)(object)character != (Object)null) { character.m_health = health; } } private static void ConfigurePurple(ZNetScene scene) { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010b: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown GameObject prefab = scene.GetPrefab("Greydwarf_Purple_Shroom"); if ((Object)(object)prefab == (Object)null) { return; } Character component = prefab.GetComponent<Character>(); if ((Object)(object)component != (Object)null) { component.m_health = 150f; component.m_name = "$mlzb_mycotic_greydwarf"; } Humanoid component2 = prefab.GetComponent<Humanoid>(); GameObject val = FindPrefab(scene, "Greydwarf_elite_attack"); int num = 0; if ((Object)(object)component2 != (Object)null && (Object)(object)val != (Object)null) { num += ReplaceAttackReference(component2.m_defaultItems, "Greydwarf_attack", val); num += ReplaceAttackReference(component2.m_randomWeapon, "Greydwarf_attack", val); if (component2.m_randomSets != null) { ItemSet[] randomSets = component2.m_randomSets; foreach (ItemSet val2 in randomSets) { if (val2?.m_items != null) { num += ReplaceAttackReference(val2.m_items, "Greydwarf_attack", val); } } } } SetCharacterDrops(scene, prefab, new Drop { m_prefab = FindPrefab(scene, "MushroomBlue"), m_amountMin = 1, m_amountMax = 2, m_chance = 1f, m_onePerPlayer = false, m_levelMultiplier = false }, new Drop { m_prefab = FindPrefab(scene, "Mushroom"), m_amountMin = 1, m_amountMax = 2, m_chance = 1f, m_onePerPlayer = false, m_levelMultiplier = false }); Plugin.Log.LogInfo((object)("Greydwarf_Purple_Shroom: Grisucio micótico / Mycotic Greydwarf, HP 150, " + $"Brute melee replacements={num}, MushroomBlue 1-2, Mushroom 1-2.")); } private static void ConfigureDwarfGoblin(ZNetScene scene) { GameObject prefab = scene.GetPrefab("DwarfGoblin"); if (!((Object)(object)prefab == (Object)null)) { SetHealth(scene, "DwarfGoblin", 80f); SetCharacterDrops(scene, prefab, MakeDrop(scene, "Coins", 3, 5, 1f)); Plugin.Log.LogInfo((object)"DwarfGoblin: HP 80, Coins 3-5."); } } private static void ConfigureDwarfGoblinShaman(ZNetScene scene) { GameObject prefab = scene.GetPrefab("DwarfGoblinShaman"); if (!((Object)(object)prefab == (Object)null)) { SetHealth(scene, "DwarfGoblinShaman", 60f); SetCharacterDrops(scene, prefab, MakeDrop(scene, "Coins", 4, 6, 1f)); Plugin.Log.LogInfo((object)"DwarfGoblinShaman: HP 60, Coins 4-6; original attacks preserved."); } } private static void ConfigureDwarfGoblinLoot(ZNetScene scene) { GameObject prefab = scene.GetPrefab("DwarfGoblinLoot"); if (!((Object)(object)prefab == (Object)null)) { SetHealth(scene, "DwarfGoblinLoot", 60f); SetCharacterDrops(scene, prefab, MakeDrop(scene, "Coins", 5, 8, 1f), MakeDrop(scene, "Amber", 2, 4, 1f), MakeDrop(scene, "Ruby", 1, 3, 1f)); Plugin.Log.LogInfo((object)"DwarfGoblinLoot: HP 60, Coins 5-8, Amber 2-4, Ruby 1-3; original AI preserved."); } } private static void ConfigureGoblinShip(ZNetScene scene) { GameObject prefab = scene.GetPrefab("ML_GoblinShip"); if (!((Object)(object)prefab == (Object)null)) { SetHealth(scene, "ML_GoblinShip", 800f); FilterShipDrops(prefab, "ML_GoblinShip_Cargo", includeDwarfNoAttack: true); Plugin.Log.LogInfo((object)"ML_GoblinShip: HP 800; structural material drops removed; cargo/crew drops preserved."); } } private static void ConfigureDraugrShip(ZNetScene scene) { GameObject prefab = scene.GetPrefab("ML_DraugrShip"); if (!((Object)(object)prefab == (Object)null)) { SetHealth(scene, "ML_DraugrShip", 500f); NormalizeDropAmount(prefab, "ML_DraugrShip_Cargo", 3, 5); Plugin.Log.LogInfo((object)"ML_DraugrShip: HP 500; original hull drops preserved; cargo count normalized to 3-5."); } } private static void ConfigureDeepSeaSerpent(ZNetScene scene) { GameObject prefab = scene.GetPrefab("DeepSea_Serpent"); if (!((Object)(object)prefab == (Object)null)) { SetHealth(scene, "DeepSea_Serpent", 800f); GameObject val = FindPrefab(scene, "DeepSea_Serpent_Cast"); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null); if (val2?.m_itemData?.m_shared != null) { val2.m_itemData.m_shared.m_damages.m_blunt = 35f; val2.m_itemData.m_shared.m_damages.m_fire = 40f; } else { Plugin.Log.LogWarning((object)"DeepSea_Serpent_Cast could not be adjusted."); } SetCharacterDrops(scene, prefab, MakeDrop(scene, "SerpentMeat", 4, 6, 1f), MakeDrop(scene, "SerpentScale", 8, 12, 1f), MakeDrop(scene, "FishRaw", 2, 4, 1f), MakeDrop(scene, "TrophyDeepSeaSerpent", 1, 1, 0.125f)); Plugin.Log.LogInfo((object)"DeepSea_Serpent: HP 800; Cast 35 blunt + 40 fire; loot 4-6 SerpentMeat, 8-12 SerpentScale, 2-4 FishRaw, TrophyDeepSeaSerpent 12.5%. Other attacks/resistances preserved."); } } private static Drop MakeDrop(ZNetScene scene, string item, int min, int max, float chance) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return new Drop { m_prefab = FindPrefab(scene, item), m_amountMin = min, m_amountMax = max, m_chance = chance, m_onePerPlayer = false, m_levelMultiplier = false }; } private static void SetCharacterDrops(ZNetScene scene, GameObject prefab, params Drop[] desiredDrops) { if ((Object)(object)prefab == (Object)null) { return; } if (desiredDrops.Any((Drop x) => x == null || (Object)(object)x.m_prefab == (Object)null)) { Plugin.Log.LogWarning((object)(((Object)prefab).name + ": one or more desired drop prefabs were not found; drops left unchanged.")); return; } CharacterDrop val = prefab.GetComponent<CharacterDrop>(); if ((Object)(object)val == (Object)null) { val = prefab.AddComponent<CharacterDrop>(); } val.m_drops = desiredDrops.ToList(); } private static void FilterShipDrops(GameObject ship, string cargoName, bool includeDwarfNoAttack) { CharacterDrop component = ship.GetComponent<CharacterDrop>(); if (component?.m_drops != null) { component.m_drops.RemoveAll(delegate(Drop drop) { string text = (((Object)(object)drop?.m_prefab != (Object)null) ? ((Object)drop.m_prefab).name : ""); return text == "DeerHide" || text == "ElderBark" || text == "FineWood"; }); NormalizeDropAmount(ship, cargoName, 3, 5); if (includeDwarfNoAttack) { NormalizeDropAmount(ship, "DwarfGoblin_NoAttack", 3, 5); } } } private static void NormalizeDropAmount(GameObject prefab, string dropPrefabName, int min, int max) { CharacterDrop val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<CharacterDrop>() : null); if (val?.m_drops == null) { return; } foreach (Drop drop in val.m_drops) { if (!((Object)(object)drop?.m_prefab == (Object)null) && !(((Object)drop.m_prefab).name != dropPrefabName)) { drop.m_amountMin = min; drop.m_amountMax = max; drop.m_chance = 1f; drop.m_levelMultiplier = false; } } } internal static void ResetRuntimeGuardLog() { RuntimeGuardCorrectionLogged = false; } internal static void EnforceWorldSpawnWhitelist(List<SpawnData> spawners) { if (spawners == null) { return; } bool flag = false; foreach (SpawnData spawner in spawners) { if (!((Object)(object)spawner?.m_prefab == (Object)null)) { string text = CleanPrefabName(((Object)spawner.m_prefab).name); if (MonsterLabZCreaturePrefabs.Contains(text) && !ConfigureWhitelistedSpawn(spawner, text) && spawner.m_enabled) { spawner.m_enabled = false; flag = true; } } } if (flag && !RuntimeGuardCorrectionLogged) { RuntimeGuardCorrectionLogged = true; Plugin.Log.LogInfo((object)"Runtime guard corrected non-curated MonsterLabZ world-spawn state."); } } internal static bool ConfigureDraugrCargo(ZNetScene scene) { GameObject prefab = scene.GetPrefab("ML_DraugrShip_Cargo"); if ((Object)(object)prefab == (Object)null) { return false; } Container val = prefab.GetComponent<Container>() ?? prefab.GetComponentInChildren<Container>(true); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"ML_DraugrShip_Cargo has no Container component."); return false; } ContainerDropSpec[] draugrCargoSpecs = DraugrCargoSpecs; foreach (ContainerDropSpec containerDropSpec in draugrCargoSpecs) { if ((Object)(object)FindPrefab(scene, containerDropSpec.Prefab) == (Object)null) { return false; } } try { object obj = FindField(((object)val).GetType(), "m_defaultItems")?.GetValue(val); if (obj == null) { Plugin.Log.LogWarning((object)"ML_DraugrShip_Cargo default drop table not found."); return false; } if (!(FindField(obj.GetType(), "m_drops")?.GetValue(obj) is IList list)) { Plugin.Log.LogWarning((object)"ML_DraugrShip_Cargo drop list not found."); return false; } Type listElementType = GetListElementType(list.GetType()); if (listElementType == null) { Plugin.Log.LogWarning((object)"ML_DraugrShip_Cargo drop element type not found."); return false; } list.Clear(); draugrCargoSpecs = DraugrCargoSpecs; foreach (ContainerDropSpec containerDropSpec2 in draugrCargoSpecs) { object obj2 = Activator.CreateInstance(listElementType); SetField(obj2, "m_item", FindPrefab(scene, containerDropSpec2.Prefab)); SetField(obj2, "m_stackMin", containerDropSpec2.Min); SetField(obj2, "m_stackMax", containerDropSpec2.Max); SetFieldIfPresent(obj2, "m_weight", containerDropSpec2.Weight); SetFieldIfPresent(obj2, "m_dontScale", true); list.Add(obj2); } SetFieldIfPresent(obj, "m_dropMin", 1); SetFieldIfPresent(obj, "m_dropMax", 3); Plugin.Log.LogInfo((object)"ML_DraugrShip_Cargo: 1-3 entries from BoarJerky 3-6, IronScrap 3-6, AmberPearl 4-6, RottenMeat 2-4. Processed Iron and Entrails removed."); return true; } catch (Exception arg) { Plugin.Log.LogWarning((object)$"ML_DraugrShip_Cargo could not be configured: {arg}"); return false; } } internal static void EnsureSpawnSystemConfigured(SpawnSystem spawnSystem) { if (!((Object)(object)spawnSystem == (Object)null) && !ConfiguredSpawnSystems.TryGetValue(spawnSystem, out var _) && ConfigureSpawnSystem(spawnSystem, ZNetScene.instance)) { ConfiguredSpawnSystems.Add(spawnSystem, new SpawnSystemState()); } } private static bool ConfigureSpawnSystem(SpawnSystem spawnSystem, ZNetScene scene) { if (spawnSystem?.m_spawnLists == null || spawnSystem.m_spawnLists.Count == 0 || (Object)(object)scene == (Object)null) { return false; } bool flag = false; foreach (SpawnSystemList spawnList in spawnSystem.m_spawnLists) { if (spawnList?.m_spawners == null) { continue; } foreach (SpawnData spawner in spawnList.m_spawners) { if ((Object)(object)spawner?.m_prefab == (Object)null) { continue; } string text = CleanPrefabName(((Object)spawner.m_prefab).name); if (MonsterLabZCreaturePrefabs.Contains(text)) { if (text == "Greydwarf_Purple_Shroom") { flag = true; } if (!ConfigureWhitelistedSpawn(spawner, text)) { spawner.m_enabled = false; } } } } if (!flag && !EnsurePurpleSpawn(spawnSystem, scene)) { return false; } return true; } private static bool ConfigureWhitelistedSpawn(SpawnData spawn, string prefabName) { switch (prefabName) { case "Greydwarf_Purple_Shroom": ConfigureLandSpawn(spawn, (Biome)8, (BiomeArea)3, day: false, night: true, 1, 1, 600f, 5f, 1, 0f, 1000f); return true; case "DwarfGoblin": ConfigureLandSpawn(spawn, (Biome)16, (BiomeArea)3, day: true, night: true, 3, 4, 450f, 15f, 5, 1f, 1000f); return true; case "DwarfGoblinShaman": ConfigureLandSpawn(spawn, (Biome)16, (BiomeArea)3, day: true, night: true, 1, 2, 450f, 10f, 2, 1f, 1000f); return true; case "DwarfGoblinLoot": ConfigureLandSpawn(spawn, (Biome)16, (BiomeArea)3, day: true, night: false, 1, 1, 300f, 5f, 1, 1f, 1000f); return true; case "ML_GoblinShip": ConfigureSeaSpawn(spawn, (Biome)16, (BiomeArea)1, day: true, night: false, "defeated_dragon", 15f, 20f, 1000f, 10f, 1); return true; case "ML_DraugrShip": ConfigureSeaSpawn(spawn, (Biome)8, (BiomeArea)1, day: false, night: true, "defeated_gdking", 15f, 20f, 1000f, 10f, 1, "Misty"); return true; case "DeepSea_Serpent": ConfigureSeaSpawn(spawn, (Biome)256, (BiomeArea)2, day: false, night: true, "defeated_bonemass", 20f, 30f, 1000f, 5f, 1, null, -10f, -10f); return true; default: return false; } } private static void ConfigureLandSpawn(SpawnData spawn, Biome biome, BiomeArea area, bool day, bool night, int groupMin, int groupMax, float interval, float chance, int maxSpawned, float minAltitude, float maxAltitude) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) spawn.m_enabled = true; spawn.m_biome = biome; spawn.m_biomeArea = area; spawn.m_spawnAtDay = day; spawn.m_spawnAtNight = night; spawn.m_requiredGlobalKey = ""; SetRequiredEnvironment(spawn, null); spawn.m_groupSizeMin = groupMin; spawn.m_groupSizeMax = groupMax; spawn.m_groupRadius = 3f; spawn.m_spawnInterval = interval; spawn.m_spawnChance = chance; spawn.m_maxSpawned = maxSpawned; spawn.m_spawnDistance = 10f; spawn.m_spawnRadiusMin = 0f; spawn.m_spawnRadiusMax = 0f; spawn.m_minAltitude = minAltitude; spawn.m_maxAltitude = maxAltitude; spawn.m_minTilt = 0f; spawn.m_maxTilt = 35f; spawn.m_inForest = true; spawn.m_outsideForest = true; spawn.m_minOceanDepth = 0f; spawn.m_maxOceanDepth = 0f; spawn.m_huntPlayer = false; spawn.m_groundOffset = 0.5f; DisableStars(spawn); } private static void ConfigureSeaSpawn(SpawnData spawn, Biome biome, BiomeArea area, bool day, bool night, string globalKey, float minDepth, float maxDepth, float interval, float chance, int maxSpawned, string requiredEnvironment = null, float groundOffset = 20f, float maxAltitude = 0f) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) spawn.m_enabled = true; spawn.m_biome = biome; spawn.m_biomeArea = area; spawn.m_spawnAtDay = day; spawn.m_spawnAtNight = night; spawn.m_requiredGlobalKey = globalKey ?? ""; SetRequiredEnvironment(spawn, requiredEnvironment); spawn.m_groupSizeMin = 1; spawn.m_groupSizeMax = 1; spawn.m_groupRadius = 3f; spawn.m_spawnInterval = interval; spawn.m_spawnChance = chance; spawn.m_maxSpawned = maxSpawned; spawn.m_spawnDistance = 10f; spawn.m_spawnRadiusMin = 0f; spawn.m_spawnRadiusMax = 0f; spawn.m_minAltitude = -1000f; spawn.m_maxAltitude = maxAltitude; spawn.m_minTilt = 0f; spawn.m_maxTilt = 35f; spawn.m_inForest = true; spawn.m_outsideForest = true; spawn.m_minOceanDepth = minDepth; spawn.m_maxOceanDepth = maxDepth; spawn.m_huntPlayer = false; spawn.m_groundOffset = groundOffset; DisableStars(spawn); } private static void SetRequiredEnvironment(SpawnData spawn, string environment) { List<string> list = spawn.m_requiredEnvironments; if (list == null) { list = (spawn.m_requiredEnvironments = new List<string>((!string.IsNullOrEmpty(environment)) ? 1 : 0)); } if (string.IsNullOrEmpty(environment)) { if (list.Count != 0) { list.Clear(); } } else if (list.Count != 1 || !(list[0] == environment)) { list.Clear(); list.Add(environment); } } private static void DisableStars(SpawnData spawn) { spawn.m_minLevel = 1; spawn.m_maxLevel = 1; spawn.m_overrideLevelupChance = 0f; } private static bool EnsurePurpleSpawn(SpawnSystem spawnSystem, ZNetScene scene) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown GameObject prefab = scene.GetPrefab("Greydwarf_Purple_Shroom"); if ((Object)(object)prefab == (Object)null) { return false; } foreach (SpawnSystemList spawnList in spawnSystem.m_spawnLists) { if (spawnList?.m_spawners != null) { SpawnData val = ((IEnumerable<SpawnData>)spawnList.m_spawners).FirstOrDefault((Func<SpawnData, bool>)((SpawnData x) => (Object)(object)x?.m_prefab != (Object)null && CleanPrefabName(((Object)x.m_prefab).name) == "Greydwarf_Purple_Shroom")); if (val != null) { ConfigureWhitelistedSpawn(val, "Greydwarf_Purple_Shroom"); return true; } } } SpawnSystemList val2 = ((IEnumerable<SpawnSystemList>)spawnSystem.m_spawnLists).FirstOrDefault((Func<SpawnSystemList, bool>)((SpawnSystemList x) => (Object)(object)x != (Object)null && x.m_spawners != null)); if ((Object)(object)val2 == (Object)null) { return false; } SpawnData val3 = new SpawnData { m_name = "MLZB_Purple_Shroom", m_prefab = prefab }; ConfigureWhitelistedSpawn(val3, "Greydwarf_Purple_Shroom"); val2.m_spawners.Add(val3); return true; } private static int ReplaceAttackReference(GameObject[] items, string oldName, GameObject replacement) { if (items == null) { return 0; } int num = 0; for (int i = 0; i < items.Length; i++) { if ((Object)(object)items[i] != (Object)null && CleanPrefabName(((Object)items[i]).name) == oldName) { items[i] = replacement; num++; } } return num; } private static string CleanPrefabName(string name) { if (string.IsNullOrEmpty(name)) { return ""; } if (!name.EndsWith("(Clone)", StringComparison.Ordinal)) { return name; } return name.Substring(0, name.Length - "(Clone)".Length); } private static FieldInfo FindField(Type type, string fieldName) { while (type != null) { FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } type = type.BaseType; } return null; } private static void SetField(object target, string fieldName, object value) { FieldInfo fieldInfo = FindField(target.GetType(), fieldName); if (fieldInfo == null) { throw new MissingFieldException(target.GetType().FullName, fieldName); } fieldInfo.SetValue(target, value); } private static void SetFieldIfPresent(object target, string fieldName, object value) { FindField(target.GetType(), fieldName)?.SetValue(target, value); } private static Type GetListElementType(Type listType) { if (listType.IsGenericType) { return listType.GetGenericArguments().FirstOrDefault(); } Type[] interfaces = listType.GetInterfaces(); foreach (Type type in interfaces) { if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IList<>)) { return type.GetGenericArguments()[0]; } } return null; } } [HarmonyPatch] internal static class SpawnSystemUpdateSpawnListPatch { private static MethodBase TargetMethod() { MethodInfo methodInfo = AccessTools.Method(typeof(SpawnSystem), "UpdateSpawnList", new Type[4] { typeof(List<SpawnData>), typeof(DateTime), typeof(bool), typeof(string) }, (Type[])null); if (methodInfo == null) { throw new MissingMethodException("SpawnSystem.UpdateSpawnList(List<SpawnData>, DateTime, bool, string) was not found."); } return methodInfo; } [HarmonyPrefix] [HarmonyPriority(0)] private static void Prefix(SpawnSystem __instance, List<SpawnData> __0, bool __2) { if (!__2) { Balance.EnsureSpawnSystemConfigured(__instance); Balance.EnforceWorldSpawnWhitelist(__0); } } } }