Decompiled source of Super Hard and Extreme v2.0.0
SuperHardKnuckle.dll
Decompiled 2 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace SuperHardKnuckle; internal static class Buddy { public const string GivenFlag = "skmod_run_buddy_given"; public const string OldSavedFlag = "skmod_buddy_given"; [ThreadStatic] public static bool Granting; public static float Left = -1f; private static readonly HashSet<string> names = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static float runTime; private static bool granted; private static bool gaveUp; private static int attempts; private static float verifyAt = -1f; private static Trinket trinket; public static void Reset() { Left = -1f; runTime = 0f; granted = false; gaveUp = false; names.Clear(); attempts = 0; verifyAt = -1f; trinket = null; } public static void Tick() { if (!Cfg.BuddyEnabled.Value) { Left = -1f; return; } ENT_Player val = Util.Player(); if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead() || (Object)(object)Inventory.instance == (Object)null || ((Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.gMan.isPaused)) { return; } runTime += Time.deltaTime; if (!granted && !gaveUp && runTime > 2f) { Grant(); } if (!granted) { return; } if (verifyAt > 0f && runTime >= verifyAt) { if (HasBuddyInInventory()) { verifyAt = -1f; Util.Debug("Calming Buddy is in the inventory."); } else if (attempts < 3 && (Object)(object)trinket != (Object)null) { attempts++; Util.Debug("Calming Buddy missing from inventory, giving it again (try " + attempts + ")."); Granting = true; try { trinket.Activate(0f); } catch (Exception ex) { Util.LogOnce("buddyretry", "Retry failed: " + ex.Message); } finally { Granting = false; } verifyAt = runTime + 3f; } else { verifyAt = -1f; Util.LogOnce("buddygone", "Calming Buddy never showed up in the inventory."); } } if (Left < 0f) { Left = Cfg.BuddyPetSeconds.Value; } Left -= Time.deltaTime; if (!(Left <= 0f)) { return; } Left = Cfg.BuddyPetSeconds.Value; Util.Debug("You forgot to pet your Calming Buddy."); try { ((GameEntity)val).Kill("calmingbuddy", DamageInfo.CreateDamageInfo(99999f, "calmingbuddy")); } catch (Exception ex2) { Util.LogOnce("buddykill", "Buddy kill failed: " + ex2.Message); } } private static void Grant() { Trinket val = FindTrinket(); if ((Object)(object)val == (Object)null) { gaveUp = true; Util.LogOnce("nobuddy", "Calming Buddy trinket not found - the buddy rule is off this run."); return; } if (val.itemsToGrant != null) { foreach (Item_Object item in val.itemsToGrant) { if ((Object)(object)item == (Object)null) { continue; } names.Add(Util.Clean(((Object)item).name)); if (item.itemData != null) { if (!string.IsNullOrEmpty(item.itemData.prefabName)) { names.Add(item.itemData.prefabName); } if (!string.IsNullOrEmpty(item.itemData.itemName)) { names.Add(item.itemData.itemName); } } } } if (names.Count == 0) { gaveUp = true; Util.LogOnce("buddynoitem", "Calming Buddy trinket '" + ((Object)val).name + "' has no item to pet - the buddy rule is off this run."); return; } bool flag = HasBuddyInInventory(); if (!flag) { try { flag = CL_GameManager.HasActiveFlag("skmod_run_buddy_given", false); } catch { } } if (!flag) { Granting = true; try { val.Activate(0f); } catch (Exception ex) { Util.LogOnce("buddygrant", "Giving the Calming Buddy failed: " + ex.Message); gaveUp = true; return; } finally { Granting = false; } try { CL_GameManager.SetGameFlag("skmod_run_buddy_given", true, "", false, false); } catch { } if (!HasBuddyInInventory()) { Util.Debug("Calming Buddy trinket ran but no buddy item showed up in the inventory yet."); } } granted = true; trinket = val; verifyAt = runTime + 3f; Left = Cfg.BuddyPetSeconds.Value; Util.Debug("Calming Buddy given (" + ((Object)val).name + "): " + string.Join(", ", new List<string>(names).ToArray())); } private static Trinket FindTrinket() { WKAssetDatabase val = Util.Db(); List<Trinket> list = new List<Trinket>(); if ((Object)(object)val != (Object)null && val.trinketAssets != null) { list.AddRange(val.trinketAssets); } M_Gamemode currentGamemode = CL_GameManager.GetCurrentGamemode(); if ((Object)(object)currentGamemode != (Object)null && (Object)(object)currentGamemode.availableTrinkets != (Object)null && currentGamemode.availableTrinkets.trinkets != null) { list.AddRange(currentGamemode.availableTrinkets.trinkets); } foreach (Trinket item in list) { if (!((Object)(object)item == (Object)null) && !item.isBinding) { string text = (((Object)item).name + " " + item.title).ToLowerInvariant().Replace(" ", ""); if (text.Contains("calmingbuddy") || (text.Contains("calm") && text.Contains("buddy"))) { return item; } } } foreach (Trinket item2 in list) { if (!((Object)(object)item2 == (Object)null) && !item2.isBinding && (((Object)item2).name + " " + item2.title).ToLowerInvariant().Contains("buddy")) { return item2; } } return null; } private static bool HasBuddyInInventory() { try { Inventory instance = Inventory.instance; if ((Object)(object)instance == (Object)null) { return false; } foreach (Item item in instance.GetItems(true, true, true)) { if (IsBuddy(item)) { return true; } } } catch { } return false; } public static bool IsBuddy(Item item) { if (item == null || names.Count == 0) { return false; } if (item.prefabName == null || !names.Contains(item.prefabName)) { if (item.itemName != null) { return names.Contains(item.itemName); } return false; } return true; } public static void OnUse(Item item) { if (granted && IsBuddy(item)) { Left = Cfg.BuddyPetSeconds.Value; Util.Debug("Petted the Calming Buddy."); } } } internal static class RedRoaches { private static float timer; private static readonly List<GameObject> spawned = new List<GameObject>(); public static void Reset() { timer = 0f; spawned.Clear(); } public unsafe static void Tick() { //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) if (Cfg.RedRoachSpawnSeconds.Value <= 0f || Zones.Current == Zone.None) { return; } ENT_Player val = Util.Player(); if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead() || ((Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.gMan.isPaused) || ((Object)(object)CL_EventManager.currentLevel != (Object)null && CL_EventManager.currentLevel.safeArea)) { return; } timer += Time.deltaTime; if (timer < Cfg.RedRoachSpawnSeconds.Value) { return; } timer = 0f; spawned.RemoveAll((GameObject g) => (Object)(object)g == (Object)null || !g.activeInHierarchy); if (spawned.Count >= Cfg.RedRoachMax.Value) { return; } GameObject val2 = Util.FindPrefabNamed("roach_explosive"); if (!((Object)(object)val2 == (Object)null) && Util.SpotAroundPlayer(8f, 18f, out var pos)) { Transform parent = null; try { parent = WorldLoader.GetCurrentLevelParentRoot(); } catch { } GameObject val3 = Util.Spawn(val2, pos + Vector3.up * 0.3f, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f), parent); if ((Object)(object)val3 != (Object)null) { spawned.Add(val3); EntityRules.MarkSpawned(val3); Util.Debug("Red roach spawned at " + ((object)(*(Vector3*)(&pos))/*cast due to .constrained prefix*/).ToString()); } } } } internal static class SilosSturges { private static float timer; private static readonly List<GameObject> spawned = new List<GameObject>(); public static void Reset() { timer = 0f; spawned.Clear(); } public unsafe static void Tick() { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) if (Zones.Current != Zone.Silos || Cfg.SilosSturgeInterval.Value <= 0f) { return; } ENT_Player val = Util.Player(); if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead() || ((Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.gMan.isPaused)) { return; } timer += Time.deltaTime; if (timer < Cfg.SilosSturgeInterval.Value) { return; } timer = 0f; spawned.RemoveAll((GameObject g) => (Object)(object)g == (Object)null || !g.activeInHierarchy); if (spawned.Count >= Cfg.SilosSturgeMax.Value) { return; } GameObject val2 = Util.FindPrefabNamed("sturge"); if (!((Object)(object)val2 == (Object)null) && Util.SpotAroundPlayer(12f, 22f, out var pos)) { Transform parent = null; try { parent = WorldLoader.GetCurrentLevelParentRoot(); } catch { } GameObject val3 = Util.Spawn(val2, pos + Vector3.up * 2.5f, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f), parent); if ((Object)(object)val3 != (Object)null) { spawned.Add(val3); EntityRules.MarkSpawned(val3); Util.Debug("Sturge spawned in the Silos at " + ((object)(*(Vector3*)(&pos))/*cast due to .constrained prefix*/).ToString()); } } } } internal static class CavityRoute { public const string Flag = "skmod_run_cavity_done"; public const string OldSavedFlag = "skmod_cavity_done"; private static bool doneLocal; private static M_Level lastLevel; private static M_Level levelBeforeCavity; private static bool inCavity; private static bool ratKingSeen; private static bool ratKingDealt; private static bool hasBreakRoom; private static Vector3 breakRoomPos; private static M_Level breakRoomLevel; private static bool hasOutside; private static Vector3 lastOutsidePos; private static readonly Queue<Vector3> history = new Queue<Vector3>(); private static float blockCooldown; private static float nextTick; public static bool Done { get { if (doneLocal) { return true; } try { return CL_GameManager.HasActiveFlag("skmod_run_cavity_done", false); } catch { return false; } } } public static void Reset() { doneLocal = false; lastLevel = null; levelBeforeCavity = null; inCavity = false; ratKingSeen = (ratKingDealt = false); hasBreakRoom = false; breakRoomLevel = null; hasOutside = false; blockCooldown = 0f; history.Clear(); } private static bool HasAny(string text, string csv) { string[] array = csv.Split(','); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim().ToLowerInvariant(); if (text2.Length > 0 && text.Contains(text2)) { return true; } } return false; } public static void Tick() { //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) if (!Cfg.CavityRoute.Value) { return; } ENT_Player val = Util.Player(); if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead()) { return; } M_Level currentLevel = CL_EventManager.currentLevel; M_Subregion currentSubregion = CL_EventManager.currentSubregion; bool flag = ((((Object)(object)currentLevel != (Object)null) ? (currentLevel.levelName + " " + ((Object)currentLevel).name) : "") + " " + (((Object)(object)currentSubregion != (Object)null) ? (currentSubregion.subregionName + " " + ((Object)currentSubregion).name) : "")).ToLowerInvariant().Contains("cavity"); bool flag2 = IsServiceShaft(currentLevel, currentSubregion); bool flag3 = false; try { flag3 = val.IsGrounded(false); } catch { } if (Zones.Current == Zone.Habitation && (Object)(object)currentLevel != (Object)null && currentLevel.safeArea && !flag && !flag2 && flag3) { hasBreakRoom = true; breakRoomPos = ((Component)val).transform.position; breakRoomLevel = currentLevel; } if (!flag2 && !flag && flag3 && Time.unscaledTime >= nextTick) { nextTick = Time.unscaledTime + 0.5f; history.Enqueue(((Component)val).transform.position); while (history.Count > 10) { history.Dequeue(); } hasOutside = true; lastOutsidePos = history.Peek(); } if (inCavity) { List<DEN_RatKing> activeRatKings = DEN_RatKing.activeRatKings; bool flag4 = false; if (activeRatKings != null) { foreach (DEN_RatKing item in activeRatKings) { if ((Object)(object)item != (Object)null && !((GameEntity)item).dead && ((Component)item).gameObject.activeInHierarchy) { flag4 = true; ratKingSeen = true; } } } if (ratKingSeen && !flag4 && !ratKingDealt) { ratKingDealt = true; Util.Debug("Body cavity: Rat King dealt with."); } } if ((Object)(object)currentLevel != (Object)(object)lastLevel) { M_Level val2 = lastLevel; lastLevel = currentLevel; if (flag && !inCavity) { inCavity = true; levelBeforeCavity = val2; ratKingSeen = (ratKingDealt = false); Util.Debug("Entered the body cavity from " + (((Object)(object)val2 != (Object)null) ? val2.levelName : "?")); } else if (!flag && inCavity) { inCavity = false; bool flag5 = (Object)(object)currentLevel != (Object)(object)levelBeforeCavity; if ((flag5 || ratKingDealt) && !Done) { Complete(flag5 ? "reached the end of the body cavity" : "came back after dealing with the Rat King"); } else { Util.Debug("Left the body cavity without finishing it."); } } } if (flag2 && !Done && Time.unscaledTime >= blockCooldown) { blockCooldown = Time.unscaledTime + 1.5f; Vector3? val3 = (hasOutside ? new Vector3?(lastOutsidePos) : (hasBreakRoom ? new Vector3?(breakRoomPos) : ((Vector3?)null))); if (val3.HasValue && GroundBelow(val3.Value)) { CL_GameManager.gMan.TeleportPlayer(val3.Value + Vector3.up * 0.2f); Util.Debug("Security Shaft is sealed - pushed back to " + ((object)val3.Value/*cast due to .constrained prefix*/).ToString()); } Hud.Flash("SECURITY GATE SEALED - beat the Body Cavity first"); } } public static void OnChamberLeft() { if (Cfg.CavityRoute.Value && inCavity && !Done) { Complete("left the body cavity chamber"); } } private static void Complete(string why) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) doneLocal = true; try { CL_GameManager.SetGameFlag("skmod_run_cavity_done", true, "", false, false); } catch (Exception ex) { Util.LogOnce("cavflag", "Could not save the body cavity flag: " + ex.Message); } Util.Debug("Body cavity beaten (" + why + "). Security Shaft unlocked."); Hud.Flash("BODY CAVITY BEATEN - the security gate opens"); if (hasBreakRoom && (Object)(object)breakRoomLevel != (Object)null && ((Component)breakRoomLevel).gameObject.activeInHierarchy && GroundBelow(breakRoomPos)) { CL_GameManager.gMan.TeleportPlayer(breakRoomPos + Vector3.up * 0.2f); Util.Debug("Teleported back to the break room (" + breakRoomLevel.levelName + ")."); } else { Util.Debug("Break room isn't loaded any more, so no teleport back."); } } private static bool IsServiceShaft(M_Level lv, M_Subregion sr) { string text = (((Object)(object)lv != (Object)null) ? (lv.levelName + " " + ((Object)lv).name).ToLowerInvariant() : ""); if (text.Contains("intro") || text.Contains("interlude") || text.Contains("cavity")) { return false; } if ((Object)(object)lv != (Object)null && lv.safeArea) { return false; } if (text.Length > 0 && HasAny(text, Cfg.ServiceShaftKeywords.Value)) { return true; } string text2 = (((Object)(object)sr != (Object)null) ? (sr.subregionName + " " + ((Object)sr).name).ToLowerInvariant() : ""); if (text.Length > 0 && (text2.Contains("service shaft") || text2.Contains("service_shaft"))) { return !text2.Contains("ending"); } return false; } public static void OnFlag(string name, bool state) { if (state && !string.IsNullOrEmpty(name) && Cfg.CavityRoute.Value && !Done) { string text = name.ToLowerInvariant(); if (text.Contains("cavity") && !text.Contains("intro") && (text.Contains("complete") || text.Contains("finish") || text.Contains("beat") || text.Contains("end") || text.Contains("escape") || text.Contains("exit") || text.Contains("done") || text.Contains("win"))) { Complete("game flag " + name); } } } private static bool GroundBelow(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) return Physics.Raycast(pos + Vector3.up * 1f, Vector3.down, 3f, -1, (QueryTriggerInteraction)1); } public static bool IsAmalgam(string name) { if (string.IsNullOrEmpty(name)) { return false; } return HasAny(name.ToLowerInvariant(), Cfg.AmalgamKeywords.Value); } } internal static class EntityRules { private static readonly HashSet<int> seen = new HashSet<int>(); private static readonly HashSet<int> clones = new HashSet<int>(); private static float nextScan; private static float nextFaceCheck; private static int faceClonesThisVisit; private static Zone lastZone; private static int dronesThisZone; public static void Reset() { seen.Clear(); clones.Clear(); faceClonesThisVisit = 0; dronesThisZone = 0; lastZone = Zone.None; Util.ResetCaches(); } public static bool IsClone(GameObject g) { if ((Object)(object)g != (Object)null) { return clones.Contains(((Object)g).GetInstanceID()); } return false; } public static void Tick() { if (Zones.Current != lastZone) { lastZone = Zones.Current; faceClonesThisVisit = 0; dronesThisZone = 0; } if (Time.unscaledTime >= nextScan) { nextScan = Time.unscaledTime + 0.25f; Scan(); } if (Zones.Current == Zone.Abyss && Time.unscaledTime >= nextFaceCheck) { nextFaceCheck = Time.unscaledTime + 1f; KeepFaces(); } } private static void Scan() { List<GameEntity> entities = GameEntity.entities; if (entities == null) { return; } GameEntity[] array = entities.ToArray(); foreach (GameEntity val in array) { if (!((Object)(object)val == (Object)null) && !(val is ENT_Player) && seen.Add(((Object)val).GetInstanceID())) { try { OnNewEntity(val); } catch (Exception ex) { Util.LogOnce("ent" + ((object)val).GetType().Name, "Rule for " + ((object)val).GetType().Name + " failed: " + ex.Message); } } } } private static void OnNewEntity(GameEntity e) { //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_030e: 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_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) Zone current = Zones.Current; string text = ((Object)((Component)e).gameObject).name.ToLowerInvariant(); bool num = clones.Contains(((Object)((Component)e).gameObject).GetInstanceID()); DEN_RatKing val = (DEN_RatKing)(object)((e is DEN_RatKing) ? e : null); if (val != null) { val.speed *= Cfg.RatKingSpeedMult.Value; Util.Debug("Rat King speed x" + Cfg.RatKingSpeedMult.Value); } DEN_Teeth val2 = (DEN_Teeth)(object)((e is DEN_Teeth) ? e : null); if (val2 != null && current == Zone.Habitation) { float value = Cfg.TeethSpeedMult.Value; val2.baseSpeed *= value; val2.chargeSpeed *= value; val2.walkSpeed *= value; val2.jumpSpeed *= value; Util.Debug("Teeth speed x" + value); } DEN_VentThing val3 = (DEN_VentThing)(object)((e is DEN_VentThing) ? e : null); if (val3 != null && current == Zone.Habitation) { float value2 = Cfg.VentThingSpeedMult.Value; val3.handSpeed *= value2; val3.pullForce *= value2; Util.Debug("Vent thing speed/pull x" + value2); } if (num || Util.HasGameEntityAncestor(e) || (Object)(object)((Component)e).GetComponent<Item_Object>() != (Object)null) { return; } bool flag = e is Denizen || e is AIGameEntity; int num2 = 0; string why = null; if (current == Zone.Silos && (e is DEN_Bloodbug || (flag && text.Contains("bloodbug")))) { num2 = Cfg.SilosBloodbugExtra.Value; why = "bloodbug"; } else if (e is DEN_Barnacle || (flag && text.Contains("barnacle") && !text.Contains("zombie") && !text.Contains("tentacle"))) { switch (current) { case Zone.Pipeworks: num2 = Cfg.PipeworksBarnacleExtra.Value; why = "barnacle"; break; case Zone.Nest: num2 = Cfg.NestBarnacleExtra.Value; why = "barnacle"; break; } } else if (current == Zone.Pipeworks && e is DEN_Hopper && !(e is DEN_Hopper_Tick)) { num2 = Cfg.PipeworksHopperExtra.Value; why = "hopper roach"; } if (e is DEN_Turret) { num2 = Cfg.TurretExtra.Value; why = "turret"; } if (current == Zone.Silos && flag && text.Contains("sturge")) { num2 = Cfg.SilosSturgeExtra.Value; why = "sturge"; } if (flag && SpawnRules.IsRedRoach(text)) { num2 = Cfg.RedRoachExtra.Value; why = "red roach"; } if (num2 > 0) { MakeCopies(e, num2, why); } if (current == Zone.Habitation && (e is DEN_Turret || e is DEN_GantryTurret) && dronesThisZone < 8 && Random.value < Cfg.TurretDroneChance.Value) { GameObject val4 = Util.FindPrefabWith<DEN_Drone>(); if ((Object)(object)val4 != (Object)null) { Vector3 pos = ((Component)e).transform.position + Vector3.up * 2f + Random.insideUnitSphere * 1.5f; MarkClone(Util.Spawn(val4, pos, Quaternion.identity, ((Component)e).transform.parent)); dronesThisZone++; Util.Debug("Drone spawned next to turret " + ((Object)((Component)e).gameObject).name); } } } private static void MakeCopies(GameEntity e, int count, string why) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < count; i++) { Vector3 val = Util.NearbySpot(((Component)e).transform); GameObject val2 = Object.Instantiate<GameObject>(((Component)e).gameObject, val, ((Component)e).transform.rotation, ((Component)e).transform.parent); ((Object)val2).name = ((Object)((Component)e).gameObject).name; if (!val2.activeSelf) { val2.SetActive(true); } MarkClone(val2); } Util.Debug("+" + count + " " + why + " (" + ((Object)((Component)e).gameObject).name + ") in " + Zones.Current); } public static void MarkSpawned(GameObject g) { MarkClone(g); } private static void MarkClone(GameObject g) { if (!((Object)(object)g == (Object)null)) { clones.Add(((Object)g).GetInstanceID()); GameEntity[] componentsInChildren = g.GetComponentsInChildren<GameEntity>(true); foreach (GameEntity val in componentsInChildren) { seen.Add(((Object)val).GetInstanceID()); clones.Add(((Object)((Component)val).gameObject).GetInstanceID()); } } } private static void KeepFaces() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) List<DEN_Face> faceInstances = DEN_Face.faceInstances; if (faceInstances == null) { return; } List<DEN_Face> list = faceInstances.Where((DEN_Face f) => (Object)(object)f != (Object)null && ((Component)f).gameObject.activeInHierarchy && !((GameEntity)f).dead).ToList(); if (list.Count == 0 || list.Count >= Cfg.AbyssFaceCount.Value || faceClonesThisVisit >= Cfg.AbyssFaceCount.Value * 2) { return; } DEN_Face val = list[0]; int num = Cfg.AbyssFaceCount.Value - list.Count; for (int num2 = 0; num2 < num; num2++) { Vector3 val2 = Random.insideUnitSphere * 12f; GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.position + val2, ((Component)val).transform.rotation, ((Component)val).transform.parent); ((Object)val3).name = ((Object)((Component)val).gameObject).name; if (!val3.activeSelf) { val3.SetActive(true); } MarkClone(val3); faceClonesThisVisit++; } Util.Debug("Abyss: faces topped up to " + Cfg.AbyssFaceCount.Value); } } internal static class Hud { private static GUIStyle style; private static GUIStyle big; private static string flash; private static float flashUntil; public static void Flash(string text) { flash = text; flashUntil = Time.unscaledTime + 4f; } public static void Draw() { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00bf: 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_016a: Unknown result type (might be due to invalid IL or missing references) if (Cfg.ShowHud.Value && Mode.IsActive() && (!((Object)(object)CL_GameManager.gMan != (Object)null) || !CL_GameManager.gMan.isPaused)) { if (style == null) { style = new GUIStyle(GUI.skin.label) { fontSize = 14, fontStyle = (FontStyle)1, alignment = (TextAnchor)1 }; style.normal.textColor = new Color(1f, 0.25f, 0.2f, 0.85f); big = new GUIStyle(style) { fontSize = 30 }; big.normal.textColor = new Color(1f, 0.15f, 0.1f, 1f); } float num = Screen.width; GUI.Label(new Rect(0f, 6f, num, 24f), "SUPER HARD", style); if (Timers.MotherLeft >= 0f) { GUI.Label(new Rect(0f, 34f, num, 40f), "MOTHER: " + Mathf.CeilToInt(Timers.MotherLeft) + "s", big); } if (flash != null && Time.unscaledTime < flashUntil) { GUI.Label(new Rect(0f, (float)Screen.height * 0.3f, num, 40f), flash, big); } } } } internal static class ItemRules { private static readonly HashSet<int> seenItems = new HashSet<int>(); private static readonly HashSet<int> seenVendors = new HashSet<int>(); private static Dictionary<string, string> extraMap; private static readonly Regex tierRx = new Regex("_T([2-9])(?=$|_)", RegexOptions.Compiled); public static void Reset() { seenItems.Clear(); seenVendors.Clear(); extraMap = null; } public static void SlowTick() { //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) Zone current = Zones.Current; ENT_Player val = Util.Player(); Item_Object[] array = Object.FindObjectsByType<Item_Object>((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (Item_Object val2 in array) { if ((Object)(object)val2 == (Object)null || !seenItems.Add(((Object)val2).GetInstanceID())) { continue; } try { if ((val2.itemData != null && (val2.itemData.hasBeenPickedUp || val2.itemData.inBag)) || ((Object)(object)val != (Object)null && ((Component)val2).transform.IsChildOf(((Component)val).transform)) || (Object)(object)((Component)val2).GetComponentInParent<Inventory>() != (Object)null) { continue; } string text = ItemName(val2); if (Cfg.CavityRoute.Value && CavityRoute.IsAmalgam(text)) { Util.Debug("No Amalgamator on Super Hard: removed " + text); Object.Destroy((Object)(object)((Component)val2).gameObject); } else if (current != Zone.Silos && current != Zone.Abyss) { seenItems.Remove(((Object)val2).GetInstanceID()); } else if (current == Zone.Abyss && text.ToLowerInvariant().Contains("artifact")) { Util.Debug("Abyss: removed artifact " + text); Object.Destroy((Object)(object)((Component)val2).gameObject); } else { if (current != Zone.Silos) { continue; } string text2 = TierOne(text); if (text2 == null) { continue; } GameObject val3 = Util.ItemPrefab(text2); if ((Object)(object)val3 == (Object)null) { Util.DebugOnce("noT1" + text2, "Silos: wanted to swap " + text + " -> " + text2 + " but no such item."); continue; } GameObject val4 = Util.Spawn(val3, ((Component)val2).transform.position, ((Component)val2).transform.rotation, ((Component)val2).transform.parent); Item_Object val5 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent<Item_Object>() : null); if ((Object)(object)val5 != (Object)null) { seenItems.Add(((Object)val5).GetInstanceID()); } Util.Debug("Silos: swapped " + text + " -> " + text2); Object.Destroy((Object)(object)((Component)val2).gameObject); continue; } } catch (Exception ex) { Util.LogOnce("item" + ((Object)val2).name, "Item rule failed on " + ((Object)val2).name + ": " + ex.Message); } } if (current == Zone.Silos) { FixVendors(); } } private static void FixVendors() { ENV_Vendor_Disk[] array = Object.FindObjectsByType<ENV_Vendor_Disk>((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (ENV_Vendor_Disk val in array) { if (!((Object)(object)val == (Object)null) && seenVendors.Add(((Object)val).GetInstanceID()) && !((Object)(object)val.purchaseObject == (Object)null)) { Item_Object val2 = TierOneObject(val.purchaseObject); if ((Object)(object)val2 != (Object)null) { Util.Debug("Silos: disk vendor now sells " + ((Object)val2).name + " instead of " + ((Object)val.purchaseObject).name); val.purchaseObject = val2; } } } ENV_VendingMachine[] array2 = Object.FindObjectsByType<ENV_VendingMachine>((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (ENV_VendingMachine val3 in array2) { if ((Object)(object)val3 == (Object)null || !seenVendors.Add(((Object)val3).GetInstanceID()) || val3.purchaseList == null) { continue; } foreach (Purchase purchase in val3.purchaseList) { if (purchase != null && !((Object)(object)purchase.itemObject == (Object)null)) { Item_Object val4 = TierOneObject(purchase.itemObject); if ((Object)(object)val4 != (Object)null) { Util.Debug("Silos: vending machine slot " + ((Object)purchase.itemObject).name + " -> " + ((Object)val4).name); purchase.itemObject = val4; } } } } } private static Item_Object TierOneObject(Item_Object io) { string text = TierOne(Util.Clean(((Object)io).name)); if (text == null) { return null; } GameObject val = Util.ItemPrefab(text); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<Item_Object>(); } private static string ItemName(Item_Object io) { string text = null; try { if (io.itemData != null) { text = io.itemData.prefabName; } } catch { } if (string.IsNullOrEmpty(text)) { text = ((Object)((Component)io).gameObject).name; } return Util.Clean(text); } public static string TierOne(string name) { if (string.IsNullOrEmpty(name)) { return null; } if (extraMap == null) { extraMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); string[] array = Cfg.TierOneMap.Value.Split(';', ','); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split('='); if (array2.Length == 2 && array2[0].Trim().Length > 0 && array2[1].Trim().Length > 0) { extraMap[array2[0].Trim()] = array2[1].Trim(); } } } if (extraMap.TryGetValue(name, out var value)) { return value; } if (tierRx.IsMatch(name)) { return tierRx.Replace(name, "_T1"); } return null; } } internal static class Mode { public const string SettingId = "skmod_super"; public const string Title = "SUPER HARD"; private static GamemodeSetting setting; internal static readonly HashSet<string> HardIds = new HashSet<string>(); internal static readonly HashSet<string> SurvivalIds = new HashSet<string>(); private static readonly HashSet<M_Gamemode> injected = new HashSet<M_Gamemode>(); private static float nextMenuTick; private static int cacheFrame = -1; private static bool cacheValue; [ThreadStatic] internal static bool InCheck; private static bool leaderboardsTouched; private static bool leaderboardsBefore; private static readonly Dictionary<M_Subregion, KeyValuePair<float, bool>> cavityBackup = new Dictionary<M_Subregion, KeyValuePair<float, bool>>(); internal static bool Broken; public static string Description => "Everything at once: +20% gravity, 3-second grip, no trinkets, weaker hammer, Remains every 10 minutes, 40% Engraved Doors, red roaches always, Hard Mode + Survival on. Every zone gets nastier."; public static GamemodeSetting Setting => setting; public static void MenuTick() { if (Time.unscaledTime < nextMenuTick) { return; } nextMenuTick = Time.unscaledTime + 1f; try { WKAssetDatabase val = Util.Db(); if ((Object)(object)val != (Object)null && val.gamemodeAssets != null) { foreach (M_Gamemode gamemodeAsset in val.gamemodeAssets) { EnsureInjected(gamemodeAsset); } } EnsureInjected(CL_GameManager.GetCurrentGamemode()); } catch (Exception ex) { Util.LogOnce("menutick", "Gamemode scan failed: " + ex.Message); } } public static void RemoveEverywhere() { foreach (M_Gamemode item in injected) { if ((Object)(object)item != (Object)null && item.gamemodeSettings != null) { item.gamemodeSettings.RemoveAll((GamemodeSetting x) => (Object)(object)x != (Object)null && x.id == "skmod_super"); } } } public static void EnsureInjected(M_Gamemode mode) { if ((Object)(object)mode == (Object)null || mode.gamemodeSettings == null) { return; } List<GamemodeSetting> gamemodeSettings = mode.gamemodeSettings; if (Broken) { gamemodeSettings.RemoveAll((GamemodeSetting x) => (Object)(object)x != (Object)null && x.id == "skmod_super"); } else { if (gamemodeSettings.Count == 0) { return; } GamemodeSetting val = null; GamemodeSetting val2 = null; GamemodeSetting val3 = null; foreach (GamemodeSetting item in gamemodeSettings) { if ((Object)(object)item == (Object)null || (Object)(object)item == (Object)(object)setting) { continue; } if ((Object)(object)val3 == (Object)null) { val3 = item; } string text = (item.id + " " + item.title + " " + ((Object)item).name).ToLowerInvariant(); if (text.Contains("hard")) { HardIds.Add(item.id); if ((Object)(object)val == (Object)null) { val = item; } } if (text.Contains("iron") && (Object)(object)val2 == (Object)null) { val2 = item; } if (text.Contains("surviv")) { SurvivalIds.Add(item.id); } } if ((Object)(object)val == (Object)null && (Object)(object)val2 == (Object)null && !mode.allowHardmode) { return; } if (!gamemodeSettings.Any((GamemodeSetting s) => (Object)(object)s != (Object)null && s.id == "skmod_super")) { GamemodeSetting val4 = val ?? val2 ?? val3; if ((Object)(object)val4 == (Object)null) { return; } if ((Object)(object)setting == (Object)null) { setting = Create(val4); } gamemodeSettings.Add(setting); } if (injected.Add(mode)) { Util.Debug("Added SUPER HARD to gamemode '" + mode.gamemodeName + "'. Its settings: " + string.Join(", ", (from s in gamemodeSettings where (Object)(object)s != (Object)null select s.id + " (" + s.title + ")").ToArray())); BlacklistTrinkets(mode); } } } private static GamemodeSetting Create(GamemodeSetting template) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) GamemodeSetting obj = Object.Instantiate<GamemodeSetting>(template); ((Object)obj).name = "GamemodeSetting_SuperHard"; ((Object)obj).hideFlags = (HideFlags)32; obj.id = "skmod_super"; obj.title = "SUPER HARD"; obj.description = Description; obj.color = new Color(1f, 0.12f, 0.08f, 1f); obj.exclusiveSettings = new List<string>(); obj.nameAppend = "Super Hard"; obj.leaderboardAppendID = "superhardmod"; obj.allowDownstream = false; obj.downstreamId = ""; return obj; } private static void BlacklistTrinkets(M_Gamemode mode) { try { List<Trinket> list = new List<Trinket>(); if ((Object)(object)mode.availableTrinkets != (Object)null && mode.availableTrinkets.trinkets != null) { list.AddRange(mode.availableTrinkets.trinkets); } WKAssetDatabase val = Util.Db(); if ((Object)(object)val != (Object)null && val.trinketAssets != null) { list.AddRange(val.trinketAssets); } foreach (Trinket item in list) { if (!((Object)(object)item == (Object)null) && !item.isBinding) { if (item.settingBlacklist == null) { item.settingBlacklist = new List<string>(); } if (!item.settingBlacklist.Contains("skmod_super")) { item.settingBlacklist.Add("skmod_super"); } } } } catch (Exception ex) { Util.LogOnce("trinketbl", "Trinket blacklist failed: " + ex.Message); } } public static bool IsActive() { if (cacheFrame == Time.frameCount) { return cacheValue; } cacheFrame = Time.frameCount; cacheValue = false; try { if ((Object)(object)CL_GameManager.gMan == (Object)null) { return false; } cacheValue = IsOnFor(CL_GameManager.GetCurrentGamemode()); } catch { cacheValue = false; } return cacheValue; } public static bool IsOnFor(M_Gamemode mode) { if ((Object)(object)mode == (Object)null) { return false; } if (InCheck) { return false; } InCheck = true; try { return mode.HasActiveSetting("skmod_super"); } catch { return false; } finally { InCheck = false; } } public static void ApplyGlobalToggles(bool active) { try { if (active && Cfg.DisableLeaderboards.Value) { if (!leaderboardsTouched) { leaderboardsBefore = WK_Leaderboard_Core.disableLeaderboards; leaderboardsTouched = true; } WK_Leaderboard_Core.disableLeaderboards = true; } else if (leaderboardsTouched) { WK_Leaderboard_Core.disableLeaderboards = leaderboardsBefore; leaderboardsTouched = false; } } catch (Exception ex) { Util.LogOnce("lb", "Leaderboard toggle failed: " + ex.Message); } try { if (active) { if (cavityBackup.Count != 0) { return; } WKAssetDatabase val = Util.Db(); if (!((Object)(object)val != (Object)null) || val.subRegionAssets == null) { return; } { foreach (M_Subregion subRegionAsset in val.subRegionAssets) { if (!((Object)(object)subRegionAsset == (Object)null) && (((Object)subRegionAsset).name + " " + subRegionAsset.subregionName).ToLowerInvariant().Contains("cavity")) { cavityBackup[subRegionAsset] = new KeyValuePair<float, bool>(subRegionAsset.chance, subRegionAsset.guaranteeIfNotVisited); subRegionAsset.chance = Mathf.Max(subRegionAsset.chance, 1f); subRegionAsset.guaranteeIfNotVisited = true; Util.Debug("Forcing body cavity route: " + ((Object)subRegionAsset).name); } } return; } } if (cavityBackup.Count <= 0) { return; } foreach (KeyValuePair<M_Subregion, KeyValuePair<float, bool>> item in cavityBackup) { if ((Object)(object)item.Key != (Object)null) { item.Key.chance = item.Value.Key; item.Key.guaranteeIfNotVisited = item.Value.Value; } } cavityBackup.Clear(); } catch (Exception ex2) { Util.LogOnce("cavity", "Body cavity forcing failed: " + ex2.Message); } } } internal static class Patches { private static int ok; private static int failed; [ThreadStatic] private static bool hopperHit; private static readonly FieldRef<DEN_Hopper_Tick, bool> tickAttached = Util.SafeFieldRef<DEN_Hopper_Tick, bool>("isAttached"); private static readonly FieldRef<DEN_Hopper_Tick, float> tickDrained = Util.SafeFieldRef<DEN_Hopper_Tick, float>("currentBloodDrained"); private static readonly FieldRef<DEN_Hopper_Tick, GameEntity> tickTarget = Util.SafeFieldRef<DEN_Hopper_Tick, GameEntity>("attachTarget"); internal static bool MassPatched; public static void ApplyAll(Harmony h) { P(h, typeof(UI_GamemodeScreen_Panel), "FillSettings", null, "FillSettings_Pre"); P(h, typeof(UI_GamemodeScreen), "Initialize", new Type[1] { typeof(M_Gamemode) }, "ScreenInit_Pre"); P(h, typeof(UI_GamemodeSetting), "Initialize", new Type[2] { typeof(GamemodeSetting), typeof(UI_GamemodeScreen_Panel) }, null, null, "SettingInit_Finalizer"); P(h, typeof(UI_GamemodeScreen_Panel), "FillSettings", null, null, null, "FillSettings_Finalizer"); P(h, typeof(M_Gamemode), "HasActiveSetting", new Type[1] { typeof(string) }, null, "HasActiveSetting_Post"); P(h, typeof(M_Gamemode), "GetActiveSettings", Type.EmptyTypes, null, "GetActiveSettings_Post"); P(h, typeof(M_Gamemode), "IsHardMode", Type.EmptyTypes, null, "ModeIsHard_Post"); P(h, typeof(CL_GameManager), "IsHardmode", Type.EmptyTypes, null, "GameIsHard_Post"); P(h, typeof(Trinket), "Activate", null, "Trinket_Activate_Pre"); P(h, typeof(HandItem), "TryUse", Type.EmptyTypes, "HandItemUse_Pre"); P(h, typeof(HandItem_Buff_Grub), "Activate", Type.EmptyTypes, "HandItemUse_Pre"); P(h, typeof(ENT_Player), "HandStamina", null, "HandStamina_Pre", "HandStamina_Post"); P(h, typeof(ENT_Player), "Damage", new Type[1] { typeof(DamageInfo) }, "PlayerDamage_Pre", "PlayerDamage_Post"); P(h, typeof(HandItem_Melee), "Hit", Type.EmptyTypes, "Melee_Pre", "Melee_Post"); P(h, typeof(HandItem_Melee), "OnChargeAttackHit", null, "Melee_Pre", "Melee_Post"); P(h, typeof(SpawnSettings), "RandomCheck", null, null, "RandomCheck_Post"); P(h, typeof(UT_SpawnChance), "Check", Type.EmptyTypes, "SpawnChance_Pre"); P(h, typeof(UT_EventChance), "Check", Type.EmptyTypes, "EventChance_Pre"); P(h, typeof(UT_SpawnEntityByID), "Start", Type.EmptyTypes, "SpawnById_Pre"); P(h, typeof(UT_SpawnEntityByID), "Spawn", Type.EmptyTypes, "SpawnById_Pre"); P(h, typeof(SpawnTable), "GetRandomSpawnObject", Type.EmptyTypes, "SpawnTable_Pre"); P(h, typeof(ENT_Player), "AddPerk", null, "AddPerk_Pre"); P(h, typeof(UT_ChamberLoader), "LeaveChamber", Type.EmptyTypes, null, "LeaveChamber_Post"); P(h, typeof(UT_BranchGenerator), "MovePlayerIntoBranch", Type.EmptyTypes, "Branch_Pre"); P(h, typeof(CL_GameManager), "SetGameFlag", null, "SetGameFlag_Pre"); P(h, typeof(CL_Button), "Interact", Type.EmptyTypes, null, "Button_Post"); P(h, typeof(CL_Button), "Interact", new Type[1] { typeof(InteractionInfo) }, null, "Button_Post"); P(h, typeof(CL_HoldButton), "Update", Type.EmptyTypes, null, "HoldButton_Post"); P(h, typeof(DEN_Hopper_Tick), "Damage", new Type[1] { typeof(DamageInfo) }, "Tick_Damage_Pre"); P(h, typeof(DEN_Hopper_Tick), "Detach", Type.EmptyTypes, "Tick_Detach_Pre"); P(h, typeof(DEN_BasicDenizen), "Kill", new Type[2] { typeof(string), typeof(DamageInfo) }, "Tick_Kill_Pre"); P(h, typeof(Denizen), "Kill", new Type[2] { typeof(string), typeof(DamageInfo) }, "Tick_Kill_Pre"); P(h, typeof(DEN_Teeth), "Despawn", Type.EmptyTypes, "Teeth_Despawn_Pre"); MassPatched = P(h, typeof(DEN_DeathFloor), "Update", Type.EmptyTypes, "Mass_Update_Pre"); Plugin.Log.LogInfo((object)("Patches: " + ok + " applied, " + failed + " failed.")); } private static bool P(Harmony h, Type t, string method, Type[] args, string prefix, string postfix = null, string finalizer = null) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) try { MethodInfo methodInfo = ((args == null) ? AccessTools.Method(t, method, (Type[])null, (Type[])null) : AccessTools.Method(t, method, args, (Type[])null)); if (methodInfo == null) { throw new MissingMethodException(t.Name, method); } h.Patch((MethodBase)methodInfo, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Patches), prefix, (Type[])null), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Patches), postfix, (Type[])null), (HarmonyMethod)null, (finalizer == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Patches), finalizer, (Type[])null), (HarmonyMethod)null); ok++; return true; } catch (Exception ex) { failed++; Plugin.Log.LogWarning((object)("Could not patch " + t.Name + "." + method + ": " + ex.Message + " (that rule is off)")); return false; } } private static void FillSettings_Pre(UI_GamemodeScreen_Panel __instance) { try { Mode.EnsureInjected(__instance.GetGamemode()); } catch (Exception ex) { Util.LogOnce("fill", "Inject failed: " + ex.Message); } } private static Exception SettingInit_Finalizer(Exception __exception, GamemodeSetting setting) { if (__exception == null) { return null; } if ((Object)(object)setting == (Object)null || setting.id != "skmod_super") { return __exception; } Plugin.Log.LogError((object)("SUPER HARD button failed to build, removing it so the menu keeps working: " + __exception)); Mode.Broken = true; return null; } private static Exception FillSettings_Finalizer(Exception __exception) { if (__exception != null && !Mode.Broken && (Object)(object)Mode.Setting != (Object)null) { Plugin.Log.LogError((object)("Run setup crashed with SUPER HARD added, removing it: " + __exception)); Mode.Broken = true; Mode.RemoveEverywhere(); } return __exception; } private static void ScreenInit_Pre(M_Gamemode mode) { try { Mode.EnsureInjected(mode); } catch (Exception ex) { Util.LogOnce("init", "Inject failed: " + ex.Message); } } private static bool ForcedId(string id) { if (id != null && id != "skmod_super") { if (!Cfg.ForceHardMode.Value || !Mode.HardIds.Contains(id)) { if (Cfg.ForceSurvival.Value) { return Mode.SurvivalIds.Contains(id); } return false; } return true; } return false; } private static void HasActiveSetting_Post(M_Gamemode __instance, string id, ref bool __result) { if (!__result && !Mode.InCheck && ForcedId(id) && Mode.IsOnFor(__instance)) { __result = true; } } private static void GetActiveSettings_Post(M_Gamemode __instance, ref List<GamemodeSetting> __result) { if (Mode.InCheck || (Object)(object)__instance == (Object)null || __instance.gamemodeSettings == null || !Mode.IsOnFor(__instance)) { return; } List<GamemodeSetting> list = ((__result != null) ? new List<GamemodeSetting>(__result) : new List<GamemodeSetting>()); foreach (GamemodeSetting gamemodeSetting in __instance.gamemodeSettings) { if ((Object)(object)gamemodeSetting != (Object)null && ForcedId(gamemodeSetting.id) && !list.Contains(gamemodeSetting)) { list.Add(gamemodeSetting); } } __result = list; } private static void ModeIsHard_Post(M_Gamemode __instance, ref bool __result) { if (!__result && Cfg.ForceHardMode.Value && !Mode.InCheck && Mode.IsOnFor(__instance)) { __result = true; } } private static void GameIsHard_Post(ref bool __result) { if (!__result && Cfg.ForceHardMode.Value && !Mode.InCheck && Mode.IsActive()) { __result = true; } } private static bool Trinket_Activate_Pre(Trinket __instance) { if ((Object)(object)__instance == (Object)null || __instance.isBinding || Buddy.Granting || !Mode.IsActive()) { return true; } Util.Debug("Trinket blocked: " + __instance.title); return false; } private static void HandItemUse_Pre(HandItem __instance) { if ((Object)(object)__instance == (Object)null || !Mode.IsActive()) { return; } try { Buddy.OnUse(__instance.item); } catch { } } private static void HandStamina_Pre(Hand curhand, out float __state) { __state = curhand?.gripStrength ?? (-1f); } private static void HandStamina_Post(ENT_Player __instance, Hand curhand, float __state) { if (__state < 0f || curhand == null || !Mode.IsActive()) { return; } try { if (!curhand.IsHanging() || PlayerRules.HasInfiniteStamina(__instance)) { return; } float gripStrengthMax = curhand.GetGripStrengthMax(); if (!(gripStrengthMax <= 0f)) { float num = __state - gripStrengthMax / Mathf.Max(0.25f, Cfg.HangSeconds.Value) * Time.deltaTime; if (curhand.gripStrength > num) { curhand.gripStrength = Mathf.Max(0f, num); } } } catch (Exception ex) { Util.LogOnce("stam", "Grip drain failed: " + ex.Message); } } private static void PlayerDamage_Post(ENT_Player __instance) { if (!hopperHit) { return; } hopperHit = false; if ((Object)(object)__instance == (Object)null || ((GameEntity)__instance).dead) { return; } Util.Debug("Hopper roach hit - instant death."); try { ((GameEntity)__instance).Kill("hopper", DamageInfo.CreateDamageInfo(99999f, "hopper")); } catch (Exception ex) { Util.LogOnce("hopkill", "Hopper kill failed: " + ex.Message); } } private static void PlayerDamage_Pre(DamageInfo info) { hopperHit = false; if (info == null || !Mode.IsActive()) { return; } try { GameObject val = (((Object)(object)info.sourceEntity != (Object)null) ? ((Component)info.sourceEntity).gameObject : info.sourceObject); string text = ((((Object)(object)val != (Object)null) ? (((Object)val).name + " " + ((Object)val.transform.root).name) : "") + " " + info.type + " " + ((info.tags != null) ? string.Join(" ", info.tags.ToArray()) : "")).ToLowerInvariant(); Zone current = Zones.Current; float amount = info.amount; if ((Object)(object)val != (Object)null && Cfg.HopperInstakill.Value) { DEN_Hopper componentInParent = val.GetComponentInParent<DEN_Hopper>(); if ((Object)(object)componentInParent != (Object)null && !(componentInParent is DEN_Hopper_Tick) && (((object)componentInParent).GetType() == typeof(DEN_Hopper) || ((Object)((Component)componentInParent).gameObject).name.ToLowerInvariant().Contains("hopper"))) { info.amount = 99999f; hopperHit = true; } } if (current == Zone.Silos && text.Contains("sturge")) { info.amount *= Cfg.SturgeDamageMult.Value; } if (current == Zone.Pipeworks && text.Contains("steam")) { info.amount *= Cfg.SteamDamageMult.Value; } if (current == Zone.Habitation && (text.Contains("turret") || ((Object)(object)val != (Object)null && ((Object)(object)val.GetComponentInParent<DEN_Turret>() != (Object)null || (Object)(object)val.GetComponentInParent<DEN_GantryTurret>() != (Object)null)))) { info.amount *= Cfg.TurretDamageMult.Value; } if (info.amount != amount) { Util.DebugOnce("dmg" + text, "Damage " + amount + " -> " + info.amount + " from: " + text); } } catch (Exception ex) { Util.LogOnce("pdmg", "Damage rule failed: " + ex.Message); } } private static bool IsHammer(HandItem_Melee m) { if ((Object)(object)m != (Object)null && ((object)m).GetType() == typeof(HandItem_Melee) && !m.banHammer) { return ((Object)((Component)m).gameObject).name.ToLowerInvariant().Contains("hammer"); } return false; } private static void Melee_Pre(HandItem_Melee __instance, out Vector2 __state) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) __state = new Vector2(float.NaN, float.NaN); if (IsHammer(__instance) && Mode.IsActive()) { __state = new Vector2(__instance.damage, __instance.chargeAttackDamage); __instance.damage *= Cfg.HammerDamageMult.Value; __instance.chargeAttackDamage *= Cfg.HammerDamageMult.Value; } } private static void Melee_Post(HandItem_Melee __instance, Vector2 __state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!float.IsNaN(__state.x) && !((Object)(object)__instance == (Object)null)) { __instance.damage = __state.x; __instance.chargeAttackDamage = __state.y; } } private static void RandomCheck_Post(SpawnSettings __instance, ref bool __result) { if (__instance == null || !Mode.IsActive()) { return; } try { SpawnRules.Decide(__instance, ref __result); } catch (Exception ex) { Util.LogOnce("rc", "Spawn rule failed: " + ex.Message); } } private static void SpawnChance_Pre(UT_SpawnChance __instance) { if (!Mode.IsActive()) { return; } try { SpawnRules.RegisterComponent((MonoBehaviour)(object)__instance, __instance.spawnSettings, (UnityEventBase)(object)__instance.onSuccess, ""); } catch { } } private static void EventChance_Pre(UT_EventChance __instance) { if (!Mode.IsActive()) { return; } try { SpawnRules.RegisterComponent((MonoBehaviour)(object)__instance, __instance.spawnSettings, (UnityEventBase)(object)__instance.successEvent, ""); } catch { } } private static void SpawnById_Pre(UT_SpawnEntityByID __instance) { if (!Mode.IsActive()) { return; } try { string extra = __instance.idToSpawn + " " + SpawnRules.PrefabDescription(__instance.idToSpawn, __instance.customDatabase); SpawnRules.RegisterComponent((MonoBehaviour)(object)__instance, __instance.spawnSettings, null, extra); } catch { } } private static void SpawnTable_Pre(SpawnTable __instance) { if (!Mode.IsActive()) { return; } try { SpawnRules.RegisterTable(__instance); } catch { } } private static bool AddPerk_Pre(Perk perk, ref Perk __result) { if ((Object)(object)perk == (Object)null || !Cfg.CavityRoute.Value || !Mode.IsActive()) { return true; } if (!CavityRoute.IsAmalgam(perk.id + " " + perk.title + " " + ((Object)perk).name)) { return true; } Util.Debug("No Amalgamator on Super Hard: blocked perk " + perk.id); __result = null; return false; } private static void LeaveChamber_Post(UT_ChamberLoader __instance) { if (Mode.IsActive()) { Util.Debug("Left chamber via " + (((Object)(object)__instance != (Object)null) ? ((Object)((Component)__instance).gameObject).name : "?")); CavityRoute.OnChamberLeft(); } } private static void Branch_Pre(UT_BranchGenerator __instance) { if (Mode.IsActive() && !((Object)(object)__instance == (Object)null)) { Util.Debug("Moving into branch from " + ((Object)((Component)__instance).gameObject).name + " (level " + (((Object)(object)__instance.currentLevel != (Object)null) ? __instance.currentLevel.levelName : "?") + ")"); } } private static void SetGameFlag_Pre(string name, bool state) { if (Mode.IsActive() && !(name == "skmod_run_cavity_done")) { if (!name.StartsWith("unlock_")) { Util.DebugOnce("flag" + name + state, "Game flag set: " + name + " = " + state + " [" + Zones.Where + "]"); } CavityRoute.OnFlag(name, state); } } private static void Button_Post(CL_Button __instance) { if ((Object)(object)__instance == (Object)null || !__instance.hasBeenPressed || !Mode.IsActive()) { return; } try { Timers.OnButtonPressed((Component)(object)__instance); } catch { } } private static void HoldButton_Post(CL_HoldButton __instance) { if ((Object)(object)__instance == (Object)null || !__instance.hasFinished || Zones.Current != Zone.Nest || !Mode.IsActive()) { return; } try { Timers.OnButtonPressed((Component)(object)__instance); } catch { } } private static bool TickStillSucking(DEN_Hopper_Tick t) { if ((Object)(object)t == (Object)null || !Cfg.TicksHoldOn.Value || tickAttached == null || tickDrained == null) { return false; } try { if (!tickAttached.Invoke(t)) { return false; } GameEntity obj = ((tickTarget != null) ? tickTarget.Invoke(t) : null); ENT_Player val = (ENT_Player)(object)((obj is ENT_Player) ? obj : null); if (val == null || ((GameEntity)val).dead || CL_GameManager.isDead()) { return false; } return tickDrained.Invoke(t) < t.maxBloodDrain; } catch { return false; } } private static bool Tick_Damage_Pre(DEN_Hopper_Tick __instance, ref bool __result) { if (!Mode.IsActive()) { return true; } if (Zones.Current != Zone.Nest && !TickStillSucking(__instance)) { return true; } __result = false; return false; } private static bool Tick_Detach_Pre(DEN_Hopper_Tick __instance) { if (!Mode.IsActive() || !TickStillSucking(__instance)) { return true; } Util.DebugOnce("tickhold" + ((Object)__instance).GetInstanceID(), "Tick won't let go until it's full."); return false; } private static bool Tick_Kill_Pre(Denizen __instance) { if (Mode.IsActive()) { DEN_Hopper_Tick val = (DEN_Hopper_Tick)(object)((__instance is DEN_Hopper_Tick) ? __instance : null); if (val != null) { return !TickStillSucking(val); } } return true; } private static bool Teeth_Despawn_Pre() { if (!Cfg.TeethStaysUntilHidden.Value || !Mode.IsActive() || Zones.Current != Zone.Habitation) { return true; } ENT_Player val = Util.Player(); if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead()) { return true; } float num = 1f; try { num = ((GameEntity)val).GetVisibility(); } catch { return true; } if (num < Cfg.HiddenVisibility.Value) { Util.Debug("Hidden (visibility " + num.ToString("0.00") + ") - Teeth may leave."); return true; } Util.DebugOnce("teethstay", "Teeth tried to leave but you're not hidden (visibility " + num.ToString("0.00") + ")."); return false; } private static void Mass_Update_Pre(DEN_DeathFloor __instance) { ApplyMass(__instance); } internal static void ApplyMass(DEN_DeathFloor __instance) { if ((Object)(object)__instance == (Object)null || !Mode.IsActive()) { return; } float num = Cfg.MassSpeedMult.Value; if (Zones.Current == Zone.Silos) { num *= Cfg.SilosMassMult.Value; } else if (Zones.Current == Zone.Nest && Zones.NestLastSection) { float num2 = 1f; if ((Object)(object)CL_EventManager.currentSubregion != (Object)null && CL_EventManager.currentSubregion.massSpeedMult > 0.05f) { num2 *= CL_EventManager.currentSubregion.massSpeedMult; } if ((Object)(object)CL_EventManager.currentLevel != (Object)null && CL_EventManager.currentLevel.massSpeedMult > 0.05f) { num2 *= CL_EventManager.currentLevel.massSpeedMult; } num = ((Mathf.Abs(num2 - 1f) > 0.01f) ? (1f / num2) : 1f); } if (!(Mathf.Abs(num - 1f) > 0.001f)) { return; } try { __instance.SetUpdateSpeedMultiplier(num); } catch (Exception ex) { Util.LogOnce("mass", "Mass speed failed: " + ex.Message); } } } internal static class PlayerRules { private static ENT_Player gravityPlayer; private static float appliedMult = 1f; private static float poisonTimer; private static bool fallKillDone; private static readonly FieldRef<ENT_Player, bool> infiniteStamina = Util.SafeFieldRef<ENT_Player, bool>("infiniteStamina"); public static void Reset() { gravityPlayer = null; appliedMult = 1f; poisonTimer = 0f; fallKillDone = false; } public static void Tick() { ENT_Player val = Util.Player(); if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)gravityPlayer != (Object)(object)val) { gravityPlayer = val; appliedMult = Cfg.GravityMult.Value; val.gravity *= appliedMult; Util.Debug("Gravity x" + appliedMult + " -> " + val.gravity); } if (((GameEntity)val).dead || CL_GameManager.isDead()) { return; } if (Zones.Current == Zone.Nest && Cfg.NestWaterDps.Value > 0f && val.IsSwimming()) { poisonTimer += Time.deltaTime; if (poisonTimer >= 0.5f) { poisonTimer = 0f; float num = Mathf.Max(1f, ((GameEntity)val).maxHealth * Cfg.NestWaterDps.Value / 100f * 0.5f); try { ((GameEntity)val).Damage(DamageInfo.CreateDamageInfo(num, "poison")); } catch (Exception ex) { Util.LogOnce("poison", "Water poison failed: " + ex.Message); } } } else { poisonTimer = 0f; } if (Zones.Current == Zone.Abyss && !fallKillDone) { float num2 = 0f; try { num2 = val.GetCurrentFallDistance(); } catch { } if (num2 >= Cfg.AbyssFallDeath.Value) { fallKillDone = true; Util.Debug("Fell " + num2.ToString("0") + " m in the Abyss - the nightmare takes you."); try { ((GameEntity)val).Kill("nightmare", DamageInfo.CreateDamageInfo(99999f, "nightmare")); } catch (Exception ex2) { Util.LogOnce("fallkill", "Abyss fall kill failed: " + ex2.Message); } } } if (fallKillDone && !((GameEntity)val).dead) { fallKillDone = false; } } public static bool HasInfiniteStamina(ENT_Player p) { if (infiniteStamina == null || (Object)(object)p == (Object)null) { return false; } try { return infiniteStamina.Invoke(p); } catch { return false; } } } [BepInPlugin("com.wkmods.superhardknuckle", "SuperHardKnuckle", "1.0.12")] public class Plugin : BaseUnityPlugin { public const string GUID = "com.wkmods.superhardknuckle"; public const string NAME = "SuperHardKnuckle"; public const string VERSION = "1.0.12"; internal static Plugin Instance; internal static ManualLogSource Log; internal static Harmony Harmony; private CL_GameManager lastGameManager; private float nextSlowTick; private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Cfg.Bind(((BaseUnityPlugin)this).Config); Harmony = new Harmony("com.wkmods.superhardknuckle"); Patches.ApplyAll(Harmony); Log.LogInfo((object)"SuperHardKnuckle 1.0.12 loaded. Pick SUPER HARD next to Hard Mode / Iron Knuckle on the run setup screen."); } private void Update() { try { Mode.MenuTick(); CL_GameManager gMan = CL_GameManager.gMan; if ((Object)(object)gMan != (Object)(object)lastGameManager) { lastGameManager = gMan; if ((Object)(object)gMan != (Object)null) { OnNewRun(); } } bool num = Mode.IsActive(); Mode.ApplyGlobalToggles(num); if (num && !((Object)(object)gMan == (Object)null)) { Zones.Tick(); PlayerRules.Tick(); EntityRules.Tick(); Timers.Tick(); CavityRoute.Tick(); Buddy.Tick(); SilosSturges.Tick(); RedRoaches.Tick(); if (!Patches.MassPatched) { Patches.ApplyMass(DEN_DeathFloor.instance); } if (Time.unscaledTime >= nextSlowTick) { nextSlowTick = Time.unscaledTime + 1f; ItemRules.SlowTick(); } } } catch (Exception ex) { Util.LogOnce("update", "Update error: " + ex); } } private void OnNewRun() { EntityRules.Reset(); ItemRules.Reset(); Timers.Reset(); PlayerRules.Reset(); Zones.Reset(); CavityRoute.Reset(); Buddy.Reset(); SilosSturges.Reset(); RedRoaches.Reset(); SpawnRules.RegisterAssetOwners(); ClearOldSavedFlags(); } private static void ClearOldSavedFlags() { string[] array = new string[2] { "skmod_buddy_given", "skmod_cavity_done" }; foreach (string text in array) { try { if (CL_GameManager.HasActiveFlag(text, false)) { CL_GameManager.SetGameFlag(text, false, "", true, false); Log.LogInfo((object)("Cleared leftover saved flag " + text)); } } catch { } } } private void OnGUI() { try { Hud.Draw(); } catch (Exception ex) { Util.LogOnce("gui", "HUD error: " + ex.Message); } } } internal static class Cfg { public static ConfigEntry<bool> DebugLog; public static ConfigEntry<bool> ShowHud; public static ConfigEntry<bool> ForceHardMode; public static ConfigEntry<bool> ForceSurvival; public static ConfigEntry<bool> DisableLeaderboards; public static ConfigEntry<float> GravityMult; public static ConfigEntry<float> HangSeconds; public static ConfigEntry<float> HammerDamageMult; public static ConfigEntry<float> EngravedDoorChance; public static ConfigEntry<string> RedRoachKeywords; public static ConfigEntry<float> RemainsInterval; public static ConfigEntry<float> MassSpeedMult; public static ConfigEntry<bool> HopperInstakill; public static ConfigEntry<bool> TicksHoldOn; public static ConfigEntry<int> RedRoachExtra; public static ConfigEntry<float> RedRoachSpawnSeconds; public static ConfigEntry<int> RedRoachMax; public static ConfigEntry<int> TurretExtra; public static ConfigEntry<int> SilosSturgeExtra; public static ConfigEntry<bool> BuddyEnabled; public static ConfigEntry<float> BuddyPetSeconds; public static ConfigEntry<float> SilosSturgeInterval; public static ConfigEntry<int> SilosSturgeMax; public static ConfigEntry<int> SilosBloodbugExtra; public static ConfigEntry<float> SilosMassMult; public static ConfigEntry<float> SturgeDamageMult; public static ConfigEntry<string> TierOneMap; public static ConfigEntry<int> PipeworksBarnacleExtra; public static ConfigEntry<int> PipeworksHopperExtra; public static ConfigEntry<float> SteamDamageMult; public static ConfigEntry<bool> CavityRoute; public static ConfigEntry<string> ServiceShaftKeywords; public static ConfigEntry<string> AmalgamKeywords; public static ConfigEntry<float> RatKingSpeedMult; public static ConfigEntry<float> TeethSpeedMult; public static ConfigEntry<bool> TeethStaysUntilHidden; public static ConfigEntry<float> HiddenVisibility; public static ConfigEntry<float> VentThingSpeedMult; public static ConfigEntry<float> TurretDamageMult; public static ConfigEntry<float> TurretDroneChance; public static ConfigEntry<int> AbyssFaceCount; public static ConfigEntry<float> AbyssFallDeath; public static ConfigEntry<int> NestBarnacleExtra; public static ConfigEntry<float> MotherSeconds; public static ConfigEntry<int> MotherButtons; public static ConfigEntry<float> MotherRoomRadius; public static ConfigEntry<float> NestWaterDps; public static ConfigEntry<string> NestLastSectionKeywords; public static void Bind(ConfigFile c) { DebugLog = c.Bind<bool>("General", "DebugLog", true, "Write what the mod changes (zones, boosted spawns, clones, replaced items) to the BepInEx log. Handy for tuning."); ShowHud = c.Bind<bool>("General", "ShowHud", true, "Show the small SUPER HARD label and timers on screen."); ForceHardMode = c.Bind<bool>("General", "ForceHardMode", true, "Super Hard always includes vanilla Hard Mode."); ForceSurvival = c.Bind<bool>("General", "ForceSurvival", true, "Super Hard always turns on the Survival setting (if the gamemode has one)."); DisableLeaderboards = c.Bind<bool>("General", "DisableLeaderboards", true, "Don't submit modded Super Hard runs to the online leaderboards."); GravityMult = c.Bind<float>("Global", "GravityMult", 1.2f, "Player gravity multiplier (1.2 = +20%)."); HangSeconds = c.Bind<float>("Global", "HangSeconds", 3f, "A full grip drains in this many seconds while hanging."); HammerDamageMult = c.Bind<float>("Global", "HammerDamageMult", 0.6f, "Hammer damage multiplier."); EngravedDoorChance = c.Bind<float>("Global", "EngravedDoorChance", 0.4f, "Spawn chance for Engraved Doors."); RedRoachKeywords = c.Bind<string>("Global", "RedRoachNames", "roach_explosive,redroach,red_roach,roach_red", "Names that count as red roaches (the game calls them Denizen_Roach_Explosive)."); RedRoachExtra = c.Bind<int>("Global", "RedRoachExtraCopies", 3, "Extra copies of every red roach that appears."); RedRoachSpawnSeconds = c.Bind<float>("Global", "RedRoachSpawnSeconds", 35f, "A red roach also spawns near you this often, everywhere (0 = off)."); RedRoachMax = c.Bind<int>("Global", "RedRoachMaxAlive", 8, "Most extra red roaches from the timer alive at once."); TurretExtra = c.Bind<int>("Global", "TurretExtraCopies", 2, "Extra copies of every turret, and every turret spawn chance is forced on."); HopperInstakill = c.Bind<bool>("Global", "HopperRoachInstakill", true, "Getting hurt by a hopper roach (Denizen_Hopper) kills you instantly, everywhere."); TicksHoldOn = c.Bind<bool>("Global", "TicksCantBeThrownOff", true, "Tick roaches can't be thrown off or killed while latched on - they let go only once they've drunk their fill."); MassSpeedMult = c.Bind<float>("Global", "MassSpeedMult", 1.6f, "Mass speed everywhere. The Silos multiplier stacks on top of this, and the Nest's last section stays at 1x."); RemainsInterval = c.Bind<float>("Global", "RemainsIntervalSeconds", 600f, "A Remains spawns near you every this many seconds."); BuddyEnabled = c.Bind<bool>("Global", "CalmingBuddy", true, "You always start with the Calming Buddy and must pet it (use it in your hand) regularly or you die."); BuddyPetSeconds = c.Bind<float>("Global", "CalmingBuddyPetSeconds", 300f, "Seconds you can go without petting the Calming Buddy."); SilosSturgeInterval = c.Bind<float>("Silos", "SturgeEverySeconds", 25f, "A Sturge spawns near you this often in the Silos (0 = off)."); SilosSturgeMax = c.Bind<int>("Silos", "SturgeMaxAlive", 8, "Most extra Sturges from the timer alive at once."); SilosSturgeExtra = c.Bind<int>("Silos", "SturgeExtraCopies", 1, "Extra copies of every Sturge that appears in the Silos."); SilosBloodbugExtra = c.Bind<int>("Silos", "BloodbugExtra", 1, "Extra copies of every bloodbug (any variant). 1 = double."); SilosMassMult = c.Bind<float>("Silos", "MassSpeedMult", 0.6f, "Mass speed multiplier in the Silos."); SturgeDamageMult = c.Bind<float>("Silos", "SturgeDamageMult", 2f, "Sturge damage multiplier."); TierOneMap = c.Bind<string>("Silos", "TierOneReplacements", "Item_RebarRope=Item_Rebar", "Extra item swaps for Silos (name=replacement; ...). Anything ending _T2/_T3 is swapped to _T1 automatically."); PipeworksBarnacleExtra = c.Bind<int>("Pipeworks", "BarnacleExtra", 1, "Extra copies of every barnacle in Pipeworks."); PipeworksHopperExtra = c.Bind<int>("Pipeworks", "HopperExtra", 1, "Extra copies of every hopper roach in Pipeworks."); SteamDamageMult = c.Bind<float>("Pipeworks", "SteamDamageMult", 2.5f, "Steam pipe damage multiplier."); CavityRoute = c.Bind<bool>("Habitation", "SecurityShaftNeedsBodyCavity", true, "The Security Shaft stays sealed until you beat the Body Cavity shortcut in this run. Beating it sends you back to the Habitation break room."); ServiceShaftKeywords = c.Bind<string>("Habitation", "ServiceShaftLevelKeywords", "habitation_shaft_0,habitation_shaft_1,habitation_shaft_to,security", "Level names that count as the shaft behind the break-room gate (the game calls it Service Shaft). The break room (M3_Habitation_Shaft_Intro) never counts."); AmalgamKeywords = c.Bind<string>("Habitation", "AmalgamatorKeywords", "amalgam", "Items/perks with these names are never given out (the Amalgamator)."); RatKingSpeedMult = c.Bind<float>("Habitation", "RatKingSpeedMult", 2.5f, "Rat King speed multiplier."); TeethSpeedMult = c.Bind<float>("Habitation", "TeethSpeedMult", 1.8f, "Teeth speed multiplier."); TeethStaysUntilHidden = c.Bind<bool>("Habitation", "TeethStaysUntilHidden", true, "Teeth won't despawn until you are hidden."); HiddenVisibility = c.Bind<float>("Habitation", "HiddenVisibility", 0.35f, "You count as hidden when the game's visibility value is below this."); VentThingSpeedMult = c.Bind<float>("Habitation", "VentThingSpeedMult", 1.8f, "Vent thing hand speed and pull multiplier."); TurretDamageMult = c.Bind<float>("Habitation", "TurretDamageMult", 2f, "Turret damage multiplier."); TurretDroneChance = c.Bind<float>("Habitation", "TurretDroneChance", 0.5f, "Chance a drone spawns next to each turret."); AbyssFaceCount = c.Bind<int>("Abyss", "FaceCount", 5, "How many faces hunt you in the Abyss."); AbyssFallDeath = c.Bind<float>("Abyss", "FallDeathMeters", 100f, "Falling this far in the Abyss kills you."); NestBarnacleExtra = c.Bind<int>("Nest", "BarnacleExtra", 2, "Extra copies of every barnacle in the Nest."); MotherSeconds = c.Bind<float>("Nest", "MotherSeconds", 30f, "Seconds you get near the Mother before she kills you."); MotherButtons = c.Bind<int>("Nest", "MotherSavedAfterButtons", 3, "Pressing this many different buttons in the Mother's room saves her and stops the timer."); MotherRoomRadius = c.Bind<float>("Nest", "MotherRoomRadius", 80f, "Buttons within this many metres of the Mother count as hers."); NestWaterDps = c.Bind<float>("Nest", "WaterPoisonPercentPerSecond", 8f, "Percent of max health lost per second while in Nest water."); NestLastSectionKeywords = c.Bind<string>("Nest", "LastSectionKeywords", "mother", "Level/subregion names that count as the Nest's last section (the final subregion always counts)."); } } internal static class SpawnRules { private sealed class RefEq : IEqualityComparer<SpawnSettings> { public bool Equals(SpawnSettings a, SpawnSettings b) { return a == b; } public int GetHashCode(SpawnSettings s) { return RuntimeHelpers.GetHashCode(s); } } private static readonly Dictionary<SpawnSettings, string> owners = new Dictionary<SpawnSettings, string>(new RefEq()); private static string[] redRoachKeys; public static void RegisterAssetOwners() { redRoachKeys = null; try { WKAssetDatabase val = Util.Db(); if ((Object)(object)val == (Object)null) { return; } if (val.sessionEvents != null) { foreach (SessionEvent sessionEvent in val.sessionEvents) { if ((Object)(object)sessionEvent != (Object)null && sessionEvent.spawnSettings != null) { owners[sessionEvent.spawnSettings] = ("event " + sessionEvent.id + " " + ((Object)sessionEvent).name).ToLowerInvariant(); } } } if (val.subRegionAssets != null) { foreach (M_Subregion subRegionAsset in val.subRegionAssets) { if ((Object)(object)subRegionAsset != (Object)null && subRegionAsset.spawnSettings != null) { owners[subRegionAsset.spawnSettings] = ("subregion " + ((Object)subRegionAsset).name + " " + subRegionAsset.subregionName).ToLowerInvariant(); } } } if (val.perkAssets == null) { return; } foreach (Perk perkAsset in val.perkAssets) { if ((Object)(object)perkAsset != (Object)null && perkAsset.spawnSettings != null) { owners[perkAsset.spawnSettings] = ("perk " + perkAsset.id).ToLowerInvariant(); } } } catch (Exception ex) { Util.LogOnce("owners", "Spawn owner scan failed: " + ex.Message); } } public static void RegisterComponent(MonoBehaviour c, SpawnSettings s, UnityEventBase ev, string extra) { if (!((Object)(object)c == (Object)null) && s != null && !owners.ContainsKey(s)) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(((object)c).GetType().Name).Append(' ').Append(extra) .Append(' '); Transform val = ((Component)c).transform; int num = 0; while (num < 3 && (Object)(object)val != (Object)null) { stringBuilder.Append(((Object)val).name).Append(' '); num++; val = val.parent; } if (ev != null) { DescribeEvent(ev, stringBuilder); } owners[s] = stringBuilder.ToString().ToLowerInvariant(); } } public static void RegisterTable(SpawnTable table) { if ((Object)(object)table == (Object)null || table.spawnList == null) { return; } foreach (SpawnTableAsset spawn in table.spawnList) { if (spawn == null || spawn.spawnSettings == null || owners.ContainsKey(spawn.spawnSettings)) { continue; } StringBuilder stringBuilder = new StringBuilder("table ").Append(((Object)table).name).Append(' ').Append(spawn.name) .Append(' '); if (spawn.prefabs != null) { foreach (GameObject prefab in spawn.prefabs) { if ((Object)(object)prefab != (Object)null) { DescribeHierarchy(prefab, stringBuilder); } } } owners[spawn.spawnSettings] = stringBuilder.ToString().ToLowerInvariant(); } } public static string PrefabDescription(string id, string database) { try { GameObject assetGameObject = CL_AssetManager.GetAssetGameObject(id, database); if ((Object)(object)assetGameObject == (Object)null) { return ""; } StringBuilder stringBuilder = new StringBuilder(); DescribeHierarchy(assetGameObject, stringBuilder); return stringBuilder.ToString(); } catch { return ""; } } private static void DescribeEvent(UnityEventBase ev, StringBuilder sb) { int persistentEventCount = ev.GetPersistentEventCount(); for (int i = 0; i < persistentEventCount; i++) { Object persistentTarget = ev.GetPersistentTarget(i); if (persistentTarget == (Object)null) { continue; } GameObject val = (GameObject)(object)((persistentTarget is GameObject) ? persistentTarget : null); if ((Object)(object)val == (Object)null) { Component val2 = (Component)(object)((persistentTarget is Component) ? persistentTarget : null); if (val2 != null) { val = val2.gameObject; } } if ((Object)(object)val != (Object)null) { DescribeHierarchy(val, sb); } else { sb.Append(persistentTarget.name).Append(' '); } } } private static void DescribeHierarchy(GameObject g, StringBuilder sb) { sb.Append(((Object)g).name).Append(' '); if (g.GetComponentsInChildren<Transform>(true).Length > 40) { return; } HashSet<string> hashSet = new HashSet<string>(); MonoBehaviour[] componentsInChildren = g.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { if (val is GameEntity) { hashSet.Add(((object)val).GetType().Name); } UT_SpawnEntityByID val2 = (UT_SpawnEntityByID)(object)((val is UT_SpawnEntityByID) ? val : null); if (val2 != null) { sb.Append(val2.idToSpawn).Append(' '); } } } foreach (string item in hashSet) { sb.Append(item).Append(' '); } } public static void Decide(SpawnSettings s, ref bool result) { if (owners.TryGetValue(s, out var value) && !string.IsNullOrEmpty(value)) { float? num = null; string text = null; if (Zones.Current == Zone.Habitation && value.Contains("cavity")) { num = 1f; text = "body cavity forced"; } else if (IsRedRoach(value)) { num = 1f; text = "red roach always"; } else if (value.Contains("turret")) { num = 1f; text = "turrets always"; } else if (value.Contains("engraved")) { num = Cfg.EngravedDoorChance.Value; text = "engraved door " + (Cfg.EngravedDoorChance.Value * 100f).ToString("0") + "%"; } if (num.HasValue) { bool flag = result; result = num.Value >= 1f || Random.value < num.Value; Util.DebugOnce(text + value, "Spawn rule '" + text + "' on: " + Short(value) + " (" + flag + " -> " + result + ")"); } } } public static bool IsRedRoach(string desc) { string[] array; if (redRoachKeys == null) { List<string> list = new List<string>(); array = Cfg.RedRoachKeywords.Value.Split(','); foreach (string text in array) { if (text.Trim().Length > 0) { list.Add(text.Trim().ToLowerInvariant()); } } redRoachKeys = list.ToArray(); } array = redRoachKeys; foreach (string value in array) { if (desc.Contains(value)) { return true; } } return false; } private static string Short(string s) { if (s.Length <= 160) { return s; } return s.Substring(0, 160) + "..."; } } internal static class Timers { public static float RemainsTimer; public static float MotherLeft = -1f; private static DEN_Mother timedMother; private static bool motherDone; private static bool motherSaved; private static readonly HashSet<int> motherButtons = new HashSet<int>(); public static void Reset() { RemainsTimer = 0f; MotherLeft = -1f; timedMother = null; motherDone = false; motherSaved = false; motherButtons.Clear(); } public static void Tick() { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) ENT_Player val = Util.Player(); if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead() || ((Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.gMan.isPaused)) { return; } RemainsTimer += Time.deltaTime; if (RemainsTimer >= Cfg.RemainsInterval.Value) { RemainsTimer = 0f; SpawnRemains(); } if (Zones.Current == Zone.Nest) { DEN_Mother instance = DEN_Mother.instance; if ((Object)(object)instance != (Object)null && ((Component)instance).gameObject.activeInHierarchy && !((GameEntity)instance).dead) { if ((Object)(object)instance != (Object)(object)timedMother) { timedMother = instance; MotherLeft = -1f; motherDone = false; motherSaved = false; motherButtons.Clear(); } if (motherSaved) { MotherLeft = -1f; return; } float num = Vector3.Distance(((Component)val).transform.position, ((Component)instance).transform.position); if (MotherLeft < 0f && !motherDone && num < 35f) { MotherLeft = Cfg.MotherSeconds.Value; Util.Debug("Mother section: " + MotherLeft + " seconds."); } if (!(MotherLeft >= 0f)) { return; } if (num > 70f) { MotherLeft = -1f; motherDone = true; Util.Debug("Made it past the Mother."); return; } MotherLeft -= Time.deltaTime; if (MotherLeft <= 0f) { MotherLeft = -1f; motherDone = true; Util.Debug("Mother timer ran out."); try { instance.Enrage(true); } catch (Exception ex) { Util.LogOnce("enrage", "Enrage failed: " + ex.Message); } try { instance.KillPlayer(); } catch (Exception ex2) { Util.LogOnce("motherkill", "Mother kill failed: " + ex2.Message); } } } else if (MotherLeft >= 0f) { MotherLeft = -1f; motherDone = true; } } else { MotherLeft = -1f; } } public static void OnButtonPressed(Component button) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)button == (Object)null || motherSaved || Zones.Current != Zone.Nest) { return; } DEN_Mother instance = DEN_Mother.instance; if (!((Object)(object)instance == (Object)null) && !((GameEntity)instance).dead && !(Vector3.Distance(button.transform.position, ((Component)instance).transform.position) > Cfg.MotherRoomRadius.Value) && motherButtons.Add(((Object)button).GetInstanceID())) { Util.Debug("Mother's room button pressed: " + ((Object)button.gameObject).name + " (" + motherButtons.Count + "/" + Cfg.MotherButtons.Value + ")"); if (motherButtons.Count >= Cfg.MotherButtons.Value) { motherSaved = true; motherDone = true; timedMother = instance; MotherLeft = -1f; Util.Debug("The Mother is saved - her timer stops."); Hud.Flash("SHE IS SAVED"); } } } private unsafe static void SpawnRemains() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) GameObject val = Util.FindPrefabWith<DEN_Remains_Active>(); if ((Object)(object)val == (Object)null) { return; } if (!Util.SpotAroundPlayer(14f, 26f, out var pos)) { RemainsTimer = Cfg.RemainsInterval.Value - 15f; return; } Transform parent = null; try { parent = WorldLoader.GetCurrentLevelParentRoot(); } catch { } GameObject val2 = Util.Spawn(val, pos, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f), parent); DEN_Remains_Active val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponentInChildren<DEN_Remains_Active>(true) : null); if ((Object)(object)val3 != (Object)null) { val3.active = true; } Util.Debug("Remains spawned at " + ((object)(*(Vector3*)(&pos))/*cast due to .constrained prefix*/).ToString() + " (" + (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "failed") + ")"); Hud.Flash("Something remains..."); } } internal static class Util { private static readonly HashSet<string> once = new HashSet<string>(); private static WKAssetDatabase dbCache; private static int dbScene = -1; private static CL_GameManager dbGameManager; private static float dbRetryAt; private static readonly Dictionary<Type, GameObject> prefabByType = new Dictionary<Type, GameObject>(); private static readonly Dictionary<string, GameObject> itemByName = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, GameObject> prefabByName = new Dictionary<string, GameObject>(); public static void Debug(string msg) { if (Cfg.DebugLog != null && Cfg.DebugLog.Value) { Plugin.Log.LogInfo((object)msg); } } public static void DebugOnce(string key, string msg) { if (once.Add("d:" + key)) { Debug(msg); } } public static void LogOnce(string key, string msg) { if (once.Add("e:" + key)) { Plugin.Log.LogWarning((object)msg); } } public static string Clean(string n) { if (n == null) { return ""; } int num = n.IndexOf("(Clone)", StringComparison.Ordinal); if (num >= 0) { n = n.Substring(0, num); } return n.Trim(); } public static ENT_Player Player() { try { return ENT_Player.GetPlayer(); } catch { return null; } } public static WKAssetDatabase Db() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); int num = SceneHandle.op_Implicit(((Scene)(ref activeScene)).handle); if (num != dbScene || (Object)(object)CL_GameManager.gMan != (Object)(object)dbGameManager || ((Object)(object)dbCache == (Object)null && Time.unscaledTime >= dbRetryAt)) { dbRetryAt = Time.unscaledTime + 5f; dbScene = num; dbGameManager = CL_GameManager.gMan; try { dbCache = CL_AssetManager.GetFullCombinedAssetDatabase(); } catch { dbCache = null; } } return dbCache; } public static void ResetCaches() { prefabByType.Clear(); itemByName.Clear(); prefabByName.Clear(); } public static GameObject FindPrefabWith<T>() where T : Component { if (prefabByType.TryGetValue(typeof(T), out var value) && (Object)(object)value != (Object)null) { return value; } GameObject val = null; try { WKAssetDatabase val2 = Db(); if ((Object)(object)val2 != (Object)null) { val = Scan<T>(val2.denizenPrefabs) ?? Scan<T>(val2.entityPrefabs); } if ((Object)(object)val == (Object)null && (Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.gMan.gameEntityPrefabs != null) { foreach (GameEntity gameEntityPrefab in CL_GameManager.gMan.gameEntityPrefabs) { if ((Object)(object)gameEntityPrefab != (Object)null && (Object)(object)((Component)gameEntityPrefab).GetComponentInChildren<T>(true) != (Object)null) { val = ((Component)gameEntityPrefab).gameObject; break; } } } } catch (Exception ex) { LogOnce("prefab" + typeof(T).Name, "Prefab search for " + typeof(T).Name + " failed: " + ex.Message); } prefabByType[typeof(T)] = val; if ((Object)(object)val == (Object)null) { LogOnce("noprefab" + typeof(T).Name, "No prefab with " + typeof(T).Name + " found, that rule is skipped."); } else { Debug("Using prefab '" + ((Object)val).name + "' for " + typeof(T).Name); } return val; } public static GameObject FindPrefabNamed(string part) { part = part.ToLowerInvariant(); if (prefabByName.TryGetValue(part, out var value) && (Object)(object)value != (Object)null) { return value; } GameObject val = null; try { WKAssetDatabase val2 = Db(); List<List<GameObject>> list = new List<List<GameObject>>(); if ((Object)(object)val2 != (Object)null) { list.Add(val2.denizenPrefabs); list.Add(val2.entityPrefabs); } foreach (List<GameObject> item in list) { if (item == null) { continue; } foreach (GameObject item2 in item) { if (!((Object)(object)item2 == (Object)null)) { string text = ((Object)item2).name.ToLowerInvariant(); if (text.Contains(part) && ((Object)(object)val == (Object)null || text == "denizen_" + part || (text.Length < ((Object)val).name.Length && ((Object)val).name.ToLowerInvariant() != "denizen_" + part))) { val = item2; } } } } } catch (Exception ex) { LogOnce("pname" + part, "Prefab search for '" + part + "' failed: " + ex.Message); } prefabByName[part] = val; if ((Object)(object)val == (Object)null) { LogOnce("nopname" + part, "No prefab named like '" + part + "' found, that rule is skipped."); } else { Debug("Using prefab '" + ((Object)val).name + "' for '" + part + "'"); } return val; } private static GameObject Scan<T>(List<GameObject> list) where T : Component { if (list == null) { return null; } foreach (GameObject item in list) { if ((Object)(object)item != (Object)null && (Object)(object)item.GetComponentInChildren<T>(true) != (Object)null) { return item; } } return null; } public static GameObject ItemPrefab(string name) { if (string.IsNullOrEmpty(name)) { return null; } if (itemByName.Count == 0) { try { WKAssetDatabase val = Db(); if ((Object)(object)val != (Object)null && val.itemPrefabs != null) { foreach (GameObject itemPrefab in val.itemPrefabs) { if ((Object)(object)itemPrefab != (Object)null && !itemByName.ContainsKey(((Object)itemPrefab).name)) { itemByName[((Object)itemPrefab).name] = itemPrefab; } } } } catch (Exception ex) { LogOnce("itemdb", "Item list failed: " + ex.Message); } } itemByName.TryGetValue(name, out var value); return value; } public static GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot, Transform parent = null) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return null; } bool activeSelf = prefab.activeSelf; if (activeSelf) { prefab.SetActive(false); } GameObject val; try { val = (((Object)(object)parent != (Object)null) ? Object.Instantiate<GameObject>(prefab, pos, rot, parent) : Object.Instantiate<GameObject>(prefab, pos, rot)); } finally { if (activeSelf) { prefab.SetActive(true); } } ((Object)val).name = Clean(((Object)prefab).name); val.SetActive(true); return val; } public static Vector3 NearbySpot(Transform t) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: 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_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) Vector3 position = t.position; Vector3 up = t.up; float num = 0.05f; bool flag = false; RaycastHit val = default(RaycastHit); if (Physics.Raycast(position + up * 0.5f, -up, ref val, 3f, -1, (QueryTriggerInteraction)1) && !((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(t)) { flag = true; num = Mathf.Max(0.02f, Vector3.Dot(position - ((RaycastHit)(ref val)).point, ((RaycastHit)(ref val)).normal)); } RaycastHit val4 = default(RaycastHit); RaycastHit val5 = default(RaycastHit); for (int i = 0; i < 12; i++) { Vector3 val2 = Random.onUnitSphere; val2 -= Vector3.Project(val2, up); if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { continue; } ((Vector3)(ref val2)).Normalize(); Vector3 val3 = position + val2 * Random.Range(1.5f, 4f); if (!Physics.Linecast(position + up * 0.3f, val3 + up * 0.3f, ref val4, -1, (QueryTriggerInteraction)1) || ((Component)((RaycastHit)(ref val4)).collider).transform.IsChildOf(t)) { if (!flag) { return val3; } if (Physics.Raycast(val3 + up * 1f, -up, ref val5, 4f, -1, (QueryTriggerInteraction)1) && !((Component)((RaycastHit)(ref val5)).collider).transform.IsChildOf(t)) { return ((RaycastHit)(ref val5)).point + ((RaycastHit)(ref v
ExtremeKnuckle.dll
Decompiled 2 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace ExtremeKnuckle; public class AlwaysHunterTag : MonoBehaviour { } public static class Chaser { public const float FirstDelay = 20f; public const float RespawnDelay = 25f; public const float SpeedFactor = 0.55f; private const float TooFar = 160f; private static DEN_Hunter hunter; private static GameObject prefab; private static float baseSpeed; private static float spawnAt = -1f; private static float farTime; private static bool warnedNoPrefab; public static void Reset() { hunter = null; spawnAt = Time.time + 20f; farTime = 0f; } public static bool Is(GameObject g) { if ((Object)(object)g != (Object)null) { return (Object)(object)g.GetComponent<AlwaysHunterTag>() != (Object)null; } return false; } public static void Tick() { //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) ENT_Player val = Ext.Player(); if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || Ext.Paused()) { return; } if (spawnAt < 0f) { spawnAt = Time.time + 20f; } if (!((Object)(object)hunter != (Object)null) || ((GameEntity)hunter).dead || !((Component)hunter).gameObject.activeInHierarchy) { if ((Object)(object)hunter != (Object)null) { hunter = null; spawnAt = Time.time + 25f; Ext.Debug("The Hunter is gone... for now."); } if (Time.time >= spawnAt) { Spawn(val); } return; } try { float num = baseSpeed * 0.55f; hunter.speedIncreaseRate = 0f; hunter.startSpeed = num; if (R.Get(hunter, "curSpeed", 0f) > num) { R.Set(hunter, "curSpeed", num); } R.Set(hunter, "active", true); ((Denizen)hunter).diesInMass = false; } catch { } float num2 = Vector3.Distance(((Component)hunter).transform.position, ((Component)val).transform.position); farTime = ((num2 > 160f) ? (farTime + Time.deltaTime) : 0f); if (!(farTime > 8f)) { return; } farTime = 0f; if (!SHB.Util.SpotAroundPlayer(45f, 70f, out var pos)) { return; } try { ((Component)hunter).transform.position = pos; hunter.WipeTrackPositions(); hunter.ResetSegments(); Ext.Debug("The Hunter caught up with you (" + num2.ToString("0") + " m away)."); } catch (Exception ex) { Ext.LogOnce("hunttp", "Hunter catch-up failed: " + ex.Message); } } private static void Spawn(ENT_Player p) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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_0198: Unknown result type (might be due to invalid IL or missing references) spawnAt = Time.time + 5f; if ((Object)(object)prefab == (Object)null) { prefab = FindPrefab(); } if ((Object)(object)prefab == (Object)null) { if (!warnedNoPrefab) { warnedNoPrefab = true; Plugin.Log.LogWarning((object)"EXTREME: couldn't find a Hunter prefab, the always-on Hunter is off for now (will keep looking)."); } return; } if (!SHB.Util.SpotAroundPlayer(40f, 60f, out var pos)) { pos = ((Component)p).transform.position - ((Component)p).transform.forward * 45f + Vector3.down * 10f; } try { GameObject val = Object.Instantiate<GameObject>(prefab, pos, Quaternion.identity); ((Object)val).name = "EXTREME_Hunter"; val.AddComponent<AlwaysHunterTag>(); val.SetActive(true); SHB.EntityRules.MarkSpawned(val); hunter = val.GetComponent<DEN_Hunter>() ?? val.GetComponentInChildren<DEN_Hunter>(true); if ((Object)(object)hunter == (Object)null) { Object.Destroy((Object)(object)val); Ext.LogOnce("nohunt", "Hunter prefab has no DEN_Hunter on it."); return; } baseSpeed = ((hunter.startSpeed > 0.01f) ? hunter.startSpeed : 5f); hunter.startSpeed = baseSpeed * 0.55f; hunter.speedIncreaseRate = 0f; R.Set(hunter, "active", true); ((Denizen)hunter).diesInMass = false; SHB.Hud.Flash("IT'S FOLLOWING YOU"); Ext.Debug("The always-on Hunter spawned " + Vector3.Distance(pos, ((Component)p).transform.position).ToString("0") + " m away (speed x" + 0.55f + ")."); } catch (Exception ex) { Ext.LogOnce("huntspawn", "Hunter spawn failed: " + ex); } } private static GameObject FindPrefab() { //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) try { UT_Hunter_Controller[] array = Resources.FindObjectsOfTypeAll<UT_Hunter_Controller>(); foreach (UT_Hunter_Controller val in array) { if ((Object)(object)val != (Object)null && (Object)(object)val.hunterPrefab != (Object)null) { return ((Component)val.hunterPrefab).gameObject; } } WKAssetDatabase val2 = SHB.Util.Db(); if ((Object)(object)val2 != (Object)null) { List<GameObject>[] array2 = new List<GameObject>[2] { val2.denizenPrefabs, val2.entityPrefabs }; foreach (List<GameObject> list in array2) { if (list == null) { continue; } foreach (GameObject item in list) { object obj = ((item is GameObject) ? item : null); if (obj == null) { GameObject obj2 = ((item is Component) ? item : null); obj = ((obj2 != null) ? ((Component)obj2).gameObject : null); } GameObject val3 = (GameObject)obj; if ((Object)(object)val3 != (Object)null && (Object)(object)val3.GetComponentInChildren<DEN_Hunter>(true) != (Object)null) { return val3; } } } } GameObject val4 = SHB.Util.FindPrefabWith<DEN_Hunter>() ?? SHB.Util.FindPrefabNamed("Hunter"); if ((Object)(object)val4 != (Object)null && (Object)(object)val4.GetComponentInChildren<DEN_Hunter>(true) != (Object)null) { return val4; } DEN_Hunter[] array3 = Resources.FindObjectsOfTypeAll<DEN_Hunter>(); foreach (DEN_Hunter val5 in array3) { if ((Object)(object)val5 != (Object)null) { Scene scene = ((Component)val5).gameObject.scene; if (!((Scene)(ref scene)).IsValid() && !Is(((Component)val5).gameObject)) { return ((Component)val5).gameObject; } } } } catch (Exception ex) { Ext.LogOnce("huntfind", "Hunter prefab search failed: " + ex.Message); } return null; } } public static class Drones { private static int extraThisZone; private static SHB.Zone lastZone; private const int MaxPerZone = 12; public static void OnTurret(GameEntity turret) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if (Ext.Zone != lastZone) { lastZone = Ext.Zone; extraThisZone = 0; } if (Ext.Zone != SHB.Zone.Habitation || (Object)(object)turret == (Object)null || SHB.EntityRules.IsClone(((Component)turret).gameObject) || extraThisZone >= 12 || Random.value >= 0.5f) { return; } try { GameObject val = SHB.Util.FindPrefabWith<DEN_Drone>(); if ((Object)(object)val == (Object)null) { Ext.DebugOnce("nodrone", "No drone prefab found for the second drone."); return; } Transform transform = ((Component)turret).transform; Vector3 pos = transform.position + Vector3.up * 2.5f + Random.insideUnitSphere * 1.5f; GameObject val2 = SHB.Util.Spawn(val, pos, Quaternion.identity, transform.parent); if ((Object)(object)val2 != (Object)null) { SHB.EntityRules.MarkSpawned(val2); extraThisZone++; Ext.Debug("Second drone next to turret " + ((Object)((Component)turret).gameObject).name); } } catch (Exception ex) { Ext.LogOnce("drone2", "Second drone failed: " + ex.Message); } } } public class ExtremeTag : MonoBehaviour { } public class EntityRule { public string Name; public Tune Tune = new Tune(); public int ExtraCopies; public bool Escalates = true; public Action<GameEntity> Custom; } public static class EntityTuner { private static readonly HashSet<int> seen = new HashSet<int>(); private static int copiesThisSubregion; private static string lastWhere = ""; private const int MaxCopiesPerSubregion = 90; public static bool PendingBonusCopy; public static readonly List<GameEntity> RecentHostiles = new List<GameEntity>(); public static void Reset() { seen.Clear(); copiesThisSubregion = 0; lastWhere = ""; PendingBonusCopy = false; RecentHostiles.Clear(); } public static void Scan() { List<GameEntity> entities = GameEntity.entities; if (entities == null) { return; } string text = Ext.Where; if (text != lastWhere) { lastWhere = text; copiesThisSubregion = 0; } GameEntity[] array = entities.ToArray(); foreach (GameEntity val in array) { if ((Object)(object)val == (Object)null || val is ENT_Player) { continue; } GameObject gameObject = ((Component)val).gameObject; if (!((Object)(object)gameObject == (Object)null) && seen.Add(((Object)gameObject).GetInstanceID())) { try { OnNew(val); } catch (Exception ex) { Ext.LogOnce("ent" + ((object)val).GetType().Name, "EXTREME rule for " + ((object)val).GetType().Name + " failed: " + ex.Message); } } } RecentHostiles.RemoveAll((GameEntity x) => (Object)(object)x == (Object)null || x.dead); } private static void OnNew(GameEntity e) { GameObject gameObject = ((Component)e).gameObject; if (Chaser.Is(gameObject)) { return; } bool flag = (Object)(object)gameObject.GetComponent<ExtremeTag>() != (Object)null; bool flag2 = SHB.EntityRules.IsClone(gameObject); string n = ((Object)gameObject).name.ToLowerInvariant(); EntityRule entityRule = Rules.For(e, n, Ext.Zone); if (entityRule == null) { return; } if (!flag2 && !flag) { int num = entityRule.ExtraCopies; if (PendingBonusCopy && num >= 0 && Rules.IsHostile(e)) { PendingBonusCopy = false; if (Random.value < 0.5f) { num++; Ext.Debug("Anti-camping bonus copy for " + ((Object)gameObject).name); } } if (num > 0) { MakeCopies(e, num, entityRule.Name); } } if (!flag) { Tune tune = entityRule.Tune; if (entityRule.Escalates) { float num2 = Ext.EscalationBonus(); if (num2 > 0f) { Tune tune2 = new Tune { Speed = tune.Speed * (1f + num2), Detect = tune.Detect, Time = tune.Time, Damage = tune.Damage }; foreach (KeyValuePair<string, float> item in tune.Extra) { tune2.Extra[item.Key] = item.Value; } foreach (string item2 in tune.Skip) { tune2.Skip.Add(item2); } tune = tune2; } } int num3 = Tuner.Apply(e, tune); _ = ((AIGameEntity)(((e is AIGameEntity) ? e : null)?)).sight; num3 += Tuner.ApplyPathfinding(gameObject, tune.Speed); entityRule.Custom?.Invoke(e); gameObject.AddComponent<ExtremeTag>(); Ext.DebugOnce("tune" + entityRule.Name + Ext.Zone, "Tuned " + entityRule.Name + " (" + ((Object)gameObject).name + ", " + ((object)e).GetType().Name + ") in " + Ext.Zone.ToString() + ": speed x" + tune.Speed.ToString("0.##") + ", detection x" + tune.Detect.ToString("0.##") + ", timing x" + tune.Time.ToString("0.##") + ", damage x" + tune.Damage.ToString("0.##") + " (" + num3 + " fields)"); } if (Rules.IsHostile(e)) { RecentHostiles.Add(e); } DEN_Strider val = (DEN_Strider)(object)((e is DEN_Strider) ? e : null); if (val != null) { Striders.Track(val); } } public static void MakeCopies(GameEntity e, int count, string why) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (copiesThisSubregion >= 90) { Ext.DebugOnce("cap" + lastWhere, "Extra-copy cap reached for this area (" + 90 + ")."); return; } count = Mathf.Min(count, 90 - copiesThisSubregion); GameObject gameObject = ((Component)e).gameObject; Transform transform = ((Component)e).transform; int num = 0; for (int i = 0; i < count; i++) { try { Vector3 val = SHB.Util.NearbySpot(transform); GameObject obj = Object.Instantiate<GameObject>(gameObject, val, transform.rotation, transform.parent); ((Object)obj).name = ((Object)gameObject).name; obj.SetActive(gameObject.activeSelf); SHB.EntityRules.MarkSpawned(obj); num++; } catch (Exception ex) { Ext.LogOnce("copy" + why, "Copy of " + why + " failed: " + ex.Message); break; } } copiesThisSubregion += num; if (num > 0) { Ext.Debug("+" + num + " " + why + " (" + ((Object)gameObject).name + ") in " + Ext.Zone); } } public unsafe static GameObject SpawnNearPlayer(GameObject source, float min, float max, string why) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)source == (Object)null) { return null; } if (!SHB.Util.SpotAroundPlayer(min, max, out var pos)) { return null; } GameObject val = Object.Instantiate<GameObject>(source, pos, Quaternion.identity, source.transform.parent); ((Object)val).name = ((Object)source).name; val.SetActive(true); SHB.EntityRules.MarkSpawned(val); Ext.Debug(why + ": " + ((Object)source).name + " at " + ((object)(*(Vector3*)(&pos))/*cast due to .constrained prefix*/).ToString()); return val; } } public static class Ext { public const string SettingId = "skmod_extreme"; public const string Title = "EXTREME"; private static GamemodeSetting setting; private static readonly HashSet<M_Gamemode> injected = new HashSet<M_Gamemode>(); public static bool Broken; private static float nextMenuTick; private static int cacheFrame = -1; private static bool cacheValue; [ThreadStatic] private static bool inCheck; private static ProgressionUnlock safeUnlock; private static string lastRegionKey = ""; private static string lastSubKey = ""; public static float RegionTime; public static float SubregionTime; private static readonly HashSet<string> once = new HashSet<string>(); public static string Description => "The hardest run possible. Includes SUPER HARD, Hard Mode, Survival and Iron Knuckle. +50% gravity, half health, a Hunter that never stops chasing you, 1-minute Calming Buddy, swarms of red roaches and turrets, a 2.2x Mass, faster and deadlier enemies in every zone, 3x vendor prices, no trinkets, no shortcuts."; public static SHB.Zone Zone => SHB.Zones.Current; public static string Where => (SHB.Zones.Where ?? "").ToLowerInvariant(); public static bool SelectedFor(M_Gamemode mode) { if ((Object)(object)mode == (Object)null || StatManager.saveData == null || inCheck) { return false; } inCheck = true; try { GameModeData gameMode = StatManager.saveData.GetGameMode(mode.gamemodeName); return gameMode != null && gameMode.activeSettings != null && gameMode.activeSettings.Contains("skmod_extreme"); } catch { return false; } finally { inCheck = false; } } public static bool IsOn() { if (cacheFrame == Time.frameCount) { return cacheValue; } cacheFrame = Time.frameCount; cacheValue = false; try { if ((Object)(object)CL_GameManager.gMan == (Object)null) { return false; } cacheValue = SelectedFor(CL_GameManager.GetCurrentGamemode()) || SelectedFor(CL_GameManager.GetBaseGamemode()); } catch { cacheValue = false; } return cacheValue; } public static bool IsForcedId(string id) { if (!string.IsNullOrEmpty(id)) { switch (id) { case "skmod_extreme": break; case "skmod_super": case "hardmode": return true; default: try { if (SHB.Mode.HardIds.Contains(id) || SHB.Mode.SurvivalIds.Contains(id)) { return true; } } catch { } return false; } } return false; } public static void IsSettingActive_Post(SaveData __instance, string gameModeName, string settingID, ref bool __result) { if (__result || inCheck) { return; } inCheck = true; try { if (IsForcedId(settingID)) { GameModeData gameMode = __instance.GetGameMode(gameModeName); if (gameMode != null && gameMode.activeSettings != null && gameMode.activeSettings.Contains("skmod_extreme")) { __result = true; } } } catch { } finally { inCheck = false; } } public static void MenuTick() { if (Time.unscaledTime < nextMenuTick) { return; } nextMenuTick = Time.unscaledTime + 1f; try { WKAssetDatabase val = SHB.Util.Db(); if ((Object)(object)val != (Object)null && val.gamemodeAssets != null) { foreach (M_Gamemode gamemodeAsset in val.gamemodeAssets) { EnsureInjected(gamemodeAsset); } } EnsureInjected(CL_GameManager.GetCurrentGamemode()); } catch (Exception ex) { LogOnce("menutick", "Gamemode scan failed: " + ex.Message); } } public static void EnsureInjected(M_Gamemode mode) { if ((Object)(object)mode == (Object)null || mode.gamemodeSettings == null) { return; } List<GamemodeSetting> gamemodeSettings = mode.gamemodeSettings; if (Broken || SHB.Mode.Broken) { gamemodeSettings.RemoveAll((GamemodeSetting x) => (Object)(object)x != (Object)null && x.id == "skmod_extreme"); return; } int num = gamemodeSettings.FindIndex((GamemodeSetting x) => (Object)(object)x != (Object)null && x.id == "skmod_super"); if (num < 0) { return; } if (!gamemodeSettings.Any((GamemodeSetting x) => (Object)(object)x != (Object)null && x.id == "skmod_extreme")) { if ((Object)(object)setting == (Object)null) { setting = Create(gamemodeSettings[num]); } if ((Object)(object)setting == (Object)null) { return; } gamemodeSettings.Insert(num + 1, setting); } if (injected.Add(mode)) { Debug("Added EXTREME to gamemode '" + mode.gamemodeName + "'."); } } private static GamemodeSetting Create(GamemodeSetting template) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) GamemodeSetting obj = Object.Instantiate<GamemodeSetting>(template); ((Object)obj).name = "GamemodeSetting_Extreme"; ((Object)obj).hideFlags = (HideFlags)32; obj.id = "skmod_extreme"; obj.title = "EXTREME"; obj.description = Description; obj.color = new Color(0.55f, 0f, 0f, 1f); obj.exclusiveSettings = new List<string>(); obj.nameAppend = "Extreme"; obj.leaderboardAppendID = "extrememod"; obj.allowDownstream = false; obj.downstreamId = ""; obj.unlock = SafeUnlock(); return obj; } public static ProgressionUnlock SafeUnlock() { if ((Object)(object)safeUnlock != (Object)null) { return safeUnlock; } safeUnlock = ScriptableObject.CreateInstance<ProgressionUnlock>(); ((Object)safeUnlock).name = "Unlock_ModSetting"; ((Object)safeUnlock).hideFlags = (HideFlags)32; safeUnlock.id = "skmod_unlock"; safeUnlock.unlockRequirements = new List<UnlockRequirement>(); safeUnlock.state = true; safeUnlock.unlockHint = ""; safeUnlock.unlockTitle = ""; safeUnlock.unlockDescription = ""; safeUnlock.showProgression = false; return safeUnlock; } public static void Sanitize(GamemodeSetting s) { if (!((Object)(object)s == (Object)null)) { bool flag = s.id == "skmod_extreme" || s.id == "skmod_super"; if ((Object)(object)s.unlock == (Object)null || (flag && s.unlock.unlockRequirements == null)) { s.unlock = SafeUnlock(); } if (s.unlock.unlockRequirements == null) { s.unlock.unlockRequirements = new List<UnlockRequirement>(); } if (s.title == null) { s.title = s.id ?? ""; } if (s.description == null) { s.description = ""; } if (s.exclusiveSettings == null) { s.exclusiveSettings = new List<string>(); } } } public static bool SafeFillSettings(UI_GamemodeScreen_Panel panel) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown M_Gamemode gamemode; try { gamemode = panel.GetGamemode(); try { EnsureInjected(gamemode); } catch (Exception ex) { LogOnce("fill", "EXTREME inject failed: " + ex.Message); } if ((Object)(object)gamemode == (Object)null || gamemode.gamemodeSettings == null || (Object)(object)panel.settingRoot == (Object)null) { return true; } } catch (Exception ex2) { LogOnce("fillpre", "Run setup pre-check failed, using the game's own code: " + ex2.Message); return true; } try { List<GameObject> list = new List<GameObject>(); foreach (Transform item in panel.settingRoot) { Transform val = item; list.Add(((Component)val).gameObject); } foreach (GameObject item2 in list) { Object.Destroy((Object)(object)item2); } } catch (Exception ex3) { LogOnce("filldel", "Clearing old setting buttons failed: " + ex3.Message); } GamemodeSetting[] array = gamemode.gamemodeSettings.ToArray(); foreach (GamemodeSetting val2 in array) { if ((Object)(object)val2 == (Object)null) { gamemode.gamemodeSettings.Remove(val2); continue; } UI_GamemodeSetting val3 = null; try { Sanitize(val2); UI_GamemodeSetting val4 = (((Object)(object)val2.gamemodeButtonAsset != (Object)null) ? val2.gamemodeButtonAsset : panel.gamemodeSettingAsset); if ((Object)(object)val4 == (Object)null) { LogOnce("noasset" + val2.id, "No button asset for setting " + val2.id); continue; } val3 = Object.Instantiate<UI_GamemodeSetting>(val4, panel.settingRoot); val3.Initialize(val2, panel); } catch (Exception ex4) { Plugin.Log.LogError((object)("Setting button '" + val2.id + "' failed to build (the run setup screen still opens): " + ex4)); if (val2.id == "skmod_extreme" || val2.id == "skmod_super") { if ((Object)(object)val3 != (Object)null) { Object.Destroy((Object)(object)((Component)val3).gameObject); } if (val2.id == "skmod_extreme") { Broken = true; RemoveEverywhere(); } } } } return false; } public static void RemoveEverywhere() { foreach (M_Gamemode item in injected) { if ((Object)(object)item != (Object)null && item.gamemodeSettings != null) { item.gamemodeSettings.RemoveAll((GamemodeSetting x) => (Object)(object)x != (Object)null && x.id == "skmod_extreme"); } } } public static bool InSafeRoom() { string text = Where; if (!text.Contains("safe") && !text.Contains("break room")) { return text.Contains("breakroom"); } return true; } public static bool Sub(params string[] keys) { string text = Where; for (int i = 0; i < keys.Length; i++) { if (text.Contains(keys[i])) { return true; } } return false; } public static void ResetRegion() { lastRegionKey = (lastSubKey = ""); RegionTime = (SubregionTime = 0f); } public static void TrackRegion() { string text = (((Object)(object)CL_EventManager.currentRegion != (Object)null) ? ((Object)CL_EventManager.currentRegion).name : ""); string text2 = (((Object)(object)CL_EventManager.currentSubregion != (Object)null) ? ((Object)CL_EventManager.currentSubregion).name : ""); if (text != lastRegionKey) { lastRegionKey = text; RegionTime = 0f; } if (text2 != lastSubKey) { lastSubKey = text2; SubregionTime = 0f; } if ((Object)(object)CL_GameManager.gMan != (Object)null && !CL_GameManager.gMan.isPaused) { RegionTime += Time.deltaTime; SubregionTime += Time.deltaTime; } } public static float EscalationBonus() { return Zone switch { SHB.Zone.Pipeworks => 0.1f, SHB.Zone.Habitation => 0.2f, SHB.Zone.Abyss => 0.3f, SHB.Zone.Nest => 0.4f, _ => 0f, }; } public static void Debug(string msg) { if (Plugin.DebugLog == null || Plugin.DebugLog.Value) { Plugin.Log.LogInfo((object)("[EXTREME] " + msg)); } } public static void DebugOnce(string key, string msg) { if (once.Add(key)) { Debug(msg); } } public static void LogOnce(string key, string msg) { if (once.Add("!" + key)) { Plugin.Log.LogWarning((object)msg); } } public static ENT_Player Player() { return SHB.Util.Player(); } public static bool PlayerAlive() { ENT_Player val = Player(); if ((Object)(object)val == (Object)null || ((GameEntity)val).dead) { return false; } try { if (CL_GameManager.isDead()) { return false; } } catch { } return true; } public static bool Paused() { if ((Object)(object)CL_GameManager.gMan != (Object)null) { return CL_GameManager.gMan.isPaused; } return false; } public static string Describe(DamageInfo info, out GameObject src) { src = (((Object)(object)info.sourceEntity != (Object)null) ? ((Component)info.sourceEntity).gameObject : info.sourceObject); string text = (((Object)(object)src != (Object)null) ? (((Object)src).name + " " + ((Object)src.transform.root).name) : ""); text = text + " " + info.type; if (info.tags != null && info.tags.Count > 0) { text = text + " " + string.Join(" ", info.tags.ToArray()); } return text.ToLowerInvariant(); } } public static class Items { private static readonly HashSet<int> seenItems = new HashSet<int>(); private static readonly HashSet<int> pricedVendors = new HashSet<int>(); private static readonly HashSet<int> stockedVendors = new HashSet<int>(); private static readonly string[] Banned = new string[7] { "amalgam", "revive", "extralife", "extra_life", "extra life", "1up", "oneup" }; private static readonly string[] Critical = new string[20] { "key", "card", "fuse", "valve", "crank", "battery", "part", "quest", "artifact", "mother", "door", "lever", "progress", "story", "piton", "rebar", "rope", "hammer", "grapple", "buddy" }; private static readonly string[] Consumable = new string[15] { "item_", "pill", "injector", "food", "ration", "bandage", "medkit", "heal", "flare", "soda", "can_", "candy", "snack", "drink", "battery" }; public static void Reset() { seenItems.Clear(); pricedVendors.Clear(); stockedVendors.Clear(); } private static bool HasAny(string s, string[] keys) { foreach (string value in keys) { if (s.Contains(value)) { return true; } } return false; } public static void SlowTick() { ENT_Player val = Ext.Player(); if ((Object)(object)val == (Object)null) { return; } Item_Object[] array = Object.FindObjectsByType<Item_Object>((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (Item_Object val2 in array) { if ((Object)(object)val2 == (Object)null || !seenItems.Add(((Object)val2).GetInstanceID())) { continue; } try { if ((val2.itemData == null || (!val2.itemData.hasBeenPickedUp && !val2.itemData.inBag)) && !((Component)val2).transform.IsChildOf(((Component)val).transform)) { string text = SHB.ItemRules.ItemName(val2).ToLowerInvariant(); if (HasAny(text, Banned)) { Ext.Debug("Removed " + text + " (not allowed in EXTREME)"); Object.Destroy((Object)(object)((Component)val2).gameObject); } } } catch { } } ENV_Vendor_Disk[] array2 = Object.FindObjectsByType<ENV_Vendor_Disk>((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (ENV_Vendor_Disk val3 in array2) { if ((Object)(object)val3 != (Object)null && pricedVendors.Add(((Object)val3).GetInstanceID())) { val3.cost *= 3; Ext.DebugOnce("diskv", "Disk vendor prices x3 (" + val3.cost + ")"); } } ENV_Vendor_Event[] array3 = Object.FindObjectsByType<ENV_Vendor_Event>((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (ENV_Vendor_Event val4 in array3) { if ((Object)(object)val4 != (Object)null && pricedVendors.Add(((Object)val4).GetInstanceID())) { val4.cost *= 3; Ext.DebugOnce("evv", "Event vendor prices x3 (" + val4.cost + ")"); } } } public static void Vending_Post(ENV_VendingMachine __instance) { if ((Object)(object)__instance == (Object)null || !Ext.IsOn()) { return; } try { int instanceID = ((Object)__instance).GetInstanceID(); if (__instance.purchaseList != null && pricedVendors.Add(instanceID)) { foreach (Purchase purchase in __instance.purchaseList) { if (purchase != null) { purchase.price *= 3; } } } if (__instance.buttons == null || !stockedVendors.Add(instanceID)) { return; } Random random = new Random(R.Get(__instance, "localSeed", 0) ^ 0x5EED); int num = 0; int num2 = 0; List<VendingButton> list = new List<VendingButton>(); VendingButton[] buttons = __instance.buttons; foreach (VendingButton val in buttons) { if (val != null && val.available) { list.Add(val); } } num2 = list.Count; int num3 = Mathf.Max(1, Mathf.RoundToInt((float)num2 * 0.4f)); for (int num4 = list.Count - 1; num4 > 0; num4--) { int index = random.Next(num4 + 1); VendingButton value = list[num4]; list[num4] = list[index]; list[index] = value; } for (int j = 0; j < list.Count; j++) { if (j < num3) { num++; } else { list[j].available = false; } } R.Call(__instance, "UpdateButtons"); Ext.Debug("Vending machine: prices x3, stock " + num + "/" + num2); } catch (Exception ex) { Ext.LogOnce("vend", "Vendor rule failed: " + ex.Message); } } public static bool Decide_Pre(SpawnSettings __0, ref bool __1) { if (!Ext.IsOn()) { return true; } string text = Desc(__0); if (text != null && text.Contains("cavity")) { if (__1) { Ext.DebugOnce("cav" + text.GetHashCode(), "Shortcut disabled: " + text); } __1 = false; return false; } return true; } public static void Decide_Post(SpawnSettings __0, ref bool __1) { if (!Ext.IsOn()) { return; } string text = Desc(__0); if (string.IsNullOrEmpty(text) || text.Contains("cavity")) { return; } bool flag = __1; SHB.Zone zone = Ext.Zone; if (!text.Contains("item_") && !text.Contains("item ")) { if (((zone == SHB.Zone.Abyss && Ext.Sub("deadman", "dead man", "handle")) || (zone == SHB.Zone.Nest && Ext.Sub("infested", "hot zone", "hotzone", "feeding", "trough")) || (zone == SHB.Zone.Habitation && Ext.Sub("delta"))) && HasAny(text, new string[12] { "hazard", "trap", "steam", "laser", "electr", "spike", "orchid", "spore", "mine", "denizen_", "den_", "turret" }) && !text.Contains("roach_gold") && !text.Contains("buddy")) { __1 = true; } } else if (__1 && HasAny(text, Consumable) && !HasAny(text, Critical)) { float num = 0.35f * ((zone == SHB.Zone.Silos) ? 0.5f : 1f); if (Random.value > num) { __1 = false; } } if (flag != __1) { Ext.DebugOnce("dec" + text.GetHashCode() + __1, "Spawn " + (__1 ? "forced on" : "removed") + ": " + text); } } private static string Desc(SpawnSettings s) { if (s == null) { return null; } return SHB.SpawnRules.Owner(s); } } public static class MassRules { private static readonly HashSet<int> quieted = new HashSet<int>(); private static float lastLogged = -1f; public static void Reset() { quieted.Clear(); lastLogged = -1f; } public static float CurrentMult() { SHB.Zone zone = Ext.Zone; float regionTime = Ext.RegionTime; float subregionTime = Ext.SubregionTime; switch (zone) { case SHB.Zone.Silos: if (!(subregionTime >= 240f)) { return 1.1f; } return 1.4f; case SHB.Zone.Pipeworks: if (Ext.Sub("organ")) { return Mathf.Lerp(2.2f, 2.6f, Mathf.InverseLerp(90f, 300f, subregionTime)); } break; } if (zone == SHB.Zone.Nest && (SHB.Zones.NestLastSection || Ext.Sub("feeding", "trough"))) { if (!(subregionTime >= 180f)) { return 2.2f; } return 2.75f; } return Mathf.Min(2.75f, 2.2f + 0.1f * Mathf.Floor(regionTime / 180f)); } public static bool ApplyMass_Pre(DEN_DeathFloor __0) { if ((Object)(object)__0 == (Object)null || !Ext.IsOn()) { return true; } try { float num = CurrentMult(); __0.SetUpdateSpeedMultiplier(num); if (quieted.Add(((Object)__0).GetInstanceID())) { __0.globalVolume *= 0.6f; Ext.Debug("The Mass: 40% quieter, speed x" + num.ToString("0.00")); } if (Mathf.Abs(num - lastLogged) > 0.04f) { lastLogged = num; Ext.Debug("Mass speed now x" + num.ToString("0.00") + " (" + Ext.Zone.ToString() + ")"); } } catch (Exception ex) { Ext.LogOnce("mass", "Mass rule failed: " + ex.Message); } return false; } } public static class ExtTimers { private static DEN_Mother timedMother; private static bool motherDone; public const float MotherStart = 50f; public const float MotherEscape = 100f; public static void Reset() { timedMother = null; motherDone = false; } public static bool Tick_Pre() { if (!Ext.IsOn()) { return true; } try { Tick(); } catch (Exception ex) { Ext.LogOnce("timers", "Timer rule failed: " + ex.Message); } return false; } private static void Tick() { //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) ENT_Player val = Ext.Player(); if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead() || Ext.Paused()) { return; } if (!Ext.InSafeRoom()) { SHB.Timers.RemainsTimer += Time.deltaTime; } if (SHB.Timers.RemainsTimer >= SHB.Cfg.RemainsInterval.Value) { SHB.Timers.RemainsTimer = 0f; int num = 0; DEN_Remains_Active[] array = Object.FindObjectsByType<DEN_Remains_Active>((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (DEN_Remains_Active val2 in array) { if ((Object)(object)val2 != (Object)null && !((GameEntity)val2).dead) { num++; } } if (num < 2) { SHB.Timers.SpawnRemains(); } else { Ext.Debug("Remains timer: already 2 Remains hunting you."); } } if (Ext.Zone != SHB.Zone.Nest) { SHB.Timers.MotherLeft = -1f; return; } DEN_Mother instance = DEN_Mother.instance; if ((Object)(object)instance == (Object)null || !((Component)instance).gameObject.activeInHierarchy || ((GameEntity)instance).dead) { if (SHB.Timers.MotherLeft >= 0f) { SHB.Timers.MotherLeft = -1f; motherDone = true; } return; } if ((Object)(object)instance != (Object)(object)timedMother) { timedMother = instance; motherDone = false; SHB.Timers.MotherLeft = -1f; } float num2 = Vector3.Distance(((Component)val).transform.position, ((Component)instance).transform.position); if (SHB.Timers.MotherLeft < 0f && !motherDone && num2 < 50f) { SHB.Timers.MotherLeft = SHB.Cfg.MotherSeconds.Value; SHB.Hud.Flash("SHE SEES YOU - RUN"); Ext.Debug("Mother: " + SHB.Timers.MotherLeft + " s to get 100 m away."); } if (SHB.Timers.MotherLeft < 0f) { return; } if (num2 > 100f) { SHB.Timers.MotherLeft = -1f; motherDone = true; SHB.Hud.Flash("ESCAPED"); Ext.Debug("Escaped the Mother."); return; } SHB.Timers.MotherLeft -= Time.deltaTime; if (SHB.Timers.MotherLeft > 0f) { return; } SHB.Timers.MotherLeft = -1f; motherDone = true; Ext.Debug("Mother escape countdown ran out."); try { instance.Enrage(true); } catch (Exception ex) { Ext.LogOnce("enrage", "Enrage failed: " + ex.Message); } try { instance.KillPlayer(); } catch (Exception ex2) { Ext.LogOnce("mkill", "Mother kill failed: " + ex2.Message); ((GameEntity)val).Kill("mother"); } } } public static class ExtHud { private static GUIStyle label; private static GUIStyle big; public static bool Draw_Pre() { if (!Ext.IsOn()) { return true; } try { Draw(); } catch (Exception ex) { Ext.LogOnce("hud", "HUD failed: " + ex.Message); } return false; } private static void Draw() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_004b: 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_005d: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) if (SHB.Cfg.ShowHud.Value && !Ext.Paused()) { if (label == null) { label = new GUIStyle(GUI.skin.label) { fontSize = 15, fontStyle = (FontStyle)1, alignment = (TextAnchor)1 }; big = new GUIStyle(label) { fontSize = 30 }; big.normal.textColor = new Color(1f, 0.12f, 0.08f, 1f); } if (Plugin.ShowLabel.Value) { float num = 0.5f + 0.5f * Mathf.Sin(Time.unscaledTime * 3.2f); label.normal.textColor = new Color(0.45f + 0.25f * num, 0f, 0f, 0.55f + 0.45f * num); label.fontSize = 15 + Mathf.RoundToInt(num * 2f); GUI.Label(new Rect(0f, 6f, (float)Screen.width, 26f), "EXTREME", label); } if (SHB.Timers.MotherLeft >= 0f) { GUI.Label(new Rect(0f, 34f, (float)Screen.width, 40f), "MOTHER: " + Mathf.CeilToInt(SHB.Timers.MotherLeft) + "s", big); } if (SHB.Hud.flash != null && Time.unscaledTime < SHB.Hud.flashUntil) { GUI.Label(new Rect(0f, (float)Screen.height * 0.3f, (float)Screen.width, 40f), SHB.Hud.flash, big); } } } } public static class Overrides { private static bool applied; private static bool savedSaveFlag; private static readonly Dictionary<ConfigEntryBase, object> backup = new Dictionary<ConfigEntryBase, object>(); public const float Gravity = 1.5f; private static List<KeyValuePair<ConfigEntryBase, object>> Targets() { List<KeyValuePair<ConfigEntryBase, object>> t = new List<KeyValuePair<ConfigEntryBase, object>>(); S(SHB.Cfg.ForceHardMode, true); S(SHB.Cfg.ForceSurvival, true); S(SHB.Cfg.DisableLeaderboards, true); S(SHB.Cfg.GravityMult, 1.5f); S(SHB.Cfg.HangSeconds, 7f); S(SHB.Cfg.HammerDamageMult, 0.35f); S(SHB.Cfg.EngravedDoorChance, 0.8f); S((ConfigEntryBase)(object)SHB.Cfg.RemainsInterval, 240f); S(SHB.Cfg.MassSpeedMult, 2.2f); S(SHB.Cfg.HopperInstakill, true); S(SHB.Cfg.TicksHoldOn, true); S(SHB.Cfg.RedRoachExtra, 5); S(SHB.Cfg.RedRoachSpawnSeconds, 10f); S(SHB.Cfg.RedRoachMax, 16); S(SHB.Cfg.TurretExtra, 3); S(SHB.Cfg.BuddyEnabled, true); S(SHB.Cfg.BuddyPetSeconds, 60f); S(SHB.Cfg.SilosSturgeInterval, 12f); S(SHB.Cfg.SilosSturgeMax, 16); S(SHB.Cfg.SilosSturgeExtra, 3); S(SHB.Cfg.SilosBloodbugExtra, 3); S(SHB.Cfg.SilosMassMult, 0.5f); S(SHB.Cfg.SturgeDamageMult, 3f); S(SHB.Cfg.PipeworksBarnacleExtra, 4); S(SHB.Cfg.PipeworksHopperExtra, 3); S(SHB.Cfg.SteamDamageMult, 4f); S(SHB.Cfg.CavityRoute, false); S(SHB.Cfg.TeethSpeedMult, 3f); S(SHB.Cfg.TeethStaysUntilHidden, true); S(SHB.Cfg.VentThingSpeedMult, 3f); S(SHB.Cfg.TurretDamageMult, 4f); S(SHB.Cfg.TurretDroneChance, 1f); S(SHB.Cfg.AbyssFaceCount, 8); S(SHB.Cfg.AbyssFallDeath, 40f); S(SHB.Cfg.NestBarnacleExtra, 5); S((ConfigEntryBase)(object)SHB.Cfg.MotherSeconds, 15f); S(SHB.Cfg.NestWaterDps, 20f); return t; void S(ConfigEntryBase e, object v) { if (e != null) { t.Add(new KeyValuePair<ConfigEntryBase, object>(e, v)); } } } public static void Apply(bool on) { if (on == applied) { return; } ConfigFile val = ((SHB.Cfg.DebugLog != null) ? SHB.Cfg.DebugLog.ConfigFile : null); if (on) { if (val != null) { savedSaveFlag = val.SaveOnConfigSet; val.SaveOnConfigSet = false; } backup.Clear(); foreach (KeyValuePair<ConfigEntryBase, object> item in Targets()) { try { backup[item.Key] = item.Key.BoxedValue; item.Key.BoxedValue = item.Value; } catch (Exception ex) { Ext.LogOnce("ov" + (object)item.Key.Definition, "Could not override " + ((object)item.Key.Definition)?.ToString() + ": " + ex.Message); } } applied = true; Ext.Debug("SUPER HARD numbers switched to EXTREME (" + backup.Count + " values)."); return; } foreach (KeyValuePair<ConfigEntryBase, object> item2 in backup) { try { item2.Key.BoxedValue = item2.Value; } catch { } } backup.Clear(); if (val != null) { val.SaveOnConfigSet = savedSaveFlag; } applied = false; Ext.Debug("EXTREME off: SUPER HARD numbers restored."); } } public static class Patches { private static int ok; private static int failed; private static bool cavityZeroed; private static void P(Harmony h, Type t, string method, Type[] args, string prefix = null, string postfix = null, string finalizer = null, int priority = 400) { try { MethodBase methodBase = ((args == null) ? AccessTools.Method(t, method, (Type[])null, (Type[])null) : AccessTools.Method(t, method, args, (Type[])null)); if (methodBase == null) { failed++; Plugin.Log.LogWarning((object)("EXTREME: method not found: " + t?.Name + "." + method)); } else { h.Patch(methodBase, Hm(prefix), Hm(postfix), (HarmonyMethod)null, Hm(finalizer), (HarmonyMethod)null); ok++; } } catch (Exception ex) { failed++; Plugin.Log.LogWarning((object)("EXTREME: patch " + t?.Name + "." + method + " failed: " + ex.Message)); } HarmonyMethod Hm(string n) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown if (n != null) { return new HarmonyMethod(typeof(Patches).GetMethod(n, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) { priority = priority }; } return null; } } public static void ApplyAll(Harmony h) { P(h, SHB.T("Plugin"), "Update", null, "SHUpdate_Pre"); P(h, SHB.T("Mode"), "ApplyGlobalToggles", null, null, "GlobalToggles_Post"); P(h, SHB.T("SpawnRules"), "Decide", null, "Decide_Pre", "Decide_Post"); P(h, SHB.T("Timers"), "Tick", null, "Timers_Pre"); P(h, SHB.T("Hud"), "Draw", null, "Hud_Pre"); P(h, SHB.T("Patches"), "ApplyMass", null, "Mass_Pre"); P(h, SHB.T("Buddy"), "OnUse", null, null, "BuddyUse_Post"); P(h, typeof(SaveData), "IsSettingActive", new Type[2] { typeof(string), typeof(string) }, null, "IsSettingActive_Post"); P(h, typeof(UI_GamemodeScreen_Panel), "FillSettings", null, "FillSettings_Pre", null, "FillSettings_Fin", 0); P(h, typeof(UI_GamemodeScreen), "Initialize", new Type[1] { typeof(M_Gamemode) }, "ScreenInit_Pre", null, null, 200); P(h, typeof(UI_GamemodeSetting), "Initialize", new Type[2] { typeof(GamemodeSetting), typeof(UI_GamemodeScreen_Panel) }, "SettingInit_Pre", null, "SettingInit_Fin", 800); P(h, typeof(CL_GameManager), "AreAchievementsAllowed", null, null, "Achievements_Post"); P(h, typeof(CL_AchievementManager), "SetAchievementValue", new Type[2] { typeof(string), typeof(bool) }, "SetAchievement_Pre"); P(h, typeof(ENT_Player), "FallingDamage", null, "Falling_Pre", "Falling_Post"); P(h, typeof(ENT_Player), "Damage", new Type[1] { typeof(DamageInfo) }, "Damage_Pre", null, null, 200); P(h, typeof(ENT_Player), "AddPerk", new Type[3] { typeof(Perk), typeof(int), typeof(bool) }, "AddPerk_Pre"); P(h, typeof(InjuryType), "GetInjury", null, "Scope_Pre", null, "Scope_Fin"); P(h, typeof(DEN_Phage), "OnAttackHit", null, "Scope_Pre", null, "Scope_Fin"); P(h, typeof(DEN_Mask), "Update", null, "Scope_Pre", null, "Scope_Fin"); P(h, typeof(SaveData), "LoadDataIntoPlayer", null, "Scope_Pre", null, "Scope_Fin"); P(h, typeof(ENV_VendingMachine), "GenerateOptions", null, null, "Vending_Post"); P(h, typeof(Denizen), "Kill", new Type[2] { typeof(string), typeof(DamageInfo) }, null, "Kill_Post"); P(h, typeof(DEN_BasicDenizen), "Kill", new Type[2] { typeof(string), typeof(DamageInfo) }, null, "Kill_Post"); P(h, typeof(DEN_Barnacle), "Kill", new Type[2] { typeof(string), typeof(DamageInfo) }, null, "Kill_Post"); Plugin.Log.LogInfo((object)("EXTREME patches: " + ok + " applied, " + failed + " failed.")); } private static void SHUpdate_Pre() { Plugin.BeforeSuperHard(); } private static void GlobalToggles_Post(bool active) { try { if (Ext.IsOn()) { foreach (KeyValuePair<M_Subregion, KeyValuePair<float, bool>> item in SHB.Mode.cavityBackup) { if ((Object)(object)item.Key != (Object)null && (item.Key.chance != 0f || item.Key.guaranteeIfNotVisited)) { item.Key.chance = 0f; item.Key.guaranteeIfNotVisited = false; Ext.Debug("Shortcut closed: " + ((Object)item.Key).name); } } cavityZeroed = true; } else { if (!cavityZeroed) { return; } cavityZeroed = false; { foreach (KeyValuePair<M_Subregion, KeyValuePair<float, bool>> item2 in SHB.Mode.cavityBackup) { if ((Object)(object)item2.Key != (Object)null) { if (active) { item2.Key.chance = Mathf.Max(item2.Value.Key, 1f); item2.Key.guaranteeIfNotVisited = true; } else { item2.Key.chance = item2.Value.Key; item2.Key.guaranteeIfNotVisited = item2.Value.Value; } } } return; } } } catch (Exception ex) { Ext.LogOnce("cavity", "Shortcut rule failed: " + ex.Message); } } private static bool Decide_Pre(SpawnSettings __0, ref bool __1) { return Items.Decide_Pre(__0, ref __1); } private static void Decide_Post(SpawnSettings __0, ref bool __1) { Items.Decide_Post(__0, ref __1); } private static bool Timers_Pre() { return ExtTimers.Tick_Pre(); } private static void BuddyUse_Post(Item __0) { PlayerRules.BuddyUse_Post(__0); } private static bool Hud_Pre() { return ExtHud.Draw_Pre(); } private static bool Mass_Pre(DEN_DeathFloor __0) { return MassRules.ApplyMass_Pre(__0); } private static void IsSettingActive_Post(SaveData __instance, string gameModeName, string settingID, ref bool __result) { Ext.IsSettingActive_Post(__instance, gameModeName, settingID, ref __result); } private static bool FillSettings_Pre(UI_GamemodeScreen_Panel __instance) { try { return Ext.SafeFillSettings(__instance); } catch (Exception ex) { Ext.LogOnce("fillsafe", "Safe run setup failed, using the game's own code: " + ex.Message); return true; } } private static Exception FillSettings_Fin(Exception __exception) { if (__exception == null) { return null; } Plugin.Log.LogError((object)("Run setup settings crashed; the screen opens anyway: " + __exception)); if (!Ext.Broken) { Ext.Broken = true; Ext.RemoveEverywhere(); } return null; } private static void ScreenInit_Pre(M_Gamemode __0) { try { Ext.EnsureInjected(__0); } catch (Exception ex) { Ext.LogOnce("init", "EXTREME inject failed: " + ex.Message); } } private static void SettingInit_Pre(GamemodeSetting __0) { try { Ext.Sanitize(__0); } catch { } } private static Exception SettingInit_Fin(Exception __exception, GamemodeSetting __0) { if (__exception == null) { return null; } Plugin.Log.LogError((object)("Setting button '" + (((Object)(object)__0 != (Object)null) ? __0.id : "?") + "' failed to build: " + __exception)); if ((Object)(object)__0 != (Object)null && __0.id == "skmod_extreme") { Ext.Broken = true; } return null; } private static void Achievements_Post(ref bool __result) { if (__result && Ext.IsOn()) { __result = false; } } private static bool SetAchievement_Pre() { return !Ext.IsOn(); } private static void Falling_Pre(ENT_Player __instance, out PlayerRules.FallState __state) { PlayerRules.Falling_Pre(__instance, out __state); } private static void Falling_Post(ENT_Player __instance, PlayerRules.FallState __state) { PlayerRules.Falling_Post(__instance, __state); } private static void Damage_Pre(ENT_Player __instance, DamageInfo __0) { PlayerRules.Damage_Pre(__instance, __0); } private static bool AddPerk_Pre(Perk __0, ref Perk __result) { return PlayerRules.AddPerk_Pre(__0, ref __result); } private static void Scope_Pre() { PlayerRules.PerkScope_Pre(); } private static Exception Scope_Fin(Exception __exception) { PlayerRules.PerkScope_Post(); return __exception; } private static void Vending_Post(ENV_VendingMachine __instance) { Items.Vending_Post(__instance); } private static void Kill_Post(Denizen __instance) { Pressure.OnKill(__instance); } } public static class PlayerRules { public struct FallState { public bool falling; public float dist; public float ignore; public bool valid; } public const float LethalFall = 25f; public const float AbyssLethalFall = 40f; private static float fallTimer; private static int perkScope; public const float HealthFactor = 0.5f; private static int healthPlayer; private static float baseMaxHealth; private static readonly string[] Electric = new string[6] { "electr", "spark", "shock", "zap", "lightning", "taser" }; private static readonly string[] Bio = new string[9] { "orchid", "spore", "flesh", "bio", "growth", "fung", "acid", "goo", "infest" }; private static float lastBuddyBoost = -99f; public const float BuddyStaminaFraction = 0.2f; public const float BuddyStaminaCooldown = 3f; public static void Reset() { fallTimer = 0f; healthPlayer = 0; } public static void Tick() { //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: 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_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) ENT_Player val = Ext.Player(); if ((Object)(object)val == (Object)null) { return; } try { if ((Object)(object)SHB.PlayerRules.gravityPlayer == (Object)(object)val && Mathf.Abs(SHB.PlayerRules.appliedMult - 1.5f) > 0.001f && SHB.PlayerRules.appliedMult > 0.01f) { val.gravity = val.gravity / SHB.PlayerRules.appliedMult * 1.5f; SHB.PlayerRules.appliedMult = 1.5f; Ext.Debug("Gravity set to x" + 1.5f + " -> " + val.gravity); } } catch (Exception ex) { Ext.LogOnce("grav", "Gravity rule failed: " + ex.Message); } try { int instanceID = ((Object)val).GetInstanceID(); if (instanceID != healthPlayer) { healthPlayer = instanceID; baseMaxHealth = ((GameEntity)val).maxHealth; } float num = baseMaxHealth * 0.5f; if (((GameEntity)val).maxHealth > num + 0.001f) { if (((GameEntity)val).maxHealth > baseMaxHealth + 0.001f) { baseMaxHealth = ((GameEntity)val).maxHealth; } num = (((GameEntity)val).maxHealth = baseMaxHealth * 0.5f); Ext.DebugOnce("hp" + instanceID + num, "Max health halved: " + num.ToString("0.#")); } if (((GameEntity)val).health > ((GameEntity)val).maxHealth) { ((GameEntity)val).health = ((GameEntity)val).maxHealth; } } catch (Exception ex2) { Ext.LogOnce("hp", "Health rule failed: " + ex2.Message); } if (!Ext.PlayerAlive() || Ext.Paused()) { return; } if (R.Get(val, "falling", fallback: false)) { fallTimer += Time.deltaTime; } else { fallTimer = 0f; } if (Ext.Zone != SHB.Zone.Abyss || !(fallTimer > 2.5f) || DEN_Face.faceInstances == null || DEN_Face.faceInstances.Count <= 0) { return; } Vector3 overrideTargetPosition = ((Component)val).transform.position + Vector3.down * 20f; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(((Component)val).transform.position, Vector3.down, ref val2, 300f, -1, (QueryTriggerInteraction)1)) { overrideTargetPosition = ((RaycastHit)(ref val2)).point; } foreach (DEN_Face faceInstance in DEN_Face.faceInstances) { if ((Object)(object)faceInstance != (Object)null && !((GameEntity)faceInstance).dead) { try { ((AIGameEntity)faceInstance).SetOverrideTargetPosition(overrideTargetPosition); } catch { } } } Ext.DebugOnce("facefall" + Mathf.FloorToInt(Time.time / 10f), "Falling for 2.5 s in the Abyss: the faces head for your landing spot."); } public static void Falling_Pre(ENT_Player __instance, out FallState __state) { __state = default(FallState); if (Ext.IsOn() && !((Object)(object)__instance == (Object)null)) { __state = new FallState { falling = R.Get(__instance, "falling", fallback: false), dist = R.Get(__instance, "curFallDistance", 0f), ignore = R.Get(__instance, "ignoreFallDamageTime", 0f), valid = true }; } } public static void Falling_Post(ENT_Player __instance, FallState __state) { if (!__state.valid || (Object)(object)__instance == (Object)null || ((GameEntity)__instance).dead || !__state.falling || R.Get(__instance, "falling", fallback: false)) { return; } try { float num = ((Ext.Zone == SHB.Zone.Abyss) ? 40f : 25f); if (!(__state.dist < num) && !(__state.ignore > 0f) && !__instance.IsHanging() && !__instance.IsSwimming() && !R.Get(__instance, "noclip", fallback: false) && (!((Object)(object)CL_GameManager.gMan != (Object)null) || !CL_GameManager.gMan.IsReviving())) { Ext.Debug("Fell " + __state.dist.ToString("0.0") + " m (limit " + num + " m): dead."); ((GameEntity)__instance).Kill("falling"); } } catch (Exception ex) { Ext.LogOnce("fall", "Fall rule failed: " + ex.Message); } } public static void Damage_Pre(ENT_Player __instance, DamageInfo info) { //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) if (info == null || !Ext.IsOn()) { return; } try { GameObject src; string text = Ext.Describe(info, out src); GameEntity val = (((Object)(object)src != (Object)null) ? src.GetComponentInParent<GameEntity>() : null); float amount = info.amount; string text2 = (info.type ?? "").ToLowerInvariant(); string text3 = Instakill(text2, text, src, val); if (text3 != null) { info.amount = 99999f; Ext.Debug("Instant death: " + text3 + " (" + text.Trim() + ")"); } else { float num = 1f; if (text2 == "falling") { num = 2.5f; } else if (val is DEN_Bloodbug && !text.Contains("spit") && !text.Contains("swarm")) { num = 2.5f; } else if (val is DEN_Drone) { num = 2.5f; } else if ((Object)(object)val == (Object)null || (!(val is Denizen) && !(val is AIGameEntity))) { num = EnvMult(text2, text); } info.amount *= num; } float num2 = 1f; if (__instance.IsHanging()) { num2 *= 2f; } if (text.Contains("explo") || text.Contains("gasbag") || SHB.SpawnRules.IsRedRoach(text)) { num2 *= 2f; } if (num2 != 1f) { info.force *= num2; } if (info.amount != amount) { Ext.DebugOnce("dmg" + text.GetHashCode(), "Damage " + amount.ToString("0.##") + " -> " + info.amount.ToString("0.##") + " from: " + text.Trim()); } } catch (Exception ex) { Ext.LogOnce("pdmg", "EXTREME damage rule failed: " + ex.Message); } } private static string Instakill(string type, string desc, GameObject src, GameEntity srcEnt) { if (srcEnt is DEN_Teeth || type == "teeth") { return "caught by Teeth"; } if (srcEnt is DEN_Face) { return "caught by a Nightmare face"; } if (desc.Contains("crush")) { return "crusher"; } if (Ext.Sub("delta") && (desc.Contains("laser") || ((Object)(object)src != (Object)null && (Object)(object)src.GetComponentInParent<DEN_Deathwall>() != (Object)null))) { return "Delta Labs laser"; } return null; } private static bool HasAny(string s, string[] keys) { foreach (string value in keys) { if (s.Contains(value)) { return true; } } return false; } private static float EnvMult(string type, string desc) { switch (type) { default: if (!desc.Contains("steam")) { SHB.Zone zone = Ext.Zone; if (zone == SHB.Zone.Nest && Ext.Sub("hot zone", "hotzone", "hot-zone", "hot_zone")) { return 3f; } if (zone == SHB.Zone.Nest && Ext.Sub("infested") && HasAny(desc, Bio)) { return 2.5f; } if (zone == SHB.Zone.Abyss && Ext.Sub("deadman", "dead man", "handle")) { return 2.5f; } if (zone == SHB.Zone.Habitation && Ext.Sub("pier") && desc.Contains("fog")) { return 3f; } if (zone == SHB.Zone.Silos && HasAny(desc, Electric)) { return 3f; } return 1f; } goto case "poison"; case "poison": case "hunger": case "nonlethal": case "drowned": return 1f; } } public static void BuddyUse_Post(Item item) { try { if (item == null || !Ext.IsOn() || !SHB.Buddy.IsBuddy(item)) { return; } ENT_Player val = Ext.Player(); if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || val.hands == null || !val.IsGrounded(false) || val.IsHanging() || Time.time - lastBuddyBoost < 3f) { return; } lastBuddyBoost = Time.time; for (int i = 0; i < val.hands.Length; i++) { if (val.hands[i] != null) { val.hands[i].AddGripStrength(val.GetCurrentGripStrengthTimer(i) * 0.2f); } } Ext.Debug("Petted the Calming Buddy on the ground: +" + 20f.ToString("0") + "% grip."); } catch (Exception ex) { Ext.LogOnce("buddystam", "Buddy stamina failed: " + ex.Message); } } public static void PerkScope_Pre() { perkScope++; } public static void PerkScope_Post() { if (perkScope > 0) { perkScope--; } } public static bool AddPerk_Pre(Perk perk, ref Perk __result) { if ((Object)(object)perk == (Object)null || !Ext.IsOn()) { return true; } if (!(perk.id + " " + perk.title + " " + ((Object)perk).name).ToLowerInvariant().Contains("amalgam")) { return true; } Ext.Debug("EXTREME: blocked perk " + perk.id + " (Amalgamator)"); __result = null; return false; } } [BepInPlugin("com.wkmods.extremeknuckle", "ExtremeKnuckle", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string GUID = "com.wkmods.extremeknuckle"; public const string NAME = "ExtremeKnuckle"; public const string VERSION = "1.2.0"; public static Plugin Instance; public static ManualLogSource Log; public static Harmony Harmony; public static ConfigEntry<bool> DebugLog; public static ConfigEntry<bool> ShowLabel; private CL_GameManager lastGameManager; private float nextSlowTick; private float nextEntityScan; private float nextWorldScan; private void Awake() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLog", true, "Write everything EXTREME changes (tuned enemies, extra copies, hazards, vendors, deaths) to BepInEx/LogOutput.log."); ShowLabel = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowLabel", true, "Show the pulsing EXTREME label at the top of the screen."); Harmony = new Harmony("com.wkmods.extremeknuckle"); Patches.ApplyAll(Harmony); Log.LogInfo((object)"ExtremeKnuckle 1.2.0 loaded. Pick EXTREME on the run setup screen (next to SUPER HARD)."); } public static void BeforeSuperHard() { try { Overrides.Apply(Ext.IsOn()); } catch (Exception ex) { Ext.LogOnce("pre", "Pre-tick error: " + ex); } } private void Update() { try { Ext.MenuTick(); if ((Object)(object)CL_GameManager.gMan != (Object)(object)lastGameManager) { lastGameManager = CL_GameManager.gMan; if ((Object)(object)lastGameManager != (Object)null) { OnNewRun(); } } bool num = Ext.IsOn(); Overrides.Apply(num); if (num && !((Object)(object)CL_GameManager.gMan == (Object)null)) { Ext.TrackRegion(); PlayerRules.Tick(); Pressure.Tick(); Striders.Tick(); Chaser.Tick(); float unscaledTime = Time.unscaledTime; if (unscaledTime >= nextEntityScan) { nextEntityScan = unscaledTime + 0.25f; EntityTuner.Scan(); } if (unscaledTime >= nextWorldScan) { nextWorldScan = unscaledTime + 1.5f; WorldTuner.Scan(); } if (unscaledTime >= nextSlowTick) { nextSlowTick = unscaledTime + 1f; Items.SlowTick(); } } } catch (Exception ex) { Ext.LogOnce("update", "Update error: " + ex); } } private void OnNewRun() { EntityTuner.Reset(); WorldTuner.Reset(); Items.Reset(); PlayerRules.Reset(); Pressure.Reset(); Striders.Reset(); Chaser.Reset(); ExtTimers.Reset(); MassRules.Reset(); Ext.ResetRegion(); } private void OnGUI() { } } public static class Pressure { private static Vector3 anchor; private static float campTime; private static float nextAmbushAt; private static float bonusTimer; private static bool alerted; private static bool hasAnchor; private static readonly HashSet<int> killed = new HashSet<int>(); private static readonly List<DEN_EngravedDoor> doors = new List<DEN_EngravedDoor>(); private static readonly HashSet<int> doorsPassed = new HashSet<int>(); private static float waveAt = -1f; private static readonly List<GameObject> attracted = new List<GameObject>(); public static void Reset() { hasAnchor = false; campTime = 0f; alerted = false; nextAmbushAt = 60f; bonusTimer = 0f; killed.Clear(); doors.Clear(); doorsPassed.Clear(); waveAt = -1f; } public static void Tick() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) if (!Ext.PlayerAlive() || Ext.Paused()) { return; } Vector3 position = ((Component)Ext.Player()).transform.position; float deltaTime = Time.deltaTime; bool flag = Ext.InSafeRoom(); if (!flag) { bonusTimer += deltaTime; if (bonusTimer >= 300f) { bonusTimer = 0f; EntityTuner.PendingBonusCopy = true; Ext.Debug("5 minutes outside safe rooms: next spawn may get a bonus copy."); } } Vector3 val; if (!(!hasAnchor || flag)) { val = position - anchor; if (!(((Vector3)(ref val)).sqrMagnitude > 9f)) { campTime += deltaTime; if (campTime >= 30f && !alerted) { alerted = true; Ext.Debug("Camping for 30 s: " + AlertAround(position, 45f, int.MaxValue, null) + " enemies come to investigate."); } if (campTime >= nextAmbushAt) { nextAmbushAt += 20f; if (Random.value < 0.5f) { Ambush("Camping ambush", 1); } } goto IL_0137; } } anchor = position; hasAnchor = true; campTime = 0f; alerted = false; nextAmbushAt = 60f; goto IL_0137; IL_0137: for (int num = doors.Count - 1; num >= 0; num--) { DEN_EngravedDoor val2 = doors[num]; if ((Object)(object)val2 == (Object)null) { doors.RemoveAt(num); } else if (!doorsPassed.Contains(((Object)val2).GetInstanceID())) { val = ((Component)val2).transform.position - position; if (((Vector3)(ref val)).sqrMagnitude < 12.25f) { doorsPassed.Add(((Object)val2).GetInstanceID()); waveAt = Time.time + 4f; } } } if (waveAt > 0f && Time.time >= waveAt) { waveAt = -1f; if (!flag) { Ambush("Engraved Door wave", 2); } } } public static void OnEngravedDoor(GameEntity g) { DEN_EngravedDoor val = (DEN_EngravedDoor)(object)((g is DEN_EngravedDoor) ? g : null); if (val != null && !doors.Contains(val)) { doors.Add(val); } } private static void Ambush(string why, int count) { List<GameEntity> recentHostiles = EntityTuner.RecentHostiles; AIGameEntity ai = default(AIGameEntity); for (int i = 0; i < count; i++) { GameEntity val = null; for (int j = 0; j < 8; j++) { if (recentHostiles.Count <= 0) { break; } GameEntity val2 = recentHostiles[Random.Range(0, recentHostiles.Count)]; if ((Object)(object)val2 != (Object)null && !val2.dead && ((Component)val2).gameObject.activeInHierarchy && !(val2 is DEN_Turret) && !(val2 is DEN_Barnacle) && !(val2 is DEN_Strider)) { val = val2; break; } } if ((Object)(object)val == (Object)null) { Ext.DebugOnce("noamb" + Ext.Where, why + ": nothing nearby to send."); break; } GameObject val3 = EntityTuner.SpawnNearPlayer(((Component)val).gameObject, 9f, 18f, why); if ((Object)(object)val3 != (Object)null && val3.TryGetComponent<AIGameEntity>(ref ai)) { Alert(ai); } } } private static void Alert(AIGameEntity ai) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) ENT_Player val = Ext.Player(); if ((Object)(object)ai == (Object)null || (Object)(object)val == (Object)null) { return; } try { ai.SetTarget(((Component)val).transform); } catch { } try { ai.SetTargetPosition(((Component)val).transform.position); } catch { } } private static int AlertAround(Vector3 pos, float radius, int max, Func<GameEntity, bool> filter) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) int num = 0; List<GameEntity> entities = GameEntity.entities; if (entities == null) { return 0; } GameEntity[] array = entities.ToArray(); foreach (GameEntity val in array) { if (num >= max) { break; } if ((Object)(object)val == (Object)null || val.dead) { continue; } AIGameEntity val2 = (AIGameEntity)(object)((val is AIGameEntity) ? val : null); if (val2 != null && Rules.IsHostile(val) && !(val is DEN_Mother) && !(val is DEN_Turret) && (filter == null || filter(val))) { Vector3 val3 = ((Component)val).transform.position - pos; if (!(((Vector3)(ref val3)).sqrMagnitude > radius * radius)) { Alert(val2); num++; } } } return num; } public static void OnKill(Denizen d) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //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_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)d == (Object)null || !Ext.IsOn() || !killed.Add(((Object)d).GetInstanceID())) { return; } try { string text = ((Object)((Component)d).gameObject).name.ToLowerInvariant(); SHB.Zone zone = Ext.Zone; Vector3 position = ((Component)d).transform.position; if (zone == SHB.Zone.Silos && (d is DEN_Bloodbug || text.Contains("bloodbug")) && Random.value < 0.35f) { GameObject source = SHB.Util.FindPrefabNamed("Denizen_Bloodbug") ?? ((Component)d).gameObject; for (int i = 0; i < 2; i++) { EntityTuner.SpawnNearPlayer(source, 10f, 20f, "Bloodbug death attracts another"); } } else if (zone == SHB.Zone.Pipeworks && d is DEN_Barnacle && Random.value < 0.4f) { ENT_Player val = Ext.Player(); int num = 0; GameEntity[] array = GameEntity.entities.ToArray(); foreach (GameEntity obj in array) { DEN_Barnacle val2 = (DEN_Barnacle)(object)((obj is DEN_Barnacle) ? obj : null); if (val2 == null || !((Object)(object)val2 != (Object)(object)d) || ((GameEntity)val2).dead) { continue; } Vector3 val3 = ((Component)val2).transform.position - position; if (((Vector3)(ref val3)).sqrMagnitude < 324f && (Object)(object)val != (Object)null) { try { val2.ReachTongues(((Component)val).transform); num++; } catch { } } } if (num > 0) { Ext.Debug("Barnacle killed: " + num + " nearby barnacles lash out."); } } else if (zone == SHB.Zone.Nest && (text.Contains("sprider") || text.Contains("spider"))) { int num2 = AlertAround(position, 35f, 4, delegate(GameEntity e) { string text2 = ((Object)((Component)e).gameObject).name.ToLowerInvariant(); return text2.Contains("sprider") || text2.Contains("spider"); }); if (num2 > 0) { Ext.Debug("Sprider killed: " + num2 + " Spriders alerted."); } } else if (zone == SHB.Zone.Nest && (d is DEN_BasicDenizen_Flier_Swarm || text.Contains("swarm"))) { AlertAround(position, 30f, 6, (GameEntity e) => e is DEN_BasicDenizen_Flier_Swarm || ((Object)((Component)e).gameObject).name.ToLowerInvariant().Contains("swarm")); } else if (zone == SHB.Zone.Nest && text.Contains("aunt")) { AlertAround(position, 30f, 2, (GameEntity e) => ((Object)((Component)e).gameObject).name.ToLowerInvariant().Contains("aunt")); } } catch (Exception ex) { Ext.LogOnce("onkill", "Kill rule failed: " + ex.Message); } } } public static class R { private const BindingFlags All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static readonly Dictionary<string, FieldInfo> fields = new Dictionary<string, FieldInfo>(); private static readonly Dictionary<string, MethodInfo> methods = new Dictionary<string, MethodInfo>(); private static FieldInfo F(Type t, string name) { string key = t.FullName + "." + name; if (fields.TryGetValue(key, out var value)) { return value; } Type type = t; while (type != null && value == null) { value = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); type = type.BaseType; } fields[key] = value; return value; } public static T Get<T>(object o, string name, T fallback = default(T)) { if (o == null) { return fallback; } try { FieldInfo fieldInfo = F(o.GetType(), name); return (fieldInfo != null && fieldInfo.GetValue(o) is T val) ? val : fallback; } catch { return fallback; } } public static void Set(object o, string name, object value) { if (o == null) { return; } try { FieldInfo fieldInfo = F(o.GetType(), name); if (fieldInfo != null) { fieldInfo.SetValue(o, value); } } catch { } } public static void Mul(object o, string name, float k) { if (o == null || k == 1f) { return; } try { FieldInfo fieldInfo = F(o.GetType(), name); if (fieldInfo != null && fieldInfo.FieldType == typeof(float)) { fieldInfo.SetValue(o, (float)fieldInfo.GetValue(o) * k); } } catch { } } public static object Call(object o, string name, params object[] args) { if (o == null) { return null; } Type type = o.GetType(); string key = type.FullName + "::" + name; if (!methods.TryGetValue(key, out var value)) { Type type2 = type; while (type2 != null && value == null) { MethodInfo[] array = type2.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in array) { if (methodInfo.Name == name && methodInfo.GetParameters().Length == args.Length) { value = methodInfo; break; } } type2 = type2.BaseType; } methods[key] = value; } try { return (value != null) ? value.Invoke(o, args) : null; } catch { return null; } } } public static class Rules { private static bool Has(string n, params string[] keys) { for (int i = 0; i < keys.Length; i++) { if (n.Contains(keys[i])) { return true; } } return false; } public static bool IsHostile(GameEntity e) { if ((Object)(object)e == (Object)null) { return false; } if (e is DEN_Roach || e is DEN_Critter || e is DEN_SlugGrub || e is DEN_Mother || e is DEN_EngravedDoor) { return false; } string text = ((Object)((Component)e).gameObject).name.ToLowerInvariant(); if (text.Contains("roach") && !SHB.SpawnRules.IsRedRoach(text)) { return false; } if (text.Contains("buddy")) { return false; } if (!(e is Denizen)) { return e is AIGameEntity; } return true; } private static bool IsUnique(GameEntity e) { if (!(e is DEN_Teeth) && !(e is DEN_Hunter) && !(e is DEN_Face) && !(e is DEN_VentThing) && !(e is DEN_Remains_Active) && !(e is DEN_RatKing) && !(e is DEN_Mother) && !(e is DEN_Mask) && !(e is DEN_Phage) && !(e is DEN_Tracker) && !(e is DEN_Pseudopod)) { return e is DEN_SimpleChaseKiller; } return true; } public static EntityRule For(GameEntity e, string n, SHB.Zone z) { EntityRule entityRule = new EntityRule(); Tune tune = entityRule.Tune; bool flag = z == SHB.Zone.Nest; bool flag2 = z == SHB.Zone.Pipeworks; bool flag3 = z == SHB.Zone.Habitation; bool flag4 = z == SHB.Zone.Abyss; if (e is DEN_Hopper_Tick) { entityRule.Name = "tick roach"; tune.Speed = (flag ? 2f : 1.5f); tune.Detect = 2f; tune.Set("drainDamage", flag ? 3f : 2f); if (flag) { tune.Set("maxBloodDrain", 1.5f); entityRule.ExtraCopies = 3; } return entityRule; } if (e is DEN_Hopper || (Has(n, "hopper") && !Has(n, "tick"))) { entityRule.Name = "hopper roach"; tune.Speed = 1.6f; tune.Detect = 2f; tune.Time = 0.5f; entityRule.ExtraCopies = ((!flag2) ? 2 : 0); return entityRule; } if (SHB.SpawnRules.IsRedRoach(n)) { entityRule.Name = "red roach"; tune.Speed = 1.5f; entityRule.Escalates = false; entityRule.Custom = delegate(GameEntity g) { ScaleExplosions(((Component)g).gameObject, 1.5f, 1f); }; return entityRule; } if (e is DEN_Roach || e is DEN_Critter || e is DEN_SlugGrub) { return null; } if (e is DEN_GantryTurret) { entityRule.Name = "gantry turret"; tune.Speed = 1.5f; tune.Set("repositionTimerMin", 0.5f).Set("repositionTimerMax", 0.5f); return entityRule; } if (e is DEN_Turret) { entityRule.Name = "turret"; entityRule.Escalates = false; tune.Set("lookSpeed", 2.5f).Set("shootDelay", 0.5f).Set("maxRange", 1.75f) .Set("spinScanSpeed", 1.6f) .Set("horizontalTurnSpeed", 2.5f) .Set("verticalTurnSpeed", 2.5f); tune.NoDamageField("damage"); entityRule.Custom = delegate(GameEntity g) { Drones.OnTurret(g); }; return entityRule; } if (e is DEN_Drone) { entityRule.Name = "drone"; tune.Speed = 1.75f; tune.Detect = 2f; tune.Time = 0.5f; tune.Set("chargeCooldown", 0.5f); return entityRule; } if (e is DEN_Remains_Active) { entityRule.Name = "Remains"; entityRule.Escalates = false; tune.Set("moveSpeed", 1.5f).Set("moveSpeedRand", 1.5f).Set("viewRadius", 2f) .Set("scanDistance", 2f); return entityRule; } if (e is DEN_EngravedDoor) { entityRule.Name = "Engraved Door"; entityRule.Escalates = false; tune.Set("damage", 2f).Set("damageTime", 2f / 3f).Set("pullForce", 1.5f) .Set("lookForce", 1.5f) .Set("lookFreq", 1.5f); entityRule.Custom = delegate(GameEntity g) { Pressure.OnEngravedDoor(g); }; return entityRule; } if (e is DEN_Teeth) { entityRule.Name = "Teeth"; entityRule.Escalates = false; tune.Set("aggressionRate", 2f).Set("attackDamage", 99999f).Set("jumpArcHeight", 1.5f); return entityRule; } if (e is DEN_VentThing) { entityRule.Name = "Vent Thing"; entityRule.Escalates = false; tune.Set("activationDistance", 1.8f).Set("retreatTime", 0.4f).Set("finalStrikeSpeedMult", 1.5f) .Set("handRetreatSpeed", 3f); return entityRule; } if (e is DEN_Face) { entityRule.Name = "Nightmare face"; entityRule.Escalates = false; tune.Set("baseVelocityMult", 1.6f).Set("aggressionIncreaseRate", 2f).Set("commandSpeedMult", 1.6f); return entityRule; } if (e is DEN_Hunter) { entityRule.Name = "Hunter"; entityRule.Escalates = false; tune.Set("startSpeed", 2.5f).Set("lurchSpeed", 2.5f).Set("turnSpeed", 2f) .Set("stunTime", 0.35f) .Set("freezeTime", 0.35f) .Set("slamRecoveryRate", 2.5f) .Set("collisionDamage", 3f) .Set("trackPositionDistance", 2f); tune.Detect = 2f; return entityRule; } if (e is DEN_Strider) { entityRule.Name = "strider"; entityRule.Escalates = false; tune.Set("speed", 1.8f).Set("acceleration", 1.8f).Set("turnSpeed", 1.5f); return entityRule; } if (IsUnique(e)) { return null; } if (e is DEN_Bloodbug || Has(n, "bloodbug")) { if (Has(n, "spit")) { entityRule.Name = "spitter bloodbug"; tune.Detect = 2f; tune.Time = 0.4f; tune.Damage = 3f; tune.Set("rangedAttackCooldown", 0.4f).Set("projectileShootDelay", 0.5f); entityRule.ExtraCopies = (flag ? 3 : 0); return entityRule; } if (e is DEN_BasicDenizen_Flier_Swarm || Has(n, "swarm")) { entityRule.Name = "swarm bloodbug"; tune.Speed = 1.75f; tune.Detect = 2f; tune.Time = 0.5f; tune.Damage = 3f; entityRule.Custom = delegate(GameEntity g) { DEN_BasicDenizen_Flier_Swarm val = (DEN_BasicDenizen_Flier_Swarm)(object)((g is DEN_BasicDenizen_Flier_Swarm) ? g : null); if (val != null) { val.swarmCount *= 3; } }; return entityRule; } entityRule.Name = "bloodbug"; tune.Speed = 1.7f; tune.Detect = 2f; tune.Time = 0.4f; return entityRule; } if (Has(n, "sturge")) { entityRule.Name = "Sturge"; tune.Detect = 2f; tune.Time = 0.5714286f; tune.NoDamageField("meleeAttackHitDamage"); return entityRule; } if (e is DEN_Barnacle_Zombie || Has(n, "zombie")) { entityRule.Name = (Has(n, "security") ? "security barnacle zombie" : (Has(n, "scientist") ? "scientist barnacle zombie" : "barnacle zombie")); tune.Speed = 1.9f; tune.Time = 0.4f; tune.Damage = 3f; if (Has(n, "scientist")) { tune.Detect = 2f; } tune.Set("timeToAttack", 0.4f); if (flag) { entityRule.ExtraCopies = 3; } entityRule.Custom = delegate(GameEntity g) { if (Has(n, "security")) { BoostHealth(g, 1.5f); } }; return entityRule; } if (e is DEN_Barnacle || Has(n, "barnacle")) { entityRule.Name = "barnacle"; entityRule.Escalates = false; float mult = (flag ? 2f : 1.6f); tune.Set("attackDistance", mult).Set("scanDistance", mult).Set("damage", 3f) .Set("attackRate", flag ? 0.3f : 0.5f) .Set("tongueSpeed", flag ? 2.5f : 2f) .Set("tongueRetractSpeed", 1.8f) .Set("tongueAimTime", 0.6f) .Set("pullStrength", 1.3f); return entityRule; } if (e is DEN_Gasbag || Has(n, "gasbag")) { entityRule.Name = (flag ? "vernal gasbag" : "gasbag"); tune.Speed = (flag ? 1.75f : 2f); tune.Detect = 2f; tune.Set("explodeDamage", 3f).Set("explodeForce", 2f); entityRule.ExtraCopies = (flag ? 2 : (flag2 ? 3 : 0)); entityRule.Custom = delegate(GameEntity g) { ScaleExplosions(((Component)g).gameObject, 2f, 3f); }; return entityRule; } if (Has(n, "sprider", "spider")) { entityRule.Name = "Sprider"; tune.Speed = 2f; tune.Damage = 2.5f; tune.Detect = 2f; tune.Time = 0.4f; entityRule.ExtraCopies = (flag ? 4 : 0); return entityRule; } if (Has(n, "aunt")) { entityRule.Name = "Grub Aunt"; tune.Speed = 1.75f; tune.Damage = 3f; tune.Detect = 2f; entityRule.ExtraCopies = (flag ? 2 : 0); return entityRule; } if (Has(n, "sister")) { entityRule.Name = "Grub Sister"; tune.Speed = 1.5f; tune.Time = 0.5f; tune.Set("spotTime", 0.4f); return entityRule; } if (Has(n, "myzont")) { entityRule.Name = "Myzont"; tune.Speed = 1.75f; tune.Time = 0.25f; tune.Detect = 2f; tune.Damage = 2.5f; tune.Set("memoryLength", 2f); entityRule.ExtraCopies = (flag ? 2 : 0); return entityRule; } if (e is DEN_Ravelin || Has(n, "ravelin")) { entityRule.Name = "Ravelin"; tune.Speed = 1.6f; tune.Time = 0.5f; tune.Damage = 3f; tune.Detect = 1.75f; entityRule.ExtraCopies = (flag ? 1 : 0); return entityRule; } if (!IsHostile(e)) { return null; } entityRule.Name = ((object)e).GetType().Name; if (flag3) { tune.Detect = 1.75f; if (e is DEN_BasicDenizen || e is DEN_BasicFlier || e is DEN_BasicNavigator || e is DEN_GiantRoach) { entityRule.ExtraCopies = 2; } } else if (flag) { tune.Time = 0.5f; tune.Detect = 1.5f; } else if (flag4) { tune.Detect = 1.5f; } return entityRule; } private static void BoostHealth(GameEntity g, float mult) { g.maxHealth *= mult; g.health *= mult; ENT_Hitbox[] componentsInChildren = ((Component)g).GetComponentsInChildren<ENT_Hitbox>(true); foreach (ENT_Hitbox obj in componentsInChildren) { obj.maxHealth *= mult; obj.health *= mult; } } public static void ScaleExplosions(GameObject g, float radius, float damage) { if (!((Object)(object)g == (Object)null)) { UT_Explosion[] componentsInChildren = g.GetComponentsInChildren<UT_Explosion>(true); foreach (UT_Explosion obj in componentsInChildren) { obj.maxDistance *= radius; obj.damageMult *= damage; } } } } public static class SHB { public enum Zone { None, Silos, Pipeworks, Habitation, Abyss, Nest } public static class Zones { public static Zone Current { get { try { object obj = Get("Zones", "Current"); return (obj != null) ? ((Zone)Convert.ToInt32(obj)) : Zone.None; } catch { return Zone.None; } } } public static string Where => G("Zones", "Where", ""); public static bool NestLastSection => G("Zones", "NestLastSection", fallback: false); } public static class Timers { public static float MotherLeft { get { return G("Timers", "MotherLeft", -1f); } set { Set("Timers", "MotherLeft", value); } } public static float RemainsTimer { get { return G("Timers", "RemainsTimer", 0f); } set { Set("Timers", "RemainsTimer", value); } } public static void SpawnRemains() { Call("Timers", "SpawnRemains"); } } public static class Mode { public const string SettingId = "skmod_super"; public static bool Broken => G("Mode", "Broken", fallback: false); public static HashSet<string> HardIds => G<HashSet<string>>("Mode", "HardIds") ?? new HashSet<string>(); public static HashSet<string> SurvivalIds => G<HashSet<string>>("Mode", "SurvivalIds") ?? new HashSet<string>(); public static Dictionary<M_Subregion, KeyValuePair<float, bool>> cavityBackup => G<Dictionary<M_Subregion, KeyValuePair<float, bool>>>("Mode", "cavityBackup") ?? new Dictionary<M_Subregion, KeyValuePair<float, bool>>(); } public static class PlayerRules { public static ENT_Player gravityPlayer => G<ENT_Player>("PlayerRules", "gravityPlayer"); public static float appliedMult { get { return G("PlayerRules", "appliedMult", 1f); } set { Set("PlayerRules", "appliedMult", value); } } } public static class Hud { public static string flash => G<string>("Hud", "flash"); public static float flashUntil => G("Hud", "flashUntil", 0f); public static void Flash(string text) { try { Call("Hud", "Flash", text); } catch { } } } public static class Buddy { public static bool IsBuddy(Item item) { try { object obj = Call("Buddy", "IsBuddy", item); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } } public static class EntityRules { public static bool IsClone(GameObject g) { try { object obj = Call("EntityRules", "IsClone", g); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } public static void MarkSpawned(GameObject g) { try { Call("EntityRules", "MarkSpawned", g); } catch { } } } public static class SpawnRules { public static bool IsRedRoach(string desc) { try { object obj = Call("SpawnRules", "IsRedRoach", desc); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } public static string Owner(object spawnSettings) { if (spawnSettings == null) { return null; } try { return (Get("SpawnRules", "owners") is IDictionary dictionary && dictionary.Contains(spawnSettings)) ? (dictionary[spawnSettings] as string) : null; } catch { return null; } } } public static class ItemRules { public static string ItemName(Item_Object io) { try { return (Call("ItemRules", "ItemName", io) as string) ?? ((Object)io).name; } catch { return ((Object)(object)io != (Object)null) ? ((Object)io).name : ""; } } } public static class Util { public static ENT_Player Player() { try { object obj = Call("Util", "Player"); return (ENT_Player)((obj is ENT_Player) ? obj : null); } catch { return null; } } public static WKAssetDatabase Db() { try { object obj = Call("Util", "Db"); return (WKAssetDatabase)((obj is WKAssetDatabase) ? obj : null); } catch { return null; } } public static Vector3 NearbySpot(Transform t) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) try { object obj = Call("Util", "NearbySpot", t); if (obj is Vector3) { return (Vector3)obj; } } catch { } return t.position + Random.insideUnitSphere * 2f; } public static bool SpotAroundPlayer(float min, float max, out Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) pos = Vector3.zero; try { object[] array = new object[3] { min, max, Vector3.zero }; object obj = Call("Util", "SpotAroundPlayer", array); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } int result = num & (flag ? 1 : 0); if (array[2] is Vector3 val) { pos = val; } return (byte)result != 0; } catch { return false; } } public static GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot, Transform parent) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) try { object obj = Call("Util", "Spawn", prefab, pos, rot, parent); return (GameObject)((obj is GameObject) ? obj : null); } catch { return ((Object)(object)prefab != (Object)null) ? Object.Instantiate<GameObject>(prefab, pos, rot, parent) : null; } } public static GameObject FindPrefabNamed(string part) { try { object obj = Call("Util", "FindPrefabNamed", part); return (GameObject)((obj is GameObject) ? obj : null); } catch { return null; } } public static GameObject FindPrefabWith<TC>() { try { MethodInfo methodInfo = M("Util", "FindPrefabWith"); return (GameObject)((methodInfo != null) ? /*isinst with value type is only supported in some contexts*/: null); } catch { return null; } } } public static class Cfg { public static ConfigEntryBase DebugLog => E("DebugLog"); public static ConfigEntry<bool> ShowHud => E<bool>("ShowHud"); public static ConfigEntryBase ForceHardMode => E("ForceHardMode"); public static ConfigEntryBase ForceSurvival => E("ForceSurvival"); public static ConfigEntryBase DisableLeaderboards => E("DisableLeaderboards"); public static ConfigEntryBase GravityMult => E("GravityMult"); public static ConfigEntryBase HangSeconds => E("HangSeconds"); public static ConfigEntryBase HammerDamageMult => E("HammerDamageMult"); public static ConfigEntryBase EngravedDoorChance => E("EngravedDoorChance"); public static ConfigEntry<float> RemainsInterval => E<float>("RemainsInterval"); public static ConfigEntryBase MassSpeedMult => E("MassSpeedMult"); public static ConfigEntryBase HopperInstakill => E("HopperInstakill"); public static ConfigEntryBase TicksHoldOn => E("TicksHoldOn"); public static ConfigEntryBase RedRoachExtra => E("RedRoachExtra"); public static ConfigEntryBase RedRoachSpawnSeconds => E("RedRoachSpawnSeconds"); public static ConfigEntryBase RedRoachMax => E("RedRoachMax"); public static ConfigEntryBase TurretExtra => E("TurretExtra"); public static ConfigEntryBase BuddyEnabled => E("BuddyEnabled"); public static ConfigEntryBase BuddyPetSeconds => E("BuddyPetSeconds"); public static ConfigEntryBase SilosSturgeInterval => E("SilosSturgeInterval"); public static ConfigEntryBase SilosSturgeMax => E("SilosSturgeMax"); public static ConfigEntryBase SilosSturgeExtra => E("SilosSturgeExtra"); public static ConfigEntryBase SilosBloodbugExtra => E("SilosBloodbugExtra"); public static ConfigEntryBase SilosMassMult => E("SilosMassMult"); public static ConfigEntryBase SturgeDamageMult => E("SturgeDamageMult"); public static ConfigEntryBase PipeworksBarnacleExtra => E("PipeworksBarnacleExtra"); public static ConfigEntryBase PipeworksHopperExtra => E("PipeworksHopperExtra"); public static ConfigEntryBase SteamDamageMult => E("SteamDamageMult"); public static ConfigEntryBase CavityRoute => E("CavityRoute"); public static ConfigEntryBase TeethSpeedMult => E("TeethSpeedMult"); public static ConfigEntryBase TeethStaysUntilHidden => E("TeethStaysUntilHidden"); public static ConfigEntryBase VentThingSpeedMult => E("VentThingSpeedMult"); public static ConfigEntryBase TurretDamageMult => E("TurretDamageMult"); public static ConfigEntryBase TurretDroneChance => E("TurretDroneChance"); public static ConfigEntryBase AbyssFaceCount => E("AbyssFaceCount"); public static ConfigEntryBase AbyssFallDeath => E("AbyssFallDeath"); public static ConfigEntryBase NestBarnacleExtra => E("NestBarnacleExtra"); public static ConfigEntry<float> MotherSeconds => E<float>("MotherSeconds"); public static ConfigEntryBase NestWaterDps => E("NestWaterDps"); private static ConfigEntryBase E(string name) { object obj = Get("Cfg", name); return (ConfigEntryBase)((obj is ConfigEntryBase) ? obj : null); } private static ConfigEntry<TV> E<TV>(string name) { return Get("Cfg", name) as ConfigEntry<TV>; } } private const BindingFlags All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static readonly Dictionary<string, Type> types = new Dictionary<string, Type>(); private static readonly Dictionary<string, FieldInfo> fields = new Dictionary<string, FieldInfo>(); private static readonly Dictionary<string, MethodInfo> methods = new Dictionary<string, MethodInfo>(); public static Type T(string name) { if (types.TryGetValue(name, out var value)) { return value; } value = AccessTools.TypeByName("SuperHardKnuckle." + name); if (value == null) { Plugin.Log.LogWarning((object)("EXTREME: SuperHard type not found: " + name)); } types[name] = value; return value; } private static FieldInfo F(string type, string field) { string text = type + "." + field; if (fields.TryGetValue(text, out var value)) { return value; } Type type2 = T(type); value = ((type2 != null) ? type2.GetField(field, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null); if (value == null) { Plugin.Log.LogWarning((object)("EXTREME: SuperHard field not found: " + text)); } fields[text] = value; return value; } private static MethodInfo M(string type, string method) { string text = type + "." + method; if (methods.TryGetValue(text, out var value)) { return value; } Type type2 = T(type); value = ((type2 != null) ? type2.GetMethod(method, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null); if (value == null) { Plugin.Log.LogWarning((object)("EXTREME: SuperHard method not found: " + text)); } methods[text] = value; return value; } private static object Get(string type, string field) { FieldInfo fieldInfo = F(type, field); if (!(fieldInfo != null)) { return null; } return fieldInfo.GetValue(null); } private static void Set(string type, string field, object v) { FieldInfo fieldInfo = F(type, field); if (fieldInfo != null) { fieldInfo.SetValue(null, v); } } private static object Call(string type, string method, params object[] args) { MethodInfo methodInfo = M(type, method); if (!(methodInfo != null)) { return null; } return methodInfo.Invoke(null, args); } private static TV G<TV>(string type, string field, TV fallback = default(TV)) { object obj = Get(type, field); if (obj is TV) { return (TV)obj; } return fallback; } } public static class Striders { private class S { public DEN_Strider d; public float speed; public float accel; public float onTime; public bool fast; } private static readonly List<S> list = new List<S>(); public static void Reset() { list.Clear(); } public static void Track(DEN_Strider d) { foreach (S item in list) { if ((Object)(object)item.d == (Object)(object)d) { return; } } list.Add(new S { d = d, speed = d.speed, accel = d.acceleration }); } public static void Tick() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if (list.Count == 0) { return; } ENT_Player val = Ext.Player(); if ((Object)(object)val == (Object)null) { return; } Vector3 position = ((Component)val).transform.position; Vector2 val2 = default(Vector2); for (int num = list.Count - 1; num >= 0; num--) { S s = list[num]; if ((Object)(object)s.d == (Object)null) { list.RemoveAt(num); } else { Vector3 position2 = ((Component)s.d).transform.position; ((Vector2)(ref val2))..ctor(position.x - position2.x, position.z - position2.z); bool flag = ((Vector2)(ref val2)).sqrMagnitude < 1