Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Silent55ModMenu v4.5.20
BepInEx\plugins\Silent55ModMenu\Silent55ModMenu.dll
Decompiled a month 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.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using EntityStates.Croco; using Microsoft.CodeAnalysis; using RoR2; using RoR2.CharacterAI; using RoR2.ConVar; using RoR2.Projectile; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Silent55ModMenu")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Silent55ModMenu")] [assembly: AssemblyTitle("Silent55ModMenu")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Silent55ModMenu { [BepInPlugin("com.silent55.modmenu", "Silent55 ModMenu", "4.5.20")] public sealed class Plugin : BaseUnityPlugin { private class PendingHostRequest { public NetworkConnection connection; public RunControlRequest request; } private class MenuPreset { public bool god; public bool noCd; public bool maxHp; public bool lockOn; public bool projectiles; public bool rapid; public bool reload; public bool secondary; public bool special; public bool markers; public bool teleporter; public bool chests; public bool shrines; public bool drops; public bool shops; public bool converters; public bool drones; public bool misc; public bool portals; public bool guaranteed; public bool summons; public bool acridTargets; public bool acridRange; public float attack; public float move; public float damage; public float difficulty; public float tp; public float lockDistance; public float lockAngle; public float tracking; public float rapidInterval; public float jumpHeight; public int jumps; public int spawnPressure; } private class LoadoutEntry { public PickupIndex pickup; public int count; } public class RunControlRequest : MessageBase { public int action; public float value; public string requester; public string version; public override void Serialize(NetworkWriter w) { w.Write(action); w.Write(value); w.Write(requester ?? ""); w.Write(version ?? ""); } public override void Deserialize(NetworkReader r) { action = r.ReadInt32(); value = r.ReadSingle(); requester = r.ReadString(); version = r.ReadString(); } } public class RunControlResponse : MessageBase { public bool approved; public string message; public override void Serialize(NetworkWriter w) { w.Write(approved); w.Write(message ?? ""); } public override void Deserialize(NetworkReader r) { approved = r.ReadBoolean(); message = r.ReadString(); } } private bool visible; private bool practiceFreeze; private bool practiceDisableAI; private bool practiceFullPause; private bool showMarkerDistance = true; private bool godMode; private bool noCooldown; private bool empoweredSummons; private bool guaranteedShrineChance; private bool acridUnlimitedTargets; private bool acridUnlimitedRange; private bool rapidFire; private bool rapidFireReload = true; private bool rapidFireSecondary = true; private bool rapidFireSpecial; private bool lockOn; private bool projectileTracking = true; private bool markers; private bool showChests = true; private bool showTeleporter = true; private bool showShrines = true; private bool showDrops = true; private bool maxPersonal; private bool showShops = true; private bool showConverters = true; private bool showDrones = true; private bool showMisc = true; private bool showPortals = true; private float markerMaxDistance = 1000f; private float jumpHeightMultiplier = 1f; private float attackMultiplier = 1f; private float moveMultiplier = 1f; private float damageMultiplier = 1f; private float difficultyRate = 1f; private float teleporterRate = 1f; private float lockDistance = 60f; private float lockAngle = 35f; private float trackingStrength = 75f; private float rapidFireInterval = 0.08f; private string itemSearch = ""; private int spawnQuantity = 1; private int spawnPressureMode; private PickupIndex selectedPickup = PickupIndex.none; private int extraJumps; private string status = "Ready"; private float saveQuitConfirmUntil; private float cleanupConfirmUntil; private float lootRunConfirmUntil; private bool lootRunActive; private bool lootContainers = true; private bool lootShops = true; private bool lootDrones = true; private bool lootEquipmentBarrels = true; private Coroutine lootRunCoroutine; private string lootRunExclusions = ""; private int tab; private string loadoutSearch = ""; private int loadoutQuantity = 1; private Vector2 loadoutScroll; private string presetName = "Custom Slot 1"; private int customPresetSlot = 1; private int presetLoadedSlot = -1; private float presetOverwriteConfirmUntil; private int selectedRecoveryPlayer; private Vector2 recoveryScroll; private int spawnerMode; private int selectedEnemyMaster; private int enemyQuantity = 1; private float enemySpawnDistance = 15f; private string enemySearch = ""; private Vector2 enemyScroll; private readonly List<GameObject> enemyMasterPrefabs = new List<GameObject>(); private readonly List<CharacterMaster> silent55SpawnedMasters = new List<CharacterMaster>(); private Rect window = new Rect(20f, 20f, 720f, 820f); private int centeredScreenW; private int centeredScreenH; private CharacterBody tracked; private HealthComponent trackedHealth; private float oldAttack; private float oldDamage; private float oldMove; private float oldHealth; private float oldRegen; private float oldJumpPower; private int originalDiseaseBounces; private float originalDiseaseBounceRange; private float originalDiseaseOrbRange; private bool diseaseDefaultsCaptured; private int oldJumps; private Vector3 savedPosition; private bool hasSavedPosition; private float nextScan; private float nextSpawnPressureApply; private float nextNetworkInit; private float nextZoneScan; private float nextShrineScan; private float unlockConfirmUntil; private float nextPracticeUpdate; private float nextSafetyScan; private int cachedBodies; private int cachedProjectiles; private int cachedPickups; private bool lastPracticeFreeze; private bool lastPracticeDisableAI; private bool lastPracticeFullPause; private float nextPracticeCache; private readonly List<CharacterBody> practiceBodies = new List<CharacterBody>(); private readonly List<BaseAI> practiceAIs = new List<BaseAI>(); private PickupIndex lastGivenPickup = PickupIndex.none; private int lastGivenCount; private float nextPrimaryFire; private float nextSecondaryFire; private float nextSpecialFire; private readonly List<ChestBehavior> chests = new List<ChestBehavior>(); private readonly List<ShrineBehavior> shrines = new List<ShrineBehavior>(); private readonly List<PickupDropletController> drops = new List<PickupDropletController>(); private readonly List<GenericPickupController> groundPickups = new List<GenericPickupController>(); private readonly List<PurchaseInteraction> interactables = new List<PurchaseInteraction>(); private readonly List<ShopTerminalBehavior> shops = new List<ShopTerminalBehavior>(); private readonly List<SummonMasterBehavior> repairables = new List<SummonMasterBehavior>(); private GUIStyle titleStyle; private GUIStyle sectionStyle; private GUIStyle onStyle; private GUIStyle offStyle; private GUIStyle tabStyle; private GUIStyle tabOnStyle; private GUIStyle cyanButtonStyle; private GUIStyle dangerButtonStyle; private Texture2D silent55Logo; private const short RequestMessageId = 28550; private const short ResponseMessageId = 28551; private const string NetworkVersion = "4.5.20"; private NetworkClient registeredClient; private bool serverHandlerRegistered; private bool autoApproveRequests; private NetworkConnection pendingConnection; private RunControlRequest pendingRequest; private readonly Queue<PendingHostRequest> requestQueue = new Queue<PendingHostRequest>(); private readonly List<string> requestHistory = new List<string>(); private readonly Dictionary<int, float> requestCooldowns = new Dictionary<int, float>(); private readonly Dictionary<string, float> subsystemErrorCooldowns = new Dictionary<string, float>(); private string lastSubsystemError = "None"; private int suppressedErrorCount; private Run previousRun; private string pendingCheckpointRaw = ""; private bool pendingCheckpointRestore; private Coroutine pendingRestoreCoroutine; private Vector2 requestScroll; private Vector2 requestHistoryScroll; private Vector2 enemyControlScroll; private readonly HashSet<HoldoutZoneController> hookedZones = new HashSet<HoldoutZoneController>(); private Run trackedRun; private float lastRunTime; private float realSessionTime; private float nextDifficultyRecalc; private int trackedStageClearCount = -1; private readonly Dictionary<string, List<LoadoutEntry>> opLoadouts = new Dictionary<string, List<LoadoutEntry>>(); private readonly Dictionary<string, List<LoadoutEntry>> grantedLoadouts = new Dictionary<string, List<LoadoutEntry>>(); private string loadedLoadoutCharacter = ""; private readonly HashSet<string> loadoutAppliedThisRun = new HashSet<string>(); private Run appliedRun; private float nextSummonScan; private readonly HashSet<CharacterMaster> empoweredMinions = new HashSet<CharacterMaster>(); private HuntressTracker silentTracker; private CharacterBody trackerBody; private readonly HashSet<ProjectileController> trackedProjectiles = new HashSet<ProjectileController>(); private MenuPreset CapturePreset() { return new MenuPreset { god = godMode, noCd = noCooldown, maxHp = maxPersonal, lockOn = lockOn, projectiles = projectileTracking, rapid = rapidFire, reload = rapidFireReload, secondary = rapidFireSecondary, special = rapidFireSpecial, markers = markers, teleporter = showTeleporter, chests = showChests, shrines = showShrines, drops = showDrops, shops = showShops, converters = showConverters, drones = showDrones, misc = showMisc, portals = showPortals, guaranteed = guaranteedShrineChance, summons = empoweredSummons, acridTargets = acridUnlimitedTargets, acridRange = acridUnlimitedRange, attack = attackMultiplier, move = moveMultiplier, damage = damageMultiplier, difficulty = difficultyRate, tp = teleporterRate, lockDistance = lockDistance, lockAngle = lockAngle, tracking = trackingStrength, rapidInterval = rapidFireInterval, jumpHeight = jumpHeightMultiplier, jumps = extraJumps, spawnPressure = spawnPressureMode }; } private void ApplyPreset(MenuPreset p, string name) { if (p == null) { return; } godMode = p.god; noCooldown = p.noCd; maxPersonal = p.maxHp; lockOn = p.lockOn; projectileTracking = p.projectiles; rapidFire = p.rapid; rapidFireReload = p.reload; rapidFireSecondary = p.secondary; rapidFireSpecial = p.special; markers = p.markers; showTeleporter = p.teleporter; showChests = p.chests; showShrines = p.shrines; showDrops = p.drops; showShops = p.shops; showConverters = p.converters; showDrones = p.drones; showMisc = p.misc; showPortals = p.portals; guaranteedShrineChance = p.guaranteed; empoweredSummons = p.summons; acridUnlimitedTargets = p.acridTargets; acridUnlimitedRange = p.acridRange; attackMultiplier = p.attack; moveMultiplier = p.move; damageMultiplier = p.damage; difficultyRate = p.difficulty; teleporterRate = p.tp; lockDistance = p.lockDistance; lockAngle = p.lockAngle; trackingStrength = p.tracking; rapidFireInterval = p.rapidInterval; jumpHeightMultiplier = Mathf.Clamp((p.jumpHeight <= 0f) ? 1f : p.jumpHeight, 0.5f, 10f); extraJumps = Mathf.Clamp(p.jumps, 0, 11); spawnPressureMode = Mathf.Clamp(p.spawnPressure, 0, 3); if (NetworkServer.active) { ApplyRunAction(1, difficultyRate); ApplyRunAction(2, teleporterRate); ApplyRunAction(6, guaranteedShrineChance ? 1f : 0f); } CharacterBody body = GetBody(); if ((Object)(object)body != (Object)null) { if ((Object)(object)body != (Object)(object)tracked) { RestoreStats(); Track(body); } ApplyStats(body); } status = "Applied preset: " + name + " | Move " + moveMultiplier.ToString("0.0") + "x | Damage " + Mathf.RoundToInt(damageMultiplier) + "x"; } private string SerializePreset(MenuPreset p) { List<string> list = new List<string>(); list.Add("V2"); list.AddRange(new bool[23] { p.god, p.noCd, p.maxHp, p.lockOn, p.projectiles, p.rapid, p.reload, p.secondary, p.special, p.markers, p.teleporter, p.chests, p.shrines, p.drops, p.shops, p.converters, p.drones, p.misc, p.portals, p.guaranteed, p.summons, p.acridTargets, p.acridRange }.Select((bool x) => (!x) ? "0" : "1")); list.AddRange(new float[10] { p.attack, p.move, p.damage, p.difficulty, p.tp, p.lockDistance, p.lockAngle, p.tracking, p.rapidInterval, p.jumpHeight }.Select((float x) => x.ToString(CultureInfo.InvariantCulture))); list.Add(p.jumps.ToString()); list.Add(p.spawnPressure.ToString()); return string.Join("|", list.ToArray()); } private MenuPreset DeserializePreset(string raw) { if (string.IsNullOrWhiteSpace(raw)) { return null; } try { string[] a = raw.Split('|'); bool flag = a.Length != 0 && a[0] == "V2"; int i = (flag ? 1 : 0); if (a.Length < (flag ? 36 : 33)) { return null; } Func<bool> func = delegate { string text = a[i++]; if (text != "0" && text != "1") { throw new FormatException("Invalid boolean"); } return text == "1"; }; Func<float> func2 = delegate { if (!float.TryParse(a[i++], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || float.IsNaN(result) || float.IsInfinity(result)) { throw new FormatException("Invalid number"); } return result; }; Func<int> func3 = delegate { if (!int.TryParse(a[i++], out var result)) { throw new FormatException("Invalid integer"); } return result; }; return new MenuPreset { god = func(), noCd = func(), maxHp = func(), lockOn = func(), projectiles = func(), rapid = func(), reload = func(), secondary = func(), special = func(), markers = func(), teleporter = func(), chests = func(), shrines = func(), drops = func(), shops = func(), converters = func(), drones = func(), misc = func(), portals = func(), guaranteed = func(), summons = func(), acridTargets = func(), acridRange = func(), attack = Mathf.Clamp(func2(), 1f, 5f), move = Mathf.Clamp(func2(), 1f, 5f), damage = Mathf.Clamp(func2(), 1f, 100000f), difficulty = Mathf.Clamp(func2(), 0f, 50f), tp = Mathf.Clamp(func2(), 0.25f, 10f), lockDistance = Mathf.Clamp(func2(), 10f, 250f), lockAngle = Mathf.Clamp(func2(), 5f, 90f), tracking = Mathf.Clamp(func2(), 5f, 100f), rapidInterval = Mathf.Clamp(func2(), 0.02f, 0.25f), jumpHeight = (flag ? Mathf.Clamp(func2(), 0.5f, 10f) : 1f), jumps = Mathf.Clamp(func3(), 0, 11), spawnPressure = (flag ? Mathf.Clamp(func3(), 0, 3) : 0) }; } catch (Exception ex) { lastSubsystemError = "Preset validation: " + ex.Message; status = "Preset data is invalid; see Safety"; return null; } } private bool CustomPresetExists(int slot) { return !string.IsNullOrWhiteSpace(((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Data", "", (ConfigDescription)null).Value); } private void SaveCustomPreset(int slot) { slot = Mathf.Clamp(slot, 1, 3); string text = (string.IsNullOrWhiteSpace(presetName) ? ("Custom Slot " + slot) : presetName.Trim()); string value = SerializePreset(CapturePreset()); ConfigEntry<string> obj = ((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Name", "Custom Slot " + slot, (ConfigDescription)null); ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Data", "", (ConfigDescription)null); obj.Value = text; val.Value = value; ((BaseUnityPlugin)this).Config.Save(); if (DeserializePreset(val.Value) == null) { lastSubsystemError = "Preset save verification failed for slot " + slot; status = lastSubsystemError; return; } presetName = text; presetLoadedSlot = slot; presetOverwriteConfirmUntil = 0f; status = "Saved preset slot " + slot + ": " + text; } private void ApplyCustomPreset(int slot) { slot = Mathf.Clamp(slot, 1, 3); ((BaseUnityPlugin)this).Config.Reload(); string value = ((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Name", "Custom Slot " + slot, (ConfigDescription)null).Value; string value2 = ((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Data", "", (ConfigDescription)null).Value; MenuPreset menuPreset = DeserializePreset(value2); if (menuPreset == null) { status = (string.IsNullOrWhiteSpace(value2) ? ("Custom slot " + slot + " is empty") : ("Custom slot " + slot + " contains invalid data")); } else { ApplyPreset(menuPreset, value); } } private void ResetCustomPreset(int slot) { presetOverwriteConfirmUntil = 0f; presetLoadedSlot = slot; ((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Name", "Custom Slot " + slot, (ConfigDescription)null).Value = "Custom Slot " + slot; ((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Data", "", (ConfigDescription)null).Value = ""; ((BaseUnityPlugin)this).Config.Save(); presetName = "Custom Slot " + slot; status = "Reset custom slot " + slot; } private MenuPreset BuiltInPreset(string name) { MenuPreset menuPreset = CapturePreset(); menuPreset.god = false; menuPreset.noCd = false; menuPreset.maxHp = false; menuPreset.lockOn = false; menuPreset.projectiles = true; menuPreset.rapid = false; menuPreset.markers = true; menuPreset.guaranteed = false; menuPreset.summons = false; menuPreset.acridTargets = false; menuPreset.acridRange = false; menuPreset.attack = 1f; menuPreset.move = 1f; menuPreset.damage = 1f; menuPreset.difficulty = 1f; menuPreset.tp = 1f; menuPreset.jumps = 0; switch (name) { case "Practice": menuPreset.god = true; menuPreset.noCd = true; menuPreset.maxHp = true; menuPreset.lockOn = true; menuPreset.damage = 5f; menuPreset.move = 2f; menuPreset.jumps = 3; break; case "OP Showcase": menuPreset.god = true; menuPreset.noCd = true; menuPreset.maxHp = true; menuPreset.lockOn = true; menuPreset.rapid = true; menuPreset.reload = true; menuPreset.secondary = true; menuPreset.special = true; menuPreset.attack = 5f; menuPreset.move = 3f; menuPreset.damage = 100f; menuPreset.jumps = 5; menuPreset.guaranteed = true; break; case "Extreme Challenge": menuPreset.difficulty = 25f; menuPreset.tp = 1f; menuPreset.markers = false; break; case "Drone Commander": menuPreset.summons = true; menuPreset.guaranteed = true; menuPreset.move = 1.5f; break; } return menuPreset; } private void ResetLegacyPersonalPresetsOnce() { ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Migration", "ClearedPersonalPresetsFor4511", false, (ConfigDescription)null); if (!val.Value) { for (int i = 1; i <= 3; i++) { ((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + i + "Name", "Custom Slot " + i, (ConfigDescription)null).Value = "Custom Slot " + i; ((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + i + "Data", "", (ConfigDescription)null).Value = ""; } val.Value = true; ((BaseUnityPlugin)this).Config.Save(); presetName = "Custom Slot 1"; customPresetSlot = 1; presetLoadedSlot = -1; status = "Three empty custom preset slots are ready"; } } private void LoadLootRunSettings() { lootContainers = ((BaseUnityPlugin)this).Config.Bind<bool>("Loot Run", "Include Containers", true, (ConfigDescription)null).Value; lootShops = ((BaseUnityPlugin)this).Config.Bind<bool>("Loot Run", "Include Shops", true, (ConfigDescription)null).Value; lootDrones = ((BaseUnityPlugin)this).Config.Bind<bool>("Loot Run", "Include Drones", true, (ConfigDescription)null).Value; lootEquipmentBarrels = ((BaseUnityPlugin)this).Config.Bind<bool>("Loot Run", "Include Equipment Barrels", true, (ConfigDescription)null).Value; lootRunExclusions = ((BaseUnityPlugin)this).Config.Bind<string>("Loot Run", "Excluded Names", "", "Comma-separated internal name fragments to skip during Loot Run.").Value ?? ""; } private void SaveLootRunSettings() { ((BaseUnityPlugin)this).Config.Bind<bool>("Loot Run", "Include Containers", true, (ConfigDescription)null).Value = lootContainers; ((BaseUnityPlugin)this).Config.Bind<bool>("Loot Run", "Include Shops", true, (ConfigDescription)null).Value = lootShops; ((BaseUnityPlugin)this).Config.Bind<bool>("Loot Run", "Include Drones", true, (ConfigDescription)null).Value = lootDrones; ((BaseUnityPlugin)this).Config.Bind<bool>("Loot Run", "Include Equipment Barrels", true, (ConfigDescription)null).Value = lootEquipmentBarrels; ((BaseUnityPlugin)this).Config.Bind<string>("Loot Run", "Excluded Names", "", "Comma-separated internal name fragments to skip during Loot Run.").Value = lootRunExclusions ?? ""; ((BaseUnityPlugin)this).Config.Save(); status = "Loot Run filters saved"; } private void ResetLootRunFilters() { lootContainers = true; lootShops = true; lootDrones = true; lootEquipmentBarrels = true; lootRunExclusions = ""; SaveLootRunSettings(); status = "Loot Run filters restored to safe defaults"; } private bool LootRunNameExcluded(string searchable) { if (string.IsNullOrWhiteSpace(lootRunExclusions)) { return false; } string[] array = lootRunExclusions.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim().ToLowerInvariant(); if (text.Length > 0 && searchable.Contains(text)) { return true; } } return false; } private void Awake() { LoadLootRunSettings(); ResetLegacyPersonalPresetsOnce(); Stage.onStageStartGlobal += OnSilent55StageStarted; try { int num = AppDomain.CurrentDomain.GetAssemblies().Count((Assembly a) => string.Equals(a.GetName().Name, "Silent55ModMenu", StringComparison.OrdinalIgnoreCase)); if (num > 1) { status = "Duplicate Silent55 assemblies detected"; ((BaseUnityPlugin)this).Logger.LogWarning((object)(status + ": " + num)); } } catch { } } private void SafeUpdate(string n, Action a) { try { a(); } catch (Exception ex) { lastSubsystemError = n + ": " + ex.GetType().Name + " - " + ex.Message; if (!subsystemErrorCooldowns.TryGetValue(n, out var value) || Time.unscaledTime - value >= 10f) { subsystemErrorCooldowns[n] = Time.unscaledTime; ((BaseUnityPlugin)this).Logger.LogError((object)("Silent55 " + lastSubsystemError + "\n" + ex.StackTrace)); status = n + " error; see Safety diagnostics"; } else { suppressedErrorCount++; } } } private void ResetEverythingSafe() { godMode = false; noCooldown = false; maxPersonal = false; lockOn = false; projectileTracking = false; rapidFire = false; rapidFireReload = true; rapidFireSecondary = true; rapidFireSpecial = false; markers = false; showMarkerDistance = false; empoweredSummons = false; guaranteedShrineChance = false; acridUnlimitedTargets = false; acridUnlimitedRange = false; practiceFreeze = false; practiceDisableAI = false; practiceFullPause = false; attackMultiplier = 1f; moveMultiplier = 1f; damageMultiplier = 1f; jumpHeightMultiplier = 1f; extraJumps = 0; difficultyRate = 1f; teleporterRate = 1f; spawnPressureMode = 0; cleanupConfirmUntil = 0f; unlockConfirmUntil = 0f; presetOverwriteConfirmUntil = 0f; requestQueue.Clear(); pendingConnection = null; pendingRequest = null; requestCooldowns.Clear(); if (NetworkServer.active) { ApplyRunAction(1, 1f); ApplyRunAction(2, 1f); RefreshPracticeCache(); ApplyPracticeState(force: true); } RestoreAcridEpidemic(); DisableLockTracker(); if ((Object)(object)trackedHealth != (Object)null) { trackedHealth.godMode = false; } RestoreStats(); status = "All settings reset to safe defaults"; } private void Update() { if (Input.GetKeyDown((KeyCode)288)) { visible = !visible; } if (Time.unscaledTime >= nextNetworkInit) { nextNetworkInit = Time.unscaledTime + 1f; SafeUpdate("network", InitRequestNetwork); } SafeUpdate("run", UpdateRunControls); SafeUpdate("enemy limit", UpdateEnemyLimit); if ((Object)(object)Run.instance != (Object)(object)appliedRun) { previousRun = appliedRun; appliedRun = Run.instance; loadoutAppliedThisRun.Clear(); grantedLoadouts.Clear(); empoweredMinions.Clear(); requestQueue.Clear(); pendingConnection = null; pendingRequest = null; requestCooldowns.Clear(); if ((Object)(object)appliedRun == (Object)null) { godMode = false; noCooldown = false; practiceFreeze = false; practiceDisableAI = false; practiceFullPause = false; spawnPressureMode = 0; difficultyRate = 1f; teleporterRate = 1f; RestoreAcridEpidemic(); DisableLockTracker(); } } CharacterBody body = GetBody(); if ((Object)(object)body == (Object)null) { if ((Object)(object)tracked != (Object)null) { RestoreStats(); } return; } if ((Object)(object)body != (Object)(object)tracked) { RestoreStats(); Track(body); } SafeUpdate("loadouts", EnsureCharacterLoadout); if (guaranteedShrineChance && Time.unscaledTime >= nextShrineScan) { nextShrineScan = Time.unscaledTime + 1f; SafeUpdate("shrines", UpdateGuaranteedShrines); } if (IsCurrentCharacterAcrid() && (acridUnlimitedTargets || acridUnlimitedRange)) { SafeUpdate("acrid", UpdateAcridEpidemic); } else if (diseaseDefaultsCaptured) { RestoreAcridEpidemic(); } if (rapidFire) { SafeUpdate("rapid", UpdateRapidFire); } if (lockOn) { SafeUpdate("lock", UpdateLockOn); } else if ((Object)(object)silentTracker != (Object)null) { DisableLockTracker(); } if (NetworkServer.active && empoweredSummons && Time.unscaledTime >= nextSummonScan) { EmpowerOwnedMinions(body.master); nextSummonScan = Time.unscaledTime + 1f; } if (Input.GetKeyDown((KeyCode)287)) { godMode = !godMode; status = "God Mode " + (godMode ? "enabled" : "disabled"); } if (Input.GetKeyDown((KeyCode)286)) { noCooldown = !noCooldown; } SafeUpdate("practice", UpdatePracticeState); if (tab == 10 && visible) { SafeUpdate("safety counters", UpdateSafetyCounters); } ApplyGodMode(); if (noCooldown) { ResetSkills(body); } ApplyStats(body); } private string SaveKey() { LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); if (firstLocalUser != null && firstLocalUser.userProfile != null && !string.IsNullOrWhiteSpace(firstLocalUser.userProfile.name)) { string name = firstLocalUser.userProfile.name; ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", "LastProfileKey", "Default", (ConfigDescription)null).Value = name; return name; } return ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", "LastProfileKey", "Default", (ConfigDescription)null).Value; } private string EncodeText(string v) { return Convert.ToBase64String(Encoding.UTF8.GetBytes(v ?? "")); } private string DecodeText(string v) { try { return Encoding.UTF8.GetString(Convert.FromBase64String(v ?? "")); } catch { return ""; } } private string CaptureItems(Inventory inv) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 //IL_0037: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)inv == (Object)null) { return ""; } List<string> list = new List<string>(); foreach (PickupDef allPickup in PickupCatalog.allPickups) { if (allPickup != null && (int)allPickup.itemIndex != -1) { int itemCount = inv.GetItemCount(allPickup.itemIndex); if (itemCount > 0) { list.Add(allPickup.internalName + ":" + itemCount); } } } return string.Join(",", list.ToArray()); } private string CaptureCheckpoint() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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) CharacterBody body = GetBody(); Run instance = Run.instance; if ((Object)(object)body == (Object)null || (Object)(object)body.inventory == (Object)null || (Object)(object)instance == (Object)null) { return ""; } EquipmentIndex currentEquipmentIndex = body.inventory.currentEquipmentIndex; string v = (((int)currentEquipmentIndex != -1) ? ((Object)EquipmentCatalog.GetEquipmentDef(currentEquipmentIndex)).name : ""); string[] obj = new string[15] { EncodeText(CurrentCharacterKey()), null, null, null, null, null, null, null, null, null, null, null, null, null, null }; Scene activeScene = SceneManager.GetActiveScene(); obj[1] = EncodeText(((Scene)(ref activeScene)).name); obj[2] = EncodeText(v); obj[3] = EncodeText(CaptureItems(body.inventory)); obj[4] = body.master.money.ToString(); obj[5] = instance.GetRunStopwatch().ToString(CultureInfo.InvariantCulture); obj[6] = difficultyRate.ToString(CultureInfo.InvariantCulture); obj[7] = teleporterRate.ToString(CultureInfo.InvariantCulture); obj[8] = jumpHeightMultiplier.ToString(CultureInfo.InvariantCulture); obj[9] = moveMultiplier.ToString(CultureInfo.InvariantCulture); obj[10] = attackMultiplier.ToString(CultureInfo.InvariantCulture); obj[11] = damageMultiplier.ToString(CultureInfo.InvariantCulture); obj[12] = extraJumps.ToString(); obj[13] = (((Object)(object)TeamManager.instance != (Object)null) ? TeamManager.instance.GetTeamLevel((TeamIndex)1).ToString() : "1"); obj[14] = instance.stageClearCount.ToString(); return string.Join("|", obj); } private void CreateCheckpoint() { //IL_0139: 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 (!NetworkServer.active || (Object)(object)Run.instance == (Object)null) { status = "Start a host or solo run first"; return; } string value = CaptureCheckpoint(); if (string.IsNullOrEmpty(value)) { status = "Checkpoint capture failed"; return; } string text = SaveKey(); string value2 = ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", text + "_Primary", "", (ConfigDescription)null).Value; if (!string.IsNullOrEmpty(value2)) { ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", text + "_Backup", "", (ConfigDescription)null).Value = value2; ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", "Global_Backup", "", (ConfigDescription)null).Value = value2; } ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", text + "_Primary", "", (ConfigDescription)null).Value = value; ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", "Global_Primary", "", (ConfigDescription)null).Value = value; ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", "LastProfileKey", "Default", (ConfigDescription)null).Value = text; ((BaseUnityPlugin)this).Config.Save(); Scene activeScene = SceneManager.GetActiveScene(); status = "Checkpoint saved for " + text + " on " + ((Scene)(ref activeScene)).name; } private bool SetSavedStageClearCount(Run run, int value) { if ((Object)(object)run == (Object)null) { return false; } value = Mathf.Max(0, value); try { PropertyInfo property = typeof(Run).GetProperty("stageClearCount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanWrite) { property.SetValue(run, value, null); return run.stageClearCount == value; } FieldInfo fieldInfo = typeof(Run).GetField("stageClearCount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(Run).GetField("<stageClearCount>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); if (fieldInfo != null) { fieldInfo.SetValue(run, value); return run.stageClearCount == value; } } catch (Exception ex) { lastSubsystemError = "Stage progression restore: " + ex.Message; ((BaseUnityPlugin)this).Logger.LogError((object)("Silent55 " + lastSubsystemError)); } return false; } private bool RestoreCheckpoint(string raw) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Invalid comparison between Unknown and I4 //IL_00ff: 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_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Invalid comparison between Unknown and I4 //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(raw)) { return false; } string[] array = raw.Split('|'); if (array.Length < 14) { lastSubsystemError = "Checkpoint validation: incomplete data"; return false; } string text = DecodeText(array[0]); string text2 = DecodeText(array[1]); if (string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(text2)) { lastSubsystemError = "Checkpoint validation: missing survivor or stage"; return false; } Scene activeScene = SceneManager.GetActiveScene(); if (!string.Equals(text2, ((Scene)(ref activeScene)).name, StringComparison.OrdinalIgnoreCase)) { status = "Checkpoint stage does not match the active stage"; return false; } CharacterBody body = GetBody(); if ((Object)(object)body != (Object)null && !string.Equals(text, CurrentCharacterKey(), StringComparison.OrdinalIgnoreCase)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Silent55 saved survivor differs from selected survivor; restoring checkpoint to the selected survivor."); } if ((Object)(object)body == (Object)null || (Object)(object)body.inventory == (Object)null || (Object)(object)Run.instance == (Object)null) { return false; } foreach (PickupDef allPickup in PickupCatalog.allPickups) { if (allPickup != null && (int)allPickup.itemIndex != -1) { int itemCount = body.inventory.GetItemCount(allPickup.itemIndex); if (itemCount > 0) { body.inventory.RemoveItemPermanent(allPickup.itemIndex, itemCount); } } } string[] array2 = DecodeText(array[3]).Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text3 in array2) { string[] bits = text3.Split(':'); if (bits.Length == 2 && int.TryParse(bits[1], out var result)) { PickupDef val = PickupCatalog.allPickups.FirstOrDefault((Func<PickupDef, bool>)((PickupDef x) => x != null && x.internalName == bits[0])); if (val != null && (int)val.itemIndex != -1) { body.inventory.GiveItemPermanent(val.itemIndex, result); } } } string text4 = DecodeText(array[2]); EquipmentDef val2 = null; for (int num = 0; num < EquipmentCatalog.equipmentCount; num++) { EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef((EquipmentIndex)num); if ((Object)(object)equipmentDef != (Object)null && ((Object)equipmentDef).name == text4) { val2 = equipmentDef; break; } } if ((Object)(object)val2 != (Object)null) { body.inventory.SetEquipmentIndex(val2.equipmentIndex); } if (uint.TryParse(array[4], out var result2) && (Object)(object)body.master != (Object)null) { body.master.money = result2; } if (float.TryParse(array[5], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { Run.instance.SetRunStopwatch(result3); } if (float.TryParse(array[6], NumberStyles.Float, CultureInfo.InvariantCulture, out result3)) { difficultyRate = result3; } if (float.TryParse(array[7], NumberStyles.Float, CultureInfo.InvariantCulture, out result3)) { teleporterRate = result3; } if (float.TryParse(array[8], NumberStyles.Float, CultureInfo.InvariantCulture, out result3)) { jumpHeightMultiplier = result3; } if (float.TryParse(array[9], NumberStyles.Float, CultureInfo.InvariantCulture, out result3)) { moveMultiplier = result3; } if (float.TryParse(array[10], NumberStyles.Float, CultureInfo.InvariantCulture, out result3)) { attackMultiplier = result3; } if (float.TryParse(array[11], NumberStyles.Float, CultureInfo.InvariantCulture, out result3)) { damageMultiplier = result3; } if (int.TryParse(array[12], out var result4)) { extraJumps = result4; } if (int.TryParse(array[13], out result4) && (Object)(object)TeamManager.instance != (Object)null) { TeamManager.instance.SetTeamLevel((TeamIndex)1, (uint)Mathf.Max(1, result4)); } int result5 = 0; if (array.Length >= 15 && int.TryParse(array[14], out result5)) { if (!SetSavedStageClearCount(Run.instance, result5)) { status = "Checkpoint restored, but stage progression could not be restored"; return false; } trackedStageClearCount = result5; Run.instance.RecalculateDifficultyCoefficent(); } status = "Checkpoint restored at Stage " + (Run.instance.stageClearCount + 1); return true; } private string GetSavedCheckpoint(bool allowBackup, out bool usedBackup) { usedBackup = false; string text = SaveKey(); string value = ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", text + "_Primary", "", (ConfigDescription)null).Value; if (IsCheckpointHeaderValid(value)) { return value; } if (allowBackup) { value = ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", text + "_Backup", "", (ConfigDescription)null).Value; if (IsCheckpointHeaderValid(value)) { usedBackup = true; return value; } } value = ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", "Global_Primary", "", (ConfigDescription)null).Value; if (IsCheckpointHeaderValid(value)) { return value; } if (allowBackup) { value = ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", "Global_Backup", "", (ConfigDescription)null).Value; if (IsCheckpointHeaderValid(value)) { usedBackup = true; return value; } } return ""; } private bool IsCheckpointHeaderValid(string raw) { if (string.IsNullOrWhiteSpace(raw)) { return false; } string[] array = raw.Split('|'); if (array.Length < 14) { return false; } string value = DecodeText(array[0]); string text = DecodeText(array[1]); if (!string.IsNullOrWhiteSpace(value) && !string.IsNullOrWhiteSpace(text)) { return (Object)(object)SceneCatalog.FindSceneDef(text) != (Object)null; } return false; } private string SavedRunPreview() { bool usedBackup; string savedCheckpoint = GetSavedCheckpoint(allowBackup: true, out usedBackup); if (string.IsNullOrEmpty(savedCheckpoint)) { return "No usable saved run"; } string[] array = savedCheckpoint.Split('|'); float result = 0f; float.TryParse(array[5], NumberStyles.Float, CultureInfo.InvariantCulture, out result); SceneDef val = SceneCatalog.FindSceneDef(DecodeText(array[1])); string text = (((Object)(object)val != (Object)null) ? Language.GetString(val.nameToken) : DecodeText(array[1])); if (string.IsNullOrWhiteSpace(text) || text == val.nameToken) { text = DecodeText(array[1]); } int result2 = 0; if (array.Length >= 15) { int.TryParse(array[14], out result2); } return (usedBackup ? "Backup | " : "") + text + " | Stage " + (result2 + 1) + " | " + FormatClock(result); } private void LoadSavedRun() { if ((Object)(object)Run.instance != (Object)null) { status = "Finish or leave the current run before loading a saved run"; return; } if (!NetworkServer.active || (Object)(object)PreGameController.instance == (Object)null) { status = "Open a solo or hosted character-select lobby first"; return; } bool usedBackup; string savedCheckpoint = GetSavedCheckpoint(allowBackup: true, out usedBackup); if (string.IsNullOrEmpty(savedCheckpoint)) { status = "No usable saved run found"; return; } string[] array = savedCheckpoint.Split('|'); string text = DecodeText(array[1]); SceneDef val = SceneCatalog.FindSceneDef(text); if ((Object)(object)val == (Object)null) { status = "Saved map is unavailable: " + text; return; } pendingCheckpointRaw = savedCheckpoint; pendingCheckpointRestore = true; FieldInfo field = typeof(Run).GetField("cvRunSceneOverride", BindingFlags.Static | BindingFlags.NonPublic); StringConVar val2 = (StringConVar)((field != null) ? /*isinst with value type is only supported in some contexts*/: null); if (val2 == null) { pendingCheckpointRaw = ""; pendingCheckpointRestore = false; status = "Saved-map override is unavailable"; lastSubsystemError = status; return; } ((BaseConVar)val2).SetString(val.cachedName); string text2 = ((BaseConVar)val2).GetString(); if (!string.Equals(text2, val.cachedName, StringComparison.OrdinalIgnoreCase)) { pendingCheckpointRaw = ""; pendingCheckpointRestore = false; status = "Saved-map override verification failed"; lastSubsystemError = status + ": expected " + val.cachedName + ", got " + text2; } else { PreGameController.instance.StartLaunch(); status = "Loading saved map: " + val.cachedName + (usedBackup ? " (backup)" : ""); } } private void ClearSceneOverride() { try { FieldInfo field = typeof(Run).GetField("cvRunSceneOverride", BindingFlags.Static | BindingFlags.NonPublic); StringConVar val = (StringConVar)((field != null) ? /*isinst with value type is only supported in some contexts*/: null); if (val != null) { ((BaseConVar)val).SetString(""); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Silent55 could not clear saved-map override: " + ex.Message)); } } private void OnSilent55StageStarted(Stage stage) { if (pendingCheckpointRestore && !string.IsNullOrEmpty(pendingCheckpointRaw)) { ClearSceneOverride(); if (pendingRestoreCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(pendingRestoreCoroutine); } pendingRestoreCoroutine = ((MonoBehaviour)this).StartCoroutine(RestoreSavedRunWhenReady()); } } private IEnumerator RestoreSavedRunWhenReady() { float timeout = Time.unscaledTime + 25f; string raw = pendingCheckpointRaw; Scene activeScene; while (Time.unscaledTime < timeout) { if (NetworkServer.active && (Object)(object)Run.instance != (Object)null && (Object)(object)Stage.instance != (Object)null) { CharacterBody body = GetBody(); if ((Object)(object)body != (Object)null && (Object)(object)body.inventory != (Object)null && RestoreCheckpoint(raw)) { pendingCheckpointRaw = ""; pendingCheckpointRestore = false; pendingRestoreCoroutine = null; Plugin plugin = this; activeScene = SceneManager.GetActiveScene(); plugin.status = "Saved run restored on " + ((Scene)(ref activeScene)).name; yield break; } } yield return (object)new WaitForSecondsRealtime(0.5f); } string text = ""; try { string[] array = raw.Split('|'); if (array.Length > 1) { text = DecodeText(array[1]); } } catch { } activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; pendingCheckpointRaw = ""; pendingCheckpointRestore = false; pendingRestoreCoroutine = null; lastSubsystemError = "Saved-run restore timed out. Saved map: " + text + "; active map: " + name + "; body: " + ((Object)(object)GetBody() != (Object)null); status = lastSubsystemError; ((BaseUnityPlugin)this).Logger.LogError((object)("Silent55 " + lastSubsystemError)); } private void LoadCheckpoint() { if (!NetworkServer.active || (Object)(object)Run.instance == (Object)null) { status = "Start the matching survivor and stage first"; return; } string value = ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", SaveKey() + "_Primary", "", (ConfigDescription)null).Value; if (!RestoreCheckpoint(value)) { value = ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", SaveKey() + "_Backup", "", (ConfigDescription)null).Value; if (!RestoreCheckpoint(value)) { status = "No usable checkpoint found"; } else { status = "Primary failed; backup restored"; } } } private void DeleteCheckpoint() { pendingCheckpointRaw = ""; pendingCheckpointRestore = false; ClearSceneOverride(); string text = SaveKey(); ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", text + "_Primary", "", (ConfigDescription)null).Value = ""; ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", text + "_Backup", "", (ConfigDescription)null).Value = ""; ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", "Global_Primary", "", (ConfigDescription)null).Value = ""; ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", "Global_Backup", "", (ConfigDescription)null).Value = ""; ((BaseUnityPlugin)this).Config.Save(); status = "Saved checkpoints deleted"; } private void SaveAndQuit() { if (Time.unscaledTime > saveQuitConfirmUntil) { saveQuitConfirmUntil = Time.unscaledTime + 5f; status = "Press Save and Quit again within 5 seconds"; return; } CreateCheckpoint(); if (!status.StartsWith("Checkpoint saved")) { return; } saveQuitConfirmUntil = 0f; status = "Saved; returning to main menu"; Console instance = Console.instance; if (!((Object)(object)instance != (Object)null)) { return; } MethodInfo methodInfo = ((object)instance).GetType().GetMethods().FirstOrDefault((MethodInfo x) => x.Name == "SubmitCmd" && x.GetParameters().Length >= 2); if (methodInfo != null) { ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; for (int num = 0; num < array.Length; num++) { array[num] = ((parameters[num].ParameterType == typeof(string)) ? "disconnect" : null); } methodInfo.Invoke(instance, array); } } private float SpawnPressureMultiplier() { if (spawnPressureMode != 0) { if (spawnPressureMode != 1) { if (spawnPressureMode != 2) { return 8f; } return 4f; } return 2f; } return 1f; } private void UpdateEnemyLimit() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Invalid comparison between Unknown and I4 if (!NetworkServer.active || Time.unscaledTime < nextSpawnPressureApply) { return; } nextSpawnPressureApply = Time.unscaledTime + 0.5f; if (spawnPressureMode == 0) { return; } float num = SpawnPressureMultiplier(); foreach (CombatDirector instances in CombatDirector.instancesList) { if (!((Object)(object)instances == (Object)null) && ((Behaviour)instances).enabled && (int)instances.teamIndex == 2) { instances.monsterCredit += Time.deltaTime * instances.creditMultiplier * (num - 1f); instances.monsterSpawnTimer = Mathf.Min(instances.monsterSpawnTimer, Mathf.Max(0.1f, 1f / num)); } } } private void InitRequestNetwork() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown if (NetworkServer.active && !serverHandlerRegistered) { NetworkServer.RegisterHandler((short)28550, new NetworkMessageDelegate(OnServerRequest)); serverHandlerRegistered = true; } NetworkClient val = (((Object)(object)NetworkManager.singleton != (Object)null) ? NetworkManager.singleton.client : null); if (val != null && val.isConnected && val != registeredClient) { val.RegisterHandler((short)28551, new NetworkMessageDelegate(OnClientResponse)); registeredClient = val; } } private string FormatClock(float seconds) { seconds = Mathf.Max(0f, seconds); int num = Mathf.FloorToInt(seconds); return (num / 60).ToString("00") + ":" + (num % 60).ToString("00"); } private void UpdateRunControls() { //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Expected O, but got Unknown if (!NetworkServer.active) { return; } Run instance = Run.instance; if ((Object)(object)instance != (Object)(object)trackedRun) { trackedRun = instance; lastRunTime = (((Object)(object)instance != (Object)null) ? instance.GetRunStopwatch() : 0f); realSessionTime = lastRunTime; trackedStageClearCount = (((Object)(object)instance != (Object)null) ? instance.stageClearCount : (-1)); nextDifficultyRecalc = 0f; } if ((Object)(object)instance != (Object)null) { float runStopwatch = instance.GetRunStopwatch(); float num = Mathf.Clamp(runStopwatch - lastRunTime, 0f, 0.25f); if (instance.stageClearCount != trackedStageClearCount) { trackedStageClearCount = instance.stageClearCount; lastRunTime = runStopwatch; num = 0f; nextDifficultyRecalc = 0f; } if (num > 0f) { realSessionTime += num; if (!Mathf.Approximately(difficultyRate, 1f)) { float num2 = runStopwatch + num * (Mathf.Clamp(difficultyRate, 0f, 50f) - 1f); instance.SetRunStopwatch(Mathf.Max(0f, num2)); } } lastRunTime = instance.GetRunStopwatch(); if (!Mathf.Approximately(difficultyRate, 1f) && Time.unscaledTime >= nextDifficultyRecalc) { nextDifficultyRecalc = Time.unscaledTime + 0.25f; instance.RecalculateDifficultyCoefficent(); } } else { realSessionTime = 0f; trackedStageClearCount = -1; } if (!(Time.unscaledTime >= nextZoneScan)) { return; } nextZoneScan = Time.unscaledTime + 1f; foreach (HoldoutZoneController instances in InstanceTracker.GetInstancesList<HoldoutZoneController>()) { if ((Object)(object)instances != (Object)null && hookedZones.Add(instances)) { instances.calcChargeRate += new CalcChargeRateDelegate(ScaleChargeRate); } } hookedZones.RemoveWhere((HoldoutZoneController z) => (Object)(object)z == (Object)null); } private void SyncCombatDirectors(Run run, float extraDelta) { } private void UpdateGuaranteedShrines() { if (!NetworkServer.active) { return; } ShrineChanceBehavior[] array = Object.FindObjectsOfType<ShrineChanceBehavior>(); foreach (ShrineChanceBehavior val in array) { if (!((Object)(object)val == (Object)null) && guaranteedShrineChance) { val.failureChance = 0f; val.failureWeight = 0f; } } } private void ToggleOrRequestShrineChance() { if (NetworkServer.active) { guaranteedShrineChance = !guaranteedShrineChance; ApplyRunAction(6, guaranteedShrineChance ? 1f : 0f); } else { RequestOrApply(6, guaranteedShrineChance ? 0f : 1f); } } private void ScaleChargeRate(ref float rate) { if (rate > 0f) { rate *= teleporterRate; } } private string ActionName(int action, float value) { return action switch { 1 => "Difficulty time scaling " + value.ToString("0.00") + "x", 2 => "Teleporter rate " + value.ToString("0.00") + "x", 3 => "Instant teleporter charge", 4 => "Default OP loadout", 5 => "Empowered Summons", _ => "Shrine of Chance " + ((value >= 0.5f) ? "GUARANTEED" : "NORMAL"), }; } private void RequestOrApply(int action, float value) { if (NetworkServer.active) { ApplyRunAction(action, value); return; } NetworkClient val = (((Object)(object)NetworkManager.singleton != (Object)null) ? NetworkManager.singleton.client : null); if (val == null || !val.isConnected) { status = "Not connected to a compatible host"; return; } LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); string requester = ((firstLocalUser != null && (Object)(object)firstLocalUser.currentNetworkUser != (Object)null) ? firstLocalUser.currentNetworkUser.userName : "Client"); val.Send((short)28550, (MessageBase)(object)new RunControlRequest { action = action, value = value, requester = requester, version = "4.5.20" }); status = "Request sent to host: " + ActionName(action, value); } private void ApplyRunAction(int action, float value) { if (!NetworkServer.active) { status = "Host or single-player required"; return; } switch (action) { case 1: difficultyRate = Mathf.Clamp(value, 0f, 50f); if ((Object)(object)Run.instance != (Object)null) { lastRunTime = Run.instance.GetRunStopwatch(); } nextDifficultyRecalc = 0f; status = "Difficulty rate set to " + difficultyRate.ToString("0.00") + "x"; break; case 2: teleporterRate = Mathf.Clamp(value, 0.25f, 10f); status = "Teleporter rate set to " + teleporterRate.ToString("0.00") + "x"; break; case 6: guaranteedShrineChance = value >= 0.5f; UpdateGuaranteedShrines(); status = "Shrine of Chance " + (guaranteedShrineChance ? "guaranteed" : "normal"); break; case 3: { TeleporterInteraction instance = TeleporterInteraction.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.holdoutZoneController == (Object)null) { status = "No active teleporter found"; break; } instance.holdoutZoneController.FullyChargeHoldoutZone(); status = "Teleporter fully charged"; break; } } } private void OnServerRequest(NetworkMessage netMsg) { RunControlRequest runControlRequest = netMsg.ReadMessage<RunControlRequest>(); if (runControlRequest.version != "4.5.20") { netMsg.conn.Send((short)28551, (MessageBase)(object)new RunControlResponse { approved = false, message = "Silent55 version mismatch. Both players need v4.5.20" }); return; } int key = ((netMsg.conn != null) ? netMsg.conn.connectionId : (-1)); if (requestCooldowns.TryGetValue(key, out var value) && Time.unscaledTime - value < 1.5f) { netMsg.conn.Send((short)28551, (MessageBase)(object)new RunControlResponse { approved = false, message = "Please wait before sending another request" }); return; } requestCooldowns[key] = Time.unscaledTime; if (autoApproveRequests) { bool flag = ((runControlRequest.action == 4) ? ApplyRequestedLoadout(netMsg.conn) : ((runControlRequest.action == 5) ? ApplyRequestedSummons(netMsg.conn) : ApplyApprovedRunAction(runControlRequest.action, runControlRequest.value))); string text = (flag ? ("Host auto-approved: " + ActionName(runControlRequest.action, runControlRequest.value)) : "Request could not be applied"); netMsg.conn.Send((short)28551, (MessageBase)(object)new RunControlResponse { approved = flag, message = text }); AddRequestHistory(runControlRequest.requester + " - " + text); } else if (pendingRequest == null) { pendingConnection = netMsg.conn; pendingRequest = runControlRequest; status = runControlRequest.requester + " requested " + ActionName(runControlRequest.action, runControlRequest.value); } else { requestQueue.Enqueue(new PendingHostRequest { connection = netMsg.conn, request = runControlRequest }); status = "Queued request from " + runControlRequest.requester + " (" + requestQueue.Count + " waiting)"; } } private bool ApplyApprovedRunAction(int action, float value) { ApplyRunAction(action, value); return true; } private void AddRequestHistory(string text) { requestHistory.Insert(0, DateTime.Now.ToString("HH:mm:ss") + " " + text); if (requestHistory.Count > 20) { requestHistory.RemoveAt(requestHistory.Count - 1); } } private void LoadNextRequest() { pendingConnection = null; pendingRequest = null; while (requestQueue.Count > 0 && pendingRequest == null) { PendingHostRequest pendingHostRequest = requestQueue.Dequeue(); if (pendingHostRequest != null && pendingHostRequest.connection != null && pendingHostRequest.request != null) { pendingConnection = pendingHostRequest.connection; pendingRequest = pendingHostRequest.request; } } } private void ResolvePending(bool approve) { if (pendingRequest != null) { string requester = pendingRequest.requester; string text = ActionName(pendingRequest.action, pendingRequest.value); bool flag = false; if (approve) { flag = ((pendingRequest.action == 4) ? ApplyRequestedLoadout(pendingConnection) : ((pendingRequest.action == 5) ? ApplyRequestedSummons(pendingConnection) : ApplyApprovedRunAction(pendingRequest.action, pendingRequest.value))); } string text2 = ((approve && flag) ? ("Host approved: " + text) : (approve ? "Request could not be applied" : ("Host rejected: " + text))); if (pendingConnection != null) { pendingConnection.Send((short)28551, (MessageBase)(object)new RunControlResponse { approved = (approve && flag), message = text2 }); } AddRequestHistory(requester + " - " + text2); LoadNextRequest(); status = ((pendingRequest != null) ? (pendingRequest.requester + " requested " + ActionName(pendingRequest.action, pendingRequest.value)) : text2); } } private void ResolveAllRequests(bool approve) { int num = 0; while (pendingRequest != null) { ResolvePending(approve); num++; } status = (approve ? "Approved " : "Rejected ") + num + " request(s)"; } private void ClearRequestHistory() { requestHistory.Clear(); status = "Request history cleared"; } private void OnClientResponse(NetworkMessage netMsg) { RunControlResponse runControlResponse = netMsg.ReadMessage<RunControlResponse>(); status = runControlResponse.message; } private string CurrentCharacterKey() { CharacterBody body = GetBody(); if (!((Object)(object)body != (Object)null)) { return "NO_CHARACTER"; } return body.baseNameToken; } private string CurrentCharacterName() { CharacterBody body = GetBody(); if ((Object)(object)body == (Object)null) { return "No active character"; } string displayName = body.GetDisplayName(); if (!string.IsNullOrEmpty(displayName)) { return displayName; } return ((Object)((Component)body).gameObject).name; } private void EnsureCharacterLoadout() { string text = CurrentCharacterKey(); if (!(text == "NO_CHARACTER") && !(text == loadedLoadoutCharacter)) { loadedLoadoutCharacter = text; if (!opLoadouts.ContainsKey(text)) { LoadCharacterLoadout(text); } } } private string LoadoutConfigKey(string key) { return "Loadout_" + key.Replace(".", "_").Replace(" ", "_"); } private void AddDefaultItem(List<LoadoutEntry> list, int count, params string[] names) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) PickupDef def = null; foreach (string text in names) { string q = text.ToLowerInvariant(); def = PickupCatalog.allPickups.FirstOrDefault((Func<PickupDef, bool>)((PickupDef x) => x != null && (int)x.itemIndex != -1 && ((x.internalName ?? "").ToLowerInvariant().Contains(q) || PickupName(x).ToLowerInvariant().Contains(q)))); if (def != null) { break; } } if (def != null) { LoadoutEntry loadoutEntry = list.Find((LoadoutEntry e) => e.pickup == def.pickupIndex); if (loadoutEntry != null) { loadoutEntry.count += count; return; } list.Add(new LoadoutEntry { pickup = def.pickupIndex, count = count }); } } private void AddDefaultEquipment(List<LoadoutEntry> list, params string[] names) { //IL_0058: 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) PickupDef val = null; foreach (string text in names) { string q = text.ToLowerInvariant(); val = PickupCatalog.allPickups.FirstOrDefault((Func<PickupDef, bool>)((PickupDef x) => x != null && (int)x.equipmentIndex != -1 && ((x.internalName ?? "").ToLowerInvariant().Contains(q) || PickupName(x).ToLowerInvariant().Contains(q)))); if (val != null) { break; } } if (val != null) { list.Add(new LoadoutEntry { pickup = val.pickupIndex, count = 1 }); } } private List<LoadoutEntry> BuildSilent55Default(string key) { List<LoadoutEntry> list = new List<LoadoutEntry>(); AddDefaultItem(list, 10, "syringe", "soldier's syringe"); AddDefaultItem(list, 10, "critglasses", "lens-maker"); AddDefaultItem(list, 10, "hoof", "paul's goat"); AddDefaultItem(list, 5, "feather", "hopoo feather"); AddDefaultItem(list, 10, "bear", "tougher times"); AddDefaultItem(list, 5, "missile", "atg missile"); AddDefaultItem(list, 3, "clover", "57 leaf"); AddDefaultItem(list, 3, "alienhead", "alien head"); AddDefaultItem(list, 2, "behemoth", "brilliant behemoth"); AddDefaultItem(list, 1, "extrALife", "dio's best friend"); AddDefaultItem(list, 5, "scythe", "harvester"); string text = key.ToLowerInvariant(); if (text.Contains("huntress")) { AddDefaultItem(list, 8, "ukulele"); AddDefaultItem(list, 8, "predatory"); AddDefaultItem(list, 6, "backupmag", "backup magazine"); } else if (text.Contains("loader")) { AddDefaultItem(list, 10, "crowbar"); AddDefaultItem(list, 10, "focuscrystal", "focus crystal"); AddDefaultItem(list, 5, "iceRing", "runald"); AddDefaultItem(list, 5, "fireRing", "kjaro"); } else if (text.Contains("engineer")) { AddDefaultItem(list, 20, "mushroom", "bustling fungus"); AddDefaultItem(list, 5, "nkuhana", "n'kuhana"); AddDefaultItem(list, 5, "aegis"); } else if (text.Contains("railgunner")) { AddDefaultItem(list, 20, "crowbar"); AddDefaultItem(list, 5, "laserScope", "laser scope"); AddDefaultItem(list, 8, "armorplate", "repulsion armor"); } else if (text.Contains("bandit")) { AddDefaultItem(list, 8, "crowbar"); AddDefaultItem(list, 8, "guillotine"); AddDefaultItem(list, 5, "brainstalk", "brainstalks"); } else if (text.Contains("merc")) { AddDefaultItem(list, 8, "predatory"); AddDefaultItem(list, 8, "scythe"); AddDefaultItem(list, 8, "focuscrystal", "focus crystal"); } else if (text.Contains("acrid") || text.Contains("croco")) { AddDefaultEquipment(list, "dronebackup", "the back-up"); AddDefaultItem(list, 1, "autocastequipment", "gesture of the drowned"); AddDefaultItem(list, 10, "fuelcell", "fuel cell"); AddDefaultItem(list, 10, "gasoline"); AddDefaultItem(list, 10, "wisp", "will-o"); AddDefaultItem(list, 8, "guillotine"); AddDefaultItem(list, 10, "bleedonhit", "tri-tip"); AddDefaultItem(list, 10, "missile", "atg missile"); AddDefaultItem(list, 5, "clover", "57 leaf"); AddDefaultItem(list, 3, "behemoth", "brilliant behemoth"); AddDefaultItem(list, 10, "bossdamage", "armor-piercing rounds"); AddDefaultItem(list, 3, "talisman", "soulbound catalyst"); } else if (text.Contains("captain")) { AddDefaultItem(list, 10, "bleedOnHit", "tri-tip"); AddDefaultItem(list, 8, "missile", "atg missile"); AddDefaultItem(list, 5, "clover"); } else if (text.Contains("treebot") || text.Contains("rex")) { AddDefaultItem(list, 10, "medkit"); AddDefaultItem(list, 8, "seed", "leeching seed"); AddDefaultItem(list, 5, "rejuvenation", "rejuvenation rack"); } else if (text.Contains("mage") || text.Contains("artificer")) { AddDefaultItem(list, 10, "crowbar"); AddDefaultItem(list, 8, "ignition", "ignition tank"); AddDefaultItem(list, 6, "backupmag", "backup magazine"); } else if (text.Contains("toolbot") || text.Contains("mul-t")) { AddDefaultItem(list, 10, "syringe"); AddDefaultItem(list, 8, "missile"); AddDefaultItem(list, 6, "fuelcell", "fuel cell"); } else if (text.Contains("void")) { AddDefaultItem(list, 10, "hoof"); AddDefaultItem(list, 8, "armorplate"); AddDefaultItem(list, 5, "rejuvenation"); } return list; } private void LoadCharacterLoadout(string key) { //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>("OP Loadouts", LoadoutConfigKey(key), "", "Internal pickup names and quantities for this character."); ConfigEntry<bool> val2 = ((BaseUnityPlugin)this).Config.Bind<bool>("OP Loadouts", LoadoutConfigKey(key) + "_Initialized", false, "Whether this character loadout has been initialized."); List<LoadoutEntry> list = new List<LoadoutEntry>(); if (!val2.Value) { list = BuildSilent55Default(key); opLoadouts[key] = list; val2.Value = true; SaveCharacterLoadout(); status = "Loaded Silent55 default for " + CurrentCharacterName(); return; } string value = val.Value; if (!string.IsNullOrEmpty(value)) { string[] array = value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { string[] bits = text.Split('|'); if (bits.Length == 2) { PickupDef val3 = PickupCatalog.allPickups.FirstOrDefault((Func<PickupDef, bool>)((PickupDef x) => x != null && x.internalName == bits[0])); if (val3 != null && int.TryParse(bits[1], out var result)) { list.Add(new LoadoutEntry { pickup = val3.pickupIndex, count = Mathf.Clamp(result, 1, 999) }); } } } } opLoadouts[key] = list; } private void SaveCharacterLoadout() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) string text = CurrentCharacterKey(); if (text == "NO_CHARACTER") { return; } EnsureCharacterLoadout(); List<string> list = new List<string>(); foreach (LoadoutEntry item in opLoadouts[text]) { PickupDef pickupDef = PickupCatalog.GetPickupDef(item.pickup); if (pickupDef != null) { list.Add(pickupDef.internalName + "|" + item.count); } } ((BaseUnityPlugin)this).Config.Bind<string>("OP Loadouts", LoadoutConfigKey(text), "", "Internal pickup names and quantities for this character.").Value = string.Join(";", list.ToArray()); ((BaseUnityPlugin)this).Config.Bind<bool>("OP Loadouts", LoadoutConfigKey(text) + "_Initialized", true, "Whether this character loadout has been initialized.").Value = true; ((BaseUnityPlugin)this).Config.Save(); status = "Saved OP loadout for " + CurrentCharacterName(); } private void RestoreDefaultLoadout() { string text = CurrentCharacterKey(); if (text == "NO_CHARACTER") { status = "Start a run first"; return; } opLoadouts[text] = BuildSilent55Default(text); SaveCharacterLoadout(); status = "Restored Silent55 default for " + CurrentCharacterName(); } private void AddSelectedToLoadout() { //IL_0001: 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) PickupDef pickupDef = PickupCatalog.GetPickupDef(selectedPickup); if (!IsSpawnablePickup(pickupDef)) { status = "Select an item in Spawner or OP Loadout first"; return; } string text = CurrentCharacterKey(); if (text == "NO_CHARACTER") { status = "Start a run first"; return; } EnsureCharacterLoadout(); LoadoutEntry loadoutEntry = opLoadouts[text].Find((LoadoutEntry e) => e.pickup == selectedPickup); if (loadoutEntry != null) { loadoutEntry.count = Mathf.Clamp(loadoutEntry.count + loadoutQuantity, 1, 999); } else { opLoadouts[text].Add(new LoadoutEntry { pickup = selectedPickup, count = Mathf.Clamp(loadoutQuantity, 1, 999) }); } SaveCharacterLoadout(); } private void RemoveLoadoutEntry(int index) { string key = CurrentCharacterKey(); EnsureCharacterLoadout(); if (opLoadouts.ContainsKey(key) && index >= 0 && index < opLoadouts[key].Count) { opLoadouts[key].RemoveAt(index); SaveCharacterLoadout(); } } private void ClearCharacterLoadout() { string key = CurrentCharacterKey(); EnsureCharacterLoadout(); if (opLoadouts.ContainsKey(key)) { opLoadouts[key].Clear(); SaveCharacterLoadout(); status = "Cleared OP loadout for " + CurrentCharacterName(); } } private bool ApplyLoadoutToBody(CharacterBody body, string key, string playerKey) { //IL_0094: 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_00ac: Invalid comparison between Unknown and I4 //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Invalid comparison between Unknown and I4 //IL_00b6: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)body == (Object)null || (Object)(object)body.inventory == (Object)null) { return false; } if (loadoutAppliedThisRun.Contains(playerKey)) { status = "OP loadout already applied to this player this run"; return false; } if (!opLoadouts.ContainsKey(key)) { LoadCharacterLoadout(key); } if (!opLoadouts.ContainsKey(key) || opLoadouts[key].Count == 0) { return false; } int num = 0; List<LoadoutEntry> list = new List<LoadoutEntry>(); foreach (LoadoutEntry item in opLoadouts[key]) { PickupDef pickupDef = PickupCatalog.GetPickupDef(item.pickup); if (pickupDef != null) { if ((int)pickupDef.itemIndex != -1) { body.inventory.GiveItemPermanent(pickupDef.itemIndex, item.count); list.Add(new LoadoutEntry { pickup = item.pickup, count = item.count }); num += item.count; } else if ((int)pickupDef.equipmentIndex != -1) { body.inventory.SetEquipmentIndex(pickupDef.equipmentIndex); } } } grantedLoadouts[playerKey] = list; loadoutAppliedThisRun.Add(playerKey); status = "Applied OP loadout (" + num + " stacks)"; return true; } private void RemoveSilent55Loadout() { //IL_007b: 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_0093: Invalid comparison between Unknown and I4 //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active) { status = "Host or single-player required"; return; } CharacterBody body = GetBody(); if ((Object)(object)body == (Object)null || (Object)(object)body.inventory == (Object)null) { status = "Start a run first"; return; } if (!grantedLoadouts.TryGetValue("local", out var value) || value.Count == 0) { status = "No recorded Silent55 loadout to remove"; return; } int num = 0; foreach (LoadoutEntry item in value) { PickupDef pickupDef = PickupCatalog.GetPickupDef(item.pickup); if (pickupDef != null && (int)pickupDef.itemIndex != -1) { int num2 = Mathf.Min(body.inventory.GetItemCount(pickupDef.itemIndex), item.count); if (num2 > 0) { body.inventory.RemoveItemPermanent(pickupDef.itemIndex, num2); num += num2; } } } grantedLoadouts.Remove("local"); loadoutAppliedThisRun.Remove("local"); status = "Removed " + num + " Silent55 item stacks"; } private void ApplyOrRequestCharacterLoadout() { if (NetworkServer.active) { CharacterBody body = GetBody(); if ((Object)(object)body == (Object)null) { status = "Start a run first"; } else { ApplyLoadoutToBody(body, CurrentCharacterKey(), "local"); } } else { RequestOrApply(4, 0f); } } private CharacterBody BodyForConnection(NetworkConnection conn) { if (conn == null) { return null; } foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) { if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.networkUser == (Object)null) && ((NetworkBehaviour)instance.networkUser).connectionToClient == conn && (Object)(object)instance.master != (Object)null) { return instance.master.GetBody(); } } return null; } private bool ApplyRequestedLoadout(NetworkConnection conn) { CharacterBody val = BodyForConnection(conn); if ((Object)(object)val == (Object)null) { status = "Requesting player body not found"; return false; } string baseNameToken = val.baseNameToken; if (!opLoadouts.ContainsKey(baseNameToken)) { LoadCharacterLoadout(baseNameToken); } return ApplyLoadoutToBody(val, baseNameToken, "conn:" + conn.connectionId); } private void GiveMinionItem(Inventory inv, int count, params string[] names) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)inv == (Object)null) { return; } foreach (string text in names) { string q = text.ToLowerInvariant(); PickupDef val = PickupCatalog.allPickups.FirstOrDefault((Func<PickupDef, bool>)((PickupDef x) => x != null && (int)x.itemIndex != -1 && ((x.internalName ?? "").ToLowerInvariant().Contains(q) || PickupName(x).ToLowerInvariant().Contains(q)))); if (val != null) { inv.GiveItemPermanent(val.itemIndex, count); break; } } } private bool IsOwnedMinion(CharacterMaster minion, CharacterMaster owner) { if ((Object)(object)minion != (Object)null && (Object)(object)owner != (Object)null && (Object)(object)minion.minionOwnership != (Object)null) { return (Object)(object)minion.minionOwnership.ownerMaster == (Object)(object)owner; } return false; } private int EmpowerOwnedMinions(CharacterMaster owner) { if (!NetworkServer.active || (Object)(object)owner == (Object)null) { return 0; } int num = 0; CharacterMaster[] array = Object.FindObjectsOfType<CharacterMaster>(); foreach (CharacterMaster val in array) { if (IsOwnedMinion(val, owner) && !((Object)(object)val.inventory == (Object)null) && !empoweredMinions.Contains(val)) { GiveMinionItem(val.inventory, 10, "syringe", "soldier's syringe"); GiveMinionItem(val.inventory, 10, "critglasses", "lens-maker"); GiveMinionItem(val.inventory, 10, "bleedonhit", "tri-tip"); GiveMinionItem(val.inventory, 8, "missile", "atg missile"); GiveMinionItem(val.inventory, 5, "clover", "57 leaf"); GiveMinionItem(val.inventory, 3, "behemoth", "brilliant behemoth"); GiveMinionItem(val.inventory, 10, "bossdamage", "armor-piercing rounds"); GiveMinionItem(val.inventory, 10, "bear", "tougher times"); empoweredMinions.Add(val); num++; } } if (num > 0) { status = "Empowered " + num + " owned summon(s)"; } return num; } private void ToggleOrRequestEmpoweredSummons() { if (NetworkServer.active) { empoweredSummons = !empoweredSummons; if (empoweredSummons) { EmpowerOwnedMinions(((Object)(object)GetBody() != (Object)null) ? GetBody().master : null); } status = "Empowered Summons " + (empoweredSummons ? "enabled" : "disabled"); } else { RequestOrApply(5, 1f); } } private bool ApplyRequestedSummons(NetworkConnection conn) { CharacterBody val = BodyForConnection(conn); if ((Object)(object)val == (Object)null || (Object)(object)val.master == (Object)null) { return false; } EmpowerOwnedMinions(val.master); return true; } private bool IsCurrentCharacterBandit() { return CurrentCharacterKey().ToLowerInvariant().Contains("bandit"); } private bool SupportsRapidFire() { if (!IsCurrentCharacterBandit()) { return IsCurrentCharacterAcrid(); } return true; } private void PrepareRapidSkill(GenericSkill skill, bool refill) { if (!((Object)(object)skill == (Object)null) && refill) { skill.stock = skill.maxStock; skill.rechargeStopwatch = 0f; skill.SetBlockedCooldownSkillState(false); } } private void TryRapidSkill(GenericSkill skill, ref float nextTime, bool held, bool refill) { if (held && !((Object)(object)skill == (Object)null) && !(Time.unscaledTime < nextTime)) { PrepareRapidSkill(skill, refill); if (skill.ExecuteIfReady()) { nextTime = Time.unscaledTime + rapidFireInterval; } else { nextTime = Time.unscaledTime + Mathf.Min(0.03f, rapidFireInterval); } } } private void UpdateRapidFire() { if (!rapidFire || !SupportsRapidFire()) { return; } CharacterBody body = GetBody(); if (!((Object)(object)body == (Object)null) && !((Object)(object)body.inputBank == (Object)null) && !((Object)(object)body.skillLocator == (Object)null)) { InputBankTest inputBank = body.inputBank; SkillLocator skillLocator = body.skillLocator; TryRapidSkill(skillLocator.primary, ref nextPrimaryFire, inputBank.skill1.down, rapidFireReload); if (rapidFireSecondary) { TryRapidSkill(skillLocator.secondary, ref nextSecondaryFire, inputBank.skill2.down, refill: true); } if (rapidFireSpecial) { TryRapidSkill(skillLocator.special, ref nextSpecialFire, inputBank.skill4.down, refill: true); } } } private bool IsCurrentCharacterAcrid() { CharacterBody body = GetBody(); if ((Object)(object)body == (Object)null) { return false; } string text = (CurrentCharacterKey() + " " + ((Object)((Component)body).gameObject).name + " " + CurrentCharacterName()).ToLowerInvariant(); if (!text.Contains("acrid")) { return text.Contains("croco"); } return true; } private void CaptureDiseaseDefaults() { if (!diseaseDefaultsCaptured) { originalDiseaseBounces = Disease.maxBounces; originalDiseaseBounceRange = Disease.bounceRange; originalDiseaseOrbRange = Disease.orbRange; diseaseDefaultsCaptured = true; } } private void UpdateAcridEpidemic() { CaptureDiseaseDefaults(); bool num = IsCurrentCharacterAcrid(); Disease.maxBounces = ((num && acridUnlimitedTargets) ? 1000 : originalDiseaseBounces); Disease.bounceRange = ((num && acridUnlimitedRange) ? 10000f : originalDiseaseBounceRange); Disease.orbRange = ((num && acridUnlimitedRange) ? 10000f : originalDiseaseOrbRange); } private void RestoreAcridEpidemic() { if (diseaseDefaultsCaptured) { Disease.maxBounces = originalDiseaseBounces; Disease.bounceRange = originalDiseaseBounceRange; Disease.orbRange = originalDiseaseOrbRange; } } private void UpdateLockOn() { //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) CharacterBody body = GetBody(); if (!lockOn || (Object)(object)body == (Object)null) { DisableLockTracker(); return; } if ((Object)(object)trackerBody != (Object)(object)body || (Object)(object)silentTracker == (Object)null) { DisableLockTracker(); trackerBody = body; silentTracker = ((Component)body).GetComponent<HuntressTracker>(); if ((Object)(object)silentTracker == (Object)null) { silentTracker = ((Component)body).gameObject.AddComponent<HuntressTracker>(); } ((Behaviour)silentTracker).enabled = true; } silentTracker.maxTrackingDistance = lockDistance; silentTracker.maxTrackingAngle = lockAngle; HurtBox trackingTarget = silentTracker.GetTrackingTarget(); if ((Object)(object)trackingTarget != (Object)null && (Object)(object)trackingTarget.healthComponent != (Object)null && trackingTarget.healthComponent.alive) { InputBankTest inputBank = body.inputBank; if ((Object)(object)inputBank != (Object)null) { Vector3 val = ((Component)trackingTarget).transform.position - inputBank.aimOrigin; Vector3 normalized = ((Vector3)(ref val)).normalized; inputBank.aimDirection = normalized; } if (projectileTracking) { SteerOwnedProjectiles(((Component)body).gameObject, ((Component)trackingTarget).transform); } } trackedProjectiles.RemoveWhere((ProjectileController x) => (Object)(object)x == (Object)null); } private void DisableLockTracker() { if ((Object)(object)silentTracker != (Object)null) { scientificDisableTracker(); } trackerBody = null; trackedProjectiles.Clear(); } private void scientificDisableTracker() { ((Behaviour)silentTracker).enabled = false; silentTracker = null; } private void SteerOwnedProjectiles(GameObject owner, Transform target) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_00a9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)owner == (Object)null || (Object)(object)target == (Object)null) { return; } foreach (ProjectileController instances in InstanceTracker.GetInstancesList<ProjectileController>()) { if (!((Object)(object)instances == (Object)null) && !((Object)(object)instances.owner != (Object)(object)owner)) { Vector3 val = target.position - ((Component)instances).transform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; if (!(((Vector3)(ref normalized)).sqrMagnitude < 0.001f)) { float num = Mathf.Clamp01(trackingStrength * 0.01f * Time.deltaTime * 10f); ((Component)instances).transform.rotation = Quaternion.Slerp(((Component)instances).transform.rotation, Quaternion.LookRotation(normalized), num); trackedProjectiles.Add(instances); } } } } private CharacterBody GetBody() { LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); if (firstLocalUser == null) { return null; } return firstLocalUser.cachedBody; } private void Track(CharacterBody body) { tracked = body; if (!((Object)(object)body == (Object)null)) { oldAttack = body.baseAttackSpeed; oldDamage = body.baseDamage; oldMove = body.baseMoveSpeed; oldHealth = body.baseMaxHealth; oldRegen = body.baseRegen; oldJumpPower = body.baseJumpPower; oldJumps = body.baseJumpCount; trackedHealth = body.healthComponent; } } private void ApplyGodMode() { CharacterBody body = GetBody(); if (!((Object)(object)body == (Object)null) && !((Object)(object)body.healthComponent == (Object)null)) { body.healthComponent.godMode = godMode; trackedHealth = body.healthComponent; if (godMode) { body.healthComponent.Networkhealth = body.healthComponent.fullHealth; } } } private void ResetSkills(CharacterBody body) { GenericSkill[] components = ((Component)body).GetComponents<GenericSkill>(); foreach (GenericSkill val in components) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.skillDef == (Object)null)) { val.stock = val.maxStock; val.rechargeStopwatch = 0f; val.SetBlockedCooldownSkillState(false); } } } private void ApplyStats(CharacterBody body) { if (!((Object)(object)body == (Object)null)) { float num = oldAttack * attackMultiplier; float num2 = oldDamage * damageMultiplier; float num3 = oldMove * moveMultiplier; float num4 = oldJumpPower * jumpHeightMultiplier; float num5 = (maxPersonal ? (oldHealth * 20f) : oldHealth); float num6 = (maxPersonal ? (oldRegen * 20f + 20f) : oldRegen); int num7 = ((extraJumps >= 11) ? 999 : (oldJumps + extraJumps)); bool flag = false; if (!Mathf.Approximately(body.baseAttackSpeed, num)) { body.baseAttackSpeed = num; flag = true; } if (!Mathf.Approximately(body.baseDamage, num2)) { body.baseDamage = num2; flag = true; } if (!Mathf.Approximately(body.baseMoveSpeed, num3)) { body.baseMoveSpeed = num3; flag = true; } if (!Mathf.Approximately(body.baseJumpPower, num4)) { body.baseJumpPower = num4; flag = true; } if (!Mathf.Approximately(body.baseMaxHealth, num5)) { body.baseMaxHealth = num5; flag = true; } if (!Mathf.Approximately(body.baseRegen, num6)) { body.baseRegen = num6; flag = true; } if (body.baseJumpCount != num7) { body.baseJumpCount = num7; flag = true; } if (flag) { body.MarkAllStatsDirty(); body.RecalculateStats(); } } } private void RestoreStats() { if (!((Object)(object)tracked == (Object)null)) { tracked.baseAttackSpeed = oldAttack; tracked.baseDamage = oldDamage; tracked.baseMoveSpeed = oldMove; tracked.baseJumpPower = oldJumpPower; tracked.baseMaxHealth = oldHealth; tracked.baseRegen = oldRegen; tracked.baseJumpCount = oldJumps; tracked.MarkAllStatsDirty(); tracked.RecalculateStats(); tracked = null; } } private string PickupName(PickupDef def) { if (def == null) { return "Unknown"; } string text = Language.GetString(def.nameToken); if (!string.IsNullOrEmpty(text) && !(text == def.nameToken)) { return text; } return def.internalName; } private bool IsSpawnablePickup(PickupDef def) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 if (def != null) { if ((int)def.itemIndex == -1) { return (int)def.equipmentIndex != -1; } return true; } return false; } private void UpdateSafetyCounters() { if (!(Time.unscaledTime < nextSafetyScan)) { nextSafetyScan = Time.unscaledTime + 2f; cachedBodies = CharacterBody.readOnlyInstancesList.Count; cachedProjectiles = InstanceTracker.GetInstancesList<ProjectileController>().Count; cachedPickups = InstanceTracker.GetInstancesList<PickupDropletController>().Count; } } private bool IsMonsterBody(CharacterBody b) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 if ((Object)(object)b != (Object)null && (Object)(object)b.teamComponent != (Object)null) { return (int)b.teamComponent.teamIndex == 2; } return false; } private void RefreshPracticeCache() { practiceBodies.Clear(); practiceAIs.Clear(); foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList) { if (IsMonsterBody(readOnlyInstances)) { practiceBodies.Add(readOnlyInstances); } } foreach (CharacterMaster readOnlyInstances2 in CharacterMaster.readOnlyInstancesList) { if ((Object)(object)readOnlyInstances2 == (Object)null) { continue; } CharacterBody body = readOnlyInstances2.GetBody(); if (!IsMonsterBody(body)) { continue; } BaseAI[] components = ((Component)readOnlyInstances2).GetComponents<BaseAI>(); foreach (BaseAI val in components) { if ((Object)(object)val != (Object)null && !practiceAIs.Contains(val)) { practiceAIs.Add(val); } } } nextPracticeCache = Time.unscaledTime + 2f; } private void ApplyPracticeState(bool force = false) { //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) bool flag = practiceFreeze || practiceFullPause; bool flag2 = practiceDisableAI || practiceFullPause; int num = 0; int num2 = 0; int num3 = 0; foreach (CharacterBody practiceBody in practiceBodies) { if ((Object)(object)practiceBody == (Object)null) { continue; } if ((Object)(object)practiceBody.healthComponent != (Object)null) { if (force || practiceBody.healthComponent.isInFrozenState != flag) { practiceBody.healthComponent.isInFrozenState = flag; } num++; } if ((flag || practiceFullPause) && (Object)(object)practiceBody.inputBank != (Object)null) { practiceBody.inputBank.moveVector = Vector3.zero; practiceBody.inputBank.skill1.down = false; practiceBody.inputBank.skill2.down = false; practiceBody.inputBank.skill3.down = false; practiceBody.inputBank.skill4.down = false; practiceBody.inputBank.sprint.down = false; num2++; } } foreach (BaseAI practiceAI in practiceAIs) { if (!((Object)(object)practiceAI == (Object)null)) { bool flag3 = !flag2; if (force || ((Behaviour)practiceAI).enabled != flag3) { ((Behaviour)practiceAI).enabled = flag3; } num3++; } } status = "Practice: " + num2 + " movement inputs stopped, " + num + " frozen, " + num3 + " AI controllers"; } private void UpdatePracticeState() { if (!NetworkServer.active) { return; } bool flag = practiceFreeze || practiceDisableAI || practiceFullPause; bool flag2 = practiceFreeze != lastPracticeFreeze || practiceDisableAI != lastPracticeDisableAI || practiceFullPause != lastPracticeFullPause; if (flag || flag2) { if (Time.unscaledTime >= nextPracticeCache || practiceBodies.RemoveAll((CharacterBody x) => (Object)(object)x == (Object)null) > 0 || practiceAIs.RemoveAll((BaseAI x) => (Object)(object)x == (Object)null) > 0) { RefreshPracticeCache(); } if (flag2) { ApplyPracticeState(force: true); lastPracticeFreeze = practiceFreeze; lastPracticeDisableAI = practiceDisableAI; lastPracticeFullPause = practiceFullPause; } if (flag && Time.unscaledTime >= nextPracticeUpdate) { nextPracticeUpdate = Time.unscaledTime + 0.1f; ApplyPracticeState(); } } } private void ResumeEnemies() { if (!NetworkServer.active) { status = "Host or single-player required"; return; } practiceFreeze = false; practiceDisableAI = false; practiceFullPause = false; RefreshPracticeCache(); ApplyPracticeState(force: true); lastPracticeFreeze = false; lastPracticeDisableAI = false; lastPracticeFullPause = false; status = "Enemies resumed"; } private void HealAllEnemies() { if (!NetworkServer.active) { status = "Host required"; return; } int num = 0; CharacterBody[] array = Object.FindObjectsOfType<CharacterBody>(); foreach (CharacterBody val in array) { if (IsMonsterBody(val) && (Object)(object)val.healthComponent != (Object)null) { val.healthComponent.Networkhealth = val.healthComponent.fullHealth; val.healthComponent.Networkshield = val.healthComponent.fullShield; num++; } } status = "Restored " + num + " enemies"; } private void ClearAllEnemies() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active) { status = "Host required"; return; } int num = 0; CharacterBody[] array = Object.FindObjectsOfType<CharacterBody>(); foreach (CharacterBody val in array) { if (IsMonsterBody(val) && (Object)(object)val.healthComponent != (Object)null) { val.healthComponent.Suicide((GameObject)null, (GameObject)null, DamageTypeCombo.op_Implicit((DamageType)0)); num++; } } status = "Cleared " + num + " enemies"; } private void ClearHostileProjectiles() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 if (!NetworkServer.active) { status = "Host required"; return; } int num = 0; ProjectileController[] array = Object.FindObjectsOfType<ProjectileController>(); foreach (ProjectileController val in array) { if ((Object)(object)val != (Object)null && (Object)(object)val.teamFilter != (Object)null && (int)val.teamFilter.teamIndex == 2) { NetworkServer.Destroy(((Component)val).gameObject); num++; } } status = "Cleared " + num + " hostile projectiles"; } private bool CanCollectPickup(UniquePickup pickup, out PickupDef def) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Invalid comparison between Unknown and I4 //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Invalid comparison between Unknown and I4 //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Invalid comparison between Unknown and I4 def = PickupCatalog.GetPickupDef(pickup.pickupIndex); if (def == null || !((PickupIndex)(ref pickup.pickupIndex)).isValid) { return false; } string text = (def.internalName ?? "").ToLowerInvariant(); if (text.Contains("artifactkey") || text.Contains("quest") || text.Contains("voidcoin") || text.Contains("lunarcoin")) { return false; } if (def.coinValue != 0) { return false; } ItemDef val = (((int)def.itemIndex != -1) ? ItemCatalog.GetItemDef(def.itemIndex) : null); if ((Object)(object)val != (Object)null && (val.ContainsTag((ItemTag)33) || val.ContainsTag((ItemTag)26))) { return false; } if ((int)def.itemIndex == -1) { return (int)def.equipmentIndex != -1; } return true; } private int GatherStageDropsToBody(CharacterBody body) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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_0086: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)body == (Object)null) { return 0; } Vector3 val = body.footPosition + Vector3.up * 0.35f; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; PickupDropletController[] array = Object.FindObjectsOfType<PickupDropletController>(); foreach (PickupDropletController val2 in array) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null)) { if (!CanCollectPickup(val2.pickupState, out var _)) { num4++; continue; } ((Component)val2).transform.position = val + Random.insideUnitSphere * 0.35f; val2.ForcePickupInitialization(); num++; } } GenericPickupController[] array2 = InstanceTracker.GetInstancesList<GenericPickupController>().ToArray(); foreach (GenericPickupController val3 in array2) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((Component)val3).gameO