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 MonsterScaler v1.0.0
plugins/MonsterScaler.dll
Decompiled 5 months agousing System; 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.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using REPOLib; 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("MonsterScaler")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("MonsterScaler")] [assembly: AssemblyTitle("MonsterScaler")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 MonsterScaler { [BepInPlugin("com.PxntxrezStudio.monsterscaler", "MonsterScaler", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class MonsterScalerPlugin : BaseUnityPlugin { public const string PLUGIN_GUID = "com.PxntxrezStudio.monsterscaler"; public const string PLUGIN_NAME = "MonsterScaler"; public const string PLUGIN_VERSION = "1.0.0"; internal static MonsterScalerPlugin Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static Harmony Harmony { get; set; } internal static ConfigManager ConfigManager { get; private set; } private void Awake() { Instance = this; Logger = ((BaseUnityPlugin)this).Logger; ConfigManager = new ConfigManager(((BaseUnityPlugin)this).Config); Patch(); Logger.LogInfo((object)"MonsterScaler v1.0.0 loaded!"); } internal static void Patch() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown if (Harmony == null) { Harmony = new Harmony("com.PxntxrezStudio.monsterscaler"); } Logger.LogDebug((object)"Patching..."); Harmony.PatchAll(); Logger.LogDebug((object)"Patching complete!"); } internal static void Unpatch() { Harmony harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } public class ConfigManager { private ConfigFile _configFile; public ConfigEntry<bool> EnableSpawning { get; private set; } public ConfigEntry<int> MonsterMultiplier { get; private set; } public ConfigEntry<bool> EnableTier1 { get; private set; } public ConfigEntry<bool> EnableTier2 { get; private set; } public ConfigEntry<bool> EnableTier3 { get; private set; } public Dictionary<string, ConfigEntry<bool>> MonsterToggles { get; private set; } public ConfigManager(ConfigFile configFile) { _configFile = configFile; MonsterToggles = new Dictionary<string, ConfigEntry<bool>>(); SetupConfig(); } private void SetupConfig() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown EnableSpawning = _configFile.Bind<bool>("General", "EnableSpawning", true, "Enable or disable all monster spawning"); MonsterMultiplier = _configFile.Bind<int>("General", "MonsterMultiplier", 1, new ConfigDescription("Multiplier for total monster count (1-1000)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), Array.Empty<object>())); EnableTier1 = _configFile.Bind<bool>("Categories", "EnableTier1", true, "Enable/disable Tier 1 (easy) monsters"); EnableTier2 = _configFile.Bind<bool>("Categories", "EnableTier2", true, "Enable/disable Tier 2 (medium) monsters"); EnableTier3 = _configFile.Bind<bool>("Categories", "EnableTier3", true, "Enable/disable Tier 3 (hard) monsters"); } public void RegisterMonster(string monsterName, int tier) { if (!MonsterToggles.ContainsKey(monsterName)) { ConfigEntry<bool> value = _configFile.Bind<bool>("Monsters", monsterName, true, $"Enable/disable {monsterName} (Tier {tier})"); MonsterToggles[monsterName] = value; } } public bool IsMonsterEnabled(string monsterName, int tier) { if (!EnableSpawning.Value) { return false; } if (tier switch { 1 => EnableTier1.Value ? 1 : 0, 2 => EnableTier2.Value ? 1 : 0, 3 => EnableTier3.Value ? 1 : 0, _ => 0, } == 0) { return false; } if (MonsterToggles.TryGetValue(monsterName, out var value)) { return value.Value; } return true; } } public class MonsterData { public string Name { get; set; } public int Tier { get; set; } public EnemySetup OriginalSetup { get; set; } public bool IsEnabled { get; set; } public MonsterData(string name, int tier, EnemySetup setup) { Name = name; Tier = tier; OriginalSetup = setup; IsEnabled = true; } } public static class MonsterManager { private static bool _initialized = false; public static Dictionary<string, MonsterData> AllMonsters { get; private set; } = new Dictionary<string, MonsterData>(); public static void Initialize(EnemyDirector director) { if (_initialized) { return; } AllMonsters.Clear(); RegisterMonstersFromList(director.enemiesDifficulty1, 1); RegisterMonstersFromList(director.enemiesDifficulty2, 2); RegisterMonstersFromList(director.enemiesDifficulty3, 3); _initialized = true; MonsterScalerPlugin.Logger.LogInfo((object)$"Registered {AllMonsters.Count} monsters"); foreach (MonsterData value in AllMonsters.Values) { MonsterScalerPlugin.Logger.LogInfo((object)$" - {value.Name} (Tier {value.Tier})"); } } private static void RegisterMonstersFromList(List<EnemySetup> enemies, int tier) { foreach (EnemySetup enemy in enemies) { string name = ((Object)enemy).name; if (!AllMonsters.ContainsKey(name)) { MonsterData value = new MonsterData(name, tier, enemy); AllMonsters[name] = value; MonsterScalerPlugin.ConfigManager.RegisterMonster(name, tier); } } } public static List<MonsterData> GetEnabledMonsters() { List<MonsterData> list = new List<MonsterData>(); foreach (MonsterData value in AllMonsters.Values) { if (MonsterScalerPlugin.ConfigManager.IsMonsterEnabled(value.Name, value.Tier)) { list.Add(value); } } return list; } public static void UpdateEnabledStatus() { foreach (MonsterData value in AllMonsters.Values) { value.IsEnabled = MonsterScalerPlugin.ConfigManager.IsMonsterEnabled(value.Name, value.Tier); } } } public static class SpawnCalculator { public static Dictionary<int, int> CalculateSpawnCounts() { Dictionary<int, int> dictionary = new Dictionary<int, int>(); if (!MonsterScalerPlugin.ConfigManager.EnableSpawning.Value) { dictionary[1] = 0; dictionary[2] = 0; dictionary[3] = 0; return dictionary; } List<MonsterData> enabledMonsters = MonsterManager.GetEnabledMonsters(); if (enabledMonsters.Count == 0) { MonsterScalerPlugin.Logger.LogWarning((object)"No monsters enabled! Using default spawning."); dictionary[1] = 1; dictionary[2] = 1; dictionary[3] = 1; return dictionary; } int value = MonsterScalerPlugin.ConfigManager.MonsterMultiplier.Value; Dictionary<int, int> dictionary2 = new Dictionary<int, int> { { 1, enabledMonsters.Count((MonsterData m) => m.Tier == 1) }, { 2, enabledMonsters.Count((MonsterData m) => m.Tier == 2) }, { 3, enabledMonsters.Count((MonsterData m) => m.Tier == 3) } }; int[] array = new int[3] { 1, 2, 3 }; foreach (int key in array) { if (dictionary2[key] > 0) { dictionary[key] = value; } else { dictionary[key] = 0; } } MonsterScalerPlugin.Logger.LogInfo((object)$"Spawn calculation: Multiplier={value}"); MonsterScalerPlugin.Logger.LogInfo((object)$" Tier 1: {dictionary[1]} total spawns for {dictionary2[1]} monsters"); MonsterScalerPlugin.Logger.LogInfo((object)$" Tier 2: {dictionary[2]} total spawns for {dictionary2[2]} monsters"); MonsterScalerPlugin.Logger.LogInfo((object)$" Tier 3: {dictionary[3]} total spawns for {dictionary2[3]} monsters"); return dictionary; } } public static class ReflectionHelper { private static FieldInfo _enemyListField; private static FieldInfo _enemyListCurrentField; private static FieldInfo _totalAmountField; static ReflectionHelper() { Type typeFromHandle = typeof(EnemyDirector); _enemyListField = typeFromHandle.GetField("enemyList", BindingFlags.Instance | BindingFlags.NonPublic); _enemyListCurrentField = typeFromHandle.GetField("enemyListCurrent", BindingFlags.Instance | BindingFlags.NonPublic); _totalAmountField = typeFromHandle.GetField("totalAmount", BindingFlags.Instance | BindingFlags.NonPublic); if (_enemyListField == null || _enemyListCurrentField == null || _totalAmountField == null) { MonsterScalerPlugin.Logger.LogError((object)"Failed to find internal fields via reflection!"); } } public static List<EnemySetup> GetEnemyList(EnemyDirector director) { return (List<EnemySetup>)(_enemyListField?.GetValue(director)); } public static List<EnemySetup> GetEnemyListCurrent(EnemyDirector director) { return (List<EnemySetup>)(_enemyListCurrentField?.GetValue(director)); } public static void SetTotalAmount(EnemyDirector director, int value) { _totalAmountField?.SetValue(director, value); } public static int GetTotalAmount(EnemyDirector director) { return (int)(_totalAmountField?.GetValue(director) ?? ((object)0)); } } [HarmonyPatch(typeof(EnemyDirector))] public class EnemyDirectorPatches { private static bool _setupComplete; [HarmonyPatch("Start")] [HarmonyPostfix] public static void Start_Postfix(EnemyDirector __instance) { BundleLoader.OnAllBundlesLoaded += delegate { MonsterScalerPlugin.Logger.LogInfo((object)"All bundles loaded, initializing MonsterScaler..."); MonsterManager.Initialize(__instance); _setupComplete = true; }; } [HarmonyPatch("AmountSetup")] [HarmonyPrefix] public static bool AmountSetup_Prefix(EnemyDirector __instance) { if (!_setupComplete) { MonsterScalerPlugin.Logger.LogWarning((object)"Setup not complete yet, using default spawning"); return true; } if (!SemiFunc.IsMasterClientOrSingleplayer()) { return false; } try { CustomAmountSetup(__instance); return false; } catch (Exception arg) { MonsterScalerPlugin.Logger.LogError((object)$"Error in CustomAmountSetup: {arg}"); return true; } } private static void CustomAmountSetup(EnemyDirector director) { List<EnemySetup> enemyListCurrent = ReflectionHelper.GetEnemyListCurrent(director); List<EnemySetup> enemyList = ReflectionHelper.GetEnemyList(director); enemyListCurrent.Clear(); enemyList.Clear(); MonsterManager.UpdateEnabledStatus(); Dictionary<int, int> dictionary = SpawnCalculator.CalculateSpawnCounts(); MonsterScalerPlugin.Logger.LogInfo((object)"=== Custom Spawn Setup ==="); director.enemiesDifficulty1.Clear(); director.enemiesDifficulty2.Clear(); director.enemiesDifficulty3.Clear(); foreach (MonsterData enabledMonster in MonsterManager.GetEnabledMonsters()) { EnemySetup originalSetup = enabledMonster.OriginalSetup; switch (enabledMonster.Tier) { case 1: director.enemiesDifficulty1.Add(originalSetup); break; case 2: director.enemiesDifficulty2.Add(originalSetup); break; case 3: director.enemiesDifficulty3.Add(originalSetup); break; } } SpawnMonstersForTier(director, director.enemiesDifficulty3, dictionary[3], 3); SpawnMonstersForTier(director, director.enemiesDifficulty2, dictionary[2], 2); SpawnMonstersForTier(director, director.enemiesDifficulty1, dictionary[1], 1); ReflectionHelper.SetTotalAmount(director, enemyList.Count); MonsterScalerPlugin.Logger.LogInfo((object)$"Total spawns: {ReflectionHelper.GetTotalAmount(director)}"); MonsterScalerPlugin.Logger.LogInfo((object)"=========================="); } private static void SpawnMonstersForTier(EnemyDirector director, List<EnemySetup> enemyList, int totalCount, int tier) { if (enemyList.Count == 0 || totalCount == 0) { return; } List<EnemySetup> enemyList2 = ReflectionHelper.GetEnemyList(director); int num = totalCount / enemyList.Count; int num2 = totalCount % enemyList.Count; MonsterScalerPlugin.Logger.LogInfo((object)$"Tier {tier}: Spawning {totalCount} total ({num} each, +{num2} remainder)"); for (int i = 0; i < enemyList.Count; i++) { EnemySetup val = enemyList[i]; int num3 = num; if (i < num2) { num3++; } for (int j = 0; j < num3; j++) { enemyList2.Add(val); } MonsterScalerPlugin.Logger.LogInfo((object)$" - {((Object)val).name}: x{num3}"); } } } [HarmonyPatch(typeof(LevelGenerator))] public class LevelGeneratorPatches { [HarmonyPatch("EnemySpawn")] [HarmonyPrefix] public static bool EnemySpawn_Prefix(EnemySetup enemySetup) { if (!MonsterScalerPlugin.ConfigManager.EnableSpawning.Value) { MonsterScalerPlugin.Logger.LogInfo((object)"Spawn blocked: spawning disabled"); return false; } return true; } } }