Decompiled source of Furious Trobbio v1.0.1

FuriousTrobbio.dll

Decompiled 2 hours ago
using 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";
	}
}