From d02e594457e772f83b798a6ee84a32469cbdc398 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Sun, 3 Aug 2025 14:29:15 +0300 Subject: [PATCH] WIP: Add spawn rate patch to make the event more likely --- MuzikaGromche/Plugin.cs | 8 ++++ MuzikaGromche/SpawnRateManager.cs | 69 +++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 MuzikaGromche/SpawnRateManager.cs diff --git a/MuzikaGromche/Plugin.cs b/MuzikaGromche/Plugin.cs index 17b29ee..6f4adbf 100644 --- a/MuzikaGromche/Plugin.cs +++ b/MuzikaGromche/Plugin.cs @@ -553,6 +553,7 @@ namespace MuzikaGromche harmony.PatchAll(typeof(AllPoweredLightsPatch)); harmony.PatchAll(typeof(DiscoBallTilePatch)); harmony.PatchAll(typeof(DiscoBallDespawnPatch)); + harmony.PatchAll(typeof(SpawnRatePatch)); } else { @@ -1427,6 +1428,8 @@ namespace MuzikaGromche public static ConfigEntry SkipExplicitTracks { get; private set; } = null!; + public static SyncedEntry OverrideSpawnRates { get; private set; } = null!; + public static bool ShouldSkipWindingPhase { get; private set; } = false; public static Palette? PaletteOverride { get; private set; } = null; @@ -1455,6 +1458,11 @@ namespace MuzikaGromche new ConfigDescription("When choosing tracks at random, skip the ones with Explicit Content/Lyrics.")); LethalConfigManager.AddConfigItem(new BoolCheckBoxConfigItem(SkipExplicitTracks, requiresRestart: false)); + OverrideSpawnRates = configFile.BindSyncedEntry("General", "Override Spawn Rates", false, + new ConfigDescription("Deviate from vanilla spawn rates to experience content of this mod more often.")); + LethalConfigManager.AddConfigItem(new BoolCheckBoxConfigItem(OverrideSpawnRates.Entry, Default(new BoolCheckBoxOptions()))); + CSyncHackAddSyncedEntry(OverrideSpawnRates); + #if DEBUG SetupEntriesToSkipWinding(configFile); SetupEntriesForPaletteOverride(configFile); diff --git a/MuzikaGromche/SpawnRateManager.cs b/MuzikaGromche/SpawnRateManager.cs new file mode 100644 index 0000000..3f3c0c7 --- /dev/null +++ b/MuzikaGromche/SpawnRateManager.cs @@ -0,0 +1,69 @@ +using HarmonyLib; +using System; +using UnityEngine; + +namespace MuzikaGromche +{ + [HarmonyPatch(typeof(RoundManager))] + static class SpawnRatePatch + { + const string JesterEnemyName = "Jester"; + + // If set to null, do not override spawn chances. Otherwise, it is an index of Jester in RoundManager.currentLevel.Enemies + static int? JesterEnemyIndex = null; + static float? SpawnTime = null; + + [HarmonyPatch(nameof(RoundManager.AssignRandomEnemyToVent))] + [HarmonyPrefix] + static void AssignRandomEnemyToVentPrefix(RoundManager __instance, EnemyVent vent, float spawnTime) + { + if (!Config.OverrideSpawnRates.Value) + { + return; + } + + var index = __instance.currentLevel.Enemies.FindIndex(enemy => enemy.enemyType.enemyName == JesterEnemyName); + if (index == -1) + { + return; + } + + JesterEnemyIndex = index; + SpawnTime = spawnTime; + } + + [HarmonyPatch(nameof(RoundManager.AssignRandomEnemyToVent))] + [HarmonyPostfix] + static void AssignRandomEnemyToVentPostfix(RoundManager __instance, EnemyVent vent, float spawnTime) + { + JesterEnemyIndex = null; + SpawnTime = null; + } + + [HarmonyPatch(nameof(RoundManager.GetRandomWeightedIndex))] + [HarmonyPostfix] + static void GetRandomWeightedIndexPostfix(RoundManager __instance, ref int[] weights, ref System.Random randomSeed) + { + if (JesterEnemyIndex is int index && SpawnTime is float spawnTime) + { + if (__instance.EnemyCannotBeSpawned(index)) + { + return; + } + + var minMultiplierTime = 3 * __instance.timeScript.lengthOfHours; + var maxMultiplierTime = 7 * __instance.timeScript.lengthOfHours; + var normalizedMultiplierTime = Math.Clamp((spawnTime - minMultiplierTime) / (maxMultiplierTime - minMultiplierTime), 0f, 1f); + + // TODO: Try Expo function instead of Lerp? + var minMultiplier = Mathf.Max(1, __instance.minEnemiesToSpawn); + var maxMultiplier = 9 + __instance.minEnemiesToSpawn; + var multiplier = Mathf.Lerp(minMultiplier, maxMultiplier, normalizedMultiplierTime); + + var newWeight = (int)(weights[index] * multiplier); + Debug.Log($"{nameof(MuzikaGromche)} Overriding Jester spawn weight {weights[index]} * {multiplier} => {newWeight}"); + weights[index] = newWeight; + } + } + } +}