Decompiled source of Fire S Mythos v0.2.1
FireSMythos/FireSMythos.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using System.Xml; using BepInEx; using DM; using FireSMythos; using FireSMythos.AssetManagement; using FireSMythos.TABSSimp; using HarmonyLib; using Landfall.MonoBatch; using Landfall.TABS; using Landfall.TABS.AI; using Landfall.TABS.AI.Systems; using Landfall.TABS.GameMode; using Landfall.TABS.GameState; using Landfall.TABS.UnitEditor; using Landfall.TABS.UnitPlacement; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; using MonoMod.Cil; using MonoMod.RuntimeDetour; using Sirenix.Serialization; using TFBGames; using TMPro; using Unity.Entities; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.LowLevel; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("FireSMythos")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("FireSMythos")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("1619c49c-bc45-486c-bbca-6b52cef4f478")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] [HarmonyPatch(typeof(GameObject), "SetActive", new Type[] { typeof(bool) })] [HarmonyPriority(0)] internal static class FireSSetActivePatch { private static void Prefix(GameObject __instance, bool __0, ref bool __runOriginal) { if (!__0) { FireSFinalMethodPolicy.Apply((Object)(object)__instance, ref __runOriginal); } } } namespace FireSMythos { public class FireSAttack : GameStateListener { private static bool gameLoopPaused; private static bool gameLoopPauseScheduled; private static int pauseGeneration; private Unit unit; private TeamSystem teamSystem; private static bool pausedByFireS; private static float previousTimeScale = 1f; private bool battleStarted; private bool attackExecuted; private static readonly HashSet<FireSAttack> activeFireSUnits = new HashSet<FireSAttack>(); private bool registeredInBattle; private bool showVictoryScreen; private GUIStyle victoryStyle; private static readonly HashSet<FireSAttack> forceRemovalOwners = new HashSet<FireSAttack>(); private static bool victorySoundPlayed; public static bool IsGameLoopPaused => gameLoopPaused; public static bool BlockVanillaVictory { get { activeFireSUnits.RemoveWhere((FireSAttack x) => (Object)(object)x == (Object)null); return activeFireSUnits.Count > 0; } } public static bool ForceRemovalWindow { get { forceRemovalOwners.RemoveWhere((FireSAttack x) => (Object)(object)x == (Object)null); return forceRemovalOwners.Count > 0; } } public static bool IsSimulationPaused => pausedByFireS; private void Start() { InitializeReferences(); FireSSceneRespawnManager.NotifyFireSSpawned(unit); } private void InitializeReferences() { if ((Object)(object)unit == (Object)null) { unit = ((Component)((Component)this).transform.root).GetComponent<Unit>(); } if (teamSystem == null && World.Active != null) { teamSystem = World.Active.GetOrCreateManager<TeamSystem>(); } } public override void OnEnterBattleState() { battleStarted = true; showVictoryScreen = true; if (!victorySoundPlayed) { victorySoundPlayed = true; PlayVictorySound(); } if (!registeredInBattle) { activeFireSUnits.Add(this); registeredInBattle = true; } } public override void OnEnterPlacementState() { ResumeGameTime(); battleStarted = false; attackExecuted = false; showVictoryScreen = false; forceRemovalOwners.Remove(this); UnregisterFromBattle(); } private void OnDestroy() { forceRemovalOwners.Remove(this); UnregisterFromBattle(); } private void OnGUI() { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (showVictoryScreen) { if (victoryStyle == null) { victoryStyle = new GUIStyle(GUI.skin.label); victoryStyle.alignment = (TextAnchor)4; victoryStyle.fontStyle = (FontStyle)1; victoryStyle.fontSize = Mathf.Max(32, Screen.height / 12); victoryStyle.normal.textColor = Color.white; } Rect val = default(Rect); ((Rect)(ref val))..ctor((float)Screen.width * 0.15f, (float)Screen.height * 0.38f, (float)Screen.width * 0.7f, (float)Screen.height * 0.24f); int depth = GUI.depth; Color color = GUI.color; GUI.depth = -1000; GUI.color = new Color(0f, 0f, 0f, 0.65f); GUI.Box(val, GUIContent.none); GUI.color = Color.white; GUI.Label(val, "Fire S wins", victoryStyle); GUI.color = color; GUI.depth = depth; } } private void UnregisterFromBattle() { if (registeredInBattle) { activeFireSUnits.Remove(this); registeredInBattle = false; } activeFireSUnits.RemoveWhere((FireSAttack x) => (Object)(object)x == (Object)null); } private void Update() { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) CheckForTabResume(); if (pausedByFireS) { Time.timeScale = 0f; } if (!battleStarted || attackExecuted) { return; } InitializeReferences(); if ((Object)(object)unit == (Object)null || teamSystem == null) { return; } if ((Object)(object)unit.data != (Object)null) { unit.data.health = float.PositiveInfinity; } Team val = (Team)((int)unit.Team != 1); List<Unit> teamUnits = teamSystem.GetTeamUnits(val); if (teamUnits == null) { return; } List<Unit> list = new List<Unit>(); for (int i = 0; i < teamUnits.Count; i++) { Unit val2 = teamUnits[i]; if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)unit) { list.Add(val2); } } attackExecuted = true; forceRemovalOwners.Add(this); int num = 0; int num2 = 0; int num3 = 0; Debug.LogWarning((object)("[FireSMythos] ENEMY ELIMINATION STARTED. Targets: " + list.Count)); try { for (int j = 0; j < list.Count; j++) { Unit val3 = list[j]; if ((Object)(object)val3 == (Object)null) { continue; } GameObject val4 = null; try { val4 = ((Component)val3).gameObject; } catch (Exception ex) { num3++; Debug.LogWarning((object)("[FireSMythos] Cannot access enemy GameObject: " + ex)); continue; } if ((Object)(object)val4 == (Object)null) { continue; } string name = ((Object)val4).name; try { if ((Object)(object)val3.data != (Object)null && (Object)(object)val3.data.healthHandler != (Object)null) { if ((Object)(object)val3.unitBlueprint != (Object)null) { FireSBlockedUnits.Register(val3.unitBlueprint); } val3.data.healthHandler.Die(unit); } } catch (Exception ex2) { Debug.LogWarning((object)("[FireSMythos] ENEMY DIE FAILED: " + ex2)); } try { ForceDeath(val3); } catch (Exception ex3) { Debug.LogWarning((object)("[FireSMythos] FORCE DEATH FAILED: " + ex3)); } try { if ((Object)(object)val4 != (Object)null) { val4.SetActive(false); } } catch (Exception ex4) { num3++; Debug.LogWarning((object)("[FireSMythos] SETACTIVE FAILED: " + name + " | " + ex4)); } try { if ((Object)(object)val4 != (Object)null) { Object.Destroy((Object)(object)val4, 0f); } } catch (Exception ex5) { num3++; Debug.LogWarning((object)("[FireSMythos] DESTROY FAILED: " + name + " | " + ex5)); } num++; } if (FireSModeController.DestructionModeEnabled) { Debug.LogWarning((object)"[FireSMythos] DESTRUCTION MODE ACTIVE!"); FireSWorldDestruction.DestroyActiveScene(); } ((MonoBehaviour)this).StartCoroutine(FireSPersistentModObjectGuard.QuarantineBurst(0.8f, 0.1f)); } catch (Exception ex6) { Debug.LogError((object)("[FireSMythos] UNEXPECTED ELIMINATION ERROR: " + ex6)); } finally { forceRemovalOwners.Remove(this); try { PauseGameTime(); Debug.LogWarning((object)"[FireSMythos] GAME LOOP PAUSE REQUESTED."); } catch (Exception ex7) { Debug.LogError((object)("[FireSMythos] GAME LOOP PAUSE FAILED: " + ex7)); } Debug.LogWarning((object)("[FireSMythos] ENEMY ELIMINATION FINISHED. Processed=" + num + ", DieFailures=" + num2 + ", CleanupFailures=" + num3)); } } private void ForceDeath(Unit enemy) { if ((Object)(object)enemy == (Object)null || (Object)(object)enemy.data == (Object)null) { return; } try { enemy.data.Dead = true; enemy.dead = true; enemy.data.muscleControl = 0f; enemy.data.ragdollControl = 0f; Debug.Log((object)("[FireSMythos] FORCE DEATH APPLIED: " + ((Object)enemy).name)); } catch (Exception ex) { Debug.LogError((object)("[FireSMythos] FORCE DEATH FAILED: " + ex)); } } private void PauseGameTime() { if (!pausedByFireS) { previousTimeScale = Time.timeScale; pausedByFireS = true; } Time.timeScale = 0f; if (!gameLoopPaused && !gameLoopPauseScheduled) { gameLoopPauseScheduled = true; ((MonoBehaviour)this).StartCoroutine(FreezeGameLoopAfterDelay(++pauseGeneration)); Debug.Log((object)"[FireSMythos] Time stopped. Full PlayerLoop freeze scheduled."); } } private IEnumerator FreezeGameLoopAfterDelay(int generation) { yield return (object)new WaitForSecondsRealtime(1f); if (generation == pauseGeneration && pausedByFireS) { gameLoopPauseScheduled = false; gameLoopPaused = FireSPlayerLoopFreeze.Freeze(); if (gameLoopPaused) { Debug.Log((object)"[FireSMythos] FULL GAME LOOP FROZEN!"); } } } private static void ResumeGameTime() { pauseGeneration++; gameLoopPauseScheduled = false; FireSPlayerLoopFreeze.Restore(); gameLoopPaused = false; if (pausedByFireS) { Time.timeScale = previousTimeScale; pausedByFireS = false; Debug.Log((object)"[FireSMythos] FULL GAME LOOP RESTORED!"); } } public static void ResumeFromPlayerLoop() { ResumeGameTime(); } public static void CheckForTabResume() { if (pausedByFireS && Input.GetKeyDown((KeyCode)9)) { ResumeGameTime(); } } private static string FindVictorySoundRef(SoundPlayer player) { if ((Object)(object)player == (Object)null || (Object)(object)player.soundBank == (Object)null || player.soundBank.Categories == null) { Debug.LogError((object)"[FireSMythos] SoundBank not available!"); return null; } string text = null; int num = 0; SoundBankCategory[] categories = player.soundBank.Categories; foreach (SoundBankCategory val in categories) { if (val == null || val.soundEffects == null) { continue; } string text2 = val.categoryName ?? ""; SoundEffectInstance[] soundEffects = val.soundEffects; foreach (SoundEffectInstance val2 in soundEffects) { if (val2 == null || string.IsNullOrEmpty(val2.soundRef)) { continue; } string soundRef = val2.soundRef; string text3 = text2 + "/" + soundRef; string[] array = (text2 + " " + soundRef).ToLowerInvariant().Split(new char[5] { ' ', '/', '_', '-', '.' }, StringSplitOptions.RemoveEmptyEntries); int num2 = 0; string[] array2 = array; for (int k = 0; k < array2.Length; k++) { switch (array2[k]) { case "victory": num2 = Math.Max(num2, 100); break; case "winner": num2 = Math.Max(num2, 90); break; case "win": num2 = Math.Max(num2, 80); break; case "won": num2 = Math.Max(num2, 70); break; case "success": num2 = Math.Max(num2, 50); break; } } if (text2.Equals("UI", StringComparison.OrdinalIgnoreCase)) { num2 += 10; } if (num2 > 0) { Debug.Log((object)("[FireSMythos] Possible victory sound: " + text3 + " (score: " + num2 + ")")); if (num2 > num) { num = num2; text = text3; } } } } if (text == null) { Debug.LogWarning((object)"[FireSMythos] No victory sound found. Check available UI sound references."); SoundBankCategory[] categories2 = player.soundBank.Categories; foreach (SoundBankCategory val3 in categories2) { if (val3 == null || val3.soundEffects == null || !val3.categoryName.ToLowerInvariant().Contains("ui")) { continue; } SoundEffectInstance[] soundEffects2 = val3.soundEffects; foreach (SoundEffectInstance val4 in soundEffects2) { if (val4 != null) { Debug.Log((object)("[FireSMythos] UI sound: " + val3.categoryName + "/" + val4.soundRef)); } } } return null; } Debug.Log((object)("[FireSMythos] Selected victory sound: " + text)); return text; } private static void PlayVictorySound() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //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) try { SoundPlayer service = ServiceLocator.GetService<SoundPlayer>(); string text = FindVictorySoundRef(service); if (!string.IsNullOrEmpty(text)) { Camera main = Camera.main; Vector3 val = Vector3.zero; if ((Object)(object)main != (Object)null) { val = ((Component)main).transform.position + ((Component)main).transform.forward * 25f; } service.PlaySoundEffect(text, 1f, val, (MaterialType)0, (Transform)null, 1f); Debug.Log((object)"[FireSMythos] Victory sound played!"); } } catch (Exception ex) { Debug.LogError((object)("[FireSMythos] Victory sound error: " + ex)); } } } public class FireSBaseVisibility : MonoBehaviour { private Transform customVisualRoot; private Renderer[] baseRenderers; public void Initialize(Transform visualRoot) { customVisualRoot = visualRoot; Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true); List<Renderer> list = new List<Renderer>(); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if (!((Object)(object)val == (Object)null)) { Transform transform = ((Component)val).transform; if (!((Object)(object)transform == (Object)(object)customVisualRoot) && !transform.IsChildOf(customVisualRoot)) { val.enabled = false; list.Add(val); } } } baseRenderers = list.ToArray(); Debug.Log((object)("[FireSMythos] Hidden base renderers: " + baseRenderers.Length)); } private void OnEnable() { EnforceInvisible(); } private void LateUpdate() { EnforceInvisible(); } private void EnforceInvisible() { if (baseRenderers == null) { return; } Renderer[] array = baseRenderers; foreach (Renderer val in array) { if ((Object)(object)val != (Object)null && val.enabled) { val.enabled = false; } } } } [HarmonyPatch] internal static class FireSBehaviourEnabledPatch { private static MethodBase TargetMethod() { return AccessTools.PropertySetter(typeof(Behaviour), "enabled"); } private static bool Prefix(Behaviour __instance, bool __0) { if (__0) { return true; } return !FireSMutationGuard.ShouldBlock((Component)(object)__instance, "Behaviour.enabled = false"); } } public static class FireSBlockedUnits { private static readonly HashSet<string> blockedBlueprints = new HashSet<string>(); public static int BlockedCount => blockedBlueprints.Count; public static bool Register(UnitBlueprint blueprint) { //IL_0016: 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) if ((Object)(object)blueprint == (Object)null) { return false; } string text = ((object)blueprint.Entity.GUID/*cast due to .constrained prefix*/).ToString(); if (string.IsNullOrEmpty(text)) { return false; } bool flag = blockedBlueprints.Add(text); if (flag) { Debug.LogWarning((object)("[FireSMythos] UNIT TYPE PERMANENTLY BLOCKED: " + blueprint.Name + " | GUID: " + text)); } return flag; } public static bool IsBlocked(UnitBlueprint blueprint) { //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) if ((Object)(object)blueprint == (Object)null) { return false; } return blockedBlueprints.Contains(((object)blueprint.Entity.GUID/*cast due to .constrained prefix*/).ToString()); } public static void Reset() { blockedBlueprints.Clear(); } } internal static class FireSCallerPolicy { private static readonly HashSet<string> logged = new HashSet<string>(); private static bool IsFrameworkAssembly(string name) { return name == "mscorlib" || name == "System" || name.StartsWith("System.") || name == "netstandard" || name.StartsWith("UnityEngine") || name.StartsWith("Unity.") || name.StartsWith("Mono.") || name.StartsWith("MonoMod") || name.StartsWith("0Harmony") || name.StartsWith("Harmony") || name.StartsWith("BepInEx") || name.StartsWith("Microsoft."); } private static bool IsVanillaAssembly(Assembly assembly) { try { string location = assembly.Location; if (string.IsNullOrEmpty(location)) { return false; } string fullPath = Path.GetFullPath(Path.Combine(Application.dataPath, "Managed")); string text = fullPath; char directorySeparatorChar = Path.DirectorySeparatorChar; fullPath = text + directorySeparatorChar; string fullPath2 = Path.GetFullPath(location); return fullPath2.StartsWith(fullPath, StringComparison.OrdinalIgnoreCase); } catch { return false; } } public static bool TryGetModCaller(out string caller) { caller = null; StackFrame[] frames = new StackTrace(0, fNeedFileInfo: false).GetFrames(); if (frames == null) { return false; } Assembly assembly = typeof(FireSCallerPolicy).Assembly; StackFrame[] array = frames; foreach (StackFrame stackFrame in array) { MethodBase method = stackFrame.GetMethod(); if (method == null) { continue; } Assembly assembly2 = ((method.DeclaringType != null) ? method.DeclaringType.Assembly : method.Module.Assembly); if (!(assembly2 == null) && !(assembly2 == assembly) && !assembly2.IsDynamic) { string name = assembly2.GetName().Name ?? ""; if (!IsFrameworkAssembly(name) && !IsVanillaAssembly(assembly2)) { caller = assembly2.FullName; return true; } } } return false; } public static void LogBlocked(string operation, string caller) { string item = operation + "|" + caller; if (logged.Add(item)) { Debug.LogWarning((object)("[FireSIntegrityGuard] BLOCKED: " + operation + " | Caller: " + caller)); } } } [HarmonyPatch] internal static class FireSDataHandlerDeadPatch { private static MethodBase TargetMethod() { return AccessTools.PropertySetter(typeof(DataHandler), "Dead"); } private static bool Prefix(DataHandler __instance, bool __0) { if (!__0) { return true; } if (FireSProtection.IsProtectedObject((Object)(object)__instance)) { return false; } return !FireSMutationGuard.ShouldBlock((Component)(object)__instance, "DataHandler.Dead = true"); } } [HarmonyPatch] [HarmonyPriority(0)] internal static class FireSDiePolicyPatch { private static IEnumerable<MethodBase> TargetMethods() { foreach (MethodInfo method in AccessTools.GetDeclaredMethods(typeof(HealthHandler))) { if (method.Name == "Die") { yield return method; } } } private static void Prefix(HealthHandler __instance, ref bool __runOriginal) { FireSFinalMethodPolicy.Apply((Object)(object)__instance, ref __runOriginal); } } internal static class FireSExternalFreeze { private static readonly Assembly ownAssembly = typeof(FireSExternalFreeze).Assembly; private static readonly Dictionary<int, Behaviour> frozenBehaviours = new Dictionary<int, Behaviour>(); private static bool IsThirdPartyAssembly(Assembly assembly) { if (assembly == null || assembly == ownAssembly || assembly.IsDynamic) { return false; } string text = assembly.GetName().Name ?? ""; try { string location = assembly.Location; if (!string.IsNullOrEmpty(location)) { string fullPath = Path.GetFullPath(Path.Combine(Application.dataPath, "Managed")); char directorySeparatorChar = Path.DirectorySeparatorChar; string value = fullPath + directorySeparatorChar; string fullPath2 = Path.GetFullPath(location); if (fullPath2.StartsWith(value, StringComparison.OrdinalIgnoreCase)) { return false; } } } catch { } string[] array = new string[10] { "mscorlib", "netstandard", "System", "UnityEngine", "Unity.", "Mono", "MonoMod", "BepInEx", "Harmony", "TFBGames" }; string[] array2 = array; foreach (string text2 in array2) { if (text.Equals(text2, StringComparison.OrdinalIgnoreCase) || text.StartsWith(text2 + ".", StringComparison.OrdinalIgnoreCase)) { return false; } } return true; } public static bool IsThirdPartyServiceAssembly(Assembly assembly) { return IsThirdPartyAssembly(assembly); } private static bool IsUIOrCamera(Behaviour behaviour) { if ((Object)(object)behaviour == (Object)null) { return true; } if ((Object)(object)((Component)behaviour).GetComponentInParent<Camera>() != (Object)null) { return true; } if ((Object)(object)((Component)behaviour).GetComponentInParent<Canvas>() != (Object)null) { return true; } return false; } private static bool IsPhysicsActor(Behaviour behaviour) { GameObject gameObject = ((Component)behaviour).gameObject; return (Object)(object)gameObject.GetComponent<Rigidbody>() != (Object)null || (Object)(object)gameObject.GetComponentInParent<Rigidbody>() != (Object)null || (Object)(object)gameObject.GetComponentInChildren<Rigidbody>(true) != (Object)null || (Object)(object)gameObject.GetComponent<Collider>() != (Object)null || (Object)(object)gameObject.GetComponentInParent<Collider>() != (Object)null || (Object)(object)gameObject.GetComponentInChildren<Collider>(true) != (Object)null; } private static void FreezeBehaviour(Behaviour behaviour) { if (!((Object)(object)behaviour == (Object)null) && behaviour.enabled && !FireSProtection.IsProtectedObject((Object)(object)behaviour) && IsThirdPartyAssembly(((object)behaviour).GetType().Assembly)) { int instanceID = ((Object)behaviour).GetInstanceID(); if (!frozenBehaviours.ContainsKey(instanceID)) { frozenBehaviours.Add(instanceID, behaviour); behaviour.enabled = false; } } } public static void FreezeModdedBehaviours() { if (World.Active == null) { return; } Debug.Log((object)"[FireSIntegrityGuard] Freezing third-party behaviours..."); TeamSystem existingManager = World.Active.GetExistingManager<TeamSystem>(); if (existingManager != null) { Unit[] array = existingManager.GetAllUnits().ToArray(); Unit[] array2 = array; foreach (Unit val in array2) { if (!((Object)(object)val == (Object)null) && !FireSProtection.IsFireS(val)) { MonoBehaviour[] componentsInChildren = ((Component)val).GetComponentsInChildren<MonoBehaviour>(true); MonoBehaviour[] array3 = componentsInChildren; foreach (MonoBehaviour behaviour in array3) { FreezeBehaviour((Behaviour)(object)behaviour); } } } } MonoBehaviour[] array4 = Object.FindObjectsOfType<MonoBehaviour>(); MonoBehaviour[] array5 = array4; foreach (MonoBehaviour val2 in array5) { if (!((Object)(object)val2 == (Object)null) && !IsUIOrCamera((Behaviour)(object)val2) && !((Object)(object)((Component)val2).GetComponentInParent<Unit>() != (Object)null) && IsPhysicsActor((Behaviour)(object)val2)) { FreezeBehaviour((Behaviour)(object)val2); } } Debug.Log((object)("[FireSIntegrityGuard] Frozen components: " + frozenBehaviours.Count)); } public static void RestoreModdedBehaviours() { foreach (KeyValuePair<int, Behaviour> frozenBehaviour in frozenBehaviours) { Behaviour value = frozenBehaviour.Value; if ((Object)(object)value != (Object)null) { value.enabled = true; } } Debug.Log((object)("[FireSIntegrityGuard] Restored components: " + frozenBehaviours.Count)); frozenBehaviours.Clear(); } } internal static class FireSFinalMethodPolicy { public static void Apply(Object target, ref bool runOriginal) { if (!(target == (Object)null)) { if (FireSProtection.IsProtectedObject(target)) { runOriginal = false; } else if (FireSAttack.ForceRemovalWindow) { runOriginal = true; } } } } internal static class FireSFinalModeMusic { public static void Play() { Debug.Log((object)"[FireSMythos] Starting custom Final Mode soundtrack."); AssetImporter.PlayAudio("FinalModeMusic"); } } internal static class FireSFinalModeScreen { private static GameObject screenRoot; private static Image CreateImage(Transform parent, string name, Color color, Vector2 anchorMin, Vector2 anchorMax) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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) GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = anchorMin; component.anchorMax = anchorMax; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = color; ((Graphic)component2).raycastTarget = false; return component2; } private static Component CreateText(Component template, Transform parent, string name, string value, Vector2 anchorMin, Vector2 anchorMax, float fontSize, Color color, TextAnchor legacyAlignment) { //IL_0035: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(template.gameObject, parent, false); ((Object)val).name = name; FireSModeMenuUI.DisableLocalization(val); Component val2 = FireSModeMenuUI.FindLabel(val); FireSModeMenuUI.SetLabel(val2, value); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = anchorMin; component.anchorMax = anchorMax; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; TMP_Text val3 = (TMP_Text)(object)((val2 is TMP_Text) ? val2 : null); if ((Object)(object)val3 != (Object)null) { val3.alignment = (TextAlignmentOptions)514; val3.fontSize = fontSize; ((Graphic)val3).color = color; val3.fontStyle = (FontStyles)1; val3.enableWordWrapping = true; ((Graphic)val3).raycastTarget = false; } Text val4 = (Text)(object)((val2 is Text) ? val2 : null); if ((Object)(object)val4 != (Object)null) { val4.alignment = legacyAlignment; val4.fontSize = Mathf.RoundToInt(fontSize); ((Graphic)val4).color = color; val4.fontStyle = (FontStyle)1; ((Graphic)val4).raycastTarget = false; } return val2; } public static void Show(Button buttonTemplate, Component textTemplate) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_0418: Unknown result type (might be due to invalid IL or missing references) //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_04a9: Unknown result type (might be due to invalid IL or missing references) //IL_04b3: Expected O, but got Unknown //IL_04b6: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04fc: Unknown result type (might be due to invalid IL or missing references) //IL_0513: Unknown result type (might be due to invalid IL or missing references) //IL_052a: Unknown result type (might be due to invalid IL or missing references) //IL_0537: 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_00f4: Expected O, but got Unknown //IL_056c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)screenRoot != (Object)null) { return; } if ((Object)(object)buttonTemplate == (Object)null || (Object)(object)textTemplate == (Object)null) { Debug.LogError((object)"[FireSMythos] Final screen templates missing!"); return; } FireSFinalModeMusic.Play(); Time.timeScale = 0f; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; screenRoot = new GameObject("FireS_FinalModeCanvas"); Canvas val = screenRoot.AddComponent<Canvas>(); val.renderMode = (RenderMode)0; val.overrideSorting = true; val.sortingOrder = 32767; CanvasScaler val2 = screenRoot.AddComponent<CanvasScaler>(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); val2.matchWidthOrHeight = 0.5f; screenRoot.AddComponent<GraphicRaycaster>(); if ((Object)(object)EventSystem.current == (Object)null) { GameObject val3 = new GameObject("FireS_FinalEventSystem"); val3.AddComponent<EventSystem>(); val3.AddComponent<StandaloneInputModule>(); } CanvasGroup val4 = screenRoot.AddComponent<CanvasGroup>(); val4.alpha = 0f; Image val5 = CreateImage(screenRoot.transform, "Final_Background", Color.black, Vector2.zero, Vector2.one); ((Graphic)val5).raycastTarget = true; CreateImage(screenRoot.transform, "Final_RedAtmosphere", new Color(0.35f, 0.005f, 0.015f, 0.22f), new Vector2(0f, 0.25f), new Vector2(1f, 0.75f)); CreateImage(screenRoot.transform, "Final_TopBorder", new Color(0.8f, 0.015f, 0.035f, 0.9f), new Vector2(0.05f, 0.91f), new Vector2(0.95f, 0.914f)); CreateImage(screenRoot.transform, "Final_BottomBorder", new Color(0.8f, 0.015f, 0.035f, 0.9f), new Vector2(0.05f, 0.085f), new Vector2(0.95f, 0.089f)); CreateImage(screenRoot.transform, "Final_LeftBorder", new Color(0.5f, 0.01f, 0.025f, 0.7f), new Vector2(0.05f, 0.1f), new Vector2(0.052f, 0.9f)); CreateImage(screenRoot.transform, "Final_RightBorder", new Color(0.5f, 0.01f, 0.025f, 0.7f), new Vector2(0.948f, 0.1f), new Vector2(0.95f, 0.9f)); Image glowImage = CreateImage(screenRoot.transform, "Final_TitleGlow", new Color(0.7f, 0.01f, 0.025f, 0.12f), new Vector2(0.15f, 0.49f), new Vector2(0.85f, 0.72f)); Component val6 = CreateText(textTemplate, screenRoot.transform, "Final_Title", "You died", new Vector2(0.1f, 0.55f), new Vector2(0.9f, 0.72f), 104f, new Color(0.95f, 0.035f, 0.06f), (TextAnchor)4); CreateImage(screenRoot.transform, "Final_MessageSeparator", new Color(0.8f, 0.015f, 0.035f, 0.8f), new Vector2(0.3f, 0.465f), new Vector2(0.7f, 0.469f)); CreateText(textTemplate, screenRoot.transform, "Final_Message", "You have been killed by Fire S", new Vector2(0.12f, 0.36f), new Vector2(0.88f, 0.45f), 32f, Color.white, (TextAnchor)4); Image scanlineImage = CreateImage(screenRoot.transform, "Final_Scanline", new Color(0.95f, 0.02f, 0.045f, 0.18f), new Vector2(0.06f, 0.2f), new Vector2(0.94f, 0.205f)); GameObject val7 = Object.Instantiate<GameObject>(((Component)buttonTemplate).gameObject, screenRoot.transform, false); ((Object)val7).name = "FinalMode_LeaveGame"; Button component = val7.GetComponent<Button>(); FireSModeMenuUI.ResetButtonEvents(component); FireSModeMenuUI.DisableLocalization(val7); FireSModeMenuUI.SetLabel(FireSModeMenuUI.FindLabel(val7), "Leave game"); ((Selectable)component).interactable = true; ((UnityEvent)component.onClick).AddListener(new UnityAction(Application.Quit)); Navigation navigation = ((Selectable)component).navigation; ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)component).navigation = navigation; RectTransform component2 = val7.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0.5f, 0.19f); component2.anchorMax = new Vector2(0.5f, 0.19f); component2.pivot = new Vector2(0.5f, 0.5f); component2.sizeDelta = new Vector2(390f, 82f); component2.anchoredPosition = Vector2.zero; if ((Object)(object)((Selectable)component).image != (Object)null) { ((Graphic)((Selectable)component).image).color = new Color(0.55f, 0.015f, 0.03f); } ((Component)component).transform.SetAsLastSibling(); FireSFinalScreenAnimator fireSFinalScreenAnimator = screenRoot.AddComponent<FireSFinalScreenAnimator>(); fireSFinalScreenAnimator.Initialize(val4, (Graphic)(object)((val6 is Graphic) ? val6 : null), glowImage, scanlineImage); Camera[] array = Object.FindObjectsOfType<Camera>(); Camera[] array2 = array; foreach (Camera val8 in array2) { if ((Object)(object)val8 != (Object)null) { ((Behaviour)val8).enabled = false; } } Debug.Log((object)"[FireSMythos] FINAL MODE SCREEN CREATED!"); } } public class FireSFinalScreenAnimator : MonoBehaviour { private CanvasGroup canvasGroup; private Graphic title; private Image glow; private Image scanline; private float elapsed; public void Initialize(CanvasGroup group, Graphic titleGraphic, Image glowImage, Image scanlineImage) { canvasGroup = group; title = titleGraphic; glow = glowImage; scanline = scanlineImage; } private void Update() { //IL_0092: 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: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) float unscaledDeltaTime = Time.unscaledDeltaTime; elapsed += unscaledDeltaTime; if ((Object)(object)canvasGroup != (Object)null) { canvasGroup.alpha = Mathf.MoveTowards(canvasGroup.alpha, 1f, unscaledDeltaTime * 0.85f); } float num = (Mathf.Sin(Time.unscaledTime * 1.8f) + 1f) * 0.5f; if ((Object)(object)title != (Object)null) { title.color = Color.Lerp(new Color(0.58f, 0.015f, 0.035f), new Color(1f, 0.12f, 0.16f), num); } if ((Object)(object)glow != (Object)null) { Color color = ((Graphic)glow).color; color.a = Mathf.Lerp(0.07f, 0.23f, num); ((Graphic)glow).color = color; } if ((Object)(object)scanline != (Object)null) { RectTransform rectTransform = ((Graphic)scanline).rectTransform; float num2 = Mathf.Lerp(0.2f, 0.85f, Mathf.PingPong(Time.unscaledTime * 0.09f, 1f)); rectTransform.anchorMin = new Vector2(0.06f, num2); rectTransform.anchorMax = new Vector2(0.94f, num2 + 0.005f); } } } internal static class FireSProtection { public static bool IsFireS(Unit unit) { if ((Object)(object)unit == (Object)null) { return false; } FireSIndestructibleTag componentInChildren = ((Component)unit).GetComponentInChildren<FireSIndestructibleTag>(true); if ((Object)(object)componentInChildren != (Object)null) { return true; } if ((Object)(object)unit.unitBlueprint != (Object)null && unit.unitBlueprint.Entity != null && unit.unitBlueprint.Entity.Name == "Fire S") { return true; } return false; } public static bool IsFireS(HealthHandler handler) { if ((Object)(object)handler == (Object)null) { return false; } Unit val = Traverse.Create((object)handler).Field("unit").GetValue<Unit>(); if ((Object)(object)val == (Object)null) { val = ((Component)handler).GetComponentInParent<Unit>(); } return IsFireS(val); } public static bool IsProtectedObject(Object target) { if (target == null) { return false; } GameObject val = (GameObject)(object)((target is GameObject) ? target : null); Component val2 = (Component)(object)((target is Component) ? target : null); if ((Object)(object)val2 != (Object)null) { val = val2.gameObject; } if ((Object)(object)val == (Object)null) { return false; } Transform val3 = val.transform; while ((Object)(object)val3 != (Object)null) { if ((Object)(object)((Component)val3).GetComponent<FireSIndestructibleTag>() != (Object)null) { return true; } val3 = val3.parent; } FireSIndestructibleTag componentInChildren = val.GetComponentInChildren<FireSIndestructibleTag>(true); if ((Object)(object)componentInChildren != (Object)null) { return true; } Unit componentInParent = val.GetComponentInParent<Unit>(); if (IsFireS(componentInParent)) { return true; } Unit[] componentsInChildren = val.GetComponentsInChildren<Unit>(true); Unit[] array = componentsInChildren; foreach (Unit unit in array) { if (IsFireS(unit)) { return true; } } return false; } } [HarmonyPatch] internal static class FireSHealthHandlerPatch { private static IEnumerable<MethodBase> TargetMethods() { foreach (MethodInfo method in AccessTools.GetDeclaredMethods(typeof(HealthHandler))) { if (method.Name == "Die" || method.Name == "TakeDamage") { yield return method; } } } private static bool Prefix(HealthHandler __instance) { return !FireSProtection.IsFireS(__instance); } } [HarmonyPatch(typeof(HealthHandler), "SetInvulnerable", new Type[] { typeof(bool) })] internal static class FireSInvulnerabilityPatch { private static void Prefix(HealthHandler __instance, ref bool invulnerable) { if (FireSProtection.IsFireS(__instance)) { invulnerable = true; } } } [HarmonyPatch(typeof(BaseGameMode), "OnUnitDied", new Type[] { typeof(Unit) })] internal static class FireSOnUnitDiedPatch { private static bool Prefix(Unit unit) { return !FireSProtection.IsFireS(unit); } } [HarmonyPatch(typeof(BaseGameMode), "OnUnitRemoved", new Type[] { typeof(Unit), typeof(Team) })] internal static class FireSOnUnitRemovedPatch { private static bool Prefix(Unit unit) { return !FireSProtection.IsFireS(unit); } } [HarmonyPatch(typeof(UnitPlacementBrush), "RemoveUnitInternal")] internal static class FireSRemoveUnitPatch { private static bool Prefix(Unit unit) { return !FireSProtection.IsFireS(unit); } } [HarmonyPatch(typeof(TeamSystem), "RemoveEntity", new Type[] { typeof(Entity), typeof(Team), typeof(Unit) })] internal static class FireSTeamRemovePatch { private static bool Prefix(Unit unit) { return !FireSProtection.IsFireS(unit); } } [HarmonyPatch(typeof(UnitAPI), "SetIsDead")] internal static class FireSUnitAPISetDeadPatch { private static bool Prefix(UnitAPI __instance) { Unit val = null; try { val = Traverse.Create((object)__instance).Field("m_unit").GetValue<Unit>(); } catch { } if ((Object)(object)val == (Object)null) { val = ((Component)__instance).GetComponentInParent<Unit>(); } return !FireSProtection.IsFireS(val); } } [HarmonyPatch] [HarmonyPriority(800)] internal static class FireSUnitDestroyUnitPatch { private static IEnumerable<MethodBase> TargetMethods() { foreach (MethodInfo method in AccessTools.GetDeclaredMethods(typeof(Unit))) { if (method.Name == "DestroyUnit") { yield return method; } } } private static bool Prefix(Unit __instance) { return !FireSProtection.IsFireS(__instance); } } [HarmonyPatch(typeof(TeamSystem), "TriggerUnitDeathAction")] [HarmonyPriority(800)] internal static class FireSTeamDeathActionPatch { private static bool Prefix(Unit unit) { return !FireSProtection.IsFireS(unit); } } public class FireSIndestructibleTag : MonoBehaviour { } public static class FireSModeController { public static bool DestructionModeEnabled { get; private set; } public static bool FinalModeEnabled { get; private set; } public static void ToggleDestructionMode() { if (!FinalModeEnabled) { DestructionModeEnabled = !DestructionModeEnabled; Debug.Log((object)("[FireSMythos] Destruction Mode: " + DestructionModeEnabled)); FireSModeMenuUI.RefreshModeButton(); } } public static void EnterFinalMode(Button buttonTemplate, Component textTemplate) { if (!FinalModeEnabled) { if ((Object)(object)buttonTemplate == (Object)null || (Object)(object)textTemplate == (Object)null) { Debug.LogError((object)"[FireSMythos] Final Mode templates missing!"); return; } FinalModeEnabled = true; DestructionModeEnabled = false; Debug.Log((object)"[FireSMythos] FINAL MODE ACTIVATED!"); FireSFinalModeScreen.Show(buttonTemplate, textTemplate); } } } public class FireSModeButtonEvents : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler { private string description; private bool pointerInside; private bool selected; public void Initialize(string text) { description = text; } public void OnPointerEnter(PointerEventData eventData) { pointerInside = true; FireSModeMenuUI.ShowTooltip(description); } public void OnPointerExit(PointerEventData eventData) { pointerInside = false; if (!selected) { FireSModeMenuUI.HideTooltip(); } } public void OnSelect(BaseEventData eventData) { selected = true; FireSModeMenuUI.ShowTooltip(description); } public void OnDeselect(BaseEventData eventData) { selected = false; if (!pointerInside) { FireSModeMenuUI.HideTooltip(); } } } internal static class FireSModeMenuUI { private const string DESTRUCTION_NAME = "FireS_DestructionModeButton"; private const string FINAL_NAME = "FireS_FinalModeButton"; private const string DESTRUCTION_DESCRIPTION = "Fire S enters Berserk form. Now he can destroy entire worlds."; private const string FINAL_DESCRIPTION = "Fire S enters God of Death form. Now he will eliminate everything."; private static Button resumeTemplate; private static Button destructionButton; private static Button finalButton; private static Component textTemplate; private static TMP_Text tooltipTMP; private static Text tooltipLegacy; private static GameObject tooltipObject; internal static Component FindLabel(GameObject go) { TMP_Text componentInChildren = go.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null) { return (Component)(object)componentInChildren; } return (Component)(object)go.GetComponentInChildren<Text>(true); } internal static void SetLabel(Component label, string value) { if ((Object)(object)label == (Object)null) { return; } TMP_Text val = (TMP_Text)(object)((label is TMP_Text) ? label : null); if ((Object)(object)val != (Object)null) { val.text = value; return; } Text val2 = (Text)(object)((label is Text) ? label : null); if ((Object)(object)val2 != (Object)null) { val2.text = value; } } internal static void DisableLocalization(GameObject go) { MonoBehaviour[] componentsInChildren = go.GetComponentsInChildren<MonoBehaviour>(true); MonoBehaviour[] array = componentsInChildren; foreach (MonoBehaviour val in array) { if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == "LocalizeText") { ((Behaviour)val).enabled = false; } } } internal static void ResetButtonEvents(Button button) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown FieldInfo fieldInfo = AccessTools.Field(typeof(Button), "m_OnClick"); if (fieldInfo != null) { fieldInfo.SetValue(button, (object?)new ButtonClickedEvent()); } else { ((UnityEventBase)button.onClick).RemoveAllListeners(); } } public static void Attach(EscapeMenuComponent menu) { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Expected O, but got Unknown if ((Object)(object)menu == (Object)null) { return; } object? value = AccessTools.Field(typeof(EscapeMenuComponent), "m_ButtonsContainer").GetValue(menu); Transform val = (Transform)((value is Transform) ? value : null); object? value2 = AccessTools.Field(typeof(EscapeMenuComponent), "m_ResumeButton").GetValue(menu); resumeTemplate = (Button)((value2 is Button) ? value2 : null); if ((Object)(object)val == (Object)null || (Object)(object)resumeTemplate == (Object)null) { Debug.LogError((object)"[FireSMythos] Escape menu references missing!"); return; } textTemplate = FindLabel(((Component)resumeTemplate).gameObject); if ((Object)(object)textTemplate == (Object)null) { Debug.LogError((object)"[FireSMythos] Resume button label not found!"); return; } Canvas val2 = ((Component)menu).GetComponentInParent<Canvas>(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)menu).GetComponentInChildren<Canvas>(true); } if ((Object)(object)val2 != (Object)null) { CreateTooltip(val2, textTemplate); } destructionButton = FindOrCreateButton(val, "FireS_DestructionModeButton", "Destruction Mode", "Fire S enters Berserk form. Now he can destroy entire worlds.", new UnityAction(FireSModeController.ToggleDestructionMode)); finalButton = FindOrCreateButton(val, "FireS_FinalModeButton", "Final Mode", "Fire S enters God of Death form. Now he will eliminate everything.", new UnityAction(EnterFinalMode)); RefreshModeButton(); MethodInfo methodInfo = AccessTools.Method(typeof(EscapeMenuComponent), "RebuildNavigation", (Type[])null, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(menu, null); } Debug.Log((object)"[FireSMythos] Custom ESC buttons attached!"); } private static Button FindOrCreateButton(Transform container, string objectName, string label, string description, UnityAction action) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) Transform val = container.Find(objectName); Button val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Button>() : null); if ((Object)(object)val2 == (Object)null) { GameObject val3 = Object.Instantiate<GameObject>(((Component)resumeTemplate).gameObject, container, false); ((Object)val3).name = objectName; val2 = val3.GetComponent<Button>(); } if ((Object)(object)val2 == (Object)null) { return null; } ResetButtonEvents(val2); DisableLocalization(((Component)val2).gameObject); SetLabel(FindLabel(((Component)val2).gameObject), label); ((UnityEvent)val2.onClick).AddListener(action); ((Selectable)val2).interactable = true; Navigation navigation = ((Selectable)val2).navigation; ((Navigation)(ref navigation)).mode = (Mode)3; ((Selectable)val2).navigation = navigation; FireSModeButtonEvents fireSModeButtonEvents = ((Component)val2).GetComponent<FireSModeButtonEvents>(); if ((Object)(object)fireSModeButtonEvents == (Object)null) { fireSModeButtonEvents = ((Component)val2).gameObject.AddComponent<FireSModeButtonEvents>(); } fireSModeButtonEvents.Initialize(description); ((Component)val2).gameObject.SetActive(true); ((Component)val2).transform.SetAsLastSibling(); return val2; } private static void EnterFinalMode() { HideTooltip(); FireSModeController.EnterFinalMode(resumeTemplate, textTemplate); } public static void RefreshModeButton() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)destructionButton == (Object)null) && (Object)(object)((Selectable)destructionButton).image != (Object)null) { ((Graphic)((Selectable)destructionButton).image).color = (Color)(FireSModeController.DestructionModeEnabled ? new Color(0.85f, 0.22f, 0.12f, 1f) : Color.white); } } private static void CreateTooltip(Canvas canvas, Component template) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)tooltipObject != (Object)null) { return; } tooltipObject = Object.Instantiate<GameObject>(template.gameObject, ((Component)canvas).transform, false); ((Object)tooltipObject).name = "FireS_ModeTooltip"; DisableLocalization(tooltipObject); Component val = FindLabel(tooltipObject); tooltipTMP = (TMP_Text)(object)((val is TMP_Text) ? val : null); tooltipLegacy = (Text)(object)((val is Text) ? val : null); if ((Object)(object)tooltipTMP == (Object)null && (Object)(object)tooltipLegacy == (Object)null) { Object.Destroy((Object)(object)tooltipObject); tooltipObject = null; return; } RectTransform component = tooltipObject.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.08f, 0.045f); component.anchorMax = new Vector2(0.92f, 0.135f); component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; component.pivot = new Vector2(0.5f, 0.5f); if ((Object)(object)tooltipTMP != (Object)null) { tooltipTMP.alignment = (TextAlignmentOptions)514; ((Graphic)tooltipTMP).raycastTarget = false; } else { tooltipLegacy.alignment = (TextAnchor)4; ((Graphic)tooltipLegacy).raycastTarget = false; } SetLabel(val, ""); tooltipObject.SetActive(false); } public static void ShowTooltip(string text) { if (!((Object)(object)tooltipObject == (Object)null)) { Component label = (Component)(((Object)(object)tooltipTMP != (Object)null) ? ((object)tooltipTMP) : ((object)tooltipLegacy)); SetLabel(label, text); tooltipObject.SetActive(true); tooltipObject.transform.SetAsLastSibling(); } } public static void HideTooltip() { if ((Object)(object)tooltipObject != (Object)null) { tooltipObject.SetActive(false); } } } [HarmonyPatch(typeof(EscapeMenuComponent), "Awake")] internal static class FireSEscapeMenuAwakePatch { private static void Postfix(EscapeMenuComponent __instance) { FireSModeMenuUI.Attach(__instance); } } [HarmonyPatch(typeof(EscapeMenuComponent), "OnOpen")] internal static class FireSEscapeMenuOpenPatch { private static void Postfix(EscapeMenuComponent __instance) { FireSModeMenuUI.Attach(__instance); } } [HarmonyPatch(typeof(EscapeMenuComponent), "OnClose")] internal static class FireSEscapeMenuClosePatch { private static void Postfix() { FireSModeMenuUI.HideTooltip(); } } internal static class FireSModOrigin { private static bool IsTrustedAssembly(string name) { int result; switch (name) { default: if (!name.StartsWith("System.")) { switch (name) { case "Assembly-CSharp": case "Assembly-CSharp-firstpass": case "TFBGames": case "Unity.Entities": case "Unity.Mathematics": case "Unity.Collections": goto IL_00f3; } if (!name.StartsWith("UnityEngine") && !name.StartsWith("Unity.") && !name.StartsWith("Landfall.") && !name.StartsWith("Mono.") && !name.StartsWith("BepInEx.") && !name.StartsWith("MonoMod.")) { result = (name.StartsWith("Harmony") ? 1 : 0); break; } } goto IL_00f3; case "mscorlib": case "netstandard": case "System": goto IL_00f3; IL_00f3: result = 1; break; } return (byte)result != 0; } public static bool TryFindExternalCaller(out string caller) { caller = null; StackFrame[] frames = new StackTrace(2, fNeedFileInfo: false).GetFrames(); if (frames == null) { return false; } Assembly assembly = typeof(FireSModOrigin).Assembly; StackFrame[] array = frames; foreach (StackFrame stackFrame in array) { MethodBase method = stackFrame.GetMethod(); if (method == null || method.DeclaringType == null) { continue; } Assembly assembly2 = method.DeclaringType.Assembly; if (!(assembly2 == assembly) && !assembly2.IsDynamic) { string text = assembly2.GetName().Name ?? ""; if (!IsTrustedAssembly(text)) { caller = text + " :: " + method.DeclaringType.FullName + "." + method.Name; return true; } } } return false; } } internal static class FireSMonoBatchDispatcher { private static bool updateFreezeLogged; private static bool fixedFreezeLogged; public static bool UpdatePrefix(MonoBatchService instance) { if (!FireSAttack.IsGameLoopPaused) { return true; } if (!updateFreezeLogged) { updateFreezeLogged = true; Debug.LogWarning((object)"[FireSMythos] MonoBatchService.OnUpdate SUPPRESSED during game freeze."); } return false; } public static bool FixedUpdatePrefix(MonoBatchService instance) { if (!FireSAttack.IsGameLoopPaused) { return true; } if (!fixedFreezeLogged) { fixedFreezeLogged = true; Debug.LogWarning((object)"[FireSMythos] MonoBatchService.OnFixedUpdate SUPPRESSED during game freeze."); } return false; } } [HarmonyPatch(typeof(MonoBatchService), "OnUpdate")] internal static class FireSMonoBatchUpdatePatch { private static bool Prefix(MonoBatchService __instance) { return FireSMonoBatchDispatcher.UpdatePrefix(__instance); } } [HarmonyPatch(typeof(MonoBatchService), "OnFixedUpdate")] internal static class FireSMonoBatchFixedUpdatePatch { private static bool Prefix(MonoBatchService __instance) { return FireSMonoBatchDispatcher.FixedUpdatePrefix(__instance); } } internal static class FireSMutationGuard { public static bool ShouldBlock(Component target, string operation) { if ((Object)(object)target == (Object)null) { return false; } if (!FireSProtection.IsProtectedObject((Object)(object)target)) { return false; } if (!FireSCallerPolicy.TryGetModCaller(out var caller)) { return false; } FireSCallerPolicy.LogBlocked(operation, caller); return true; } } [BepInPlugin("fires.mythos", "Fire S Mythos", "0.2.0")] public class FireSMythosPlugin : BaseUnityPlugin { private void Awake() { FireSRuntimeApiGuard.Initialize(); Debug.Log((object)"[FireSMythos] Starting Fire S Mythos!"); FireSSceneRespawnManager.Initialize((MonoBehaviour)(object)this); AssetImporter.Initialize(); new FireSMythosMain(); } } public class FireSMythosMain : Mod { private static bool harmonyInstalled; public FireSMythosMain() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) Mod.DEV_MODE = false; if (!harmonyInstalled) { Harmony val = new Harmony("FireSMythos.VictoryScreen"); val.PatchAll(); harmonyInstalled = true; Debug.Log((object)"[FireSMythos] Victory patches installed!"); } ModFaction modFaction = Mod.CreateFaction("Fire S Mythos"); modFaction.Icon = Mod.GetIcon("Hillary"); modFaction.Color("#D8422F"); ModUnit modUnit = modFaction.NewUnit("Fire S"); modUnit.Health = float.PositiveInfinity; modUnit.Cost = 1000; modUnit.Icon = Mod.GetIcon("Teacher"); modUnit.Size = 1.2f; modUnit.Mass = 20f; ModModel model = Mod.GetModel("FireS_Blockout8"); if (model == null) { Debug.LogError((object)"[FireSMythos] Custom model not found!"); return; } GameObject unitBase = modUnit.internalObject.UnitBase; if ((Object)(object)unitBase == (Object)null) { Debug.LogError((object)"[FireSMythos] Original UnitBase is NULL!"); return; } GameObject val2 = Mod.CloneAndPoolObject(unitBase); val2.AddComponent<FireSBaseProbe>(); val2.AddComponent<FireSAttack>(); val2.AddComponent<FireSIndestructibleTag>(); Debug.Log((object)("[FireSMythos] BASE PREFAB: ActiveSelf=" + val2.activeSelf + ", ActiveHierarchy=" + val2.activeInHierarchy + ", Parent=" + ((Object)val2.transform.parent).name)); GameObject val3 = Object.Instantiate<GameObject>(model.internalObject, val2.transform, false); ((Object)val3).name = "FireS_Visual"; val3.transform.localRotation = Utilities.blenderToUnity; Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor(0.03582494f, -0.0435576f, 2.443953f); val3.transform.localPosition = Utilities.blenderToUnity * val4; val3.transform.localScale = Vector3.one; val3.SetActive(true); MeshRenderer component = val3.GetComponent<MeshRenderer>(); Debug.Log((object)("[FireSMythos] Visual position: " + ((object)val3.transform.localPosition/*cast due to .constrained prefix*/).ToString())); Debug.Log((object)("[FireSMythos] Visual bounds: " + ((object)((Renderer)component).bounds/*cast due to .constrained prefix*/).ToString())); Debug.Log((object)("[FireSMythos] Visual active: " + val3.activeInHierarchy)); val3.SetActive(true); FireSBaseVisibility fireSBaseVisibility = val2.AddComponent<FireSBaseVisibility>(); fireSBaseVisibility.Initialize(val3.transform); Debug.Log((object)"[FireSMythos] Default body hidden!"); MeshFilter component2 = val3.GetComponent<MeshFilter>(); MeshRenderer component3 = val3.GetComponent<MeshRenderer>(); if ((Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null) { Debug.LogError((object)"[FireSMythos] Visual has no MeshFilter or MeshRenderer!"); return; } Debug.Log((object)("[FireSMythos] Visual vertices: " + component2.sharedMesh.vertexCount)); ModBase modBase = new ModBase(val2); modUnit.Base = modBase; FireSSceneRespawnManager.SetBlueprint(modUnit.internalObject); Debug.Log((object)("[FireSMythos] BLUEPRINT BASE MATCH: " + ((Object)(object)modUnit.internalObject.UnitBase == (Object)(object)val2))); Debug.Log((object)"[FireSMythos] Custom UnitBase assigned!"); Debug.Log((object)"[FireSMythos] Custom visual added to UnitBase!"); } } public class FireSBaseProbe : MonoBehaviour { private bool visualCreated; private IEnumerator Start() { yield return null; AttachVisual(); } private void AttachVisual() { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) if (visualCreated) { return; } if ((Object)(object)((Component)this).transform.Find("FireS_RuntimeVisual") != (Object)null) { visualCreated = true; return; } GameObject model = Utilities.GetModel("FireS_Blockout8"); if ((Object)(object)model == (Object)null) { Debug.LogError((object)"[FireSMythos] Source model missing!"); return; } MeshFilter component = model.GetComponent<MeshFilter>(); MeshRenderer component2 = model.GetComponent<MeshRenderer>(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component.sharedMesh == (Object)null) { Debug.LogError((object)"[FireSMythos] Source mesh missing!"); return; } GameObject val = new GameObject("FireS_RuntimeVisual"); val.transform.SetParent(((Component)this).transform, false); val.transform.localRotation = Utilities.blenderToUnity; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(0.03582494f, -0.0435576f, 2.443953f); val.transform.localPosition = Utilities.blenderToUnity * val2; val.transform.localScale = Vector3.one; MeshFilter filter = val.AddComponent<MeshFilter>(); MeshRenderer renderer = val.AddComponent<MeshRenderer>(); FireSVisualIntegrity fireSVisualIntegrity = val.AddComponent<FireSVisualIntegrity>(); fireSVisualIntegrity.Initialize(filter, renderer, component.sharedMesh, ((Renderer)component2).sharedMaterials); val.SetActive(true); visualCreated = true; Debug.Log((object)"[FireSMythos] Isolated runtime visual created!"); } } internal static class FireSPersistentModObjectGuard { private const string QuarantineSceneName = "FireS_Quarantine"; private static Scene quarantineScene; private static readonly HashSet<int> processed = new HashSet<int>(); private static bool IsProtectedInfrastructure(GameObject root) { if ((Object)(object)root == (Object)null) { return true; } if (FireSProtection.IsProtectedObject((Object)(object)root)) { return true; } if ((Object)(object)root.GetComponentInChildren<ServiceLocator>(true) != (Object)null) { return true; } if ((Object)(object)root.GetComponentInChildren<Camera>(true) != (Object)null) { return true; } if ((Object)(object)root.GetComponentInChildren<Canvas>(true) != (Object)null) { return true; } if ((Object)(object)root.GetComponentInChildren<EventSystem>(true) != (Object)null) { return true; } if ((Object)(object)root.GetComponentInChildren<AudioListener>(true) != (Object)null) { return true; } MonoBehaviour[] componentsInChildren = root.GetComponentsInChildren<MonoBehaviour>(true); MonoBehaviour[] array = componentsInChildren; foreach (MonoBehaviour val in array) { if ((Object)(object)val != (Object)null && ((object)val).GetType().Assembly == typeof(FireSPersistentModObjectGuard).Assembly) { return true; } } return false; } public static bool IsExternalModOwned(Object target) { if (target == (Object)null) { return false; } GameObject val = (GameObject)(object)((target is GameObject) ? target : null); Component val2 = (Component)(object)((target is Component) ? target : null); if ((Object)(object)val2 != (Object)null) { val = val2.gameObject; } if ((Object)(object)val == (Object)null) { return false; } GameObject gameObject = ((Component)val.transform.root).gameObject; if (IsProtectedInfrastructure(gameObject)) { return false; } MonoBehaviour[] componentsInChildren = gameObject.GetComponentsInChildren<MonoBehaviour>(true); MonoBehaviour[] array = componentsInChildren; foreach (MonoBehaviour val3 in array) { if (!((Object)(object)val3 == (Object)null) && FireSRuntimeApiGuard.IsExternalModAssembly(((object)val3).GetType().Assembly)) { return true; } } return false; } private static bool IsPersistentScene(Scene scene) { return ((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).isLoaded && string.Equals(((Scene)(ref scene)).name, "DontDestroyOnLoad", StringComparison.OrdinalIgnoreCase); } private static Scene GetQuarantineScene() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (((Scene)(ref quarantineScene)).IsValid() && ((Scene)(ref quarantineScene)).isLoaded) { return quarantineScene; } quarantineScene = SceneManager.GetSceneByName("FireS_Quarantine"); if (!((Scene)(ref quarantineScene)).IsValid() || !((Scene)(ref quarantineScene)).isLoaded) { quarantineScene = SceneManager.CreateScene("FireS_Quarantine"); } return quarantineScene; } private static void DisableObjectComponents(GameObject root) { //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true); Component[] array = componentsInChildren; foreach (Component val in array) { if ((Object)(object)val == (Object)null) { continue; } Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null); if ((Object)(object)val2 != (Object)null) { try { MonoBehaviour val3 = (MonoBehaviour)(object)((val is MonoBehaviour) ? val : null); if ((Object)(object)val3 != (Object)null) { val3.StopAllCoroutines(); ((Behaviour)val3).enabled = false; } else if ((Object)(object)val2 != (Object)null) { val2.enabled = false; } } catch (Exception ex) { Debug.LogWarning((object)("[FireSIntegrityGuard] Behaviour disable failed: " + ex.Message)); } } Renderer val4 = (Renderer)(object)((val is Renderer) ? val : null); if ((Object)(object)val4 != (Object)null) { val4.enabled = false; } Collider val5 = (Collider)(object)((val is Collider) ? val : null); if ((Object)(object)val5 != (Object)null) { val5.enabled = false; } AudioSource val6 = (AudioSource)(object)((val is AudioSource) ? val : null); if ((Object)(object)val6 != (Object)null) { val6.Stop(); } ParticleSystem val7 = (ParticleSystem)(object)((val is ParticleSystem) ? val : null); if ((Object)(object)val7 != (Object)null) { val7.Stop(true, (ParticleSystemStopBehavior)0); } Rigidbody val8 = (Rigidbody)(object)((val is Rigidbody) ? val : null); if ((Object)(object)val8 != (Object)null) { val8.velocity = Vector3.zero; val8.angularVelocity = Vector3.zero; val8.isKinematic = true; } } } private static void Quarantine(GameObject root) { //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) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null || IsProtectedInfrastructure(root)) { return; } int instanceID = ((Object)root).GetInstanceID(); if (!processed.Add(instanceID)) { return; } Debug.LogWarning((object)("[FireSIntegrityGuard] Persistent mod object quarantined: " + ((Object)root).name)); DisableObjectComponents(root); try { Scene val = GetQuarantineScene(); if ((Object)(object)root.transform.parent != (Object)null) { root.transform.SetParent((Transform)null, true); } SceneManager.MoveGameObjectToScene(root, val); ((Object)root).hideFlags = (HideFlags)61; Object.Destroy((Object)(object)root, 0f); } catch (Exception ex) { Debug.LogError((object)("[FireSIntegrityGuard] Quarantine failed: " + ((Object)root).name + " | " + ex)); } } public static void QuarantinePersistentRoots() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (!FireSModeController.DestructionModeEnabled) { return; } processed.Clear(); MonoBehaviour[] array = Resources.FindObjectsOfTypeAll<MonoBehaviour>(); HashSet<GameObject> hashSet = new HashSet<GameObject>(); MonoBehaviour[] array2 = array; foreach (MonoBehaviour val in array2) { if ((Object)(object)val == (Object)null) { continue; } Scene scene = ((Component)val).gameObject.scene; if (IsPersistentScene(scene)) { GameObject gameObject = ((Component)((Component)val).transform.root).gameObject; if (IsExternalModOwned((Object)(object)gameObject)) { hashSet.Add(gameObject); } } } foreach (GameObject item in hashSet) { if ((Object)(object)item != (Object)null) { Quarantine(item); } } Debug.LogWarning((object)("[FireSIntegrityGuard] Persistent mod roots processed: " + hashSet.Count)); processed.Clear(); } public static IEnumerator QuarantineBurst(float duration, float interval) { float end = Time.realtimeSinceStartup + duration; while (Time.realtimeSinceStartup < end && FireSModeController.DestructionModeEnabled) { QuarantinePersistentRoots(); yield return (object)new WaitForSecondsRealtime(interval); } } } [HarmonyPatch(typeof(Object), "DontDestroyOnLoad", new Type[] { typeof(Object) })] internal static class FireSNoNewPersistentObjectsPatch { private static bool Prefix(Object target) { if (!FireSModeController.DestructionModeEnabled) { return true; } if (FireSPersistentModObjectGuard.IsExternalModOwned(target)) { Debug.LogWarning((object)("[FireSIntegrityGuard] External persistent registration blocked: " + target.name)); return false; } return true; } } [HarmonyPatch(typeof(SceneManager), "MoveGameObjectToScene", new Type[] { typeof(GameObject), typeof(Scene) })] internal static class FireSNoPersistentSceneMovePatch { private static bool Prefix(GameObject __0, Scene __1) { if (!FireSModeController.DestructionModeEnabled) { return true; } if (!string.Equals(((Scene)(ref __1)).name, "DontDestroyOnLoad", StringComparison.OrdinalIgnoreCase)) { return true; } return !FireSPersistentModObjectGuard.IsExternalModOwned((Object)(object)__0); } } internal static class FireSPlayerLoopFreeze { [StructLayout(LayoutKind.Sequential, Size = 1)] private struct FireSTabPollSystem { } private static PlayerLoopSystem originalLoop; private static bool hasOriginalLoop; private static bool loopFrozen; private static PlayerLoopSystem frozenLoop; private static bool hasFrozenLoop; private static bool loopWatchdogLogged; public static bool IsFrozen => loopFrozen; private static void PollTab() { if (loopFrozen) { EnsureFrozenLoop(); } if (Input.GetKeyDown((KeyCode)9)) { Debug.Log((object)"[FireSMythos] TAB PRESSED. RESTORING PLAYER LOOP."); FireSAttack.ResumeFromPlayerLoop(); } } private static bool IsMinimalLoop(PlayerLoopSystem loop) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_0079: Unknown result type (might be due to invalid IL or missing references) if (loop.subSystemList == null || loop.subSystemList.Length != 2) { return false; } bool flag = false; bool flag2 = false; PlayerLoopSystem[] subSystemList = loop.subSystemList; foreach (PlayerLoopSystem val in subSystemList) { if (val.type == null) { return false; } if (val.type.Name == "EarlyUpdate") { flag = true; } if (val.type.Name == "PostLateUpdate") { flag2 = true; } } return flag && flag2; } private static string DescribeLoop(PlayerLoopSystem loop) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (loop.subSystemList == null) { return "<NO ROOT SYSTEMS>"; } StringBuilder stringBuilder = new StringBuilder(); PlayerLoopSystem[] subSystemList = loop.subSystemList; foreach (PlayerLoopSystem val in subSystemList) { if (stringBuilder.Length > 0) { stringBuilder.Append(" | "); } stringBuilder.Append((val.type == null) ? "<NULL>" : val.type.FullName); } return stringBuilder.ToString(); } private static void EnsureFrozenLoop() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //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_0065: Unknown result type (might be due to invalid IL or missing references) if (!loopFrozen || !hasFrozenLoop) { return; } try { PlayerLoopSystem currentPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); if (!IsMinimalLoop(currentPlayerLoop)) { Debug.LogError((object)"[FireSMythos] PLAYER LOOP WAS REPLACED DURING FREEZE!"); Debug.LogError((object)("[FireSMythos] Unexpected roots: " + DescribeLoop(currentPlayerLoop))); PlayerLoop.SetPlayerLoop(frozenLoop); PlayerLoopSystem currentPlayerLoop2 = PlayerLoop.GetCurrentPlayerLoop(); if (!IsMinimalLoop(currentPlayerLoop2)) { Debug.LogError((object)"[FireSMythos] FAILED TO REASSERT MINIMAL PLAYER LOOP!"); } else if (!loopWatchdogLogged) { loopWatchdogLogged = true; Debug.LogWarning((object)"[FireSMythos] MINIMAL PLAYER LOOP REASSERTED SUCCESSFULLY."); } } } catch (Exception ex) { Debug.LogError((object)("[FireSMythos] LOOP WATCHDOG FAILED: " + ex)); } } private static bool TryFindSystem(PlayerLoopSystem root, string name, out PlayerLoopSystem result) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (root.subSystemList != null) { PlayerLoopSystem[] subSystemList = root.subSystemList; foreach (PlayerLoopSystem val in subSystemList) { if (val.type != null && val.type.Name == name) { result = val; return true; } } } result = default(PlayerLoopSystem); return false; } private static bool BuildEarlyUpdate(PlayerLoopSystem original, out PlayerLoopSystem result) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_00a7: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) result = original; if (original.subSystemList == null) { return false; } List<PlayerLoopSystem> list = new List<PlayerLoopSystem>(); bool flag = false; PlayerLoopSystem[] subSystemList = original.subSystemList; foreach (PlayerLoopSystem val in subSystemList) { if (!(val.type == null) && !(val.type.Name != "UpdateInputManager")) { list.Add(val); list.Add(new PlayerLoopSystem { type = typeof(FireSTabPollSystem), updateDelegate = new UpdateFunction(PollTab) }); flag = true; } } if (!flag) { return false; } result.subSystemList = list.ToArray(); return true; } private static PlayerLoopSystem BuildPostLateUpdate(PlayerLoopSystem original) { //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_0003: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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_010d: Unknown result type (might be due to invalid IL or missing references) PlayerLoopSystem result = original; if (original.subSystemList == null) { result.subSystemList = (PlayerLoopSystem[])(object)new PlayerLoopSystem[0]; return result; } string[] array = new string[15] { "PlayerSendFrameStarted", "UpdateRectTransform", "UpdateCanvasRectTransform", "PlayerUpdateCanvases", "UpdateAudio", "UpdateAllRenderers", "UpdateAllSkinnedMeshes", "FinishFrameRendering", "PlayerSendFrameComplete", "ClearImmediateRenderers", "UpdateCaptureScreenshot", "PresentAfterDraw", "PlayerSendFramePostPresent", "UpdateResolution", "XRPostLateUpdate" }; List<PlayerLoopSystem> list = new List<PlayerLoopSystem>(); PlayerLoopSystem[] subSystemList = original.subSystemList; foreach (PlayerLoopSystem val in subSystemList) { if (val.type == null) { continue; } string[] array2 = array; foreach (string text in array2) { if (val.type.Name == text) { list.Add(val); break; } } } result.subSystemList = list.ToArray(); return result; } public static bool Freeze() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (loopFrozen) { return true; } try { originalLoop = PlayerLoop.GetCurrentPlayerLoop(); hasOriginalLoop = true; List<PlayerLoopSystem> list = new List<PlayerLoopSystem>(); bool flag = false; bool flag2 = false; if (originalLoop.subSystemList == null) { throw new Exception("PlayerLoop has no subsystems."); } PlayerLoopSystem[] subSystemList = originalLoop.subSystemList; foreach (PlayerLoopSystem val in subSystemList) { if (val.type == null) { continue; } if (val.type.Name == "EarlyUpdate") { if (!BuildEarlyUpdate(val, out var result)) { throw new Exception("EarlyUpdate.UpdateInputManager not found."); } list.Add(result); flag = true; } else if (val.type.Name == "PostLateUpdate") { list.Add(BuildPostLateUpdate(val)); flag2 = true; } } if (!flag) { throw new Exception("EarlyUpdate not found."); } if (!flag2) { throw new Exception("PostLateUpdate not found."); } PlayerLoopSystem val2 = originalLoop; val2.subSystemList = list.ToArray(); frozenLoop = val2; hasFrozenLoop = true; loopFrozen = true; PlayerLoop.SetPlayerLoop(frozenLoop); PlayerLoopSystem currentPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); Debug.LogWarning((object)("[FireSMythos] PLAYER LOOP AFTER FREEZE: " + DescribeLoop(currentPlayerLoop))); if (!IsMinimalLoop(currentPlayerLoop)) { throw new Exception("Unity did not retain the minimal PlayerLoop."); } loopWatchdogLogged = false; Debug.Log((object)"[FireSMythos] MINIMAL PLAYER LOOP VERIFIED."); Debug.Log((object)"[FireSMythos] MINIMAL PLAYER LOOP INSTALLED."); Debug.Log((object)"[FireSMythos] Only input polling and rendering remain."); return true; } catch (Exception ex) { Debug.LogError((object)("[FireSMythos] PLAYER LOOP FREEZE FAILED: " + ex)); Restore(); return false; } } public static void Restore() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (hasOriginalLoop) { try { PlayerLoop.SetPlayerLoop(originalLoop); Debug.Log((object)"[FireSMythos] ORIGINAL PLAYER LOOP RESTORED."); } catch (Exception ex) { Debug.LogError((object)("[FireSMythos] PLAYER LOOP RESTORE FAILED: " + ex)); } loopFrozen = false; hasOriginalLoop = false; } } } [HarmonyPatch] internal static class FireSRendererPatch { private static IEnumerable<MethodBase> TargetMethods() { MethodBase setter = AccessTools.PropertySetter(typeof(Renderer), "enabled"); if (setter != null) { yield return setter; } foreach (MethodInfo method in AccessTools.GetDeclaredMethods(typeof(Renderer))) { if (method.Name == "SetPropertyBlock") { yield return method; } } } private static bool Prefix(Renderer __instance) { return !FireSMutationGuard.ShouldBlock((Component)(object)__instance, "Renderer mutation"); } } public static class FireSRuntimeApiGuard { [Flags] private enum ApiMatch { None = 0, PlayerLoop = 1, AppDomain = 2, HarmonyUnpatch = 4, TimeScaleReset = 8, RigidbodyWakeUp = 0x10, DontMoveForReset = 0x20 } private sealed class RuntimeGuardRunner : MonoBehaviour { private bool firstUpdateLogged; private void Update() { if (!firstUpdateLogged) { firstUpdateLogged = true; Debug.Log((object)"[FireSRuntimeApiGuard] Unity runner Update is ticking."); } GuardUpdate(); } } private const string PlayerLoopType = "UnityEngine.LowLevel.PlayerLoop"; private const string AppDomainType = "System.AppDomain"; private const string TimeType = "UnityEngine.Time"; private static readonly object Sync = new object(); private static readonly Assembly OwnAssembly = typeof(FireSRuntimeApiGuard).Assembly; private static readonly HashSet<Assembly> ScannedAssemblies = new HashSet<Assembly>(); private static readonly HashSet<Assembly> ScanningAssemblies = new HashSet<Assembly>(); private static readonly HashSet<MethodBase> HookedMethods = new HashSet<MethodBase>(); private static readonly HashSet<MethodBase> HookingMethods = new HashSet<MethodBase>(); private static readonly HashSet<Type> BlockedPlayerLoopTypes = new HashSet<Type>(); private static readonly List<ILHook> ActiveHooks = new List<ILHook>(); private static readonly HashSet<string> RuntimeExecutionLogged = new HashSet<string>(); private static readonly Dictionary<ushort, OpCode> OpCodeMap = BuildOpCodeMap(); private static bool initialized; private static int unityMainThreadId; private static bool playerLoopCleanupPending; private static float nextPlayerLoopSweep; private const float PlayerLoopSweepInterval = 0.25f; private static GameObject runnerObject; public static bool IsExternalModAssembly(Assembly assembly) { return IsCandidateAssembly(assembly); } public static void ReportRuntimeExecution(string methodName) { bool flag; lock (Sync) { flag = RuntimeExecutionLogged.Add(methodName); } if (flag) { Debug.LogWarning((object)("[FireSRuntimeApiGuard] RUNTIME BODY ENTERED: " + methodName)); } } private static void EmitRuntimeExecutionMarker(ILProcessor processor, MethodBody body, MethodBase target) { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) MethodInfo method = typeof(FireSRuntimeApiGuard).GetMethod("ReportRuntimeExecution", BindingFlags.Static | BindingFlags.Public); if (method == null) { throw new MissingMethodException("ReportRuntimeExecution was not found."); } MethodReference val = ((MemberReference)body.Method).Module.ImportReference((MethodBase)method); string text = target.Module.Assembly.GetName().Name + " | " + ((target.DeclaringType == null) ? "<unknown>" : target.DeclaringType.FullName) + "." + target.Name; processor.Emit(OpCodes.Ldstr, text); processor.Emit(OpCodes.Call, val); } [MethodImpl(MethodImplOptions.NoInlining)] private static int RuntimeDetourProbeTarget() { return 13579; } [MethodImpl(MethodImplOptions.NoInlining)] private static int RuntimeDetourProbeCaller() { return RuntimeDetourProbeTarget(); } private static bool VerifyRuntimeDetour() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown int num = RuntimeDetourProbeCaller(); if (num != 13579) { throw new InvalidOperationException("Pre-JIT probe failed: " + num); } Debug.LogWarning((object)("[FireSRuntimeApiGuard] PRE-JIT COMPLETE. Original result=" + num)); ILHook val = null; try { MethodInfo target = typeof(FireSRuntimeApiGuard).GetMethod("RuntimeDetourProbeTarget", BindingFlags.Static | BindingFlags.NonPublic); if (target == null) { throw new MissingMethodException("RuntimeDetourProbeTarget was not found."); } ILHookConfig val2 = new ILHookConfig { ManualApply = true, ID = "FireSMythos.RuntimeApiGuard.Probe", Priority = int.MinValue }; val = new ILHook((MethodBase)target, (Manipulator)delegate(ILContext context) { RewriteMethod(context, target); }, ref val2); val.Apply(); int num2 = RuntimeDetourProbeCaller(); Debug.LogWarning((object)("[FireSRuntimeApiGuard] PRE-JIT DETOUR TEST: Before=" + num + ", After=" + num2)); if (num2 != 0) { throw new InvalidOperationException("Detour did not intercept an already JIT-compiled callsite."); } if (!val.IsValid || !val.IsApplied) { throw new InvalidOperationException("Probe hook was not applied. Valid=" + val.IsValid + ", Applied=" + val.IsApplied); } int num3 = RuntimeDetourProbeTarget(); if (num3 != 0) { throw new InvalidOperationException("ILHook reports IsApplied=true, but execution was not redirected. Expected=0, Actual=" + num3); } lock (Sync) { ActiveHooks.Add(val); } Debug.LogWarning((object)("[FireSRuntimeApiGuard] RUNTIME DETOUR SELF-TEST PASSED. Expected=0, Actual=" + num3 + ", IsApplied=" + val.IsApplied)); return true; } catch (Exception ex) { if (val != null) { try { val.Dispose(); } catch { } } Debug.LogError((object)("[FireSRuntimeApiGuard] RUNTIME DETOUR SELF-TEST FAILED: " + ex)); return false; } } public static void Initialize() { lock (Sync) { if (initialized) { return; } initialized = true; unityMainThreadId = Thread.CurrentThread.ManagedThreadId; } Debug.Log((object)"[FireSRuntimeApiGuard] Runtime protection started."); AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad; EnsureRunner(); Assembly assembly = typeof(ILHook).Assembly; Debug.Log((object)("[FireSRuntimeApiGuard] RuntimeDetour assembly: " + assembly.FullName)); try { Debug.Log((object)("[FireSRuntimeApiGuard] RuntimeDetour location: " + assembly.Location)); } catch { } if (!VerifyRuntimeDetour()) { Debug.LogError((object)"[FireSRuntimeApiGuard] Protection disabled: RuntimeDetour execution test failed."); AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad; return; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); Assembly[] array = assemblies; foreach (Assembly assembly2 in array) { ScanAssembly(assembly2); } Debug.Log((object)"[FireSRuntimeApiGuard] Initial assembly scan completed."); } private static void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args) { if (args != null && !(args.LoadedAssembly == null)) { ScanAssembly(args.LoadedAssembly); } } private static void EnsureRunner() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown if (Thread.CurrentThread.ManagedThreadId != unityMainThreadId || (Object)(object)runnerObject != (Object)null) { return; } try { runnerObject = new GameObject("FireSMythos_RuntimeApiGuard"); ((Object)runnerObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)runnerObject); runnerObject.AddComponent<RuntimeGuardRunner>(); Debug.Log((object)"[FireSRuntimeApiGuard] Unity runner created."); } catch (Exception ex) { Debug.LogError((object)("[FireSRuntimeApiGuard] Runner creation failed: " + ex)); } } private static void GuardUpdate() { FireSSpawnHarmonyGuard.Refresh(); if (!(Time.unscaledTime < nextPlayerLoopSweep)) { nextPlayerLoopSweep = Time.unscaledTime + 0.25f; bool flag; lock (Sync) { flag = playerLoopCleanupPending || BlockedPlayerLoopTypes.Count > 0; } if (flag) { RemoveBlockedPlayerLoopNodes(); } } } private static bool IsCandidateAssembly(Assembly assembly) { if (assembly == null) { return false; } if (assembly == OwnAssembly) { return false; } string text; try { text = assembly.GetName().Name ?? ""; } catch { return false; } string[] array = new string[10] { "mscorlib", "netstandard", "System", "Microsoft", "Unity", "Mono", "MonoMod", "Mono.Cecil", "BepInEx", "TFBGames" }; string[] array2 = array; foreach (string text2 in array2) { if (text.Equals(text2, StringComparison.OrdinalIgnoreCase) |