Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Furious Trobbio v1.0.1
FuriousTrobbio.dll
Decompiled 2 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using HutongGames.PlayMaker; using HutongGames.PlayMaker.Actions; using TeamCherry.Localization; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("FuriousTrobbio")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("FuriousTrobbio")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("0A3CE2E0-F494-45DA-BED3-6A7FC5DB5A38")] [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")] internal static class FsmDiagnostics { internal static void LogChoiceMap(ManualLogSource log, PlayMakerFSM controlFsm, FsmState choiceState) { if (log != null && !((Object)(object)controlFsm == (Object)null) && choiceState != null) { log.LogInfo((object)("[DIAGNOSTIC] ===== " + ((Object)((Component)controlFsm).gameObject).name + " / " + controlFsm.FsmName + " FSM =====")); log.LogInfo((object)"[DIAGNOSTIC] ----- States -----"); FsmState[] fsmStates = controlFsm.FsmStates; foreach (FsmState val in fsmStates) { log.LogInfo((object)("[DIAGNOSTIC] State: " + val.Name)); } log.LogInfo((object)("[DIAGNOSTIC] ----- " + choiceState.Name + " transitions -----")); FsmTransition[] transitions = choiceState.Transitions; foreach (FsmTransition val2 in transitions) { log.LogInfo((object)("[DIAGNOSTIC] Event '" + val2.EventName + "' -> '" + val2.ToState + "'")); } log.LogInfo((object)("[DIAGNOSTIC] ----- " + choiceState.Name + " actions -----")); for (int k = 0; k < choiceState.Actions.Length; k++) { FsmStateAction val3 = choiceState.Actions[k]; string text = ((val3 == null) ? "<null>" : ((object)val3).GetType().FullName); log.LogInfo((object)("[DIAGNOSTIC] Action " + k + ": " + text)); } log.LogInfo((object)"[DIAGNOSTIC] ================================================"); } } internal static void LogStateDetails(ManualLogSource log, FsmState state, string label) { if (log == null || state == null) { return; } log.LogInfo((object)("[PYRO DIAGNOSTIC] ===== " + label + ": " + state.Name + " =====")); FsmTransition[] transitions = state.Transitions; foreach (FsmTransition val in transitions) { log.LogInfo((object)("[PYRO DIAGNOSTIC] Transition '" + val.EventName + "' -> '" + val.ToState + "'")); } for (int j = 0; j < state.Actions.Length; j++) { FsmStateAction val2 = state.Actions[j]; if (val2 != null) { log.LogInfo((object)("[PYRO DIAGNOSTIC] Action " + j + ": " + ((object)val2).GetType().FullName)); FieldInfo[] fields = ((object)val2).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { log.LogInfo((object)("[PYRO DIAGNOSTIC] " + fieldInfo.Name + " = " + DescribeValue(fieldInfo.GetValue(val2)))); } } } } internal static void LogFsmDetails(ManualLogSource log, PlayMakerFSM fsm, string label) { if (log != null && !((Object)(object)fsm == (Object)null)) { log.LogInfo((object)("[PYRO DIAGNOSTIC] ######## " + label + ": " + ((Object)((Component)fsm).gameObject).name + " / " + fsm.FsmName + " ########")); FsmState[] fsmStates = fsm.FsmStates; foreach (FsmState state in fsmStates) { LogStateDetails(log, state, label); } log.LogInfo((object)"[PYRO DIAGNOSTIC] ############################################"); } } internal static void LogMatchingStates(ManualLogSource log, PlayMakerFSM fsm, string label) { if (log == null || (Object)(object)fsm == (Object)null) { return; } log.LogInfo((object)("[PYRO DIAGNOSTIC] ######## " + label + ": " + ((Object)((Component)fsm).gameObject).name + " / " + fsm.FsmName + " ########")); FsmState[] fsmStates = fsm.FsmStates; foreach (FsmState val in fsmStates) { string text = val.Name.ToLowerInvariant(); bool flag = text.Contains("burst") || text.Contains("column") || text.Contains("trap"); FsmTransition[] transitions = val.Transitions; foreach (FsmTransition val2 in transitions) { string text2 = val2.EventName.ToLowerInvariant(); string text3 = val2.ToState.ToLowerInvariant(); flag |= text2.Contains("burst") || text2.Contains("column") || text2.Contains("trap") || text3.Contains("burst") || text3.Contains("column") || text3.Contains("trap"); } if (flag) { LogStateDetails(log, val, label); } } log.LogInfo((object)"[PYRO DIAGNOSTIC] ############################################"); } internal static void LogPyrotechnicsSceneObjects(ManualLogSource log, string sceneName) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (log == null) { return; } string[] array = new string[7] { "burst", "column", "trap", "floor", "fire", "flame", "pyro" }; log.LogInfo((object)"[PYRO DIAGNOSTIC] ===== Matching scene objects ====="); GameObject[] array2 = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject val in array2) { if ((Object)(object)val == (Object)null) { continue; } Scene scene = val.scene; if (!((Scene)(ref scene)).IsValid()) { continue; } scene = val.scene; if (!(((Scene)(ref scene)).name != sceneName)) { string lowerName = ((Object)val).name.ToLowerInvariant(); if (Array.Exists(array, (string term) => lowerName.Contains(term))) { log.LogInfo((object)("[PYRO DIAGNOSTIC] Object " + GetHierarchyPath(val.transform) + ", active=" + val.activeSelf + ".")); } } } log.LogInfo((object)"[PYRO DIAGNOSTIC] =================================="); } private static string GetHierarchyPath(Transform transform) { string text = ((Object)transform).name; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } internal static void LogObjectFsmMap(ManualLogSource log, GameObject gameObject, string description) { if (log == null || (Object)(object)gameObject == (Object)null) { return; } log.LogInfo((object)("[ANTIC DIAGNOSTIC] ===== " + description + " =====")); PlayMakerFSM[] componentsInChildren = gameObject.GetComponentsInChildren<PlayMakerFSM>(true); foreach (PlayMakerFSM val in componentsInChildren) { log.LogInfo((object)("[ANTIC DIAGNOSTIC] FSM=" + val.FsmName + ", active state=" + val.ActiveStateName)); FsmState[] states = val.Fsm.States; foreach (FsmState val2 in states) { FsmTransition[] transitions = val2.Transitions; foreach (FsmTransition val3 in transitions) { log.LogInfo((object)("[ANTIC DIAGNOSTIC] " + val2.Name + ": '" + val3.EventName + "' -> '" + val3.ToState + "'")); } if (val2.Name == "Explode") { LogStateActionFields(log, val2); } } } log.LogInfo((object)"[ANTIC DIAGNOSTIC] ================================"); } internal static void LogObjectHierarchy(ManualLogSource log, GameObject gameObject, string description) { if (log != null && !((Object)(object)gameObject == (Object)null)) { log.LogInfo((object)("[BOMB DIAGNOSTIC] ===== " + description + " =====")); LogTransform(log, gameObject.transform, string.Empty); log.LogInfo((object)"[BOMB DIAGNOSTIC] ================================"); } } private static void LogTransform(ManualLogSource log, Transform transform, string indent) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown string text = string.Empty; Component[] components = ((Component)transform).GetComponents<Component>(); foreach (Component val in components) { if ((Object)(object)val != (Object)null) { text = text + ((text.Length == 0) ? string.Empty : ", ") + ((object)val).GetType().Name; } } log.LogInfo((object)("[BOMB DIAGNOSTIC] " + indent + ((Object)transform).name + " (active=" + ((Component)transform).gameObject.activeSelf + "; local position=" + ((object)transform.localPosition/*cast due to .constrained prefix*/).ToString() + "; local rotation=" + ((object)transform.localEulerAngles/*cast due to .constrained prefix*/).ToString() + "; components=" + text + ")")); foreach (Transform item in transform) { Transform transform2 = item; LogTransform(log, transform2, indent + " "); } } private static void LogStateActionFields(ManualLogSource log, FsmState state) { log.LogInfo((object)"[BOMB DIAGNOSTIC] ----- Explode actions -----"); for (int i = 0; i < state.Actions.Length; i++) { FsmStateAction val = state.Actions[i]; if (val != null) { log.LogInfo((object)("[BOMB DIAGNOSTIC] Action " + i + ": " + ((object)val).GetType().FullName)); FieldInfo[] fields = ((object)val).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { object value = fieldInfo.GetValue(val); log.LogInfo((object)("[BOMB DIAGNOSTIC] " + fieldInfo.Name + " = " + DescribeValue(value))); } } } } private static string DescribeValue(object value) { if (value == null) { return "<null>"; } GameObject val = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val != (Object)null) { return "GameObject(" + ((Object)val).name + ")"; } FsmGameObject val2 = (FsmGameObject)((value is FsmGameObject) ? value : null); if (val2 != null) { return "FsmGameObject(" + (((Object)(object)val2.Value != (Object)null) ? ((Object)val2.Value).name : "<null>") + ")"; } FsmEvent val3 = (FsmEvent)((value is FsmEvent) ? value : null); if (val3 != null) { return "FsmEvent(" + val3.Name + ")"; } return value.ToString(); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("name.ryanblocker.furioustrobbio", "Furious Trobbio", "1.0.0")] public class FuriousTrobbio : BaseUnityPlugin { private sealed class FuriousTrapdoorSequenceAction : FsmStateAction { public override void OnEnter() { StartTrapdoorSequence((FsmStateAction)(object)this); } } private const string ArenaSceneName = "Library_13"; private const string BossControlFsmName = "Control"; private const string ChoiceStateName = "Choice"; private const string DazzleFlashEventName = "DAZZLE FLASH"; private const string BombThrowEventName = "BOMB THROW"; private const string TornadoEventName = "TORNADO"; private const string NativeBossAdjective = "Tormented"; private const string NativeBossName = "Trobbio"; private const string FuriousBossAdjective = "The Performer's Final Act"; private const string FuriousBossName = "Furious Trobbio"; private const int NativeBossHealth = 950; private const int FuriousBossHealth = 1500; private const int BurstColumnsThresholdActionIndex = 4; private const int FuriousBurstColumnsThreshold = 1100; private const int FuriousSecondPhaseThreshold = 600; private const float ExtraWaveBurstSpacing = 0.15f; private const float MinTrapdoorBurstSpacing = 0.15f; private const float MaxTrapdoorBurstSpacing = 0.35f; private const float WraithfulWaveBurstSpacing = 0.1f; private const float NativeFinalBurstDelay = 1.25f; private const float ComplementaryBombBlastRotation = 45f; private const float ComplementaryBombBlastLifetime = 2f; private static bool inTrobbioFight; private static PlayMakerFSM bossControlFsm; private static PlayMakerFSM runtimeBossControlFsm; private static GameObject crossBlast90; private static GameObject crossBlast45; private static GameObject crossBlastAntic90; private static GameObject crossBlastAntic45; private static bool fireworksArmed; private static bool lastSelectedAttackWasDazzleFlash; private static bool lastSelectedAttackWasTornado; private static int consecutiveBombThrowCount; private static bool fireworksExtensionRunning; private static bool nativeFireworkIsPlus; private static bool extraAnticsPrepared; private static bool healthSetupRunning; private static bool trapdoorSequenceConfigured; private static bool trapdoorSequenceRunning; private static bool trapdoorHealthThresholdConfigured; private static bool secondPhaseTriggered; private static bool tornadoBombSequenceRunning; private static bool tornadoBombsStartedThisAttack; private static bool replaceBossTitleLocalization; private static bool staggerControlDisabled; private static GameObject crossBombPrefab; private static readonly Dictionary<int, GameObject> ComplementaryBombAntics = new Dictionary<int, GameObject>(); public static FuriousTrobbio Instance { get; private set; } public ManualLogSource Log => ((BaseUnityPlugin)this).Logger; private void Awake() { Instance = this; Harmony.CreateAndPatchAll(typeof(FuriousTrobbio), (string)null); SceneManager.sceneLoaded += OnSceneLoaded; Log.LogInfo((object)"Furious Trobbio loaded and initialized."); } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { inTrobbioFight = ((Scene)(ref scene)).name == "Library_13"; ResetFightReferences(); if (inTrobbioFight) { Instance.Log.LogInfo((object)"Furious Trobbio: Tormented Trobbio arena loaded."); } } private static void ResetFightReferences() { bossControlFsm = null; runtimeBossControlFsm = null; crossBlast90 = null; crossBlast45 = null; crossBlastAntic90 = null; crossBlastAntic45 = null; fireworksArmed = false; lastSelectedAttackWasDazzleFlash = false; lastSelectedAttackWasTornado = false; consecutiveBombThrowCount = 0; fireworksExtensionRunning = false; nativeFireworkIsPlus = false; extraAnticsPrepared = false; healthSetupRunning = false; trapdoorSequenceConfigured = false; trapdoorSequenceRunning = false; trapdoorHealthThresholdConfigured = false; secondPhaseTriggered = false; tornadoBombSequenceRunning = false; tornadoBombsStartedThisAttack = false; replaceBossTitleLocalization = false; staggerControlDisabled = false; crossBombPrefab = null; ComplementaryBombAntics.Clear(); } [HarmonyPostfix] [HarmonyPatch(typeof(FsmState), "OnEnter")] private static void OnFsmStateEntered(FsmState __instance) { if (!inTrobbioFight) { return; } object obj; if (__instance == null) { obj = null; } else { Fsm fsm = __instance.Fsm; obj = ((fsm != null) ? fsm.FsmComponent : null); } if ((Object)obj == (Object)null) { return; } PlayMakerFSM fsmComponent = __instance.Fsm.FsmComponent; if (fsmComponent.FsmName == "Control" && ((Object)((Component)fsmComponent).gameObject).name == "Tormented Trobbio") { runtimeBossControlFsm = fsmComponent; } AddComplementaryBombBlast(__instance, fsmComponent); AddComplementaryBombAntic(__instance, fsmComponent); if (fsmComponent.FsmName != "Control" || !((Object)((Component)fsmComponent).gameObject).name.Contains("Trobbio")) { return; } CacheBossReferences(fsmComponent); DisableTrobbioStagger(fsmComponent); switch (__instance.Name) { case "Tornado Antic": tornadoBombsStartedThisAttack = false; if (lastSelectedAttackWasTornado) { Instance.Log.LogInfo((object)"Furious Trobbio: blocked a consecutive Tornado at its native entry state."); fsmComponent.SetState("Quick Idle"); } else { lastSelectedAttackWasTornado = true; } break; case "Flash JumpAntic": lastSelectedAttackWasTornado = false; PrepareExtraFireworkAntics(); break; case "Throw Antic": case "Will Burst Column": lastSelectedAttackWasTornado = false; break; case "Flash Burst": ExtendNativeFireworks(__instance); break; case "Tornado": StartFuriousTornadoBombs(fsmComponent); break; } } [HarmonyPrefix] [HarmonyPatch(typeof(DisplayBossTitle), "OnEnter")] private static void ArmTrobbioBossTitleReplacement(DisplayBossTitle __instance) { object obj; if (__instance == null) { obj = null; } else { Fsm fsm = ((FsmStateAction)__instance).Fsm; obj = ((fsm != null) ? fsm.FsmComponent : null); } PlayMakerFSM val = (PlayMakerFSM)obj; if (inTrobbioFight && !((Object)(object)val == (Object)null) && ((Object)((Component)val).gameObject).name.Contains("Trobbio")) { replaceBossTitleLocalization = true; ((MonoBehaviour)Instance).StartCoroutine(EndTrobbioBossTitleReplacementWindow()); } } [HarmonyPostfix] [HarmonyPatch(typeof(Language), "Get", new Type[] { typeof(string), typeof(string) })] private static void ReplaceTrobbioBossTitleLocalization(ref string __result) { if (replaceBossTitleLocalization && !string.IsNullOrEmpty(__result)) { string a = __result.Trim(); if (string.Equals(a, "Tormented", StringComparison.OrdinalIgnoreCase)) { __result = "The Performer's Final Act"; } else if (string.Equals(a, "Trobbio", StringComparison.OrdinalIgnoreCase)) { __result = "Furious Trobbio"; } } } private static IEnumerator EndTrobbioBossTitleReplacementWindow() { yield return (object)new WaitForSeconds(3f); replaceBossTitleLocalization = false; Instance.Log.LogInfo((object)"Furious Trobbio: applied localized two-line boss title replacement window."); } [HarmonyPostfix] [HarmonyPatch(typeof(FullQuestBase), "TryEndQuest")] private static void OpenArenaAfterCompletedQuest(bool __result) { if (inTrobbioFight && __result) { ((MonoBehaviour)Instance).StartCoroutine(OpenTormentedTrobbioArenaGatesAfterQuest()); } } private static IEnumerator OpenTormentedTrobbioArenaGatesAfterQuest() { yield return null; int opened = 0; PlayMakerFSM[] array = Resources.FindObjectsOfTypeAll<PlayMakerFSM>(); foreach (PlayMakerFSM fsm in array) { int num2; if (!((Object)(object)fsm == (Object)null) && !(fsm.FsmName != "BG Control") && ((Object)((Component)fsm).gameObject).name.StartsWith("Battle Gate", StringComparison.Ordinal)) { Scene scene = ((Component)fsm).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { scene = ((Component)fsm).gameObject.scene; if (!(((Scene)(ref scene)).name != "Library_13")) { num2 = ((!IsInNamedHierarchy(((Component)fsm).transform, "Boss Scene TormentedTrobbio")) ? 1 : 0); goto IL_0108; } } } num2 = 1; goto IL_0108; IL_0108: if (num2 == 0) { fsm.Fsm.Event("BG OPEN"); opened++; } } Instance.Log.LogInfo((object)("Furious Trobbio: sent BG OPEN to " + opened + " Tormented arena gates.")); } private static void DisableTrobbioStagger(PlayMakerFSM controlFsm) { if (!staggerControlDisabled && !((Object)(object)controlFsm == (Object)null) && !(((Object)((Component)controlFsm).gameObject).name != "Tormented Trobbio")) { PlayMakerFSM val = Array.Find(((Component)controlFsm).GetComponents<PlayMakerFSM>(), (PlayMakerFSM candidate) => candidate.FsmName == "Stun Control"); if (!((Object)(object)val == (Object)null)) { ((Behaviour)val).enabled = false; staggerControlDisabled = true; Instance.Log.LogInfo((object)"Furious Trobbio: disabled the native Stun Control FSM; staggers are removed."); } } } [HarmonyPrefix] [HarmonyPatch(typeof(SetHP), "OnEnter")] private static void ReplaceTrobbioStartingHealth(SetHP __instance) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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) if (__instance == null || __instance.hp == null || __instance.hp.Value != 950) { return; } GameObject safe = FSMUtility.GetSafe(__instance.target, (FsmStateAction)(object)__instance); Fsm fsm = ((FsmStateAction)__instance).Fsm; PlayMakerFSM val = ((fsm != null) ? fsm.FsmComponent : null); Scene val2; int num; if ((Object)(object)safe != (Object)null) { val2 = safe.scene; if (((Scene)(ref val2)).IsValid()) { val2 = safe.scene; num = ((((Scene)(ref val2)).name == "Library_13") ? 1 : 0); goto IL_0086; } } num = 0; goto IL_0086; IL_0086: bool flag = (byte)num != 0; bool flag2 = ((Object)(object)safe != (Object)null && IsTrobbioHierarchy(safe.transform)) || ((Object)(object)val != (Object)null && IsTrobbioHierarchy(((Component)val).transform)); if (!flag) { val2 = SceneManager.GetActiveScene(); if (((Scene)(ref val2)).name != "Library_13") { return; } } if (flag2) { __instance.hp.Value = 1500; Instance.Log.LogInfo((object)("Furious Trobbio: changed native SetHP from " + 950 + " to " + 1500 + " before scene initialization completed.")); } } private static void AddComplementaryBombBlast(FsmState state, PlayMakerFSM fsm) { //IL_0092: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) if (!(state.Name != "Explode") && !(((Object)((Component)fsm).gameObject).name != "Trobbio Cross Bomb(Clone)")) { DestroyComplementaryBombAntic(((Component)fsm).gameObject); Transform val = ((Component)fsm).transform.Find("Blast"); if ((Object)(object)val == (Object)null) { Instance.Log.LogWarning((object)"Furious Trobbio: Cross Bomb Blast child was not found."); return; } GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, val.parent); Transform transform = val2.transform; transform.localPosition = val.localPosition; transform.localRotation = val.localRotation * Quaternion.Euler(0f, 0f, 45f); transform.localScale = val.localScale; Object.Destroy((Object)(object)val2, 2f); Instance.Log.LogInfo((object)"Furious Trobbio: added complementary 45-degree Cross Bomb blast."); } } private static void AddComplementaryBombAntic(FsmState state, PlayMakerFSM fsm) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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_00be: Unknown result type (might be due to invalid IL or missing references) if (state.Name != "Antic" || ((Object)((Component)fsm).gameObject).name != "Trobbio Cross Bomb(Clone)") { return; } Transform val = ((Component)fsm).transform.Find("Pt Antic"); if ((Object)(object)val == (Object)null) { Instance.Log.LogWarning((object)"Furious Trobbio: Cross Bomb Pt Antic child was not found."); return; } GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, val.parent); Transform transform = val2.transform; transform.localPosition = val.localPosition; transform.localRotation = val.localRotation * Quaternion.Euler(0f, 0f, 45f); transform.localScale = val.localScale; val2.SetActive(true); RestartParticleSystems(val2); int instanceID = ((Object)((Component)fsm).gameObject).GetInstanceID(); if (ComplementaryBombAntics.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } ComplementaryBombAntics[instanceID] = val2; ((MonoBehaviour)Instance).StartCoroutine(DestroyComplementaryAnticWithNative(((Component)fsm).gameObject, ((Component)val).gameObject, val2)); Instance.Log.LogInfo((object)"Furious Trobbio: added complementary 45-degree Cross Bomb antic."); } private static IEnumerator DestroyComplementaryAnticWithNative(GameObject bomb, GameObject nativeAntic, GameObject complementaryAntic) { yield return null; while ((Object)(object)nativeAntic != (Object)null && nativeAntic.activeInHierarchy) { yield return null; } if ((Object)(object)complementaryAntic != (Object)null) { Object.Destroy((Object)(object)complementaryAntic); } RemoveTrackedComplementaryAntic(bomb, complementaryAntic); } private static void DestroyComplementaryBombAntic(GameObject bomb) { int instanceID = ((Object)bomb).GetInstanceID(); if (ComplementaryBombAntics.TryGetValue(instanceID, out var value)) { ComplementaryBombAntics.Remove(instanceID); if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } } private static void RemoveTrackedComplementaryAntic(GameObject bomb, GameObject complementaryAntic) { if (!((Object)(object)bomb == (Object)null)) { int instanceID = ((Object)bomb).GetInstanceID(); if (ComplementaryBombAntics.TryGetValue(instanceID, out var value) && (Object)(object)value == (Object)(object)complementaryAntic) { ComplementaryBombAntics.Remove(instanceID); } } } [HarmonyPrefix] [HarmonyPatch(typeof(SendRandomEventV4), "OnEnter")] private static bool OverrideTrobbioMoveSelection(SendRandomEventV4 __instance) { if (!IsTrobbioChoiceAction(__instance)) { return true; } ConfigureTrapdoorHealthThreshold(((FsmStateAction)__instance).Fsm.FsmComponent); if ((Object)(object)crossBombPrefab == (Object)null) { crossBombPrefab = FindCrossBombPrefab(((FsmStateAction)__instance).Fsm.FsmComponent); Instance.Log.LogInfo((object)("Furious Trobbio: runtime Choice Cross Bomb prefab = " + DescribeObject(crossBombPrefab))); } if (TryStartSecondPhase(((FsmStateAction)__instance).Fsm.FsmComponent)) { return false; } string text = ((consecutiveBombThrowCount >= 3) ? (secondPhaseTriggered ? ((Random.value < 0.5f) ? "DAZZLE FLASH" : "TORNADO") : "DAZZLE FLASH") : ((!secondPhaseTriggered) ? (lastSelectedAttackWasDazzleFlash ? "BOMB THROW" : ((Random.value < 0.5f) ? "DAZZLE FLASH" : "BOMB THROW")) : (lastSelectedAttackWasDazzleFlash ? ((Random.value < 0.5f) ? "BOMB THROW" : "TORNADO") : ((!lastSelectedAttackWasTornado) ? (Random.Range(0, 3) switch { 1 => "BOMB THROW", 0 => "DAZZLE FLASH", _ => "TORNADO", }) : ((Random.value < 0.5f) ? "DAZZLE FLASH" : "BOMB THROW"))))); bool flag = (lastSelectedAttackWasDazzleFlash = text == "DAZZLE FLASH"); consecutiveBombThrowCount = ((text == "BOMB THROW") ? (consecutiveBombThrowCount + 1) : 0); fireworksArmed = flag; fireworksExtensionRunning = false; extraAnticsPrepared = false; Instance.Log.LogInfo((object)("Furious Trobbio: replacing Choice random selection with " + text + ".")); ((FsmStateAction)__instance).Fsm.Event(text); return false; } private static bool IsTrobbioChoiceAction(SendRandomEventV4 action) { if (!inTrobbioFight || action == null) { return false; } FsmState state = ((FsmStateAction)action).State; Fsm fsm = ((FsmStateAction)action).Fsm; PlayMakerFSM val = ((fsm != null) ? fsm.FsmComponent : null); bool flag = ((state != null) ? state.Name : null) == "Choice"; bool flag2 = ((val != null) ? val.FsmName : null) == "Control"; bool flag3 = (Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name.Contains("Trobbio"); return flag && flag2 && flag3; } private static void CacheBossReferences(PlayMakerFSM fsm) { if (!((Object)(object)bossControlFsm != (Object)null)) { bossControlFsm = fsm; crossBlast90 = FindChildOrSceneObject(((Component)fsm).transform, "CrossBlast 90"); crossBlast45 = FindChildOrSceneObject(((Component)fsm).transform, "CrossBlast 45"); crossBlastAntic90 = FindChildOrSceneObject(((Component)fsm).transform, "CrossBlast Antic 90"); crossBlastAntic45 = FindChildOrSceneObject(((Component)fsm).transform, "CrossBlast Antic 45"); crossBombPrefab = FindCrossBombPrefab(fsm); if (!healthSetupRunning) { healthSetupRunning = true; ((MonoBehaviour)Instance).StartCoroutine(FindAndReplaceTrobbioHealth()); } ConfigureTrapdoorBurstSequence(); Instance.Log.LogInfo((object)"Furious Trobbio: cached Control FSM and fireworks references."); Instance.Log.LogInfo((object)("Furious Trobbio: CrossBlast 90 = " + DescribeObject(crossBlast90))); Instance.Log.LogInfo((object)("Furious Trobbio: CrossBlast 45 = " + DescribeObject(crossBlast45))); Instance.Log.LogInfo((object)("Furious Trobbio: CrossBlast Antic 90 = " + DescribeObject(crossBlastAntic90))); Instance.Log.LogInfo((object)("Furious Trobbio: CrossBlast Antic 45 = " + DescribeObject(crossBlastAntic45))); Instance.Log.LogInfo((object)("Furious Trobbio: Cross Bomb prefab = " + DescribeObject(crossBombPrefab))); } } private static GameObject FindCrossBombPrefab(PlayMakerFSM controlFsm) { FsmState val = Array.Find(controlFsm.FsmStates, (FsmState state) => state.Name == "Throw"); if (val == null) { return null; } FsmStateAction[] actions = val.Actions; foreach (FsmStateAction val2 in actions) { SpawnObjectFromGlobalPool val3 = (SpawnObjectFromGlobalPool)(object)((val2 is SpawnObjectFromGlobalPool) ? val2 : null); object obj; if (val3 == null) { obj = null; } else { FsmGameObject gameObject = val3.gameObject; obj = ((gameObject != null) ? gameObject.Value : null); } GameObject val4 = (GameObject)obj; if ((Object)(object)val4 != (Object)null && ((Object)val4).name.Contains("Trobbio Cross Bomb")) { return val4; } } return null; } private static bool TryStartSecondPhase(PlayMakerFSM controlFsm) { if (secondPhaseTriggered || (Object)(object)controlFsm == (Object)null) { return false; } HealthManager component = ((Component)controlFsm).GetComponent<HealthManager>(); if ((Object)(object)component == (Object)null || component.hp > 600) { return false; } secondPhaseTriggered = true; controlFsm.SetState("Phase Roar Antic"); Instance.Log.LogInfo((object)("Furious Trobbio: started second phase roar at " + component.hp + " HP; Furious Tornado bombs are now enabled.")); return true; } private static void StartFuriousTornadoBombs(PlayMakerFSM controlFsm) { if (secondPhaseTriggered && !tornadoBombSequenceRunning && !tornadoBombsStartedThisAttack) { if ((Object)(object)crossBombPrefab == (Object)null) { Instance.Log.LogWarning((object)"Furious Trobbio: third-phase Tornado began without a cached Cross Bomb prefab."); return; } tornadoBombsStartedThisAttack = true; ((MonoBehaviour)Instance).StartCoroutine(ReleaseTornadoBombs(controlFsm)); } } private static IEnumerator ReleaseTornadoBombs(PlayMakerFSM controlFsm) { tornadoBombSequenceRunning = true; Instance.Log.LogInfo((object)"Furious Trobbio: Furious Tornado will release 3 Cross Bombs."); for (int index = 0; index < 3; index++) { yield return (object)new WaitForSeconds(Random.Range(0.25f, 0.65f)); if ((Object)(object)controlFsm == (Object)null || (controlFsm.ActiveStateName != "Tornado" && controlFsm.ActiveStateName != "Tornado Turn")) { break; } SpawnTornadoCrossBomb(((Component)controlFsm).transform.position); } tornadoBombSequenceRunning = false; } private static void SpawnTornadoCrossBomb(Vector3 position) { //IL_0006: 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) GameObject val = ObjectPoolExtensions.Spawn(crossBombPrefab, position); if ((Object)(object)val == (Object)null) { Instance.Log.LogWarning((object)"Furious Trobbio: failed to obtain a Cross Bomb from the native pool."); return; } float num; do { num = Random.Range(-12f, 12f); } while (Mathf.Abs(num) < 4f); float num2 = Random.Range(6f, 12f); PlayMakerFSM val2 = Array.Find(val.GetComponents<PlayMakerFSM>(), (PlayMakerFSM candidate) => candidate.FsmName == "Control"); if ((Object)(object)val2 != (Object)null) { val2.FsmVariables.GetFsmFloat("X Velocity").Value = num; } Rigidbody2D component = val.GetComponent<Rigidbody2D>(); if ((Object)(object)component != (Object)null) { component.linearVelocity = new Vector2(num, num2); } Instance.Log.LogInfo((object)("Furious Trobbio: released whirlwind Cross Bomb with velocity (" + num.ToString("0.0") + ", " + num2.ToString("0.0") + ").")); } private static void ExtendNativeFireworks(FsmState flashBurstState) { if (fireworksArmed && !fireworksExtensionRunning) { GameObject nativeCrossBlast = GetNativeCrossBlast(flashBurstState); if ((Object)(object)nativeCrossBlast == (Object)null) { Instance.Log.LogWarning((object)"Furious Trobbio: could not identify the native CrossBlast; extension aborted."); fireworksArmed = false; } else { RestartCrossBlastParticles(nativeCrossBlast); ((MonoBehaviour)Instance).StartCoroutine(PlayExtraFireworkWaves()); } } } private static void PrepareExtraFireworkAntics() { if (fireworksArmed && !extraAnticsPrepared) { extraAnticsPrepared = true; Instance.Log.LogInfo((object)"Furious Trobbio: starting extra CrossBlast antics during Flash JumpAntic."); Trigger(crossBlastAntic90, "CrossBlast Antic 90"); Trigger(crossBlastAntic45, "CrossBlast Antic 45"); } } private static GameObject GetNativeCrossBlast(FsmState flashBurstState) { FsmStateAction[] actions = flashBurstState.Actions; foreach (FsmStateAction val in actions) { if (!(val is ActivateGameObject)) { continue; } try { object? obj = ((object)val).GetType().GetField("activatedGameObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val); GameObject val2 = (GameObject)((obj is GameObject) ? obj : null); if (((val2 != null) ? ((Object)val2).name : null) == "CrossBlast 90") { nativeFireworkIsPlus = true; return val2; } if (((val2 != null) ? ((Object)val2).name : null) == "CrossBlast 45") { nativeFireworkIsPlus = false; return val2; } } catch (Exception ex) { Instance.Log.LogWarning((object)("Furious Trobbio: failed to inspect Flash Burst action: " + ex.Message)); } } nativeFireworkIsPlus = true; return crossBlast90; } private static IEnumerator PlayExtraFireworkWaves() { fireworksExtensionRunning = true; GameObject secondBurst = (nativeFireworkIsPlus ? crossBlast45 : crossBlast90); GameObject thirdBurst = (nativeFireworkIsPlus ? crossBlast90 : crossBlast45); yield return (object)new WaitForSeconds(0.15f); TriggerCrossBlast(secondBurst, "Wave 2 CrossBlast"); yield return (object)new WaitForSeconds(0.15f); TriggerCrossBlast(thirdBurst, "Wave 3 CrossBlast"); fireworksArmed = false; fireworksExtensionRunning = false; Instance.Log.LogInfo((object)"Furious Trobbio: 3-wave Furious Fireworks sequence complete."); } private static void Trigger(GameObject gameObject, string description) { if ((Object)(object)gameObject == (Object)null) { Instance.Log.LogWarning((object)("Furious Trobbio: " + description + " object is missing.")); return; } gameObject.SetActive(false); gameObject.SetActive(true); } private static void TriggerCrossBlast(GameObject burst, string description) { Trigger(burst, description); RestartCrossBlastParticles(burst); } private static void RestartCrossBlastParticles(GameObject burst) { RestartParticleSystems(burst); } private static void RestartParticleSystems(GameObject effect) { if (!((Object)(object)effect == (Object)null)) { ParticleSystem[] componentsInChildren = effect.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val in componentsInChildren) { val.Stop(true, (ParticleSystemStopBehavior)0); val.Play(true); } } } private static IEnumerator FindAndReplaceTrobbioHealth() { bool loggedCandidates = false; for (int frame = 0; frame < 120; frame++) { HealthManager[] array = Resources.FindObjectsOfTypeAll<HealthManager>(); foreach (HealthManager healthManager in array) { int num2; if (!((Object)(object)healthManager == (Object)null)) { Scene scene = ((Component)healthManager).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { scene = ((Component)healthManager).gameObject.scene; if (!(((Scene)(ref scene)).name != "Library_13")) { num2 = ((!IsTrobbioHierarchy(((Component)healthManager).transform)) ? 1 : 0); goto IL_00c5; } } } num2 = 1; goto IL_00c5; IL_00c5: if (num2 == 0) { int initialHealth = Traverse.Create((object)healthManager).Field("initHp").GetValue<int>(); if (!loggedCandidates) { Instance.Log.LogInfo((object)("Furious Trobbio [HEALTH]: candidate " + GetHierarchyPath(((Component)healthManager).transform) + ", hp=" + healthManager.hp + ", initHp=" + initialHealth + ".")); } if (healthManager.hp == 950 || initialHealth == 950) { healthManager.hp = 1500; Traverse.Create((object)healthManager).Field("initHp").SetValue((object)1500); Instance.Log.LogInfo((object)("Furious Trobbio: changed actual Trobbio HealthManager from " + 950 + " to " + 1500 + " at " + GetHierarchyPath(((Component)healthManager).transform) + ".")); healthSetupRunning = false; yield break; } } } loggedCandidates = true; yield return null; } healthSetupRunning = false; Instance.Log.LogWarning((object)"Furious Trobbio [HEALTH]: no 950-HP Trobbio HealthManager appeared during startup."); } private static void ConfigureTrapdoorBurstSequence() { //IL_0062: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (trapdoorSequenceConfigured) { return; } int num = 0; PlayMakerFSM[] array = Resources.FindObjectsOfTypeAll<PlayMakerFSM>(); foreach (PlayMakerFSM val in array) { if ((Object)(object)val == (Object)null || ((Object)((Component)val).gameObject).name != "Trapdoor Bursts" || val.FsmName != "Control") { continue; } Scene scene = ((Component)val).gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { continue; } scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).name != "Library_13" || !IsInNamedHierarchy(((Component)val).transform, "Boss Scene TormentedTrobbio")) { continue; } string[] array2 = new string[8] { "L Ptn 1", "L Ptn 2", "R Ptn 1", "R Ptn 2", "M Ptn 1", "M Ptn 2", "Mid L", "Mid R" }; string[] array3 = array2; foreach (string stateName in array3) { FsmState val2 = Array.Find(val.FsmStates, (FsmState candidate) => candidate.Name == stateName); if (val2 == null) { Instance.Log.LogWarning((object)("Furious Trobbio: missing trapdoor pattern state " + stateName + ".")); return; } val2.Actions = (FsmStateAction[])(object)new FsmStateAction[1] { new FuriousTrapdoorSequenceAction() }; } num++; } if (num > 0) { trapdoorSequenceConfigured = true; Instance.Log.LogInfo((object)("Furious Trobbio: configured ten-burst sequence on " + num + " Tormented trapdoor controller(s).")); } } private static void ConfigureTrapdoorHealthThreshold(PlayMakerFSM controlFsm) { if (trapdoorHealthThresholdConfigured || (Object)(object)controlFsm == (Object)null) { return; } FsmState val = Array.Find(controlFsm.FsmStates, (FsmState state) => state.Name == "Choice"); if (val != null && val.Actions.Length > 4) { FsmStateAction obj = val.Actions[4]; CompareHPBool val2 = (CompareHPBool)(object)((obj is CompareHPBool) ? obj : null); if (val2 != null) { int value = val2.compareTo.Value; val2.compareTo.Value = 1100; trapdoorHealthThresholdConfigured = true; Instance.Log.LogInfo((object)("Furious Trobbio: changed Burst Columns health threshold from " + value + " to " + 1100 + ".")); } else { trapdoorHealthThresholdConfigured = true; Instance.Log.LogWarning((object)"Furious Trobbio: Choice action 4 was not a CompareHPBool action."); } } } private static void StartTrapdoorSequence(FsmStateAction action) { if (trapdoorSequenceRunning) { return; } object obj; if (action == null) { obj = null; } else { Fsm fsm = action.Fsm; obj = ((fsm != null) ? fsm.FsmComponent : null); } PlayMakerFSM val = (PlayMakerFSM)obj; if ((Object)(object)val == (Object)null) { Instance.Log.LogWarning((object)"Furious Trobbio: trapdoor controller was unavailable."); return; } string nativeFinalBurstName = GetNativeFinalBurstName(action.State.Name); if (nativeFinalBurstName == null) { Instance.Log.LogWarning((object)("Furious Trobbio: no native final burst mapping for " + action.State.Name + ".")); } else if (secondPhaseTriggered) { ((MonoBehaviour)Instance).StartCoroutine(PlayWraithfulWave(val, nativeFinalBurstName)); } else { ((MonoBehaviour)Instance).StartCoroutine(PlayTenTrapdoorBursts(val, nativeFinalBurstName)); } } private static IEnumerator PlayWraithfulWave(PlayMakerFSM controller, string finalBurstName) { trapdoorSequenceRunning = true; Transform burstContainer = ((Component)controller).transform.Find("Bursts"); if ((Object)(object)burstContainer == (Object)null) { Instance.Log.LogWarning((object)"Furious Trobbio: Wraithful Wave could not find the Bursts container."); trapdoorSequenceRunning = false; yield break; } List<GameObject> sequence = new List<GameObject>(); for (char letter = 'A'; letter <= 'G'; letter = (char)(letter + 1)) { Transform burst = burstContainer.Find("Burst " + letter); if ((Object)(object)burst == (Object)null) { Instance.Log.LogWarning((object)("Furious Trobbio: Wraithful Wave could not find Burst " + letter + ".")); trapdoorSequenceRunning = false; yield break; } sequence.Add(((Component)burst).gameObject); } sequence.Sort((GameObject left, GameObject right) => left.transform.position.x.CompareTo(right.transform.position.x)); int waitFrames = 0; while (((Object)(object)runtimeBossControlFsm == (Object)null || runtimeBossControlFsm.ActiveStateName != "BC Attack") && waitFrames < 120) { waitFrames++; yield return null; } if ((Object)(object)runtimeBossControlFsm == (Object)null || runtimeBossControlFsm.ActiveStateName != "BC Attack") { Instance.Log.LogWarning((object)("Furious Trobbio: Wraithful Wave boss did not reach BC Attack; active state=" + (((Object)(object)runtimeBossControlFsm == (Object)null) ? "MISSING" : runtimeBossControlFsm.ActiveStateName) + ".")); } Transform nativeEmergence = burstContainer.Find(finalBurstName); GameObject emergenceBurst = (((Object)(object)nativeEmergence == (Object)null) ? null : ((Component)nativeEmergence).gameObject); if ((Object)(object)emergenceBurst == (Object)null) { Instance.Log.LogWarning((object)("Furious Trobbio: Wraithful Wave could not resolve native emergence burst " + finalBurstName + ".")); trapdoorSequenceRunning = false; yield break; } int missingPosition; do { missingPosition = Random.Range(0, sequence.Count); } while ((Object)(object)sequence[missingPosition] == (Object)(object)emergenceBurst); GameObject missingBurst = sequence[missingPosition]; sequence.RemoveAt(missingPosition); bool travelsRight = Random.value < 0.5f; if (!travelsRight) { sequence.Reverse(); } int emergenceIndex = sequence.IndexOf(emergenceBurst); int emergenceSlot = emergenceIndex + 1; Instance.Log.LogInfo((object)("Furious Trobbio: Wraithful Wave started " + (travelsRight ? "left-to-right" : "right-to-left") + "; safe gap=" + ((Object)missingBurst).name + ", emergence slot=" + emergenceSlot + ", burst=" + ((Object)sequence[emergenceSlot - 1]).name + ".")); for (int index = 0; index < sequence.Count; index++) { GameObject burst2 = sequence[index]; if (index + 1 == emergenceSlot) { controller.FsmVariables.GetFsmGameObject("Final Burst").Value = burst2; if ((Object)(object)runtimeBossControlFsm != (Object)null && runtimeBossControlFsm.ActiveStateName == "BC Attack") { runtimeBossControlFsm.Fsm.Event("FINAL BURST"); } controller.SetState("Final Burst"); yield return null; if ((Object)(object)runtimeBossControlFsm != (Object)null && runtimeBossControlFsm.ActiveStateName == "BC Attack") { Instance.Log.LogWarning((object)"Furious Trobbio: Wraithful Wave native handoff left boss in BC Attack; sending recovery event."); runtimeBossControlFsm.Fsm.Event("FINAL BURST"); } } else { RestartTrapdoorBurst(burst2); } if (index < sequence.Count - 1) { yield return (object)new WaitForSeconds(0.1f); } } trapdoorSequenceRunning = false; Instance.Log.LogInfo((object)"Furious Trobbio: Wraithful Wave complete."); } private static IEnumerator PlayTenTrapdoorBursts(PlayMakerFSM controller, string finalBurstName) { trapdoorSequenceRunning = true; Transform burstContainer = ((Component)controller).transform.Find("Bursts"); if ((Object)(object)burstContainer == (Object)null) { Instance.Log.LogWarning((object)"Furious Trobbio: trapdoor Bursts container was not found."); trapdoorSequenceRunning = false; yield break; } List<GameObject> firstSeven = new List<GameObject>(); for (char letter = 'A'; letter <= 'G'; letter = (char)(letter + 1)) { Transform burst = burstContainer.Find("Burst " + letter); if ((Object)(object)burst == (Object)null) { Instance.Log.LogWarning((object)("Furious Trobbio: Burst " + letter + " was not found.")); trapdoorSequenceRunning = false; yield break; } firstSeven.Add(((Component)burst).gameObject); } Shuffle(firstSeven); List<GameObject> sequence = new List<GameObject>(firstSeven); List<GameObject> repeats = new List<GameObject>(); for (int index = 0; index < 3; index++) { repeats.Add(firstSeven[index]); } Shuffle(repeats); sequence.AddRange(repeats); int emergenceSlot = Random.Range(6, 9); int emergenceIndex = emergenceSlot - 1; int nativeFinalIndex = sequence.FindIndex((GameObject val) => ((Object)val).name == finalBurstName); GameObject displacedBurst = sequence[emergenceIndex]; sequence[emergenceIndex] = sequence[nativeFinalIndex]; sequence[nativeFinalIndex] = displacedBurst; float[] burstGaps = new float[sequence.Count - 1]; float timeToEmergence; do { timeToEmergence = 0f; for (int index2 = 0; index2 < burstGaps.Length; index2++) { burstGaps[index2] = Random.Range(0.15f, 0.35f); if (index2 < emergenceIndex) { timeToEmergence += burstGaps[index2]; } } } while (timeToEmergence < 1.25f); Instance.Log.LogInfo((object)("Furious Trobbio: " + sequence.Count + "-burst sequence started; emergence slot=" + emergenceSlot + ", burst=" + finalBurstName + ", emergence time=" + timeToEmergence + ".")); for (int index3 = 0; index3 < sequence.Count; index3++) { GameObject burst2 = sequence[index3]; int slot = index3 + 1; if (slot == emergenceSlot) { int waitFrames = 0; while (((Object)(object)runtimeBossControlFsm == (Object)null || runtimeBossControlFsm.ActiveStateName != "BC Attack") && waitFrames < 120) { waitFrames++; yield return null; } if ((Object)(object)runtimeBossControlFsm == (Object)null || runtimeBossControlFsm.ActiveStateName != "BC Attack") { Instance.Log.LogWarning((object)("Furious Trobbio: boss did not reach BC Attack before emergence; active state=" + (((Object)(object)runtimeBossControlFsm == (Object)null) ? "MISSING" : runtimeBossControlFsm.ActiveStateName) + ".")); } controller.FsmVariables.GetFsmGameObject("Final Burst").Value = burst2; if ((Object)(object)runtimeBossControlFsm != (Object)null && runtimeBossControlFsm.ActiveStateName == "BC Attack") { runtimeBossControlFsm.Fsm.Event("FINAL BURST"); } controller.SetState("Final Burst"); yield return null; if ((Object)(object)runtimeBossControlFsm != (Object)null && runtimeBossControlFsm.ActiveStateName == "BC Attack") { Instance.Log.LogWarning((object)"Furious Trobbio: native FINAL BURST handoff did not leave BC Attack; sending recovery event."); runtimeBossControlFsm.Fsm.Event("FINAL BURST"); } } else { RestartTrapdoorBurst(burst2); } if (index3 < sequence.Count - 1) { yield return (object)new WaitForSeconds(burstGaps[index3]); } } trapdoorSequenceRunning = false; Instance.Log.LogInfo((object)("Furious Trobbio: " + sequence.Count + "-burst trapdoor sequence complete.")); } private static string GetNativeFinalBurstName(string patternStateName) { switch (patternStateName) { case "L Ptn 1": case "L Ptn 2": return "Burst C"; case "R Ptn 1": case "R Ptn 2": return "Burst E"; case "M Ptn 1": case "M Ptn 2": return "Burst D"; case "Mid L": return "Burst B"; case "Mid R": return "Burst F"; default: return null; } } private static void RestartTrapdoorBurst(GameObject burst) { burst.SetActive(false); burst.SetActive(true); } private static void Shuffle<T>(IList<T> values) { for (int num = values.Count - 1; num > 0; num--) { int index = Random.Range(0, num + 1); T value = values[num]; values[num] = values[index]; values[index] = value; } } private static string GetHierarchyPath(Transform transform) { string text = ((Object)transform).name; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } private static bool IsTrobbioHierarchy(Transform transform) { Transform val = transform; while ((Object)(object)val != (Object)null) { if (((Object)val).name.Contains("Trobbio")) { return true; } val = val.parent; } return false; } private static bool IsInNamedHierarchy(Transform transform, string name) { Transform val = transform; while ((Object)(object)val != (Object)null) { if (((Object)val).name == name) { return true; } val = val.parent; } return false; } private static GameObject FindSceneObjectExact(string name) { //IL_0029: 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) GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject val in array) { if ((Object)(object)val != (Object)null && ((Object)val).name == name) { Scene scene = val.scene; if (((Scene)(ref scene)).IsValid()) { return val; } } } return null; } private static GameObject FindChildOrSceneObject(Transform parent, string name) { GameObject val = FindChildAnyDepth(parent, name); return val ?? FindSceneObjectExact(name); } private static GameObject FindChildAnyDepth(Transform parent, string name) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown foreach (Transform item in parent) { Transform val = item; if (((Object)val).name == name) { return ((Component)val).gameObject; } GameObject val2 = FindChildAnyDepth(val, name); if ((Object)(object)val2 != (Object)null) { return val2; } } return null; } private static string DescribeObject(GameObject gameObject) { return ((Object)(object)gameObject == (Object)null) ? "MISSING" : "FOUND"; } }