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 SilksongRandomizer v0.6.0
SilksongRandomizer.dll
Decompiled 3 months 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.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using Architect.Content.Preloads; using Architect.Objects; using Architect.Objects.Categories; using Architect.Objects.Placeable; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("SilksongRandomizer")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SilksongRandomizer")] [assembly: AssemblyTitle("SilksongRandomizer")] [assembly: AssemblyVersion("1.0.0.0")] namespace SilksongRandomizer; [BepInPlugin("com.tuusuario.silksong.randomizer", "Silksong Randomizer", "0.5.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class RandomizerMod : BaseUnityPlugin { public class ReplacementData { public HealthManager originalHM; public Vector3 originalPos; public List<PersistentBoolItem> nearbyPBIs; } [CompilerGenerated] private sealed class <AccumulateEnemyPoolDelayed>d__80 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AccumulateEnemyPoolDelayed>d__80(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; case 1: <>1__state = -1; AccumulateEnemyPool(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ApplyFontDelayed>d__117 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public RandomizerMod <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ApplyFontDelayed>d__117(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; RandomizerMod randomizerMod = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: { <>1__state = -1; Font gameFont = GetGameFont(); if ((Object)(object)gameFont != (Object)null) { if ((Object)(object)randomizerMod.popupText != (Object)null) { randomizerMod.popupText.font = gameFont; } if ((Object)(object)randomizerMod.seedText != (Object)null) { randomizerMod.seedText.font = gameFont; } } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <DisplayPopup>d__115 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public RandomizerMod <>4__this; public SavedItem original; public SavedItem randomized; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DisplayPopup>d__115(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; RandomizerMod randomizerMod = <>4__this; if (num != 0) { return false; } <>1__state = -1; Font gameFont = GetGameFont(); if ((Object)(object)gameFont != (Object)null) { randomizerMod.popupText.font = gameFont; if ((Object)(object)randomizerMod.seedText != (Object)null) { randomizerMod.seedText.font = gameFont; } } string itemDisplayName = GetItemDisplayName(original); string itemDisplayName2 = GetItemDisplayName(randomized); randomizerMod.popupText.text = itemDisplayName + " [" + GetItemCategory(original) + "]\n→ " + itemDisplayName2 + " [" + GetItemCategory(randomized) + "]"; try { Sprite popupIcon = original.GetPopupIcon(); Sprite popupIcon2 = randomized.GetPopupIcon(); randomizerMod.originalIcon.sprite = popupIcon; ((Behaviour)randomizerMod.originalIcon).enabled = (Object)(object)popupIcon != (Object)null; randomizerMod.randomIcon.sprite = popupIcon2; ((Behaviour)randomizerMod.randomIcon).enabled = (Object)(object)popupIcon2 != (Object)null; } catch { } randomizerMod.popupCanvas.SetActive(true); if (randomizerMod.hideCoroutine != null) { ((MonoBehaviour)randomizerMod).StopCoroutine(randomizerMod.hideCoroutine); } randomizerMod.hideCoroutine = ((MonoBehaviour)randomizerMod).StartCoroutine(randomizerMod.HideAfterDelay(5f)); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <DoEnemyRando>d__97 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public HealthManager hm; public PlaceableObject[] pool; public bool originalIsBoss; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DoEnemyRando>d__97(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.02f); <>1__state = 1; return true; case 1: { <>1__state = -1; if ((Object)(object)hm == (Object)null || (Object)(object)((Component)hm).gameObject == (Object)null || hm.isDead) { return false; } if ((Object)(object)((Component)hm).gameObject.GetComponent<ReplacedByRando>() != (Object)null) { return false; } Log.LogInfo((object)("[EnemyRando] Starting rando for '" + ((Object)((Component)hm).gameObject).name + "'")); Vector3 position = ((Component)hm).gameObject.transform.position; int num = (Mathf.RoundToInt(position.x * 100f) * 397) ^ (Mathf.RoundToInt(position.y * 100f) * 397); int hashCode = ((Object)((Component)hm).gameObject).name.GetHashCode(); Scene scene = ((Component)hm).gameObject.scene; int seed = hashCode ^ ((Scene)(ref scene)).name.GetHashCode() ^ num ^ currentSeed; PlaceableObject val = pool[new Random(seed).Next(pool.Length)]; if ((Object)(object)val.Prefab == (Object)null) { return false; } bool flag = (Object)(object)val.Prefab.GetComponent<HealthManager>() != (Object)null && IsBoss(val.Prefab.GetComponent<HealthManager>()); if (originalIsBoss && !flag) { Log.LogWarning((object)("[EnemyRando] ABORTED: boss '" + ((Object)((Component)hm).gameObject).name + "' would have been replaced by non-boss '" + ((SelectableObject)val).GetName() + "' — skipping")); return false; } try { Vector3 position2 = ((Component)hm).gameObject.transform.position; List<PersistentBoolItem> nearbyPersistentItems = GetNearbyPersistentItems(position2); Log.LogInfo((object)$"[DropFix] Found {nearbyPersistentItems.Count} nearby PersistentBoolItems for '{((Object)((Component)hm).gameObject).name}'"); ((Component)hm).gameObject.AddComponent<ReplacedByRando>(); Renderer[] componentsInChildren = ((Component)hm).gameObject.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } Behaviour[] componentsInChildren2 = ((Component)hm).gameObject.GetComponentsInChildren<Behaviour>(true); foreach (Behaviour val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null && ((object)val2).GetType().Name.Contains("Collider")) { val2.enabled = false; } } ((Component)hm).gameObject.transform.position = new Vector3(-9999f, -9999f, 0f); CollectableItemPickup[] componentsInChildren3 = ((Component)hm).gameObject.GetComponentsInChildren<CollectableItemPickup>(true); ((Component)hm).gameObject.GetComponent<PersistentEnemyItemDrop>(); float enemyHalfHeight = GetEnemyHalfHeight(val.Prefab); Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(position2.x, position2.y + enemyHalfHeight + 0.3f, position2.z); bool activeSelf = val.Prefab.activeSelf; val.Prefab.SetActive(false); GameObject val4 = Object.Instantiate<GameObject>(val.Prefab, val3, val.Prefab.transform.rotation); if (activeSelf) { val.Prefab.SetActive(true); } ((Object)val4).name = "[Rando] " + ((SelectableObject)val).GetName() + " (was " + ((Object)((Component)hm).gameObject).name + ")"; val4.AddComponent<RandoReplacement>().original = hm; HealthManager component = val4.GetComponent<HealthManager>(); DeathMonitor.Track(val4, component, hm, position2, nearbyPersistentItems); PersistentBoolItem component2 = val4.GetComponent<PersistentBoolItem>(); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } CollectableItemPickup[] array = componentsInChildren3; foreach (CollectableItemPickup val5 in array) { ((Component)val5).transform.SetParent(val4.transform, true); ((Component)val5).gameObject.SetActive(true); Log.LogInfo((object)("[EnemyRando] Transferred child pickup '" + ((Object)val5).name + "' from " + ((Object)((Component)hm).gameObject).name + " to " + ((SelectableObject)val).GetName())); } val4.SetActive(true); if (originalIsBoss) { Log.LogInfo((object)$"[BossRando] BOSS {((Object)((Component)hm).gameObject).name} → {((SelectableObject)val).GetName()} (offset +{enemyHalfHeight:F2})"); } else { Log.LogInfo((object)$"[EnemyRando] {((Object)((Component)hm).gameObject).name} → {((SelectableObject)val).GetName()} (offset +{enemyHalfHeight:F2})"); } } catch (Exception arg2) { ManualLogSource log = Log; HealthManager obj = hm; object arg; if (obj == null) { arg = null; } else { GameObject gameObject = ((Component)obj).gameObject; arg = ((gameObject != null) ? ((Object)gameObject).name : null); } log.LogError((object)$"[EnemyRando] EXCEPTION in DoEnemyRando for '{arg}': {arg2}"); } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <DoZoneTeleport>d__124 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public GameManager gm; private float <elapsed>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DoZoneTeleport>d__124(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (_zoneTeleportFired) { return false; } _zoneTeleportFired = true; <elapsed>5__2 = 0f; goto IL_0074; case 1: <>1__state = -1; <elapsed>5__2 += 0.1f; goto IL_0074; case 2: <>1__state = -1; <elapsed>5__2 += 0.3f; goto IL_0121; case 3: { <>1__state = -1; GetRandomZone(out var outScene, out var outGate); Log.LogInfo((object)$"[ZoneRando] Teleporting to {outScene} / {outGate} (seed: {currentSeed})"); gm.ChangeToScene(outScene, outGate, 0f); return false; } IL_0121: if (<elapsed>5__2 < 120f) { Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (!(name != "Opening_Sequence") || !(name != "Tut_01") || !(name != "Tut_01b") || string.IsNullOrEmpty(name) || menuScenes.Contains(name)) { <>2__current = (object)new WaitForSeconds(0.3f); <>1__state = 2; return true; } } <>2__current = (object)new WaitForSeconds(1f); <>1__state = 3; return true; IL_0074: if (gm.playerData == null && <elapsed>5__2 < 15f) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } <elapsed>5__2 = 0f; goto IL_0121; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <HideAfterDelay>d__116 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float delay; public RandomizerMod <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <HideAfterDelay>d__116(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown int num = <>1__state; RandomizerMod randomizerMod = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(delay); <>1__state = 1; return true; case 1: <>1__state = -1; randomizerMod.popupCanvas.SetActive(false); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <KillOriginalAndRestoreDrops>d__98 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public List<PersistentBoolItem> nearbyPBIs; public Vector3 originalPos; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <KillOriginalAndRestoreDrops>d__98(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_019e: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (nearbyPBIs == null || nearbyPBIs.Count == 0) { Log.LogInfo((object)"[DropFix] No PBIs nearby — original enemy had no item drop, skipping"); return false; } if (originalPos.x < -9000f) { Log.LogWarning((object)"[DropFix] originalPos is at -9999, skipping drop"); return false; } foreach (PersistentBoolItem nearbyPBI in nearbyPBIs) { ResetPersistentBoolItem(nearbyPBI); } <>2__current = (object)new WaitForSeconds(0.15f); <>1__state = 1; return true; case 1: { <>1__state = -1; CollectableItemPickup val = Object.FindFirstObjectByType<CollectableItemPickup>((FindObjectsInactive)1); if ((Object)(object)val != (Object)null) { SavedItem val2 = ((allItems.Count > 0) ? allItems[rng.Next(allItems.Count)] : null); if ((Object)(object)val2 == (Object)null) { Log.LogWarning((object)"[DropFix] No items in allItems pool to spawn"); return false; } GameObject obj = Object.Instantiate<GameObject>(((Component)val).gameObject, originalPos + Vector3.up * 0.5f, Quaternion.identity); ((Object)obj).name = "[RandoDrop] " + ((Object)val2).name; CollectableItemPickup component = obj.GetComponent<CollectableItemPickup>(); if ((Object)(object)component != (Object)null) { FieldInfo fieldInfo = AccessTools.Field(typeof(CollectableItemPickup), "item"); if (fieldInfo != null) { fieldInfo.SetValue(component, val2); Log.LogInfo((object)$"[DropFix] Spawned drop '{((Object)val2).name}' at {originalPos}"); } } } else { Log.LogWarning((object)"[DropFix] No existing CollectableItemPickup in scene to clone"); } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <RandomizeShopMenuDelayed>d__145 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ShopMenuStock stock; private int <instanceId>5__2; private float <elapsed>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RandomizeShopMenuDelayed>d__145(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: { <>1__state = -1; FieldInfo fieldInfo = AccessTools.Field(typeof(ShopMenuStock), "MasterList"); if (fieldInfo != null && fieldInfo.GetValue(stock) != null) { return false; } <instanceId>5__2 = ((Object)stock).GetInstanceID(); if (_shopBeingRandomized.Contains(<instanceId>5__2)) { return false; } <elapsed>5__3 = 0f; break; } case 1: <>1__state = -1; <elapsed>5__3 += 0.1f; break; } if (allShopCandidates.Count == 0 && <elapsed>5__3 < 8f) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } if (allShopCandidates.Count == 0) { return false; } FieldInfo fieldInfo2 = AccessTools.Field(typeof(ShopMenuStock), "stock"); if (fieldInfo2 == null) { return false; } if (!(fieldInfo2.GetValue(stock) is Array array) || array.Length == 0) { return false; } string shopUniqueId = GetShopUniqueId(stock); string text = $"{CfgRandomizeShops.Value}_{GetShopConfigFingerprint()}"; if (_randomizedThisScene.TryGetValue(shopUniqueId, out var value) && value == text) { return false; } _shopBeingRandomized.Add(<instanceId>5__2); try { CaptureOriginalStock(shopUniqueId, array); if (CfgRandomizeShops.Value) { RestoreOriginalStock(shopUniqueId, array); Log.LogInfo((object)$"[Shop] Randomizando '{shopUniqueId}' — {array.Length} items"); for (int i = 0; i < array.Length; i++) { object value2 = array.GetValue(i); if (value2 != null) { RandomizeShopItemDirect(value2, shopUniqueId, i); } } } else { RestoreOriginalStock(shopUniqueId, array); } _randomizedThisScene[shopUniqueId] = text; } finally { _shopBeingRandomized.Remove(<instanceId>5__2); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ReRandomizeStaleOriginals>d__119 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; private HashSet<HealthManager> <coveredOriginals>5__2; private HealthManager[] <>7__wrap2; private int <>7__wrap3; private HealthManager <hm>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ReRandomizeStaleOriginals>d__119(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <coveredOriginals>5__2 = null; <>7__wrap2 = null; <hm>5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; case 1: { <>1__state = -1; if (!CfgEnemiesRandomizer.Value) { return false; } if (!PreloadManager.HasPreloaded) { return false; } PlaceableObject[] enemyPool = GetEnemyPool(); if (enemyPool == null || enemyPool.Length == 0) { return false; } HealthManager[] array = Object.FindObjectsByType<HealthManager>((FindObjectsInactive)1, (FindObjectsSortMode)0); <coveredOriginals>5__2 = new HashSet<HealthManager>(); RandoReplacement[] array2 = Object.FindObjectsByType<RandoReplacement>((FindObjectsSortMode)0); foreach (RandoReplacement randoReplacement in array2) { if ((Object)(object)randoReplacement != (Object)null && (Object)(object)randoReplacement.original != (Object)null) { <coveredOriginals>5__2.Add(randoReplacement.original); } } <>7__wrap2 = array; <>7__wrap3 = 0; goto IL_0271; } case 2: { <>1__state = -1; ((Component)<hm>5__5).gameObject.SetActive(true); <hm>5__5 = null; goto IL_0263; } IL_0263: <>7__wrap3++; goto IL_0271; IL_0271: if (<>7__wrap3 < <>7__wrap2.Length) { <hm>5__5 = <>7__wrap2[<>7__wrap3]; if (!((Object)(object)<hm>5__5 == (Object)null) && !((Object)(object)((Component)<hm>5__5).gameObject == (Object)null) && !((Object)(object)((Component)<hm>5__5).gameObject.GetComponent<ReplacedByRando>() == (Object)null)) { if (<hm>5__5.isDead) { <hm>5__5.isDead = false; } if (!<coveredOriginals>5__2.Contains(<hm>5__5)) { Log.LogInfo((object)("[EnemyRando] Re-randomizing stale original '" + ((Object)((Component)<hm>5__5).gameObject).name + "'")); Object.Destroy((Object)(object)((Component)<hm>5__5).gameObject.GetComponent<ReplacedByRando>()); Renderer[] componentsInChildren = ((Component)<hm>5__5).gameObject.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = true; } Behaviour[] componentsInChildren2 = ((Component)<hm>5__5).gameObject.GetComponentsInChildren<Behaviour>(true); foreach (Behaviour val in componentsInChildren2) { if ((Object)(object)val != (Object)null && ((object)val).GetType().Name.Contains("Collider")) { val.enabled = true; } } ((Component)<hm>5__5).gameObject.SetActive(false); <>2__current = null; <>1__state = 2; return true; } } goto IL_0263; } <>7__wrap2 = null; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ShowSkillsPopup>d__127 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public List<string> skillFields; private GameObject <canvas>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ShowSkillsPopup>d__127(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <canvas>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_0115: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_041e: 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_0461: Unknown result type (might be due to invalid IL or missing references) //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_049a: Unknown result type (might be due to invalid IL or missing references) //IL_04af: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Unknown result type (might be due to invalid IL or missing references) //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Unknown result type (might be due to invalid IL or missing references) //IL_04f2: Expected O, but got Unknown //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Expected O, but got Unknown //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0364: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_03df: 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) switch (<>1__state) { default: return false; case 0: <>1__state = -1; if ((Object)(object)Instance == (Object)null || skillFields == null || skillFields.Count == 0) { return false; } <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; case 1: { <>1__state = -1; Font gameFont = GetGameFont(); <canvas>5__2 = new GameObject("SkillsPopup"); Canvas obj = <canvas>5__2.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 1001; <canvas>5__2.AddComponent<CanvasScaler>(); GameObject val = new GameObject("BG"); val.transform.SetParent(<canvas>5__2.transform, false); ((Graphic)val.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.82f); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; GameObject val2 = new GameObject("Title"); val2.transform.SetParent(val.transform, false); Text obj2 = val2.AddComponent<Text>(); obj2.font = gameFont; obj2.fontSize = 26; obj2.alignment = (TextAnchor)4; ((Graphic)obj2).color = Color.white; obj2.text = "Starting Skills"; RectTransform component2 = val2.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0f, 1f); component2.anchorMax = new Vector2(1f, 1f); component2.pivot = new Vector2(0.5f, 1f); component2.anchoredPosition = new Vector2(0f, -40f); component2.sizeDelta = new Vector2(0f, 44f); GameObject val3 = new GameObject("Sep"); val3.transform.SetParent(val.transform, false); ((Graphic)val3.AddComponent<Image>()).color = new Color(1f, 1f, 1f, 0.2f); RectTransform component3 = val3.GetComponent<RectTransform>(); component3.anchorMin = new Vector2(0.1f, 1f); component3.anchorMax = new Vector2(0.9f, 1f); component3.pivot = new Vector2(0.5f, 1f); component3.anchoredPosition = new Vector2(0f, -86f); component3.sizeDelta = new Vector2(0f, 2f); float num = -110f; float num2 = 90f; foreach (string skillField in skillFields) { string value; string text = (_skillDisplayNames.TryGetValue(skillField, out value) ? value : skillField); GameObject val4 = new GameObject("Row_" + skillField); val4.transform.SetParent(val.transform, false); RectTransform obj3 = val4.AddComponent<RectTransform>(); obj3.anchorMin = new Vector2(0.2f, 1f); obj3.anchorMax = new Vector2(0.8f, 1f); obj3.pivot = new Vector2(0.5f, 1f); obj3.anchoredPosition = new Vector2(0f, num); obj3.sizeDelta = new Vector2(0f, num2 - 8f); GameObject val5 = new GameObject("Name"); val5.transform.SetParent(val4.transform, false); Text obj4 = val5.AddComponent<Text>(); obj4.font = gameFont; obj4.fontSize = 22; obj4.alignment = (TextAnchor)3; ((Graphic)obj4).color = Color.white; obj4.text = text; RectTransform component4 = val5.GetComponent<RectTransform>(); component4.anchorMin = new Vector2(0f, 0f); component4.anchorMax = new Vector2(1f, 1f); component4.offsetMin = new Vector2(84f, 0f); component4.offsetMax = Vector2.zero; num -= num2; } GameObject val6 = new GameObject("Hint"); val6.transform.SetParent(val.transform, false); Text obj5 = val6.AddComponent<Text>(); obj5.font = gameFont; obj5.fontSize = 16; obj5.alignment = (TextAnchor)4; ((Graphic)obj5).color = new Color(1f, 1f, 1f, 0.5f); obj5.text = "Press any key to continue"; RectTransform component5 = val6.GetComponent<RectTransform>(); component5.anchorMin = new Vector2(0f, 0f); component5.anchorMax = new Vector2(1f, 0f); component5.pivot = new Vector2(0.5f, 0f); component5.anchoredPosition = new Vector2(0f, 30f); component5.sizeDelta = new Vector2(0f, 30f); <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 2; return true; } case 2: <>1__state = -1; break; case 3: <>1__state = -1; break; } if (!Input.anyKeyDown) { <>2__current = null; <>1__state = 3; return true; } Object.Destroy((Object)(object)<canvas>5__2); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static ManualLogSource Log; internal static List<SavedItem> allItems = new List<SavedItem>(); private static List<SavedItem> _availableFloorItems = new List<SavedItem>(); internal static HashSet<string> usedShopItems = new HashSet<string>(); internal static Dictionary<string, string> shopItemAssignments = new Dictionary<string, string>(); internal static Random rng = new Random(); internal static RandomizerMod Instance; internal static EnemyDeathMonitor DeathMonitor; internal static List<SavedItem> allShopCandidates = new List<SavedItem>(); internal static int currentSeed = 0; internal static HashSet<string> knownEnemyNames = new HashSet<string>(); internal static Dictionary<string, ReplacementData> pendingReplacementData = new Dictionary<string, ReplacementData>(); internal static ConfigEntry<int> CfgCustomSeed; internal static ConfigEntry<int> CfgOverrideSeed; internal static ConfigEntry<bool> CfgRandomizeShops; internal static ConfigEntry<int> CfgShopMinSlots; internal static ConfigEntry<int> CfgShopMaxSlots; internal static ConfigEntry<bool> CfgRandomizeMaskShards; internal static ConfigEntry<int> CfgMinMaskShards; internal static ConfigEntry<int> CfgMaxMaskShards; internal static ConfigEntry<bool> CfgRandomizeNeedleUpgrades; internal static ConfigEntry<int> CfgMinNeedleUpgrades; internal static ConfigEntry<int> CfgMaxNeedleUpgrades; internal static ConfigEntry<bool> CfgRandomizeSkills; internal static ConfigEntry<int> CfgSkillCount; internal static ConfigEntry<bool> CfgRandomizeZone; internal static ConfigEntry<bool> CfgRandomizeQuests; internal static ConfigEntry<KeyCode> CfgSeedKey; internal static ConfigEntry<bool> CfgEnemiesRandomizer; internal static ConfigEntry<bool> CfgBossesRandomizer; internal static ConfigEntry<bool> CfgShakraShopRandomizer; internal static ConfigEntry<string> CfgEnemyActFilter; internal static ConfigEntry<string> CfgEnemyCustomBlacklist; internal static ConfigEntry<bool> CfgFloorSkill; internal static ConfigEntry<bool> CfgFloorCrest; internal static ConfigEntry<bool> CfgFloorConsumable; internal static ConfigEntry<bool> CfgFloorTool; internal static ConfigEntry<bool> CfgFloorMemento; internal static ConfigEntry<bool> CfgFloorRelic; internal static ConfigEntry<bool> CfgFloorCombat; internal static ConfigEntry<bool> CfgFloorItem; internal static ConfigEntry<bool> CfgShopSkill; internal static ConfigEntry<bool> CfgShopCrest; internal static ConfigEntry<bool> CfgShopConsumable; internal static ConfigEntry<bool> CfgShopTool; internal static ConfigEntry<bool> CfgShopMemento; internal static ConfigEntry<bool> CfgShopRelic; internal static ConfigEntry<bool> CfgShopCombat; internal static ConfigEntry<bool> CfgShopItem; private GameObject popupCanvas; private Text popupText; private Image originalIcon; private Image randomIcon; private Coroutine hideCoroutine; private GameObject seedCanvas; private Text seedText; private bool seedVisible; private static readonly HashSet<string> menuScenes = new HashSet<string> { "Menu_Title", "Pre_Menu_Intro", "Quit_To_Menu" }; private static readonly HashSet<string> bossNames = new HashSet<string> { "Mossbone Mother", "Bell Beast", "Lace", "Fourth Chorus", "Sister Splinter", "Widow", "Last Judge", "Moorwing", "Savage Beastfly", "Skull Tyrant", "Great Conchfly", "Phantom", "Cogwork Dancer", "Grand Mother Silk", "Trobbio", "Groal", "Broodmother", "Lugoli", "Forebrother", "Raging Conchfly", "Father of the Flame", "Second Sentinel", "Shakra", "Unravelled", "First Sinner", "Seth", "Nyleth", "Khann", "Karmelita", "Lost Lace", "Bell Eater", "Crawfather", "Palestag", "Clover Dancer", "Gurr", "Garmond", "Voltvyrm", "Tormented Trobbio", "Pinstress", "Plasmified Zango", "Watcher at the Edge", "Skull King", "Silk Boss", "Bone Beast", "SG_head" }; private static FieldInfo _pbiIdField; private static FieldInfo _pbiSceneNameField; private static bool _pbiFieldsCached = false; private static readonly HashSet<string> Act1Scenes = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Tut_01", "Tut_01b", "Tut_02", "Tut_03", "Tut_04", "Tut_05", "Bone_01", "Bone_01b", "Bone_01c", "Bone_02", "Bone_03", "Bone_04", "Bone_05", "Bone_05b", "Bone_06", "Bone_07", "Bone_08", "Bone_09", "Bone_10", "Bone_11", "Bone_11b", "Bone_12", "Bone_14", "Bone_15", "Bone_16", "Bone_17", "Bone_18", "Bone_19", "Bone_East_01", "Bone_East_02", "Bone_East_02b", "Bone_East_03", "Bone_East_04", "Bone_East_04b", "Bone_East_04c", "Bone_East_05", "Bone_East_07", "Bone_East_08", "Bone_East_09", "Bone_East_09b", "Bone_East_10", "Bone_East_11", "Bone_East_12", "Bone_East_13", "Bone_East_14", "Bone_East_14b", "Bone_East_15", "Bone_East_16", "Bone_East_17", "Bone_East_17b", "Bone_East_18", "Bone_East_18b", "Bone_East_18c", "Bone_East_20", "Bone_East_21", "Bone_East_22", "Bone_East_24", "Bone_East_25", "Bone_East_26", "Bone_East_27", "Bonetown", "Bonegrave", "Mosstown_01", "Mosstown_02", "Mosstown_02c", "Mosstown_03", "Shellwood_01", "Shellwood_01b", "Shellwood_02", "Shellwood_03", "Shellwood_04b", "Shellwood_04c", "Shellwood_08", "Shellwood_08c", "Shellwood_10", "Shellwood_11", "Shellwood_11b", "Shellwood_13", "Shellwood_14", "Shellwood_15", "Shellwood_16", "Shellwood_18", "Shellwood_19", "Shellwood_20", "Shellwood_22", "Shellwood_25", "Shellwood_25b", "Shellwood_26", "Belltown", "Belltown_04", "Belltown_06", "Belltown_07", "Belltown_08", "Belltown_basement", "Belltown_basement_03", "Greymoor_01", "Greymoor_02", "Greymoor_03", "Greymoor_04", "Greymoor_05", "Greymoor_06", "Greymoor_07", "Greymoor_08", "Greymoor_10", "Greymoor_11", "Greymoor_12", "Greymoor_13", "Greymoor_15", "Greymoor_15b", "Greymoor_16", "Greymoor_17", "Greymoor_20b", "Greymoor_21", "Greymoor_22", "Greymoor_24", "Dock_01", "Dock_02", "Dock_02b", "Dock_03", "Dock_03b", "Dock_03c", "Dock_03d", "Dock_04", "Dock_05", "Dock_06_Church", "Dock_08", "Dock_09", "Dock_10", "Dock_11", "Dock_12", "Dock_13", "Dock_14", "Dock_15", "Dock_16", "Weave_02", "Weave_03", "Weave_04", "Weave_05b", "Weave_07", "Weave_08", "Weave_10", "Weave_11", "Weave_12", "Weave_13", "Weave_14", "Ant_02", "Ant_03", "Ant_04", "Ant_04_left", "Ant_04_mid", "Ant_05b", "Ant_05c", "Ant_08", "Ant_09", "Ant_14", "Ant_17", "Ant_19", "Ant_20", "Ant_21", "Crawl_01", "Crawl_02", "Crawl_03", "Crawl_03b", "Crawl_04", "Crawl_05", "Crawl_06", "Crawl_07", "Crawl_08", "Crawl_09", "Crawl_10", "Wisp_02", "Wisp_03", "Wisp_04", "Wisp_05", "Wisp_06", "Wisp_07", "Wisp_08", "Wisp_09" }; private static readonly HashSet<string> Act2Scenes = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Coral_02", "Coral_03", "Coral_11", "Coral_11b", "Coral_12", "Coral_19", "Coral_19b", "Coral_23", "Coral_24", "Coral_25", "Coral_26", "Coral_27", "Coral_28", "Coral_29", "Coral_32", "Coral_33", "Coral_34", "Coral_35", "Coral_35b", "Coral_36", "Coral_37", "Coral_38", "Coral_39", "Coral_40", "Coral_41", "Coral_42", "Coral_43", "Coral_44", "Under_01", "Under_02", "Under_03", "Under_03b", "Under_03c", "Under_03d", "Under_04", "Under_05", "Under_06", "Under_07", "Under_07b", "Under_07c", "Under_08", "Under_10", "Under_11", "Under_12", "Under_13", "Under_14", "Under_16", "Under_17", "Under_18", "Under_19", "Under_19b", "Under_19c", "Under_20", "Under_21", "Under_22", "Under_23", "Under_27", "Song_01", "Song_01b", "Song_01c", "Song_02", "Song_03", "Song_04", "Song_05", "Song_07", "Song_08", "Song_09", "Song_09b", "Song_10", "Song_11", "Song_12", "Song_13", "Song_14", "Song_15", "Song_17", "Song_18", "Song_19_entrance", "Song_20", "Song_20b", "Song_24", "Song_25", "Song_26", "Song_27", "Song_28", "Song_29", "Library_01", "Library_02", "Library_03", "Library_04", "Library_05", "Library_06", "Library_07", "Library_08", "Library_09", "Library_10", "Library_11", "Library_11b", "Library_12", "Library_12b", "Library_13", "Library_13b", "Library_14", "Library_15", "Library_16", "Cog_04", "Cog_05", "Cog_06", "Cog_07", "Cog_08", "Cog_09", "Cog_10", "Cog_Pass", "Cog_Dancers", "Cog_Bench", "Hang_01", "Hang_02", "Hang_03", "Hang_03_top", "Hang_04", "Hang_06", "Hang_06_bank", "Hang_06b", "Hang_07", "Hang_08", "Hang_09", "Hang_10", "Hang_12", "Hang_13", "Hang_14", "Hang_15", "Hang_16", "Hang_17b", "Arborium_01", "Arborium_02", "Arborium_03", "Arborium_04", "Arborium_05", "Arborium_06", "Arborium_07", "Arborium_08", "Arborium_09", "Arborium_10", "Arborium_11", "Arborium_Tube", "Aqueduct_01", "Aqueduct_02", "Aqueduct_03", "Aqueduct_04", "Aqueduct_05", "Aqueduct_06", "Aqueduct_07", "Aqueduct_08", "Ward_01", "Ward_02", "Ward_02b", "Ward_03", "Ward_04", "Ward_05", "Ward_06", "Ward_07", "Ward_09", "Peak_01", "Peak_02", "Peak_04", "Peak_04c", "Peak_04d", "Peak_05", "Peak_05c", "Peak_05d", "Peak_05e", "Peak_06b", "Peak_07", "Peak_08", "Peak_08b", "Peak_10", "Peak_12", "Bellway_Peak", "Bellway_Peak_02", "Bellway_City", "Bellway_02", "Bellway_03", "Bellway_04", "Dust_01", "Dust_02", "Dust_03", "Dust_04", "Dust_05", "Dust_06", "Dust_09", "Dust_10", "Dust_11", "Dust_12", "Dust_Maze_02", "Dust_Maze_03", "Dust_Maze_04", "Dust_Maze_05", "Dust_Maze_06", "Dust_Maze_07", "Dust_Maze_08", "Dust_Maze_08_completed", "Shadow_01", "Shadow_02", "Shadow_03", "Shadow_04", "Shadow_04b", "Shadow_05", "Shadow_08", "Shadow_09", "Shadow_10", "Shadow_11", "Shadow_12", "Shadow_13", "Shadow_14", "Shadow_15", "Shadow_16", "Shadow_18", "Shadow_19", "Shadow_20", "Shadow_21", "Shadow_22", "Shadow_23", "Shadow_24", "Shadow_25", "Shadow_26", "Shadow_27", "Shadow_28", "Clover_01", "Clover_01b", "Clover_02c", "Clover_03", "Clover_04b", "Clover_05c", "Clover_06", "Clover_10_web", "Clover_11", "Clover_16", "Clover_18", "Clover_19", "Clover_20", "Clover_21", "Slab_01", "Slab_02", "Slab_03", "Slab_04", "Slab_05", "Slab_06", "Slab_07", "Slab_08", "Slab_12", "Slab_13", "Slab_14", "Slab_15", "Slab_16", "Slab_16b", "Slab_17", "Slab_18", "Slab_19b", "Slab_20", "Slab_21", "Slab_22", "Slab_23" }; private static readonly HashSet<string> enemyPoolBlacklist = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Huge Flea", "Choir Flyer", "Coral Swimmer Small", "Karak Gor", "Lampbearer", "Bone Roller", "Lugoli" }; private static readonly HashSet<string> bossMinionNames = new HashSet<string> { "MossBone Cocoon", "MossBone Crawler", "MossBone Fly" }; private static readonly HashSet<string> bossReplacementBlacklist = new HashSet<string> { "Last Judge", "Watcher at the Edge", "First Sinner" }; private static readonly string[] _zoneTransitions = new string[1578] { "Tut_02", "right1", "Tut_01b", "left2", "Tut_02", "right2", "Tut_03", "right1", "Tut_01b", "left1", "Weave_04", "left1", "Tut_01", "right2", "Tut_01", "right1", "Tut_01", "left2", "Tut_01", "left3", "Tut_04", "left1", "Bonetown", "bot1", "Tut_01", "left1", "Tut_05", "left1", "Tut_03", "door2", "Tut_04", "right1", "Bone_11", "top1", "Bone_05", "left1", "Mosstown_02", "bot1", "Bone_05b", "left1", "Mosstown_01", "top1", "Mosstown_02c", "left2", "Bone_05b", "top1", "Mosstown_02", "right1", "Shellwood_25", "left1", "Bone_06", "left1", "Shellwood_03", "bot1", "Bonetown", "top6", "Mosstown_02", "left1", "Bonetown", "top3", "Crawl_04", "right1", "Shellwood_08c", "left1", "Bonetown", "top4", "Bonetown", "top5", "Bonetown", "top2", "Bone_11", "left1", "Crawl_01", "right1", "Bone_03", "left1", "Greymoor_01", "right2", "Greymoor_02", "left2", "Shellwood_08", "right1", "Shellwood_19", "left1", "Bone_East_12", "right1", "Bone_East_02", "left1", "Belltown", "right2", "Greymoor_08", "left2", "Shellwood_01", "right2", "Belltown", "left3", "Belltown_06", "left3", "Belltown_04", "bot1", "Shellwood_01", "right1", "Belltown", "door1", "Belltown_basement", "bot1", "Bone_08", "right2", "Bonetown", "door1", "Dock_16", "right1", "Bone_East_01", "left2", "Bone_East_09b", "left1", "Bone_East_07", "right2", "Greymoor_16", "top1", "Greymoor_05", "right2", "Coral_35", "right1", "Coral_03", "left1", "Library_11", "left2", "Song_20", "right6", "Peak_04", "left1", "Bellway_Peak_02", "left1", "Peak_05", "bot1", "Peak_04c", "right1", "Bellway_Peak", "right2", "Shadow_04", "right2", "Aqueduct_02", "right2", "Aqueduct_06", "left1", "Bone_05", "right1", "Greymoor_01", "right1", "Greymoor_02", "left3", "Greymoor_13", "right1", "Greymoor_12", "right1", "Greymoor_02", "left1", "Greymoor_01", "right3", "Greymoor_17", "left1", "Greymoor_15", "left3", "Greymoor_01", "right1", "Greymoor_15", "left1", "Greymoor_04", "right2", "Greymoor_12", "left1", "Halfway_01", "right1", "Greymoor_13", "left1", "Greymoor_04", "right1", "Greymoor_10", "right1", "Greymoor_03", "left2", "Greymoor_03", "left1", "Greymoor_05", "right1", "Greymoor_11", "right1", "Greymoor_06", "right4", "Greymoor_05", "left2", "Greymoor_07", "right2", "Greymoor_10", "left1", "Greymoor_11", "left1", "Greymoor_05", "left1", "Greymoor_07", "right1", "Greymoor_06", "left3", "Greymoor_06", "left2", "Greymoor_20b", "right1", "Greymoor_16", "left1", "Greymoor_07", "bot1", "Greymoor_06", "right2", "Greymoor_04", "left2", "Greymoor_06", "right1", "Greymoor_04", "left1", "Greymoor_03", "right2", "Greymoor_01", "left1", "Greymoor_03", "right3", "Greymoor_01", "left2", "Greymoor_02", "right3", "Greymoor_02", "right1", "Greymoor_15", "right2", "Greymoor_08", "right1", "Greymoor_02", "right2", "Greymoor_07", "left1", "Greymoor_03", "right5", "Greymoor_03", "right1", "Dust_02", "left2", "Dust_03", "left1", "Dust_04", "left2", "Dust_01", "right1", "Dust_05", "bot1", "Dust_10", "right1", "Dust_04", "left1", "Dust_02", "right3", "Dust_02", "right2", "Dust_02", "right1", "Dust_06", "left1", "Dust_12", "left1", "Dust_11", "left1", "Dust_05", "right1", "Shadow_05", "left1", "Dust_06", "right2", "Dust_06", "right3", "Dust_03", "bot1", "Dust_04", "right1", "Dust_03", "top1", "Dust_09", "right1", "Dust_09", "left2", "Dust_05", "left1", "Library_12", "door1", "Shadow_16", "left1", "Shadow_18", "left1", "Shadow_26", "left1", "Shadow_15", "right2", "Shadow_15", "right1", "Shadow_14", "right1", "Aqueduct_04", "bot1", "Shadow_03", "left1", "Shadow_26", "left2", "Shadow_23", "left1", "Shadow_14", "right2", "Shadow_09", "left1", "Shadow_02", "right2", "Shadow_20", "bot1", "Shadow_04", "right1", "Shadow_02", "left2", "Shadow_09", "left2", "Shadow_03", "right1", "Shadow_05", "right1", "Shadow_08", "top1", "Shadow_16", "right1", "Shadow_19", "left2", "Shadow_13", "left1", "Shadow_26", "right1", "Shadow_19", "left1", "Shadow_18", "right1", "Shadow_11", "right1", "Shadow_01", "left2", "Shadow_02", "left1", "Shadow_01", "left3", "Shadow_01", "left1", "Shadow_10", "left1", "Shadow_01", "right1", "Shadow_12", "left1", "Shadow_01", "right3", "Shadow_12", "right1", "Shadow_24", "left1", "Shadow_25", "left1", "Shadow_10", "right1", "Shadow_04", "top1", "Shadow_03", "top1", "Shadow_20", "top1", "Shadow_02", "right3", "Shadow_19", "right2", "Shadow_19", "right1", "Shadow_01", "right2", "Shadow_02", "right1", "Shadow_11", "left1", "Shadow_27", "left1", "Shadow_26", "right2", "Shadow_08", "left1", "Shadow_09", "left3", "Shadow_09", "right1", "Aqueduct_02", "left1", "Aqueduct_03", "left1", "Aqueduct_07", "right1", "Aqueduct_04", "right1", "Aqueduct_01", "right1", "Aqueduct_08", "left1", "Aqueduct_05", "left1", "Aqueduct_02", "right1", "Aqueduct_06", "bot1", "Aqueduct_02", "left2", "Aqueduct_03", "right1", "Aqueduct_03", "top1", "Aqueduct_08", "right1", "Aqueduct_02", "left3", "Belltown_08", "right1", "Greymoor_06", "left1", "Wisp_02", "right1", "Wisp_08", "left1", "Wisp_02", "top1", "Wisp_09", "right1", "Wisp_03", "top1", "Wisp_08", "right1", "Wisp_04", "right1", "Wisp_07", "left1", "Wisp_05", "left1", "Shellwood_01b", "right2", "Shellwood_02", "right2", "Shellwood_13", "left2", "Shellwood_01", "left1", "Shellwood_15", "left1", "Shellwood_20", "right1", "Shellwood_02", "right1", "Shellwood_01b", "left2", "Shellwood_16", "right1", "Shellwood_01", "left2", "Shellwood_19", "right1", "Mosstown_03", "top1", "Shellwood_14", "left1", "Shellwood_04b", "right1", "Shellwood_10", "left3", "Shellwood_16", "left1", "Shellwood_03", "left3", "Shellwood_08c", "right1", "Shellwood_04c", "bot1", "Shellwood_08", "bot1", "Shellwood_04b", "top1", "Coral_19", "right1", "Shellwood_04c", "top1", "Shellwood_04b", "left1", "Shellwood_26", "left1", "Shellwood_20", "left1", "Shellwood_11", "right2", "Shellwood_11", "right1", "Shellwood_18", "left1", "Shellwood_03", "right1", "Shellwood_10", "left2", "Shellwood_10", "left1", "Shellwood_18", "right1", "Shellwood_01b", "right1", "Shellwood_03", "right2", "Shellwood_01b", "right3", "Shellwood_03", "right3", "Shellwood_02", "left2", "Shellwood_10", "right3", "Shellwood_13", "left1", "Shellwood_03", "left1", "Shellwood_01b", "left1", "Shellwood_10", "right2", "Shellwood_25b", "left1", "Shellwood_10", "right1", "Shellwood_18", "top1", "Shellwood_02", "left3", "Shellwood_04b", "top2", "Coral_03", "left3", "Coral_19", "top2", "Coral_12", "left2", "Coral_32", "left1", "Coral_19", "top6", "Coral_11", "right1", "Coral_19", "top8", "Coral_02", "right1", "Coral_19", "top4", "Coral_19", "top5", "Coral_19", "top3", "Coral_19", "top7", "Coral_12", "left3", "Song_19_entrance", "left1", "Coral_Judge_Arena", "right1", "Coral_03", "left2", "Coral_11b", "right1", "Coral_34", "right1", "Coral_11", "left1", "Coral_37", "left1", "Coral_03", "right2", "Coral_03", "right3", "Coral_02", "bot2", "Coral_39", "right1", "Coral_35b", "left3", "Coral_25", "right1", "Coral_35b", "right2", "Coral_26", "left1", "Coral_34", "top1", "Coral_23", "left1", "Coral_44", "right1", "Coral_24", "right1", "Coral_38", "left1", "Coral_28", "right1", "Coral_35b", "left2", "Coral_27", "left1", "Coral_Tower_01", "left1", "Coral_03", "right1", "Coral_38", "bot1", "Coral_Judge_Arena", "left1", "Coral_43", "left1", "Coral_11b", "left1", "Coral_25", "bot1", "Coral_35b", "bot1", "Coral_36", "left1", "Coral_42", "right1", "Coral_43", "right1", "Coral_29", "left1", "Coral_23", "right1", "Coral_35", "top1", "Coral_24", "left1", "Coral_27", "right1", "Coral_41", "right1", "Coral_44", "left1", "Coral_40", "right1", "Coral_35", "right2", "Coral_12", "right1", "Coral_26", "right1", "Coral_32", "top1", "Coral_23", "left2", "Coral_35b", "left4", "Coral_35b", "left5", "Coral_35", "left2", "Coral_35", "left1", "Coral_33", "right1", "Coral_10", "left1", "Coral_32", "right1", "Song_19_entrance", "right2", "Under_27", "right2", "Under_27", "right1", "Under_01b", "left1", "Under_01", "right1", "Under_02", "left1", "Under_03b", "left1", "Under_07", "left3", "Under_14", "left1", "Under_16", "right1", "Under_01b", "right1", "Under_07c", "left2", "Under_03c", "left2", "Under_02", "right3", "Under_03c", "left1", "Under_03b", "right1", "Under_03", "right1", "Under_04", "left1", "Under_04", "top1", "Under_03c", "right1", "Under_05", "left2", "Under_06", "right1", "Under_12", "left1", "Under_04", "right1", "Under_10", "left1", "Under_23", "right1", "Under_11", "left1", "Under_07", "right2", "Under_05", "left1", "Under_06", "left1", "Under_07c", "bot1", "Under_02", "right2", "Under_07c", "top1", "Under_07", "top1", "Under_02", "right1", "Under_06", "top1", "Under_05", "right3", "Under_13", "left2", "Under_05", "right1", "Under_13", "left1", "Under_05", "right2", "Under_21", "right1", "Under_19", "left1", "Under_11", "right1", "Under_17", "left1", "Under_22", "right1", "Under_18", "left1", "Under_10", "right1", "Under_02", "right4", "Under_02", "left3", "Under_13", "right1", "Under_18", "top1", "Under_20", "left1", "Under_13", "right2", "Under_19c", "left1", "Under_13", "right3", "Under_19c", "left2", "Under_18", "right1", "Under_19b", "right1", "Under_19", "top1", "Under_13", "left3", "Under_13", "left4", "Under_05", "left3", "Song_01c", "top1", "Song_01b", "bot1", "Song_02", "left2", "Song_03", "bot1", "Song_01", "top1", "Song_19_entrance", "right1", "Song_01", "bot1", "Song_05", "left5", "Song_01b", "right1", "Song_01b", "top1", "Song_04", "bot1", "Song_03", "top1", "Slab_01", "right1", "Song_12", "left1", "Song_10", "left1", "Song_27", "left1", "Ward_01", "left1", "Song_02", "right1", "Song_07", "right1", "Song_11", "right3", "Song_18", "left1", "Song_05", "left4", "Song_12", "left3", "Cog_05", "left1", "Song_09b", "top1", "Song_09", "bot1", "Song_11", "right1", "Song_04", "right2", "Song_11", "left4", "Song_17", "right1", "Song_15", "right1", "Song_10", "right1", "Song_05", "left3", "Song_13", "right1", "Song_09b", "left1", "Song_26", "right1", "Song_04", "right1", "Song_15", "left1", "Song_08", "right1", "Song_28", "right1", "Song_14", "left1", "Song_13", "left1", "Song_11", "left3", "Song_12", "right3", "Song_12", "right2", "Song_11", "left2", "Song_12", "right1", "Song_11", "left1", "Song_05", "right2", "Song_27", "top1", "Song_01c", "left1", "Under_01", "left1", "Song_27", "right1", "Bellway_City", "left1", "Library_03", "left1", "Library_13", "left1", "Song_24", "right1", "Song_29", "right1", "Song_20", "top1", "Library_02", "left1", "Library_02", "left2", "Cog_06", "right1", "Song_20", "left2", "Cog_Dancers", "right1", "Song_20b", "top1", "Song_12", "left2", "Song_18", "bot1", "Song_20", "left1", "Song_05", "right4", "Library_02", "right2", "Song_25", "right1", "Library_04", "top1", "Song_20", "left1", "Song_05", "right3", "Ward_02", "right1", "Ward_05", "left1", "Ward_02b", "right1", "Ward_04", "left1", "Ward_03", "left1", "Ward_01", "left3", "Ward_02b", "bot1", "Ward_02", "top1", "Ward_01", "left2", "Ward_06", "top1", "Ward_01", "right1", "Ward_07", "bot1", "Ward_09", "left1", "Ward_01", "right2", "Ward_01", "right3", "Ward_03", "bot1", "Ward_03", "top1", "Library_04", "left2", "Library_03", "right1", "Library_04", "left1", "Library_02", "right1", "Library_15", "right1", "Library_01", "left1", "Library_01", "left2", "Library_14", "left1", "Library_05", "left1", "Library_16", "right1", "Library_13b", "right1", "Library_01", "right2", "Library_05", "left2", "Library_09", "left1", "Library_01", "right1", "Library_10", "left1", "Library_08", "left1", "Library_04", "right4", "Library_06", "left2", "Library_06", "left1", "Library_04", "right3", "Library_05", "right2", "Library_07", "left2", "Library_05", "right1", "Library_08", "right1", "Library_06", "right1", "Library_07", "left1", "Library_04", "right2", "Library_07", "top1", "Library_04", "right1", "Library_12b", "top1", "Library_04", "right5", "Library_13", "right2", "Bellway_City", "right1", "Library_12", "left2", "Library_11b", "right1", "Library_12", "left1", "Library_11", "left3", "Library_11", "right1", "Library_11", "right2", "Library_12b", "left1", "Library_12", "right1", "Library_10", "bot1", "Library_13b", "left1", "Library_11", "left1", "Library_13", "right1", "Library_04", "left3", "Library_04", "right6", "Library_01", "left3", "Library_04", "left4", "Hang_02", "left1", "Hang_03", "left1", "Hang_01", "right1", "Hang_13", "left1", "Hang_15", "right1", "Hang_10", "left1", "Hang_02", "right1", "Hang_03", "top1", "Hang_12", "right1", "Hang_06", "left1", "Hang_04", "right1", "Hang_07", "top1", "Hang_06b", "left1", "Hang_06", "right1", "Hang_06", "bot1", "Hang_10", "right1", "Hang_06", "top1", "Hang_16", "right1", "Hang_17b", "left1", "Hang_09", "right1", "Hang_13", "right1", "Hang_08", "left2", "Hang_03", "right2", "Hang_08", "left3", "Hang_04", "left1", "Hang_08", "left1", "Hang_03", "right1", "Hang_03", "left2", "Hang_08", "left4", "Hang_14", "left1", "Hang_08", "right1", "Arborium_06", "left1", "Arborium_Tube", "right1", "Arborium_08", "left1", "Arborium_09", "right1", "Arborium_04", "left1", "Arborium_07", "left1", "Arborium_02", "left1", "Arborium_03", "left3", "Arborium_01", "right4", "Arborium_06", "right1", "Arborium_02", "right1", "Arborium_04", "right1", "Arborium_05", "right1", "Arborium_10", "left1", "Arborium_11", "left1", "Arborium_01", "right5", "Arborium_03", "left4", "Arborium_06", "bot1", "Arborium_03", "left2", "Arborium_03", "left1", "Arborium_05", "top1", "Arborium_01", "right3", "Arborium_01", "right2", "Arborium_08", "bot1", "Arborium_07", "top1", "Arborium_01", "right1", "Arborium_01", "left1", "Arborium_01", "left2", "Arborium_03", "right1", "Arborium_03", "right2", "Aqueduct_01", "left1", "Arborium_01", "left3", "Cog_07", "left1", "Cog_05", "right2", "Cog_Pass", "left2", "Cog_06", "left2", "Cog_Dancers", "bot1", "Cog_Dancers", "bot2", "Cog_04", "left2", "Cog_10", "bot1", "Cog_04", "right2", "Cog_04", "right3", "Cog_Dancers", "top1", "Cog_09", "bot1", "Cog_08", "top1", "Cog_05", "top1", "Cog_Pass", "left1", "Cog_04", "top1", "Cog_04", "top2", "Cog_08", "bot1", "Peak_01", "right4", "Peak_01", "right3", "Peak_01", "right2", "Peak_01", "right1", "Peak_07", "bot1", "Peak_01", "left4", "Peak_01", "left1", "Peak_10", "right1", "Peak_01", "left2", "Peak_01", "left3", "Peak_05e", "right1", "Bellway_Peak", "right1", "Peak_04d", "left1", "Bellway_Peak", "left2", "Bellway_Peak", "left1", "Peak_02", "left1", "Peak_04", "right1", "Peak_08", "bot1", "Bellway_Peak", "top1", "Peak_05c", "left2", "Peak_05e", "left1", "Peak_05", "right3", "Peak_08", "top1", "Peak_06b", "left1", "Peak_02", "left3", "Peak_05c", "right1", "Peak_08b", "bot5", "Peak_01", "top3", "Peak_01", "top1", "Peak_08b", "bot4", "Peak_01", "top2", "Peak_05", "top2", "Peak_05d", "bot1", "Peak_08b", "left1", "Peak_12", "right1", "Peak_07", "top2", "Peak_08", "right1", "Peak_07", "top1", "Peak_02", "left2", "Peak_08b", "left2", "Slab_01", "left1", "Slab_16", "right1", "Slab_20", "left1", "Slab_04", "right1", "Slab_13", "right1", "Slab_17", "left1", "Slab_02", "left1", "Slab_15", "right1", "Slab_19b", "left1", "Slab_05", "right1", "Slab_07", "right2", "Slab_07", "right1", "Slab_14", "right1", "Slab_23", "left1", "Slab_12", "left1", "Slab_08", "left1", "Slab_18", "left1", "Slab_03", "left5", "Slab_05", "top1", "Slab_06", "top1", "Slab_04", "bot1", "Slab_03", "left6", "Slab_05", "bot1", "Peak_01", "right4", "Slab_03", "left8", "Slab_03", "left7", "Slab_03", "right8", "Slab_19b", "right1", "Slab_10b", "left1", "Slab_03", "right9", "Peak_01", "right3", "Slab_04", "top1", "Slab_03", "left4", "Slab_15", "bot1", "Slab_03", "left3", "Peak_01", "right2", "Slab_14", "top1", "Slab_16", "bot1", "Slab_03", "left2", "Slab_16b", "left1", "Slab_15", "top1", "Peak_01", "right1", "Slab_03", "left1", "Slab_03", "right1", "Slab_21", "left1", "Slab_03", "right2", "Slab_10c", "left1", "Slab_03", "right3", "Slab_23", "right1", "Slab_18", "right1", "Slab_16", "top1", "Slab_21", "top1", "Slab_03", "right4", "Slab_21", "left3", "Slab_13", "left1", "Weave_11", "right1", "Weave_07", "right1", "Weave_10", "left1", "Weave_12", "left1", "Weave_13", "left1", "Weave_04", "right2", "Weave_07", "left1", "Weave_02", "left2", "Tut_01b", "right1", "Weave_08", "right1", "Weave_02", "left4", "Weave_03", "right1", "Weave_13", "right1", "Weave_05b", "left1", "Weave_02", "right3", "Weave_02", "left3", "Weave_02", "right1", "Weave_02", "right2", "Weave_08", "left1", "Weave_11", "top1", "Clover_20", "left1", "Clover_02c", "left1", "Clover_03", "left2", "Clover_05c", "right3", "Clover_01b", "right1", "Clover_04b", "right1", "Clover_02c", "right1", "Clover_18", "left1", "Clover_03", "left1", "Clover_10_web", "left1", "Clover_11", "right1", "Clover_05c", "right1", "Clover_19", "left1", "Clover_21", "right1", "Clover_16", "right1", "Clover_04b", "left2", "Clover_02c", "left2", "Clover_04b", "left1", "Clover_05c", "left1", "Clover_06", "bot1", "Clover_03", "right1", "Clover_06", "bot2", "Clover_05c", "right2", "Clover_01", "right1", "Abyss_02b", "left2", "Abyss_06", "right1", "Abyss_07", "left1", "Abyss_04", "left1", "Abyss_02b", "right1", "Abyss_03", "left1", "Abyss_01", "right2", "Abyss_11", "bot1", "Abyss_02", "left1", "Abyss_13", "right1", "Abyss_02", "right1", "Abyss_01", "right3", "Abyss_08", "left1", "Abyss_12", "right2", "Abyss_01", "left1", "Abyss_01", "right4", "Abyss_12", "left1", "Abyss_05", "right1", "Abyss_13", "top1", "Abyss_13", "left1", "Abyss_02b", "top1", "Abyss_05", "left2", "Abyss_07", "right1", "Abyss_11", "right1", "Abyss_03", "left2", "Abyss_09", "bot1" }; private static readonly HashSet<string> _zoneBlacklist = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Tut_01", "Tut_01b", "Tut_02", "Tut_03", "Tut_04", "Tut_05", "Aspid_01", "Bonegrave", "Bone_Steel_Servant", "Chapel_Wanderer", "Room_Caravan_Spa", "Room_Caravan_Interior", "Room_CrowCourt", "Room_Forge", "Room_Huntress", "Room_Witch", "Room_Pinstress", "Room_Diving_Bell", "Room_Diving_Bell_Abyss", "Room_Diving_Bell_Abyss_Fixed", "Song_Tower_01", "Song_Tower_Destroyed", "Song_Enclave_Tube", "Bellshrine_Enclave", "Bellshrine_Coral", "Bellway_Shadow", "Cradle_01", "Cradle_02", "Cradle_03", "Cradle_01_Destroyed", "Cradle_02b", "Cradle_03_Destroyed", "Cradle_Destroyed_Challenge_01", "Cradle_Destroyed_Challenge_02", "Cradle_Destroyed_Challenge_Bench", "Abandoned_town", "Tube_Hub", "Sprintmaster_Cave", "Bone_East_LavaChallenge", "Bone_03", "Bone_East_Weavehome", "Shadow_Weavehome", "Bone_East_Umbrella", "Ant_Queen", "Slab_Cell", "Slab_Cell_Quiet", "Slab_Cell_Creature", "Slab_10c", "Slab_10b", "Peak_Mask_Maker", "Cog_10_Destroyed", "Cog_09_Destroyed", "Cog_11_Destroyed", "Coral_Judge_Arena", "Ant_Merchant" }; private static bool _zoneTeleportFired = false; private static readonly Dictionary<string, string> _skillDisplayNames = new Dictionary<string, string> { { "hasDash", "Swift Step" }, { "hasBrolly", "Drifter's Cloak" }, { "hasWalljump", "Cling Grip" }, { "hasDoubleJump", "Faydown Cloak" }, { "hasChargeSlash", "Needle Strike" }, { "hasSuperJump", "Silk Soar" } }; private static FieldInfo _siSavedItem; private static FieldInfo _siCost; private static FieldInfo _siDisplayName; private static FieldInfo _siDescription; private static FieldInfo _siItemSprite; private static bool _siFieldsCached = false; private static readonly Dictionary<string, ShopItemBackup[]> _originalStock = new Dictionary<string, ShopItemBackup[]>(); private static readonly HashSet<int> _shopBeingRandomized = new HashSet<int>(); private static readonly Dictionary<string, string> _randomizedThisScene = new Dictionary<string, string>(); private static string DataFolder { get { string text = Path.Combine(Path.GetDirectoryName(Application.dataPath), "RandomizerModData"); Directory.CreateDirectory(text); return text; } } private static string SeedsFilePath => Path.Combine(DataFolder, "seeds.txt"); private static string EnemyPoolPath => Path.Combine(DataFolder, "enemies.txt"); private static void CachePBIFields() { if (!_pbiFieldsCached) { Type typeFromHandle = typeof(PersistentBoolItem); _pbiIdField = AccessTools.Field(typeFromHandle, "id") ?? AccessTools.Field(typeFromHandle, "ID") ?? AccessTools.Field(typeFromHandle, "persistentBoolId"); _pbiSceneNameField = AccessTools.Field(typeFromHandle, "sceneName") ?? AccessTools.Field(typeFromHandle, "SceneName"); _pbiFieldsCached = true; } } private static string AssignmentsPath(int profileID) { return Path.Combine(DataFolder, $"assignments_{profileID}.txt"); } private void Awake() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Expected O, but got Unknown //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Expected O, but got Unknown //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Expected O, but got Unknown //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Expected O, but got Unknown //IL_05ba: Unknown result type (might be due to invalid IL or missing references) //IL_05c0: Expected O, but got Unknown //IL_0624: Unknown result type (might be due to invalid IL or missing references) //IL_062a: Expected O, but got Unknown //IL_0601: Unknown result type (might be due to invalid IL or missing references) //IL_060e: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; DeathMonitor = ((Component)this).gameObject.AddComponent<EnemyDeathMonitor>(); CfgCustomSeed = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "Custom Seed (New Games)", 0, new ConfigDescription("Seed for new games (0 = random)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 999999999), Array.Empty<object>())); CfgOverrideSeed = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "Override Seed (Existing Save)", 0, new ConfigDescription("Override the seed of the current loaded save (0 = disabled). Set this, load your save and it will apply.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 999999999), Array.Empty<object>())); CfgSeedKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("1 - General", "Seed Display Key", (KeyCode)48, "Key to toggle seed display in-game"); CfgRandomizeShops = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Randomize Shops", true, "Randomize items in shops"); CfgShopMinSlots = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "Shop Min Slots (Not Working)", 1, new ConfigDescription("Minimum items per shop", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>())); CfgShopMaxSlots = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "Shop Max Slots (Not Working)", 10, new ConfigDescription("Maximum items per shop", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>())); CfgRandomizeMaskShards = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Randomize Mask Shards", false, "Randomize Hornet mask shards (ONLY IN NEW GAMES!!!)"); CfgMinMaskShards = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "Min Mask Shards", 5, new ConfigDescription("Minimum Mask Shards hornet can have", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>())); CfgMaxMaskShards = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "Max Mask Shards", 10, new ConfigDescription("Maximum Mask Shards hornet can have", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>())); CfgRandomizeNeedleUpgrades = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Randomize Needle Upgrades", false, "Randomize Needle Upgrades at the start of a new game"); CfgMinNeedleUpgrades = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "Min Needle Upgrades", 0, new ConfigDescription("Minimum needle upgrade level (0=base 5dmg, 1=9dmg, 2=13dmg, 3=17dmg, 4=21dmg)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 4), Array.Empty<object>())); CfgMaxNeedleUpgrades = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "Max Needle Upgrades", 4, new ConfigDescription("Maximum needle upgrade level (0=base 5dmg, 1=9dmg, 2=13dmg, 3=17dmg, 4=21dmg)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 4), Array.Empty<object>())); CfgRandomizeSkills = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Randomize Skills", false, "Start new game with random pillar skills (ONLY IN NEW GAMES!!!)"); CfgSkillCount = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "Skill Count", 3, new ConfigDescription("How many random skills to start with (0-7)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 6), Array.Empty<object>())); CfgRandomizeZone = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Randomize Starting Zone", false, "Spawn in a random zone when starting or loading a game (seed-deterministic)"); CfgRandomizeQuests = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Randomize Quest Rewards (NOT WORKING!!!)", false, "Quest completion rewards will be random items from the item pool"); CfgEnemiesRandomizer = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Enemies", "Enemies Randomizer", false, "Randomize regular enemy encounters"); CfgBossesRandomizer = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Enemies", "Bosses Randomizer (Not Working)", false, "Randomize boss encounters (disabled until further development)"); CfgShakraShopRandomizer = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Enemies", "Shakra Shop Randomizer (Not Working)", false, "(Not implemented) Randomize Shakra shop"); CfgEnemyActFilter = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Enemies", "Enemy Replacement Act Filter", "All", new ConfigDescription("Which act enemies can be used as replacements (All, Act1, Act2, Act3)", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "All", "Act1", "Act2", "Act3" }), Array.Empty<object>())); CfgEnemyCustomBlacklist = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Enemies", "Custom Enemy Blacklist", "", "Comma-separated enemy names to never use as replacements. Example: Skarrlid,Penitent"); CfgFloorSkill = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Types of Randomizer Items", "Skill items", true, "Allow randomized Skill Items in the ground"); CfgFloorCrest = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Types of Randomizer Items", "Crest items", true, "Allow randomized Crest Items in the ground"); CfgFloorConsumable = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Types of Randomizer Items", "Consumable items", true, "Allow randomized Consumable Items in the ground"); CfgFloorTool = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Types of Randomizer Items", "Tool items", true, "Allow randomized Tool Items in the ground"); CfgFloorMemento = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Types of Randomizer Items", "Memento items", true, "Allow randomized Memento Items in the ground"); CfgFloorCombat = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Types of Randomizer Items", "Combat items", true, "Allow randomized Combat Items in the ground"); CfgFloorRelic = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Types of Randomizer Items", "Relic items", false, "Allow randomized Relic Items in the ground"); CfgFloorItem = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Types of Randomizer Items", "Normal items", true, "Allow randomized Normal Items in the ground"); CfgShopSkill = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Types of Shop Items", "Skill Shop items (Buggy)", true, "Allow randomized Skill Items on Shops"); CfgShopCrest = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Types of Shop Items", "Crest Shop items", true, "Allow randomized Crest Items on Shops"); CfgShopConsumable = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Types of Shop Items", "Consumable Shop items", true, "Allow randomized Consumable Items on Shops"); CfgShopTool = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Types of Shop Items", "Tool Shop items", true, "Allow randomized Tool Items on Shops"); CfgShopMemento = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Types of Shop Items", "Memento Shop items", true, "Allow randomized Memento Items on Shops"); CfgShopCombat = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Types of Shop Items", "Combat Shop items", true, "Allow randomized Combat Items on Shops"); CfgShopRelic = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Types of Shop Items", "Relic Shop items", false, "Allow randomized Relic Items on Shops"); CfgShopItem = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Types of Shop Items", "Shop normal items", true, "Allow randomized normal Items on Shops"); Log.LogInfo((object)"Silksong Randomizer loaded!"); Harmony val = new Harmony("com.tuusuario.silksong.randomizer"); val.PatchAll(); try { MethodInfo method = typeof(ReplacementDeathPatch).GetMethod("Postfix", BindingFlags.Static | BindingFlags.Public); MethodInfo method2 = typeof(HealthManager).GetMethod("SendDeathEvent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method2 != null) { val.Patch((MethodBase)method2, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"[DropFix] Patched HealthManager.SendDeathEvent"); } else { HarmonyMethod val2 = new HarmonyMethod(method); MethodInfo method3 = typeof(HealthManager).GetMethod("Die", BindingFlags.Instance | BindingFlags.Public, null, new Type[3] { typeof(float?), typeof(AttackTypes), typeof(bool) }, null); MethodInfo method4 = typeof(HealthManager).GetMethod("Die", BindingFlags.Instance | BindingFlags.Public, null, new Type[4] { typeof(float?), typeof(AttackTypes), typeof(bool), typeof(float) }, null); MethodInfo method5 = typeof(HealthManager).GetMethod("Die", BindingFlags.Instance | BindingFlags.Public, null, new Type[8] { typeof(float?), typeof(AttackTypes), typeof(NailElements), typeof(GameObject), typeof(bool), typeof(float), typeof(bool), typeof(bool) }, null); if (method3 != null) { val.Patch((MethodBase)method3, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"[DropFix] Fallback: Patched Die(3)"); } if (method4 != null) { val.Patch((MethodBase)method4, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"[DropFix] Fallback: Patched Die(4)"); } if (method5 != null) { val.Patch((MethodBase)method5, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"[DropFix] Fallback: Patched Die(8)"); } Log.LogWarning((object)"[DropFix] SendDeathEvent not found — using Die fallback"); } } catch (Exception ex) { Log.LogWarning((object)("[DropFix] Failed to patch: " + ex.Message)); } CreatePopupUI(); CreateSeedUI(); LoadEnemyPool(); MigrateOldFiles(); } private void Start() { SceneManager.sceneLoaded += OnSceneLoaded; } private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(CfgSeedKey.Value)) { seedVisible = !seedVisible; seedCanvas.SetActive(seedVisible); } } private static void MigrateOldFiles() { try { string directoryName = Path.GetDirectoryName(Application.dataPath); string text = Path.Combine(directoryName, "randomizer_enemies.txt"); if (File.Exists(text) && !File.Exists(EnemyPoolPath)) { File.Move(text, EnemyPoolPath); } Dictionary<int, int> dictionary = LoadAllSeeds(); string[] files = Directory.GetFiles(directoryName, "randomizer_seed_*.txt"); foreach (string path in files) { if (int.TryParse(Path.GetFileNameWithoutExtension(path).Replace("randomizer_seed_", ""), out var result) && !dictionary.ContainsKey(result)) { if (int.TryParse(File.ReadAllText(path).Trim(), out var result2)) { dictionary[result] = result2; Log.LogInfo((object)$"[Migrate] Migrated seed for profile {result}: {result2}"); } File.Delete(path); } } SaveAllSeeds(dictionary); files = Directory.GetFiles(directoryName, "randomizer_assignments_*.txt"); foreach (string text2 in files) { if (int.TryParse(Path.GetFileNameWithoutExtension(text2).Replace("randomizer_assignments_", ""), out var result3)) { string text3 = AssignmentsPath(result3); if (!File.Exists(text3)) { File.Move(text2, text3); Log.LogInfo((object)$"[Migrate] Moved assignments_{result3}.txt → RandomizerModData/"); } } } } catch (Exception ex) { Log.LogWarning((object)("[Migrate] Error: " + ex.Message)); } } private static Font GetGameFont() { Font[] array = Resources.FindObjectsOfTypeAll<Font>(); Font[] array2 = array; foreach (Font val in array2) { if (((Object)val).name == "TrajanPro-Regular") { return val; } } array2 = array; foreach (Font val2 in array2) { if (((Object)val2).name == "TrajanPro-Bold") { return val2; } } return Resources.GetBuiltinResource<Font>("Arial.ttf"); } private void CreateSeedUI() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) seedCanvas = new GameObject("SeedDisplay"); Object.DontDestroyOnLoad((Object)(object)seedCanvas); Canvas obj = seedCanvas.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 998; seedCanvas.AddComponent<CanvasScaler>(); GameObject val = new GameObject("SeedText"); val.transform.SetParent(seedCanvas.transform, false); seedText = val.AddComponent<Text>(); seedText.font = GetGameFont(); seedText.fontSize = 18; seedText.alignment = (TextAnchor)2; ((Graphic)seedText).color = new Color(1f, 1f, 1f, 0.4f); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(1f, 1f); component.offsetMin = new Vector2(0f, 0f); component.offsetMax = new Vector2(-20f, -20f); seedCanvas.SetActive(false); } private void CreatePopupUI() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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_0177: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Expected O, but got Unknown //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) popupCanvas = new GameObject("RandomizerPopup"); Object.DontDestroyOnLoad((Object)(object)popupCanvas); Canvas obj = popupCanvas.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 999; popupCanvas.AddComponent<CanvasScaler>(); popupCanvas.AddComponent<GraphicRaycaster>(); GameObject val = new GameObject("Background"); val.transform.SetParent(popupCanvas.transform, false); ((Graphic)val.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.75f); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(1f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(1f, 1f); component.anchoredPosition = new Vector2(-20f, -20f); component.sizeDelta = new Vector2(500f, 80f); GameObject val2 = new GameObject("OriginalIcon"); val2.transform.SetParent(val.transform, false); originalIcon = val2.AddComponent<Image>(); ((Graphic)originalIcon).color = Color.white; RectTransform component2 = val2.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0f, 0.5f); component2.anchorMax = new Vector2(0f, 0.5f); component2.pivot = new Vector2(0f, 0.5f); component2.anchoredPosition = new Vector2(10f, 0f); component2.sizeDelta = new Vector2(48f, 48f); GameObject val3 = new GameObject("RandomIcon"); val3.transform.SetParent(val.transform, false); randomIcon = val3.AddComponent<Image>(); ((Graphic)randomIcon).color = Color.white; RectTransform component3 = val3.GetComponent<RectTransform>(); component3.anchorMin = new Vector2(1f, 0.5f); component3.anchorMax = new Vector2(1f, 0.5f); component3.pivot = new Vector2(1f, 0.5f); component3.anchoredPosition = new Vector2(-10f, 0f); component3.sizeDelta = new Vector2(48f, 48f); GameObject val4 = new GameObject("PopupText"); val4.transform.SetParent(val.transform, false); popupText = val4.AddComponent<Text>(); popupText.font = GetGameFont(); popupText.fontSize = 15; popupText.alignment = (TextAnchor)4; ((Graphic)popupText).color = Color.white; RectTransform component4 = val4.GetComponent<RectTransform>(); component4.anchorMin = new Vector2(0.15f, 0f); component4.anchorMax = new Vector2(0.85f, 1f); component4.offsetMin = Vector2.zero; component4.offsetMax = Vector2.zero; popupCanvas.SetActive(false); } public static void SaveEnemyPool() { try { List<string> list = new List<string>(knownEnemyNames); list.Sort(); File.WriteAllLines(EnemyPoolPath, list.ToArray()); Log.LogInfo((object)$"[EnemyPool] Saved {list.Count} enemies"); } catch (Exception ex) { Log.LogWarning((object)("[EnemyPool] Can't save: " + ex.Message)); } } public static void LoadEnemyPool() { try { if (!File.Exists(EnemyPoolPath)) { return; } string[] array = File.ReadAllLines(EnemyPoolPath); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (!string.IsNullOrEmpty(text)) { knownEnemyNames.Add(text); } } Log.LogInfo((object)$"[EnemyPool] Loaded {knownEnemyNames.Count} enemies from file"); } catch (Exception ex) { Log.LogWarning((object)("[EnemyPool] Can't load: " + ex.Message)); } } [IteratorStateMachine(typeof(<AccumulateEnemyPoolDelayed>d__80))] private IEnumerator AccumulateEnemyPoolDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AccumulateEnemyPoolDelayed>d__80(0); } private static void AccumulateEnemyPool() { HealthManager[] array = Resources.FindObjectsOfTypeAll<HealthManager>(); bool flag = false; HealthManager[] array2 = array; foreach (HealthManager val in array2) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null)) { string text = Regex.Replace(((Object)((Component)val).gameObject).name, "\\s*\\(\\d+\\)$", "").Trim(); if (knownEnemyNames.Add(text)) { Log.LogInfo((object)("[EnemyNew] " + text)); flag = true; } } } if (flag) { SaveEnemyPool(); } } private static int GetActForPrefabScene(string sceneName) { if (Act1Scenes.Contains(sceneName)) { return 1; } if (Act2Scenes.Contains(sceneName)) { return 2; } return 3; } private static HashSet<string> GetCustomBlacklistNames() { HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); string[] array = (CfgEnemyCustomBlacklist?.Value ?? "").Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (!string.IsNullOrEmpty(text)) { hashSet.Add(text); } } return hashSet; } private static PlaceableObject[] GetEnemyPool() { if (!PreloadManager.HasPreloaded) { return null; } try { string text = CfgEnemyActFilter?.Value ?? "All"; int targetAct = text switch { "Act3" => 3, "Act2" => 2, "Act1" => 1, _ => 0, }; HashSet<string> customBlacklist = GetCustomBlacklistNames(); PlaceableObject[] array = (from o in ((AbstractCategory)Categories.Enemies).GetObjects().OfType<PlaceableObject>() where (Object)(object)o.Prefab != (Object)null && (Object)(object)o.Prefab.GetComponent<HealthManager>() != (Object)null select o).Where(delegate(PlaceableObject o) { //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) string text2 = ((Object)o.Prefab).name.ToLower(); foreach (string bossName in bossNames) { if (text2.Contains(bossName.ToLower())) { return false; } } foreach (string item in enemyPoolBlacklist) { if (text2.Contains(item.ToLower())) { Log.LogInfo((object)("[EnemyPool] Blacklisted: '" + ((Object)o.Prefab).name + "'")); return false; } } foreach (string item2 in customBlacklist) { if (((Object)o.Prefab).name.IndexOf(item2, StringComparison.OrdinalIgnoreCase) >= 0) { Log.LogInfo((object)("[EnemyPool] Custom blacklisted: '" + ((Object)o.Prefab).name + "'")); return false; } } if (targetAct > 0) { Scene scene = o.Prefab.scene; string name = ((Scene)(ref scene)).name; if (!string.IsNullOrEmpty(name) && GetActForPrefabScene(name) != targetAct) { return false; } } return true; }).ToArray(); PlaceableObject[] array2 = array; foreach (PlaceableObject val in array2) { if (((Object)val.Prefab).name.ToLower().Contains("flea") || ((Object)val.Prefab).name.ToLower().Contains("fertid")) { Log.LogInfo((object)("[EnemyPool] WARNING — possibly should be blacklisted: '" + ((Object)val.Prefab).name + "'")); } } Log.LogInfo((object)$"[EnemyRando] Enemy pool: {array.Length} (act filter: {text})"); return array; } catch (Exception ex) { Log.LogWarning((object)("[EnemyRando] Pool error: " + ex.Message)); return null; } } private static PlaceableObject[] GetBossPool() { if (!PreloadManager.HasPreloaded) { return null; } try { PlaceableObject[] array = (from o in Categories.All.GetObjects().OfType<PlaceableObject>() where (Object)(object)o.Prefab != (Object)null && (Object)(object)o.Prefab.GetComponent<HealthManager>() != (Object)null select o).Where(delegate(PlaceableObject o) { string text = ((Object)o.Prefab).name.ToLower(); bool flag = false; foreach (string bossName in bossNames) { if (text.Contains(bossName.ToLower())) { flag = true; break; } } if (!flag) { return false; } foreach (string item in bossReplacementBlacklist) { if (text.Contains(item.ToLower())) { return false; } } return true; }).ToArray(); Log.LogInfo((object)$"[EnemyRando] Boss pool: {array.Length}"); PlaceableObject[] array2 = array; foreach (PlaceableObject val in array2) { Log.LogInfo((object)("[BossPool] " + ((Object)val.Prefab).name)); } return array; } catch (Exception ex) { Log.LogWarning((object)("[EnemyRando] Boss pool error: " + ex.Message)); return null; } } private static bool IsBoss(HealthManager hm) { string text = ((Object)((Component)hm).gameObject).name.ToLower(); foreach (string bossName in bossNames) { if (text.Contains(bossName.ToLower())) { return true; } } return false; } private static bool IsBossMinion(HealthManager hm) { string name = ((Object)((Component)hm).gameObject).name; bool flag = false; foreach (string bossMinionName in bossMinionNames) { if (name.StartsWith(bossMinionName, StringComparison.OrdinalIgnoreCase)) { flag = true; break; } } if (!flag) { return false; } HealthManager[] array = Object.FindObjectsByType<HealthManager>((FindObjectsSortMode)0); foreach (HealthManager val in array) { if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)hm && !val.isDead && IsBoss(val)) { return true; } } return false; } public static void RandomizeEnemy(HealthManager hm) { if ((Object)(object)hm == (Object)null || (Object)(object)((Component)hm).gameObject == (Object)null || (Object)(object)((Component)hm).gameObject.GetComponent<ReplacedByRando>() != (Object)null || (Object)(object)((Component)hm).gameObject.GetComponent<RandoReplacement>() != (Object)null || IsBossMinion(hm)) { return; } bool flag = IsBoss(hm); if (flag || (!flag && !CfgEnemiesRandomizer.Value) || !PreloadManager.HasPreloaded) { return; } PlaceableObject[] array = (flag ? GetBossPool() : GetEnemyPool()); if (array == null || array.Length == 0) { if (flag) { Log.LogInfo((object)("[EnemyRando] Skipped boss '" + ((Object)((Component)hm).gameObject).name + "' — boss pool empty")); } } else { ((MonoBehaviour)Instance).StartCoroutine(DoEnemyRando(hm, array, flag)); } } private static float GetEnemyHalfHeight(GameObject prefab) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return 0.5f; } SpriteRenderer componentInChildren = prefab.GetComponentInChildren<SpriteRenderer>(); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.sprite != (Object)null) { Bounds bounds = componentInChildren.sprite.bounds; float y = ((Bounds)(ref bounds)).extents.y; float num = Mathf.Abs(prefab.transform.localScale.y); return Mathf.Clamp(y * ((num > 0f) ? num : 1f), 0.6f, 6f); } return 0.5f; } private static List<PersistentBoolItem> GetNearbyPersistentItems(Vector3 pos, float radius = 8f) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) List<PersistentBoolItem> list = new List<PersistentBoolItem>(); PersistentBoolItem[] array = Object.FindObjectsByType<PersistentBoolItem>((FindObjectsSortMode)0); foreach (PersistentBoolItem val in array) { if ((Object)(object)val != (Object)null && Vector3.Distance(((Component)val).transform.position, pos) <= radius) { list.Add(val); } } return list; } internal static void ResetPersistentBoolItem(PersistentBoolItem pbi) { if ((Object)(object)pbi == (Object)null) { return; } try { pbi.SetValueOverride(false); Log.LogInfo((object)("[DropFix] SetValueOverride(false) on PBI '" + ((Object)((Component)pbi).gameObject).name + "'")); } catch (Exception ex) { ManualLogSource log = Log; object obj; if (pbi == null) { obj = null; } else { GameObject gameObject = ((Component)pbi).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } log.LogWarning((object)("[DropFix] ResetPBI failed for '" + (string?)obj + "': " + ex.Message)); } } [IteratorStateMachine(typeof(<DoEnemyRando>d__97))] private static IEnumerator DoEnemyRando(HealthManager hm, PlaceableObject[] pool, bool originalIsBoss) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DoEnemyRando>d__97(0) { hm = hm, pool = pool, originalIsBoss = originalIsBoss }; } [IteratorStateMachine(typeof(<KillOriginalAndRestoreDrops>d__98))] public static IEnumerator KillOriginalAndRestoreDrops(HealthManager hm, Vector3 originalPos, List<PersistentBoolItem> nearbyPBIs) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <KillOriginalAndRestoreDrops>d__98(0) { originalPos = originalPos, nearbyPBIs = nearbyPBIs }; } public static void ApplySeed(int seed) { currentSeed = seed; rng = new Random(seed); usedShopItems.Clear(); shopItemAssignments.Clear(); LoadAssignments(); Log.LogInfo((object)$"[Seed] Applied seed: {seed}"); if ((Object)(object)Instance != (Object)null && (Object)(object)Instance.seedText != (Object)null) { Instance.seedText.text = $"Seed: {seed}"; } } public static void ResetSeed() { currentSeed = 0; shopItemAssignments.Clear(); usedShopItems.Clear(); _zoneTeleportFired = false; if ((Object)(object)Instance != (Object)null && (Object)(object)Instance.seedText != (Object)null) { Instance.seedText.text = "Seed: -"; } if ((Object)(object)Instance != (Object)null) { Instance.seedVisible = false; Instance.seedCanvas.SetActive(false); } Log.LogInfo((object)"[Seed] Seed reset — in menu"); } public static int GenerateNewSeed() { return new Random().Next(100000, 999999999); } private static Dictionary<int, int> LoadAllSeeds() { Dictionary<int, int> dictionary = new Dict