Decompiled source of GladiatorArenaCompat v1.0.1

BepInEx/plugins/GladiatorArenaCompat/ArenaLoaderCompat.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace ArenaLoaderCompat;

[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("chatgpt.repo.arenaloadercompat", "Arena Loader Compatibility", "0.3.2")]
public sealed class Plugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	internal static Plugin Instance;

	internal static ConfigEntry<float> FeralMusicVolume;

	internal static ConfigEntry<float> FeralPreparationDelaySeconds;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Expected O, but got Unknown
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Instance = this;
		FeralMusicVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Feral Arena", "MusicVolume", 0.05f, "Volume de la musique Gladiator/Feral Arena. 0 = muet, 1 = volume original.");
		FeralPreparationDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Feral Arena", "PreparationDelaySeconds", 12f, "Temps de preparation apres le debut du round avant que les ennemis puissent detecter les joueurs. 0 = desactive.");
		if (Mathf.Approximately(FeralMusicVolume.Value, 0.25f))
		{
			FeralMusicVolume.Value = 0.05f;
			((BaseUnityPlugin)this).Config.Save();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[ArenaCompat] Migrated Feral music volume from 0.25 to 0.05.");
		}
		_harmony = new Harmony("chatgpt.repo.arenaloadercompat.v032");
		DisableLegacyArenaLoaderPostfix();
		MethodInfo methodInfo = AccessTools.Method(typeof(LevelGenerator), "Start", (Type[])null, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(LevelGeneratorStartPatch), "Postfix", (Type[])null, (Type[])null);
		if (methodInfo == null || methodInfo2 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ArenaCompat] LevelGenerator.Start patch could not be installed.");
			return;
		}
		HarmonyMethod val = new HarmonyMethod(methodInfo2);
		val.priority = 0;
		_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		InstallStalePlayerDeathHeadGuard();
		InstallCustomArenaStaleScriptGuards();
		InstallFeralPreparationSafetyGuard();
		InstallFeralCrownGrabHooks();
		InstallFeralCrownLifetimeGuard();
		((MonoBehaviour)this).StartCoroutine(InstallFeralRuntimeCompatibility());
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Arena Loader Compatibility 0.3.2 FINAL loaded. 50/50 vanilla/Gladiator rotation active. Feral music volume=" + Mathf.Clamp01(FeralMusicVolume.Value).ToString("0.00") + ", preparation delay=" + Mathf.Max(0f, FeralPreparationDelaySeconds.Value).ToString("0.0") + "s."));
	}

	private void InstallStalePlayerDeathHeadGuard()
	{
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("PlayerDeathHead");
		if (type == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"[ArenaCompat] PlayerDeathHead type not found; stale prefab guard not installed.");
			return;
		}
		MethodInfo methodInfo = AccessTools.Method(typeof(StaleArenaComponentGuard), "PlayerDeathHeadPrefix", (Type[])null, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(type, "Start", (Type[])null, (Type[])null);
		MethodInfo methodInfo3 = AccessTools.Method(type, "Update", (Type[])null, (Type[])null);
		if (!(methodInfo == null))
		{
			HarmonyMethod val = new HarmonyMethod(methodInfo);
			val.priority = 800;
			if (methodInfo2 != null)
			{
				_harmony.Patch((MethodBase)methodInfo2, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			if (methodInfo3 != null)
			{
				_harmony.Patch((MethodBase)methodInfo3, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[ArenaCompat] Custom-arena PlayerDeathHead stale-component guard active.");
		}
	}

	private void InstallCustomArenaStaleScriptGuards()
	{
		MethodInfo methodInfo = AccessTools.Method(typeof(CustomArenaStaleScriptGuard), "ComponentPrefix", (Type[])null, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(CustomArenaStaleScriptGuard), "ArenaVisualPrefix", (Type[])null, (Type[])null);
		MethodInfo methodInfo3 = AccessTools.Method(typeof(CustomArenaStaleScriptGuard), "ArenaFinalizer", (Type[])null, (Type[])null);
		if (methodInfo == null || methodInfo2 == null || methodInfo3 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ArenaCompat] Feral stale-script guard methods were not found.");
			return;
		}
		int num = 0;
		num += PatchPrefixByName("ArenaPlatform", "Start", methodInfo);
		MethodInfo methodInfo4 = AccessTools.Method(typeof(CustomArenaStaleScriptGuard), "ArenaPlatformPulsateLightsPrefix", (Type[])null, (Type[])null);
		if (methodInfo4 != null)
		{
			num += PatchPrefixByName("ArenaPlatform", "PulsateLights", methodInfo4);
		}
		num += PatchPrefixByName("ArenaLight", "Start", methodInfo);
		num += PatchPrefixByName("ArenaLight", "Update", methodInfo);
		num += PatchPrefixByName("ArenaLight", "PulsateLight", methodInfo);
		num += PatchPrefixByName("ArenaPedistalScreen", "Update", methodInfo);
		int num2 = 0;
		MethodInfo methodInfo5 = AccessTools.Method(typeof(CustomArenaStaleScriptGuard), "ItemBatteryLookAtPrefix", (Type[])null, (Type[])null);
		if (methodInfo5 != null)
		{
			num2 += PatchPrefixByName("ItemBattery", "BatteryLookAt", methodInfo5);
		}
		int num3 = 0;
		num3 += PatchPrefixByName("Arena", "MainLightAnimation", methodInfo2);
		num3 += PatchFinalizerByName("Arena", "AllPlayersKilled", methodInfo3);
		num3 += PatchFinalizerByName("Arena", "PlayerKilledRPC", methodInfo3);
		num3 += PatchFinalizerByName("Arena", "DestroyCrownCageRPC", methodInfo3);
		num3 += PatchFinalizerByName("Arena", "CrownGrabRPC", methodInfo3);
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[ArenaCompat] Feral stale-script guards active | componentMethods=" + num + " | batteryMethods=" + num2 + " | arenaMethods=" + num3 + "."));
	}

	private int PatchPrefixByName(string typeName, string methodName, MethodInfo prefix)
	{
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Expected O, but got Unknown
		Type type = AccessTools.TypeByName(typeName);
		if (type == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[ArenaCompat] Type not found for stale guard: " + typeName + "."));
			return 0;
		}
		MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
		if (methodInfo == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[ArenaCompat] Method not found for stale guard: " + typeName + "." + methodName + "."));
			return 0;
		}
		HarmonyMethod val = new HarmonyMethod(prefix);
		val.priority = 800;
		_harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		return 1;
	}

	private int PatchFinalizerByName(string typeName, string methodName, MethodInfo finalizer)
	{
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Expected O, but got Unknown
		Type type = AccessTools.TypeByName(typeName);
		if (type == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[ArenaCompat] Type not found for finalizer: " + typeName + "."));
			return 0;
		}
		MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
		if (methodInfo == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[ArenaCompat] Method not found for finalizer: " + typeName + "." + methodName + "."));
			return 0;
		}
		HarmonyMethod val = new HarmonyMethod(finalizer);
		val.priority = 0;
		_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null);
		return 1;
	}

	private void InstallFeralPreparationSafetyGuard()
	{
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("EnemyOnScreen");
		MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "GetOnScreen", new Type[1] { typeof(PlayerAvatar) }, (Type[])null) : null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(FeralPreparationOnScreenGuard), "Prefix", (Type[])null, (Type[])null);
		if (methodInfo == null || methodInfo2 == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"[ArenaCompat] FERAL preparation EnemyOnScreen guard could not be installed.");
			return;
		}
		HarmonyMethod val = new HarmonyMethod(methodInfo2);
		val.priority = 800;
		_harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[ArenaCompat] FERAL preparation EnemyOnScreen guard active.");
	}

	private void InstallFeralCrownGrabHooks()
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("StaticGrabObject");
		MethodInfo methodInfo = AccessTools.Method(typeof(FeralCrownGrabHook), "Postfix", (Type[])null, (Type[])null);
		if (type == null || methodInfo == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"[ArenaCompat] FERAL true crown grab hooks could not be installed.");
			return;
		}
		int num = 0;
		MethodInfo methodInfo2 = AccessTools.Method(type, "GrabStarted", (Type[])null, (Type[])null);
		MethodInfo methodInfo3 = AccessTools.Method(type, "GrabStartedRPC", (Type[])null, (Type[])null);
		HarmonyMethod val = new HarmonyMethod(methodInfo);
		val.priority = 0;
		if (methodInfo2 != null)
		{
			_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			num++;
		}
		if (methodInfo3 != null)
		{
			_harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			num++;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[ArenaCompat] FERAL true crown grab hook active | methods=" + num + "."));
	}

	private void InstallFeralCrownLifetimeGuard()
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("StaticGrabObject");
		MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "Update", (Type[])null, (Type[])null) : null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(FeralCrownLifetimeGuard), "Prefix", (Type[])null, (Type[])null);
		if (type == null || methodInfo == null || methodInfo2 == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"[ArenaCompat] FERAL crown lifetime guard could not be installed.");
			return;
		}
		HarmonyMethod val = new HarmonyMethod(methodInfo2);
		val.priority = 800;
		_harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[ArenaCompat] FERAL crown lifetime guard active.");
	}

	private IEnumerator InstallFeralRuntimeCompatibility()
	{
		for (int attempt = 0; attempt < 40; attempt++)
		{
			Type feralType = AccessTools.TypeByName("CustomArenaMod.CustomArenaMod");
			if (feralType != null)
			{
				MethodInfo methodInfo = AccessTools.Method(feralType, "OnSceneLoaded", (Type[])null, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(typeof(FeralSceneLoadedPatch), "Prefix", (Type[])null, (Type[])null);
				if (methodInfo != null && methodInfo2 != null)
				{
					HarmonyMethod val = new HarmonyMethod(methodInfo2);
					val.priority = 800;
					_harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					MethodInfo methodInfo3 = AccessTools.Method(feralType, "Update", (Type[])null, (Type[])null);
					MethodInfo methodInfo4 = AccessTools.Method(typeof(FeralUpdateScopePatch), "Prefix", (Type[])null, (Type[])null);
					if (methodInfo3 != null && methodInfo4 != null)
					{
						HarmonyMethod val2 = new HarmonyMethod(methodInfo4);
						val2.priority = 800;
						_harmony.Patch((MethodBase)methodInfo3, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
					MethodInfo methodInfo5 = AccessTools.Method(feralType, "PlayArenaMusic", (Type[])null, (Type[])null);
					MethodInfo methodInfo6 = AccessTools.Method(typeof(FeralMusicPatch), "Postfix", (Type[])null, (Type[])null);
					if (methodInfo5 != null && methodInfo6 != null)
					{
						HarmonyMethod val3 = new HarmonyMethod(methodInfo6);
						val3.priority = 0;
						_harmony.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[ArenaCompat] Feral runtime scoped to Disposal Arena; Racing Arena protected.");
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[ArenaCompat] Feral music volume patch active.");
					yield break;
				}
			}
			yield return (object)new WaitForSeconds(0.25f);
		}
		((BaseUnityPlugin)this).Logger.LogWarning((object)"[ArenaCompat] Feral Arena runtime was not found; Feral-specific compatibility not installed.");
	}

	private void DisableLegacyArenaLoaderPostfix()
	{
		MethodInfo methodInfo = AccessTools.Method(typeof(LevelGenerator), "Start", (Type[])null, (Type[])null);
		if (methodInfo == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ArenaCompat] LevelGenerator.Start not found while removing legacy Arena Loader patch.");
			return;
		}
		Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
		if (patchInfo == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"[ArenaCompat] LevelGenerator.Start has no Harmony patch info yet.");
			return;
		}
		List<MethodInfo> list = new List<MethodInfo>();
		foreach (Patch postfix in patchInfo.Postfixes)
		{
			MethodInfo patchMethod = postfix.PatchMethod;
			Type type = ((patchMethod != null) ? patchMethod.DeclaringType : null);
			string text = ((type != null) ? type.FullName : "");
			if (string.Equals(text, "Empress_ArenaLoaderAPI.LevelGeneratorPatch", StringComparison.Ordinal) || text.IndexOf("Empress_ArenaLoaderAPI", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				if (patchMethod != null)
				{
					list.Add(patchMethod);
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[ArenaCompat] Found legacy Arena Loader postfix on LevelGenerator.Start | owner='" + postfix.owner + "' | method='" + ((patchMethod != null) ? patchMethod.Name : "<null>") + "'."));
			}
		}
		if (list.Count == 0)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"[ArenaCompat] No legacy Arena Loader postfix found on LevelGenerator.Start.");
			return;
		}
		int num = 0;
		for (int i = 0; i < list.Count; i++)
		{
			try
			{
				_harmony.Unpatch((MethodBase)methodInfo, list[i]);
				num++;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[ArenaCompat] Failed to remove legacy postfix '" + list[i].Name + "': " + ex));
			}
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[ArenaCompat] Legacy ArenaLoaderAPI LevelGenerator.Start postfix removed safely: " + num + "/" + list.Count + "."));
	}
}
internal static class FeralSceneLoadedPatch
{
	internal static bool Prefix(object __instance)
	{
		FeralRuntimeCompatibility.ResetFeralSceneState(__instance);
		FeralRuntimeCompatibility.QueueSceneCheck(__instance);
		return false;
	}
}
internal static class FeralUpdateScopePatch
{
	internal static bool Prefix()
	{
		return FeralRuntimeCompatibility.IsDisposalArenaLevel();
	}
}
internal static class FeralMusicPatch
{
	internal static void Postfix(object __instance)
	{
		if (__instance == null)
		{
			return;
		}
		FeralRuntimeCompatibility.NotifyFeralRoundStarted();
		if (Plugin.FeralMusicVolume != null)
		{
			AudioSource feralMusicSource = FeralRuntimeCompatibility.GetFeralMusicSource(__instance);
			if (!((Object)(object)feralMusicSource == (Object)null))
			{
				feralMusicSource.volume = Mathf.Clamp01(Plugin.FeralMusicVolume.Value);
				Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL music volume applied: " + feralMusicSource.volume.ToString("0.00") + "."));
			}
		}
	}
}
internal static class FeralPreparationOnScreenGuard
{
	private static bool _logged;

	private static bool _missingKeyLogged;

	internal static bool Prefix(object __instance, PlayerAvatar __0, ref bool __result)
	{
		if (!FeralRuntimeCompatibility.IsCustomArenaActive())
		{
			return true;
		}
		if (FeralRuntimeCompatibility.IsPreparationPhaseActive())
		{
			__result = false;
			if (!_logged)
			{
				_logged = true;
				Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL preparation phase is suppressing EnemyOnScreen detection until release.");
			}
			return false;
		}
		if (!HasPlayerEntry(__instance, __0))
		{
			__result = false;
			if (!_missingKeyLogged)
			{
				_missingKeyLogged = true;
				Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL EnemyOnScreen missing-key race suppressed until PlayerAdded catches up.");
			}
			return false;
		}
		return true;
	}

	private static bool HasPlayerEntry(object onScreen, PlayerAvatar player)
	{
		if (onScreen == null || (Object)(object)player == (Object)null)
		{
			return false;
		}
		try
		{
			object member = GetMember(player, "photonView");
			if (!(((member != null) ? GetMember(member, "ViewID") : null) is int num))
			{
				return false;
			}
			return GetMember(onScreen, "OnScreenPlayer") is IDictionary dictionary && dictionary.Contains(num);
		}
		catch
		{
			return false;
		}
	}

	private static object GetMember(object instance, string name)
	{
		if (instance == null)
		{
			return null;
		}
		Type type = instance.GetType();
		BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
		while (type != null)
		{
			FieldInfo field = type.GetField(name, bindingAttr);
			if (field != null)
			{
				return field.GetValue(instance);
			}
			PropertyInfo property = type.GetProperty(name, bindingAttr);
			if (property != null && property.CanRead)
			{
				return property.GetValue(instance, null);
			}
			type = type.BaseType;
		}
		return null;
	}

	internal static void ResetLogState()
	{
		_logged = false;
		_missingKeyLogged = false;
	}
}
internal static class StaleArenaComponentGuard
{
	private static bool _logged;

	internal static bool PlayerDeathHeadPrefix(object __instance)
	{
		Component val = (Component)((__instance is Component) ? __instance : null);
		if ((Object)(object)val == (Object)null)
		{
			return true;
		}
		if (!FeralRuntimeCompatibility.IsInsideCustomArena(val.transform))
		{
			return true;
		}
		Behaviour val2 = (Behaviour)((__instance is Behaviour) ? __instance : null);
		if ((Object)(object)val2 != (Object)null)
		{
			val2.enabled = false;
		}
		if (!_logged)
		{
			_logged = true;
			Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL stale PlayerDeathHead components suppressed inside custom arena.");
		}
		return false;
	}
}
internal static class CustomArenaStaleScriptGuard
{
	private static bool _componentLogged;

	private static bool _arenaPlatformPulsateLogged;

	private static bool _arenaVisualLogged;

	private static bool _arenaExceptionLogged;

	private static bool _postArenaCleanupLogged;

	private static readonly HashSet<int> _feralRuntimeInstanceIds = new HashSet<int>();

	private static bool TrackOrWasFeralRuntimeInstance(object instance, bool broadWhileActive)
	{
		Component val = (Component)((instance is Component) ? instance : null);
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		int instanceID = ((Object)val).GetInstanceID();
		bool flag = FeralRuntimeCompatibility.IsCustomArenaActive();
		if (flag && (broadWhileActive || FeralRuntimeCompatibility.IsInsideCustomArena(val.transform)))
		{
			_feralRuntimeInstanceIds.Add(instanceID);
			return true;
		}
		if (_feralRuntimeInstanceIds.Contains(instanceID))
		{
			if (!flag && !_postArenaCleanupLogged)
			{
				_postArenaCleanupLogged = true;
				Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL post-arena stale runtime callbacks suppressed after level transition.");
			}
			return true;
		}
		return false;
	}

	internal static bool ComponentPrefix(object __instance)
	{
		if (!TrackOrWasFeralRuntimeInstance(__instance, broadWhileActive: false))
		{
			return true;
		}
		if (!_componentLogged)
		{
			_componentLogged = true;
			Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL stale ArenaPlatform/ArenaLight/ArenaPedistalScreen runtime scripts suppressed.");
		}
		return false;
	}

	internal static bool ArenaPlatformPulsateLightsPrefix(object __instance)
	{
		if (!TrackOrWasFeralRuntimeInstance(__instance, broadWhileActive: true))
		{
			return true;
		}
		if (!_arenaPlatformPulsateLogged)
		{
			_arenaPlatformPulsateLogged = true;
			Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL obsolete ArenaPlatform.PulsateLights suppressed during platform warning.");
		}
		return false;
	}

	internal static bool ItemBatteryLookAtPrefix(object __instance)
	{
		return !TrackOrWasFeralRuntimeInstance(__instance, broadWhileActive: true);
	}

	internal static bool ArenaVisualPrefix(object __instance)
	{
		if (!TrackOrWasFeralRuntimeInstance(__instance, broadWhileActive: true))
		{
			return true;
		}
		if (!_arenaVisualLogged)
		{
			_arenaVisualLogged = true;
			Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL obsolete Arena.MainLightAnimation suppressed.");
		}
		return false;
	}

	internal static Exception ArenaFinalizer(object __instance, Exception __exception)
	{
		if (__exception == null)
		{
			return null;
		}
		if (!TrackOrWasFeralRuntimeInstance(__instance, broadWhileActive: true))
		{
			return __exception;
		}
		if (!_arenaExceptionLogged)
		{
			_arenaExceptionLogged = true;
			Plugin.Log.LogWarning((object)"[ArenaCompat] FERAL contained an obsolete vanilla Arena death/crown exception. Remaining compatible logic continues.");
		}
		return null;
	}
}
internal static class FeralCrownLifetimeGuard
{
	internal static bool Prefix(object __instance)
	{
		FeralRuntimeCompatibility.ProtectTrueCrownLifetime(__instance);
		return true;
	}
}
internal static class FeralCrownGrabHook
{
	internal static void Postfix(object __instance)
	{
		FeralRuntimeCompatibility.OnTrueCrownGrabStarted(__instance);
	}
}
internal static class FeralRuntimeCompatibility
{
	private static object _currentFeralArena;

	private static object _currentTrueCrown;

	private static bool _crownInteractionReady;

	private static bool _crownInteractionPrepared;

	private static bool _crownGrabForwardInProgress;

	private static bool _crownGameOverRequested;

	private static GameObject _crownVisibilityMarker;

	private static GameObject _crownReadableVisual;

	private static GameObject _crownGrabProxy;

	private static GameObject _crownSafeRoot;

	private static bool _crownHierarchyDetachedLogged;

	private static bool _sceneCheckRunning;

	private static NavMeshDataInstance _feralNavMeshInstance;

	private static bool _feralNavMeshAdded;

	private static Bounds _feralPlayableBounds;

	private static bool _feralPlayableBoundsValid;

	private static Bounds _feralArenaGroundBounds;

	private static bool _feralArenaGroundBoundsValid;

	private static bool _crownLifetimeGuardLogged;

	private static bool _preparationArmed;

	private static bool _preparationWaitingForRoundStart;

	private static bool _preparationReleased = true;

	private static bool _preparationReleaseLogged;

	private static float _preparationReleaseAt = -1f;

	internal static void QueueSceneCheck(object feralPlugin)
	{
		if (!_sceneCheckRunning && !((Object)(object)Plugin.Instance == (Object)null))
		{
			_sceneCheckRunning = true;
			((MonoBehaviour)Plugin.Instance).StartCoroutine(SingleSceneCheck(feralPlugin));
		}
	}

	private static IEnumerator SingleSceneCheck(object feralPlugin)
	{
		IEnumerator routine = HandleScene(feralPlugin);
		while (routine != null)
		{
			bool more;
			try
			{
				more = routine.MoveNext();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[ArenaCompat] FERAL scene-check failed: " + ex));
				break;
			}
			if (!more)
			{
				break;
			}
			yield return routine.Current;
		}
		_sceneCheckRunning = false;
	}

	internal static IEnumerator HandleScene(object feralPlugin)
	{
		int step = 0;
		while (step < 120 && (!((Object)(object)RunManager.instance != (Object)null) || !((Object)(object)LevelGenerator.Instance != (Object)null) || !LevelGenerator.Instance.Generated))
		{
			step++;
			yield return (object)new WaitForSeconds(0.25f);
		}
		if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated || !IsDisposalArenaLevel())
		{
			yield break;
		}
		Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL arena detected without obsolete Level.ResourcePath lookup.");
		GameObject arenaRoot = null;
		for (int i = 0; i < 24; i++)
		{
			if (!((Object)(object)arenaRoot == (Object)null))
			{
				break;
			}
			arenaRoot = GameObject.Find("Start Room - Arena(Clone)") ?? GameObject.Find("Start Room - Arena");
			if ((Object)(object)arenaRoot == (Object)null)
			{
				yield return (object)new WaitForSeconds(0.25f);
			}
		}
		if ((Object)(object)arenaRoot == (Object)null)
		{
			Plugin.Log.LogWarning((object)"[ArenaCompat] FERAL custom arena root was not found after generation.");
			yield break;
		}
		if (TryBuildFeralNavMesh(arenaRoot))
		{
			SnapArenaLevelPointsToNavMesh(arenaRoot);
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				((MonoBehaviour)Plugin.Instance).StartCoroutine(RepairFeralAgentsDelayed());
			}
		}
		int deathHeads = RemoveStalePlayerDeathHeads(arenaRoot);
		Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL immediate sanitizer removed " + deathHeads + " stale PlayerDeathHead component(s)."));
		IEnumerator originalSanitizer = InvokeCoroutine(feralPlugin, "SilentSanitize", arenaRoot);
		if (originalSanitizer != null && (Object)(object)Plugin.Instance != (Object)null)
		{
			yield return ((MonoBehaviour)Plugin.Instance).StartCoroutine(originalSanitizer);
		}
		EnsureArenaEnemyTrigger(arenaRoot);
		ArmFeralPreparationPhase();
		if (SemiFunc.IsMasterClientOrSingleplayer())
		{
			IEnumerator enumerator = InvokeCoroutine(feralPlugin, "RoundStartRunnerSpawn", 4);
			if (enumerator != null && (Object)(object)Plugin.Instance != (Object)null)
			{
				((MonoBehaviour)Plugin.Instance).StartCoroutine(enumerator);
			}
		}
		Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL post-load setup completed.");
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			((MonoBehaviour)Plugin.Instance).StartCoroutine(FeralLateSpawnPlayerRegistration());
			((MonoBehaviour)Plugin.Instance).StartCoroutine(FeralCrownCompatibility());
		}
	}

	private static void ArmFeralPreparationPhase()
	{
		float num = ((Plugin.FeralPreparationDelaySeconds != null) ? Mathf.Max(0f, Plugin.FeralPreparationDelaySeconds.Value) : 0f);
		_preparationArmed = num > 0f;
		_preparationWaitingForRoundStart = num > 0f;
		_preparationReleased = num <= 0f;
		_preparationReleaseLogged = false;
		_preparationReleaseAt = -1f;
		FeralPreparationOnScreenGuard.ResetLogState();
		if (num <= 0f)
		{
			Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL preparation phase disabled (PreparationDelaySeconds=0).");
		}
		else
		{
			Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL preparation phase armed | delay=" + num.ToString("0.0") + "s | trigger=PlayArenaMusic/door movement."));
		}
	}

	internal static void NotifyFeralRoundStarted()
	{
		if (_preparationArmed && !_preparationReleased && _preparationWaitingForRoundStart)
		{
			float num = ((Plugin.FeralPreparationDelaySeconds != null) ? Mathf.Max(0f, Plugin.FeralPreparationDelaySeconds.Value) : 0f);
			_preparationWaitingForRoundStart = false;
			_preparationReleaseAt = Time.unscaledTime + num;
			Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL preparation phase started | delay=" + num.ToString("0.0") + "s | enemies remain blind until release."));
		}
	}

	internal static bool IsPreparationPhaseActive()
	{
		if (!IsCustomArenaActive())
		{
			return false;
		}
		if (!_preparationArmed || _preparationReleased)
		{
			return false;
		}
		return true;
	}

	private static bool IsFeralPlayerRegistrationReleased()
	{
		if (!_preparationArmed || _preparationReleased)
		{
			return true;
		}
		if (_preparationWaitingForRoundStart)
		{
			return false;
		}
		if (_preparationReleaseAt >= 0f && Time.unscaledTime >= _preparationReleaseAt)
		{
			_preparationReleased = true;
			if (!_preparationReleaseLogged)
			{
				_preparationReleaseLogged = true;
				Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL preparation phase complete | enabling vanilla Enemy.PlayerAdded registration now.");
			}
			return true;
		}
		return false;
	}

	private static IEnumerator FeralLateSpawnPlayerRegistration()
	{
		yield return (object)new WaitForSeconds(0.25f);
		HashSet<string> handledPairs = new HashSet<string>();
		int registrations = 0;
		bool startupLogged = false;
		while (IsCustomArenaActive())
		{
			if (!IsFeralPlayerRegistrationReleased())
			{
				yield return (object)new WaitForSeconds(0.1f);
				continue;
			}
			int passRegistrations = 0;
			try
			{
				Type type = AccessTools.TypeByName("EnemyDirector");
				object obj = ((type != null) ? GetStaticMember(type, "instance") : null);
				IEnumerable enumerable = ((obj != null) ? (GetMember(obj, "enemiesSpawned") as IEnumerable) : null);
				object obj2 = null;
				Type type2 = AccessTools.TypeByName("GameDirector");
				if (type2 != null)
				{
					obj2 = GetStaticMember(type2, "instance");
				}
				IList list = ((obj2 != null) ? (GetMember(obj2, "PlayerList") as IList) : null);
				if (!startupLogged && (Object)(object)LevelGenerator.Instance != (Object)null)
				{
					startupLogged = true;
					object member = GetMember(LevelGenerator.Instance, "EnemiesSpawned");
					object member2 = GetMember(LevelGenerator.Instance, "EnemiesSpawnTarget");
					Plugin.Log.LogInfo((object)string.Concat("[ArenaCompat] FERAL late-spawn player registration active | Generated=", LevelGenerator.Instance.Generated, " | EnemiesSpawned=", member ?? "?", " | EnemiesSpawnTarget=", member2 ?? "?", "."));
				}
				if (enumerable != null && list != null && list.Count > 0)
				{
					foreach (object item2 in enumerable)
					{
						if (item2 == null)
						{
							continue;
						}
						object member3 = GetMember(item2, "Spawned");
						if (member3 is bool && !(bool)member3)
						{
							continue;
						}
						object member4 = GetMember(item2, "Enemy");
						if (member4 == null)
						{
							continue;
						}
						MethodInfo methodInfo = AccessTools.Method(member4.GetType(), "PlayerAdded", new Type[1] { typeof(int) }, (Type[])null);
						if (methodInfo == null)
						{
							continue;
						}
						int runtimeObjectId = GetRuntimeObjectId(member4);
						for (int i = 0; i < list.Count; i++)
						{
							object? obj3 = list[i];
							PlayerAvatar val = (PlayerAvatar)((obj3 is PlayerAvatar) ? obj3 : null);
							if ((Object)(object)val == (Object)null)
							{
								continue;
							}
							int playerViewId = GetPlayerViewId(val);
							if (playerViewId <= 0)
							{
								continue;
							}
							string item = runtimeObjectId + ":" + playerViewId;
							if (!handledPairs.Contains(item))
							{
								bool flag = IsEnemyVisionPlayerRegistered(member4, playerViewId);
								bool flag2 = IsEnemyOnScreenPlayerRegistered(member4, playerViewId);
								try
								{
									methodInfo.Invoke(member4, new object[1] { playerViewId });
									handledPairs.Add(item);
									registrations++;
									passRegistrations++;
									bool flag3 = IsEnemyVisionPlayerRegistered(member4, playerViewId);
									bool flag4 = IsEnemyOnScreenPlayerRegistered(member4, playerViewId);
									Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL late-spawn PlayerAdded restored | enemyId=" + runtimeObjectId + " | playerViewID=" + playerViewId + " | vision=" + flag + "->" + flag3 + " | onScreen=" + flag2 + "->" + flag4 + "."));
								}
								catch (Exception ex)
								{
									Exception ex2 = ((ex is TargetInvocationException && ex.InnerException != null) ? ex.InnerException : ex);
									Plugin.Log.LogWarning((object)("[ArenaCompat] FERAL late-spawn PlayerAdded failed | enemyId=" + runtimeObjectId + " | playerViewID=" + playerViewId + " | " + ex2.GetType().Name + ": " + ex2.Message));
								}
							}
						}
					}
				}
			}
			catch (Exception ex3)
			{
				Plugin.Log.LogWarning((object)("[ArenaCompat] FERAL late-spawn registration pass failed: " + ex3.Message));
			}
			if (passRegistrations > 0)
			{
				Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL late-spawn registration pass | addedPairs=" + passRegistrations + " | totalPairs=" + registrations + "."));
			}
			yield return (object)new WaitForSeconds(0.25f);
		}
		Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL late-spawn player registration stopped | totalPairs=" + registrations + "."));
	}

	private static IEnumerator FeralCrownCompatibility()
	{
		object arena = null;
		object crownGrab = null;
		bool startupLogged = false;
		bool releaseRequested = false;
		float releaseRequestedAt = -1f;
		bool localReleaseLogged = false;
		bool grabRequested = false;
		float grabRequestedAt = -1f;
		bool winnerLogged = false;
		bool crownPlacedForWinner = false;
		int lastAlivePlayers = -999;
		int lastTotalPlayers = -999;
		while (IsDisposalArenaLevel())
		{
			try
			{
				if (arena == null || IsUnityObjectDestroyed(arena))
				{
					arena = FindFeralArenaComponent();
					crownGrab = ((arena != null) ? GetMember(arena, "crownGrab") : null);
					if (crownGrab != null)
					{
						ProtectTrueCrownLifetime(crownGrab);
						DetachTrueCrownFromFragileHierarchy(crownGrab, arena);
					}
					_currentFeralArena = arena;
					_currentTrueCrown = crownGrab;
					_crownInteractionReady = false;
					_crownInteractionPrepared = false;
					_crownGrabForwardInProgress = false;
					_crownGameOverRequested = false;
					startupLogged = false;
					releaseRequested = false;
					releaseRequestedAt = -1f;
					localReleaseLogged = false;
					grabRequested = false;
					grabRequestedAt = -1f;
					winnerLogged = false;
					crownPlacedForWinner = false;
					lastAlivePlayers = -999;
					lastTotalPlayers = -999;
				}
				else if (crownGrab == null || IsUnityObjectDestroyed(crownGrab))
				{
					crownGrab = GetMember(arena, "crownGrab");
					if (crownGrab != null)
					{
						ProtectTrueCrownLifetime(crownGrab);
						DetachTrueCrownFromFragileHierarchy(crownGrab, arena);
					}
					_currentTrueCrown = crownGrab;
				}
				if (arena != null && crownGrab != null)
				{
					if (!startupLogged)
					{
						startupLogged = true;
						Component val = (Component)((crownGrab is Component) ? crownGrab : null);
						string text = (((Object)(object)val != (Object)null) ? ((Object)val.gameObject).name : crownGrab.GetType().Name);
						object obj;
						if (!((Object)(object)val != (Object)null))
						{
							obj = "?";
						}
						else
						{
							Vector3 position = val.transform.position;
							obj = ((Vector3)(ref position)).ToString("F2");
						}
						string text2 = (string)obj;
						object member = GetMember(crownGrab, "colliderTransform");
						Component val2 = (Component)((member is Component) ? member : null);
						string text3 = (((Object)(object)val2 != (Object)null) ? ((Object)val2.gameObject).name : "null");
						Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL crown compatibility active | trueCrown='" + text + "' | position=" + text2 + " | cageDestroyed=" + IsCrownCageDestroyed(arena) + " | dead=" + Convert.ToString(GetMember(crownGrab, "dead")) + " | grabActive=" + ((Object)(object)val != (Object)null && val.gameObject.activeInHierarchy) + " | colliderTransform='" + text3 + "'."));
					}
					if (!IsFeralPlayerRegistrationReleased())
					{
						SetTrueCrownGrabEnabled(crownGrab, enabled: false);
						HideLegacyCrownRenderers(crownGrab, arena);
						HideCrownVisibilityMarker();
						_crownInteractionReady = false;
					}
					if (IsFeralPlayerRegistrationReleased())
					{
						CountArenaPlayersVanillaSemantic(out var total, out var alive);
						bool flag = alive == 1;
						bool flag2 = IsCrownCageDestroyed(arena);
						if (alive != lastAlivePlayers || total != lastTotalPlayers)
						{
							lastAlivePlayers = alive;
							lastTotalPlayers = total;
							Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL crown eligibility | totalPlayers=" + total + " | alivePlayers=" + alive + " | eligible=" + flag + " | source=SemiFunc.PlayerGetAll()."));
						}
						if (!flag)
						{
							SetTrueCrownGrabEnabled(crownGrab, enabled: false);
							HideLegacyCrownRenderers(crownGrab, arena);
							HideCrownVisibilityMarker();
							_crownInteractionReady = false;
						}
						if (flag && !flag2)
						{
							if (SemiFunc.IsMasterClientOrSingleplayer() && !releaseRequested)
							{
								releaseRequested = true;
								releaseRequestedAt = Time.unscaledTime;
								TryInvokeArenaMethod(arena, "DestroyCrownCage");
								Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL crown cage release requested through vanilla Arena.DestroyCrownCage() | alivePlayers=1.");
							}
							if ((!releaseRequested || (releaseRequestedAt >= 0f && Time.unscaledTime - releaseRequestedAt >= 0.75f)) && !IsCrownCageDestroyed(arena))
							{
								SafeReleaseCrownLocally(arena, crownGrab);
								if (!localReleaseLogged)
								{
									localReleaseLogged = true;
									Plugin.Log.LogWarning((object)"[ArenaCompat] FERAL crown cage stale-prefab fallback applied locally.");
								}
							}
						}
						flag2 = IsCrownCageDestroyed(arena);
						if (flag && flag2)
						{
							if (!crownPlacedForWinner)
							{
								crownPlacedForWinner = true;
								_crownInteractionPrepared = false;
								Component val3 = (Component)((crownGrab is Component) ? crownGrab : null);
								ManualLogSource log = Plugin.Log;
								object obj2;
								if (!((Object)(object)val3 != (Object)null))
								{
									obj2 = "?";
								}
								else
								{
									Vector3 position2 = val3.transform.position;
									obj2 = ((Vector3)(ref position2)).ToString("F2");
								}
								log.LogInfo((object)("[ArenaCompat] FERAL final crown unlocked at original tower position | position=" + (string?)obj2 + " | alivePlayers=1."));
							}
							EnsureTrueCrownActive(crownGrab, arena);
							SetTrueCrownGrabEnabled(crownGrab, enabled: true);
							int num = HideLegacyCrownRenderers(crownGrab, arena);
							EnsureReadableCrownVisual(crownGrab);
							EnsureCrownVisibilityMarker(crownGrab, arena);
							if (!_crownInteractionPrepared)
							{
								Component val4 = (Component)((crownGrab is Component) ? crownGrab : null);
								ManualLogSource log2 = Plugin.Log;
								object[] array = new object[9] { "[ArenaCompat] FERAL tower crown READY | position=", null, null, null, null, null, null, null, null };
								object obj3;
								if (!((Object)(object)val4 != (Object)null))
								{
									obj3 = "?";
								}
								else
								{
									Vector3 position3 = val4.transform.position;
									obj3 = ((Vector3)(ref position3)).ToString("F2");
								}
								array[1] = obj3;
								array[2] = " | legacyRenderersHidden=";
								array[3] = num;
								array[4] = " | totalPlayers=";
								array[5] = total;
								array[6] = " | alivePlayers=";
								array[7] = alive;
								array[8] = ".";
								log2.LogInfo((object)string.Concat(array));
							}
							if (!_crownInteractionPrepared)
							{
								PrepareTrueCrownInteraction(crownGrab, arena);
								_crownInteractionPrepared = true;
							}
							_crownInteractionReady = true;
							object member2 = GetMember(arena, "winnerPlayer");
							if (member2 != null && !IsUnityObjectDestroyed(member2))
							{
								TryForceArenaGameOver(arena);
								if (!winnerLogged)
								{
									winnerLogged = true;
									HideCrownVisibilityMarker();
									Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL crown winner registered by vanilla Arena logic.");
								}
							}
							else if (SemiFunc.IsMasterClientOrSingleplayer() && IsCrownCurrentlyGrabbed(crownGrab))
							{
								if (!grabRequested)
								{
									grabRequested = true;
									grabRequestedAt = Time.unscaledTime;
									Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL true crown grab detected | forwarding to vanilla Arena.CrownGrab().");
									TryInvokeArenaMethod(arena, "CrownGrab");
								}
								else if (grabRequestedAt >= 0f && Time.unscaledTime - grabRequestedAt >= 1f && GetMember(arena, "winnerPlayer") == null && TryRestoreCrownWinnerFromActualGrabber(arena, crownGrab))
								{
									winnerLogged = true;
									Plugin.Log.LogWarning((object)"[ArenaCompat] FERAL crown winner fallback restored from the actual crown grabber.");
								}
							}
							else if (!IsCrownCurrentlyGrabbed(crownGrab))
							{
								grabRequested = false;
								grabRequestedAt = -1f;
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[ArenaCompat] FERAL crown compatibility pass failed: " + ex.Message));
			}
			yield return (object)new WaitForSeconds(0.2f);
		}
		DestroyCrownVisibilityMarker();
		DestroyCrownSafeRoot();
		_currentFeralArena = null;
		_currentTrueCrown = null;
		_crownInteractionReady = false;
		_crownInteractionPrepared = false;
		_crownGrabForwardInProgress = false;
		_crownGameOverRequested = false;
	}

	private static object FindFeralArenaComponent()
	{
		Type type = AccessTools.TypeByName("Arena");
		if (type == null)
		{
			return null;
		}
		Object[] array = Object.FindObjectsOfType(type);
		if (array == null || array.Length == 0)
		{
			return null;
		}
		object obj = null;
		foreach (Object obj2 in array)
		{
			Component val = (Component)(object)((obj2 is Component) ? obj2 : null);
			if (!((Object)(object)val == (Object)null))
			{
				if (obj == null && GetMember(val, "crownGrab") != null)
				{
					obj = val;
				}
				if (IsInsideCustomArena(val.transform) && GetMember(val, "crownGrab") != null)
				{
					return val;
				}
			}
		}
		return obj;
	}

	private static void CountArenaPlayersVanillaSemantic(out int total, out int alive)
	{
		total = 0;
		alive = 0;
		try
		{
			IList list = null;
			MethodInfo methodInfo = AccessTools.Method(typeof(SemiFunc), "PlayerGetAll", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				list = methodInfo.Invoke(null, null) as IList;
			}
			if (list == null)
			{
				Type type = AccessTools.TypeByName("GameDirector");
				object obj = ((type != null) ? GetStaticMember(type, "instance") : null);
				list = ((obj != null) ? (GetMember(obj, "PlayerList") as IList) : null);
			}
			if (list == null)
			{
				return;
			}
			total = list.Count;
			for (int i = 0; i < list.Count; i++)
			{
				object obj2 = list[i];
				if (obj2 != null && !IsUnityObjectDestroyed(obj2))
				{
					object member = GetMember(obj2, "isDisabled");
					if (!(member is bool) || !(bool)member)
					{
						alive++;
					}
				}
			}
		}
		catch
		{
			total = 0;
			alive = 0;
		}
	}

	internal static void ProtectTrueCrownLifetime(object instance)
	{
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (instance == null || !IsDisposalArenaLevel())
			{
				return;
			}
			Component val = (Component)((instance is Component) ? instance : null);
			if (!((Object)(object)val == (Object)null) && string.Equals(((Object)val.gameObject).name, "Crown Grab", StringComparison.OrdinalIgnoreCase) && IsInsideCustomArena(val.transform))
			{
				object member = GetMember(instance, "dead");
				bool flag = member is bool && (bool)member;
				if (flag)
				{
					SetMember(instance, "dead", false);
				}
				if (!_crownLifetimeGuardLogged)
				{
					_crownLifetimeGuardLogged = true;
					ManualLogSource log = Plugin.Log;
					object[] array = new object[5] { "[ArenaCompat] FERAL true crown lifetime protected | dead=", flag, "->False | position=", null, null };
					Vector3 position = val.transform.position;
					array[3] = ((Vector3)(ref position)).ToString("F2");
					array[4] = ".";
					log.LogInfo((object)string.Concat(array));
				}
			}
		}
		catch (Exception ex)
		{
			if (!_crownLifetimeGuardLogged)
			{
				_crownLifetimeGuardLogged = true;
				Plugin.Log.LogWarning((object)("[ArenaCompat] FERAL crown lifetime guard failed: " + ex.Message));
			}
		}
	}

	internal static void OnTrueCrownGrabStarted(object instance)
	{
		if (!_crownInteractionReady || _crownGrabForwardInProgress || !IsCustomArenaActive() || instance == null || _currentTrueCrown == null || !object.ReferenceEquals(instance, _currentTrueCrown) || !SemiFunc.IsMasterClientOrSingleplayer() || !(GetMember(instance, "playerGrabbing") is IList { Count: not 0 }))
		{
			return;
		}
		object member = GetMember(_currentFeralArena, "winnerPlayer");
		if (member == null || IsUnityObjectDestroyed(member))
		{
			_crownGrabForwardInProgress = true;
			Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL true crown GrabStarted detected | forwarding to vanilla Arena.CrownGrab().");
			TryInvokeArenaMethod(_currentFeralArena, "CrownGrab");
			object member2 = GetMember(_currentFeralArena, "winnerPlayer");
			if (member2 != null && !IsUnityObjectDestroyed(member2))
			{
				TryForceArenaGameOver(_currentFeralArena);
			}
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				((MonoBehaviour)Plugin.Instance).StartCoroutine(CrownGrabForwardFallback());
			}
		}
	}

	private static IEnumerator CrownGrabForwardFallback()
	{
		yield return (object)new WaitForSeconds(1f);
		try
		{
			if (!IsCustomArenaActive() || _currentFeralArena == null || _currentTrueCrown == null)
			{
				_crownGrabForwardInProgress = false;
				yield break;
			}
			object member = GetMember(_currentFeralArena, "winnerPlayer");
			if (member != null && !IsUnityObjectDestroyed(member))
			{
				TryForceArenaGameOver(_currentFeralArena);
				Plugin.Log.LogInfo((object)"[ArenaCompat] FERAL crown winner confirmed after GrabStarted hook.");
				_crownGrabForwardInProgress = false;
			}
			else if (IsCrownCurrentlyGrabbed(_currentTrueCrown) && TryRestoreCrownWinnerFromActualGrabber(_currentFeralArena, _currentTrueCrown))
			{
				Plugin.Log.LogWarning((object)"[ArenaCompat] FERAL crown winner fallback restored after GrabStarted hook.");
				TryForceArenaGameOver(_currentFeralArena);
			}
		}
		finally
		{
			_crownGrabForwardInProgress = false;
		}
	}

	private static void DetachTrueCrownFromFragileHierarchy(object crownGrab, object arena)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Expected O, but got Unknown
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		Component val = (Component)((crownGrab is Component) ? crownGrab : null);
		if (!((Object)(object)val == (Object)null))
		{
			if ((Object)(object)_crownSafeRoot == (Object)null)
			{
				_crownSafeRoot = new GameObject("ArenaCompat Crown Safe Root");
				_crownSafeRoot.transform.position = Vector3.zero;
				_crownSafeRoot.transform.rotation = Quaternion.identity;
				_crownSafeRoot.transform.localScale = Vector3.one;
			}
			Transform transform = val.transform;
			object member = GetMember(arena, "crownTransform");
			Transform val2 = (Transform)((member is Transform) ? member : null);
			string text = (((Object)(object)transform.parent != (Object)null) ? ((Object)((Component)transform.parent).gameObject).name : "<root>");
			string text2 = (((Object)(object)val2 != (Object)null && (Object)(object)val2.parent != (Object)null) ? ((Object)((Component)val2.parent).gameObject).name : "<root>");
			if ((Object)(object)transform.parent != (Object)(object)_crownSafeRoot.transform)
			{
				transform.SetParent(_crownSafeRoot.transform, true);
			}
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)transform && !val2.IsChildOf(transform) && (Object)(object)val2.parent != (Object)(object)_crownSafeRoot.transform)
			{
				val2.SetParent(_crownSafeRoot.transform, true);
			}
			if (!_crownHierarchyDetachedLogged)
			{
				_crownHierarchyDetachedLogged = true;
				ManualLogSource log = Plugin.Log;
				string[] array = new string[7] { "[ArenaCompat] FERAL true crown detached from fragile prefab hierarchy | grabParent='", text, "' | visualParent='", text2, "' | position=", null, null };
				Vector3 position = transform.position;
				array[5] = ((Vector3)(ref position)).ToString("F2");
				array[6] = ".";
				log.LogInfo((object)string.Concat(array));
			}
		}
	}

	private static void SetTrueCrownGrabEnabled(object crownGrab, bool enabled)
	{
		Component val = (Component)((crownGrab is Component) ? crownGrab : null);
		Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null);
		if ((Object)(object)val2 != (Object)null)
		{
			val2.enabled = enabled;
		}
	}

	private static bool TryMoveTrueCrownToArenaGround(object crownGrab, object arena, out Vector3 placedPosition)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		placedPosition = Vector3.zero;
		Component val = (Component)((crownGrab is Component) ? crownGrab : null);
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		bool flag = false;
		Bounds val2;
		if (_feralArenaGroundBoundsValid)
		{
			val2 = _feralArenaGroundBounds;
			flag = true;
		}
		else
		{
			val2 = default(Bounds);
			GameObject[] array = Object.FindObjectsOfType<GameObject>();
			foreach (GameObject val3 in array)
			{
				if (!((Object)(object)val3 == (Object)null) && string.Equals(((Object)val3).name, "Arena_Ground", StringComparison.OrdinalIgnoreCase))
				{
					Renderer component = val3.GetComponent<Renderer>();
					Collider component2 = val3.GetComponent<Collider>();
					if ((Object)(object)component != (Object)null)
					{
						val2 = component.bounds;
						flag = true;
						break;
					}
					if ((Object)(object)component2 != (Object)null)
					{
						val2 = component2.bounds;
						flag = true;
						break;
					}
				}
			}
		}
		if (!flag)
		{
			return false;
		}
		Vector3 val4 = default(Vector3);
		((Vector3)(ref val4))..ctor(((Bounds)(ref val2)).center.x, ((Bounds)(ref val2)).max.y + 0.75f, ((Bounds)(ref val2)).center.z);
		Transform val5 = (((Object)(object)_crownSafeRoot != (Object)null) ? _crownSafeRoot.transform : null);
		if ((Object)(object)val5 != (Object)null)
		{
			val.transform.SetParent(val5, true);
		}
		else
		{
			val.transform.SetParent((Transform)null, true);
		}
		val.transform.position = val4;
		val.transform.rotation = Quaternion.identity;
		val.gameObject.SetActive(true);
		object member = GetMember(arena, "crownTransform");
		Transform val6 = (Transform)((member is Transform) ? member : null);
		if ((Object)(object)val6 != (Object)null && (Object)(object)val6 != (Object)(object)val.transform)
		{
			if ((Object)(object)val5 != (Object)null)
			{
				val6.SetParent(val5, true);
			}
			else
			{
				val6.SetParent((Transform)null, true);
			}
			val6.position = val4;
			val6.rotation = Quaternion.identity;
			((Component)val6).gameObject.SetActive(true);
		}
		placedPosition = val4;
		return true;
	}

	private static int HideLegacyCrownRenderers(object crownGrab, object arena)
	{
		Component val = (Component)((crownGrab is Component) ? crownGrab : null);
		if ((Object)(object)val == (Object)null)
		{
			return 0;
		}
		int num = 0;
		HashSet<int> hashSet = new HashSet<int>();
		object member = GetMember(arena, "crownTransform");
		Transform val2 = (Transform)((member is Transform) ? member : null);
		if ((Object)(object)val2 != (Object)null)
		{
			Renderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					int instanceID = ((Object)val3).GetInstanceID();
					if (!hashSet.Contains(instanceID))
					{
						hashSet.Add(instanceID);
						val3.enabled = false;
						num++;
					}
				}
			}
		}
		return num;
	}

	private static int ForceTrueCrownRenderersVisible(object crownGrab, object arena)
	{
		Component val = (Component)((crownGrab is Component) ? crownGrab : null);
		if ((Object)(object)val == (Object)null)
		{
			return 0;
		}
		int num = 0;
		HashSet<int> hashSet = new HashSet<int>();
		object member = GetMember(arena, "crownTransform");
		Transform val2 = (Transform)((member is Transform) ? member : null);
		Transform[] array = (Transform[])(object)(((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)val.transform) ? new Transform[2] { val2, val.transform } : new Transform[1] { val.transform });
		foreach (Transform val3 in array)
		{
			if ((Object)(object)val3 == (Object)null)
			{
				continue;
			}
			Transform val4 = val3;
			while ((Object)(object)val4 != (Object)null)
			{
				if (!((Component)val4).gameObject.activeSelf)
				{
					((Component)val4).gameObject.SetActive(true);
				}
				val4 = val4.parent;
			}
			Renderer[] componentsInChildren = ((Component)val3).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val5 in componentsInChildren)
			{
				if ((Object)(object)val5 == (Object)null)
				{
					continue;
				}
				int instanceID = ((Object)val5).GetInstanceID();
				if (!hashSet.Contains(instanceID))
				{
					hashSet.Add(instanceID);
					if (!((Component)val5).gameObject.activeSelf)
					{
						((Component)val5).gameObject.SetActive(true);
					}
					val5.enabled = true;
					num++;
				}
			}
		}
		return num;
	}

	private static void EnsureReadableCrownVisual(object crownGrab)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Expected O, but got Unknown
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0261: Unknown result type (might be due to invalid IL or missing references)
		Component val = (Component)((crownGrab is Component) ? crownGrab : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Vector3 position = val.transform.position + Vector3.up * 0.85f;
		if ((Object)(object)_crownReadableVisual != (Object)null)
		{
			if (!_crownReadableVisual.activeSelf)
			{
				_crownReadableVisual.SetActive(true);
			}
			_crownReadableVisual.transform.position = position;
			_crownReadableVisual.transform.rotation = Quaternion.identity;
			return;
		}
		GameObject val2 = new GameObject("ArenaCompat Readable Crown Visual");
		val2.transform.position = position;
		val2.transform.rotation = Quaternion.identity;
		val2.transform.localScale = Vector3.one;
		int layer = (val2.layer = val.gameObject.layer);
		CreateCrownVisualPrimitive((PrimitiveType)2, "ArenaCompat Crown Band", val2.transform, new Vector3(0f, -0.18f, 0f), Quaternion.identity, new Vector3(0.72f, 0.12f, 0.72f), layer);
		Vector3 localPosition = default(Vector3);
		for (int i = 0; i < 6; i++)
		{
			float num = 60f * (float)i;
			float num2 = num * ((float)Math.PI / 180f);
			((Vector3)(ref localPosition))..ctor(Mathf.Sin(num2) * 0.48f, 0.22f, Mathf.Cos(num2) * 0.48f);
			Quaternion localRotation = Quaternion.Euler(0f, num, 0f);
			CreateCrownVisualPrimitive((PrimitiveType)3, "ArenaCompat Crown Point " + i, val2.transform, localPosition, localRotation, new Vector3(0.16f, 0.62f, 0.16f), layer);
			CreateCrownVisualPrimitive((PrimitiveType)0, "ArenaCompat Crown Jewel " + i, val2.transform, new Vector3(Mathf.Sin(num2) * 0.48f, 0.57f, Mathf.Cos(num2) * 0.48f), Quaternion.identity, new Vector3(0.2f, 0.2f, 0.2f), layer);
		}
		CreateCrownVisualPrimitive((PrimitiveType)0, "ArenaCompat Crown Center Jewel", val2.transform, new Vector3(0f, 0.52f, 0f), Quaternion.identity, new Vector3(0.32f, 0.32f, 0.32f), layer);
		Light val3 = val2.AddComponent<Light>();
		val3.type = (LightType)2;
		val3.color = new Color(1f, 0.72f, 0.08f, 1f);
		val3.range = 7f;
		val3.intensity = 2.5f;
		_crownReadableVisual = val2;
		Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL readable crown visual active | position=" + ((Vector3)(ref position)).ToString("F2") + " | parts=14 | grabProxyAligned=True."));
	}

	private static GameObject CreateCrownVisualPrimitive(PrimitiveType primitiveType, string name, Transform parent, Vector3 localPosition, Quaternion localRotation, Vector3 localScale, int layer)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = GameObject.CreatePrimitive(primitiveType);
		((Object)val).name = name;
		val.layer = layer;
		val.transform.SetParent(parent, false);
		val.transform.localPosition = localPosition;
		val.transform.localRotation = localRotation;
		val.transform.localScale = localScale;
		Collider component = val.GetComponent<Collider>();
		if ((Object)(object)component != (Object)null)
		{
			Object.Destroy((Object)(object)component);
		}
		Renderer component2 = val.GetComponent<Renderer>();
		if ((Object)(object)component2 != (Object)null)
		{
			try
			{
				component2.material.color = new Color(1f, 0.72f, 0.08f, 1f);
			}
			catch
			{
			}
		}
		return val;
	}

	private static void EnsureCrownVisibilityMarker(object crownGrab, object arena)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: 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)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0270: Unknown result type (might be due to invalid IL or missing references)
		//IL_0275: Unknown result type (might be due to invalid IL or missing references)
		//IL_0296: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		Component val = (Component)((crownGrab is Component) ? crownGrab : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Vector3 position = val.transform.position + Vector3.up * 3f;
		if ((Object)(object)_crownVisibilityMarker != (Object)null)
		{
			if (!_crownVisibilityMarker.activeSelf)
			{
				_crownVisibilityMarker.SetActive(true);
			}
			_crownVisibilityMarker.transform.position = position;
			return;
		}
		GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)0);
		((Object)val2).name = "ArenaCompat True Crown World Beacon";
		val2.transform.position = position;
		val2.transform.rotation = Quaternion.identity;
		val2.transform.localScale = new Vector3(0.9f, 0.9f, 0.9f);
		Collider component = val2.GetComponent<Collider>();
		if ((Object)(object)component != (Object)null)
		{
			Object.Destroy((Object)(object)component);
		}
		Renderer component2 = val2.GetComponent<Renderer>();
		if ((Object)(object)component2 != (Object)null)
		{
			try
			{
				component2.material.color = new Color(1f, 0.72f, 0.08f, 1f);
			}
			catch
			{
			}
		}
		Light val3 = val2.AddComponent<Light>();
		val3.type = (LightType)2;
		val3.color = new Color(1f, 0.72f, 0.08f, 1f);
		val3.range = 14f;
		val3.intensity = 4.5f;
		GameObject val4 = GameObject.CreatePrimitive((PrimitiveType)2);
		((Object)val4).name = "ArenaCompat True Crown Beacon Beam";
		val4.transform.SetParent(val2.transform, false);
		val4.transform.localPosition = new Vector3(0f, 3.5f, 0f);
		val4.transform.localRotation = Quaternion.identity;
		val4.transform.localScale = new Vector3(0.12f, 3.5f, 0.12f);
		Collider component3 = val4.GetComponent<Collider>();
		if ((Object)(object)component3 != (Object)null)
		{
			Object.Destroy((Object)(object)component3);
		}
		Renderer component4 = val4.GetComponent<Renderer>();
		if ((Object)(object)component4 != (Object)null)
		{
			try
			{
				component4.material.color = new Color(1f, 0.72f, 0.08f, 1f);
			}
			catch
			{
			}
		}
		_crownVisibilityMarker = val2;
		object member = GetMember(arena, "crownTransform");
		Transform val5 = (Transform)((member is Transform) ? member : null);
		Renderer[] array = (((Object)(object)val5 != (Object)null) ? ((Component)val5).GetComponentsInChildren<Renderer>(true) : val.GetComponentsInChildren<Renderer>(true));
		ManualLogSource log = Plugin.Log;
		object[] array2 = new object[7] { "[ArenaCompat] FERAL true crown WORLD beacon active | crownPosition=", null, null, null, null, null, null };
		Vector3 position2 = val.transform.position;
		array2[1] = ((Vector3)(ref position2)).ToString("F2");
		array2[2] = " | beaconPosition=";
		Vector3 position3 = val2.transform.position;
		array2[3] = ((Vector3)(ref position3)).ToString("F2");
		array2[4] = " | crownRenderers=";
		array2[5] = ((array != null) ? array.Length : 0);
		array2[6] = ".";
		log.LogInfo((object)string.Concat(array2));
	}

	private static void HideCrownVisibilityMarker()
	{
		if ((Object)(object)_crownVisibilityMarker != (Object)null)
		{
			_crownVisibilityMarker.SetActive(false);
		}
		if ((Object)(object)_crownReadableVisual != (Object)null)
		{
			_crownReadableVisual.SetActive(false);
		}
	}

	private static void DestroyCrownVisibilityMarker()
	{
		if ((Object)(object)_crownVisibilityMarker != (Object)null)
		{
			Object.Destroy((Object)(object)_crownVisibilityMarker);
			_crownVisibilityMarker = null;
		}
		if ((Object)(object)_crownReadableVisual != (Object)null)
		{
			Object.Destroy((Object)(object)_crownReadableVisual);
			_crownReadableVisual = null;
		}
		if ((Object)(object)_crownGrabProxy != (Object)null)
		{
			Object.Destroy((Object)(object)_crownGrabProxy);
			_crownGrabProxy = null;
		}
	}

	private static void DestroyCrownSafeRoot()
	{
		if ((Object)(object)_crownSafeRoot != (Object)null)
		{
			Object.Destroy((Object)(object)_crownSafeRoot);
		}
		_crownSafeRoot = null;
		_crownHierarchyDetachedLogged = false;
	}

	private static void PrepareTrueCrownInteraction(object crownGrab, object arena)
	{
		//IL_0272: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_0294: Unknown result type (might be due to invalid IL or missing references)
		//IL_0299: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Expected O, but got Unknown
		Component val = (Component)((crownGrab is Component) ? crownGrab : null);
		Component val2 = (Component)((arena is Component) ? arena : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Transform val3 = (((Object)(object)val2 != (Object)null) ? val2.transform : null);
		if (!val.gameObject.activeInHierarchy && (Object)(object)val3 != (Object)null)
		{
			val.transform.SetParent(val3, true);
			val.gameObject.SetActive(true);
		}
		else if (!val.gameObject.activeSelf)
		{
			val.gameObject.SetActive(true);
		}
		Behaviour val4 = (Behaviour)(object)((val is Behaviour) ? val : null);
		if ((Object)(object)val4 != (Object)null)
		{
			val4.enabled = true;
		}
		object member = GetMember(arena, "crownTransform");
		Transform val5 = (Transform)((member is Transform) ? member : null);
		if ((Object)(object)val5 != (Object)null)
		{
			if (!((Component)val5).gameObject.activeInHierarchy && (Object)(object)val3 != (Object)null)
			{
				val5.SetParent(val3, true);
				((Component)val5).gameObject.SetActive(true);
			}
			else if (!((Component)val5).gameObject.activeSelf)
			{
				((Component)val5).gameObject.SetActive(true);
			}
		}
		if ((Object)(object)_crownGrabProxy == (Object)null)
		{
			_crownGrabProxy = new GameObject("ArenaCompat Crown World Grab Proxy");
		}
		Transform transform = _crownGrabProxy.transform;
		transform.SetParent((Transform)null, true);
		transform.position = val.transform.position + Vector3.up * 0.85f;
		transform.rotation = Quaternion.identity;
		transform.localScale = Vector3.one;
		transform.SetParent(val.transform, true);
		int num = LayerMask.NameToLayer("StaticGrabObject");
		_crownGrabProxy.layer = ((num >= 0) ? num : val.gameObject.layer);
		try
		{
			_crownGrabProxy.tag = "Phys Grab Object";
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("[ArenaCompat] FERAL crown proxy tag assignment failed: " + ex.GetType().Name + " - " + ex.Message));
		}
		SphereCollider val6 = _crownGrabProxy.GetComponent<SphereCollider>();
		if ((Object)(object)val6 == (Object)null)
		{
			val6 = _crownGrabProxy.AddComponent<SphereCollider>();
		}
		val6.radius = 0.9f;
		((Collider)val6).isTrigger = false;
		((Collider)val6).enabled = true;
		SetMember(crownGrab, "colliderTransform", transform);
		SetMember(crownGrab, "hoverText", "CROWN - GRAB TO WIN");
		Renderer[] array = (((Object)(object)val5 != (Object)null) ? ((Component)val5).GetComponentsInChildren<Renderer>(true) : val.GetComponentsInChildren<Renderer>(true));
		ManualLogSource log = Plugin.Log;
		object[] array2 = new object[15]
		{
			"[ArenaCompat] FERAL true crown interaction repaired | position=", null, null, null, null, null, null, null, null, null,
			null, null, null, null, null
		};
		Vector3 position = val.transform.position;
		array2[1] = ((Vector3)(ref position)).ToString("F2");
		array2[2] = " | proxyPosition=";
		Vector3 position2 = transform.position;
		array2[3] = ((Vector3)(ref position2)).ToString("F2");
		array2[4] = " | proxyParent='";
		array2[5] = (((Object)(object)transform.parent != (Object)null) ? ((Object)((Component)transform.parent).gameObject).name : "<root>");
		array2[6] = "' | proxyTag='";
		array2[7] = _crownGrabProxy.tag;
		array2[8] = "' | proxyLayer=";
		array2[9] = _crownGrabProxy.layer;
		array2[10] = " | colliderRadius=0.90 | renderers=";
		array2[11] = ((array != null) ? array.Length : 0);
		array2[12] = " | active=";
		array2[13] = val.gameObject.activeInHierarchy;
		array2[14] = ".";
		log.LogInfo((object)string.Concat(array2));
	}

	private static bool IsCrownCageDestroyed(object arena)
	{
		object member = GetMember(arena, "crownCageDestroyed");
		if (member is bool)
		{
			return (bool)member;
		}
		return false;
	}

	private static void SafeReleaseCrownLocally(object arena, object crownGrab)
	{
		if (arena != null)
		{
			DestroyReferencedGameObject(arena, "crownSphere");
			DestroyReferencedGameObject(arena, "crownMechanic");
			SetMember(arena, "crownCageDestroyed", true);
			EnsureTrueCrownActive(crownGrab, arena);
		}
	}

	private static void DestroyReferencedGameObject(object owner, string memberName)
	{
		object member = GetMember(owner, memberName);
		Component val = (Component)((member is Component) ? member : null);
		GameObject val2 = (GameObject)((member is GameObject) ? member : null);
		if ((Object)(object)val != (Object)null)
		{
			val2 = val.gameObject;
		}
		if ((Object)(object)val2 != (Object)null)
		{
			Object.Destroy((Object)(object)val2);
		}
	}

	private static void EnsureTrueCrownActive(object crownGrab, object arena)
	{
		Component val = (Component)((crownGrab is Component) ? crownGrab : null);
		if ((Object)(object)val != (Object)null)
		{
			if (!val.gameObject.activeSelf)
			{
				val.gameObject.SetActive(true);
			}
			Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null);
			if ((Object)(object)val2 != (Object)null && !val2.enabled)
			{
				val2.enabled = true;
			}
		}
		object member = GetMember(arena, "crownTransform");
		Transform val3 = (Transform)((member is Transform) ? member : null);
		if ((Object)(object)val3 != (Object)null && !((Component)val3).gameObject.activeSelf)
		{
			((Component)val3).gameObject.SetActive(true);
		}
	}

	private static bool IsCrownCurrentlyGrabbed(object crownGrab)
	{
		object member = GetMember(crownGrab, "grabbed");
		IList list = GetMember(crownGrab, "playerGrabbing") as IList;
		if (!(member is bool) || !(bool)member)
		{
			if (list != null)
			{
				return list.Count > 0;
			}
			return false;
		}
		return true;
	}

	private static bool TryRestoreCrownWinnerFromActualGrabber(object arena, object crownGrab)
	{
		try
		{
			if (!(GetMember(crownGrab, "playerGrabbing") is IList { Count: not 0 } list) || list[0] == null)
			{
				return false;
			}
			object member = GetMember(list[0], "playerAvatar");
			if (member == null || IsUnityObjectDestroyed(member))
			{
				return false;
			}
			SetMember(arena, "winnerPlayer", member);
			object member2 = GetMember(member, "steamID");
			Type type = AccessTools.TypeByName("SessionManager");
			object obj = ((type != null) ? GetStaticMember(type, "instance") : null);
			if (obj != null && member2 != null)
			{
				SetMember(obj, "crownedPlayerSteamID", member2);
			}
			Type type2 = AccessTools.TypeByName("StatsManager");
			object obj2 = ((type2 != null) ? GetStaticMember(type2, "instance") : null);
			if (obj2 != null && member2 != null)
			{
				MethodInfo methodInfo = AccessTools.Method(obj2.GetType(), "UpdateCrown", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					try
					{
						methodInfo.Invoke(obj2, new object[1] { member2 });
					}
					catch
					{
					}
				}
			}
			TryRestoreCrownWinUi(member);
			object member3 = GetMember(arena, "crownExplosion");
			GameObject val = (GameObject)((member3 is GameObject) ? member3 : null);
			Component val2 = (Component)((member3 is Component) ? member3 : null);
			if ((Object)(object)val2 != (Object)null)
			{
				val = val2.gameObject;
			}
			if ((Object)(object)val != (Object)null)
			{
				val.SetActive(true);
			}
			return true;
		}
		catch
		{
			return false;
		}
	}

	private static void TryRestoreCrownWinUi(object player)
	{
		if (player == null)
		{
			return;
		}
		try
		{
			Type type = AccessTools.TypeByName("ArenaMessageWinUI");
			object obj = ((type != null) ? GetStaticMember(type, "instance") : null);
			object obj2 = ((obj != null) ? GetMember(obj, "kingObject") : null);
			GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null);
			Component val2 = (Component)((obj2 is Component) ? obj2 : null);
			if ((Object)(object)val2 != (Object)null)
			{
				val = val2.gameObject;
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Type type2 = AccessTools.TypeByName("MenuPlayerListed");
			if (type2 == null)
			{
				return;
			}
			Component component = val.GetComponent(type2);
			if (!((Object)(object)component == (Object)null))
			{
				MethodInfo methodInfo = AccessTools.Method(((object)component).GetType(), "ForcePlayer", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					methodInfo.Invoke(component, new object[1] { player });
				}
			}
		}
		catch
		{
		}
	}

	private static bool TryForceArenaGameOver(object arena)
	{
		if (arena == null || IsUnityObjectDestroyed(arena))
		{
			return false;
		}
		object member = GetMember(arena, "winnerPlayer");
		if (member == null || IsUnityObjectDestroyed(member))
		{
			return false;
		}
		try
		{
			Type type = arena.GetType();
			FieldInfo fieldInfo = AccessTools.Field(type, "currentState");
			if (fieldInfo == null)
			{
				return false;
			}
			Type fieldType = fieldInfo.FieldType;
			object value = fieldInfo.GetValue(arena);
			int num = ((value != null) ? Convert.ToInt32(value) : (-1));
			if (num == 8)
			{
				_crownGameOverRequested = true;
				return true;
			}
			if (_crownGameOverRequested)
			{
				return true;
			}
			if (!fieldType.IsEnum)
			{
				Plugin.Log.LogWarning((object)"[ArenaCompat] FERAL crown victory could not resolve Arena.States enum.");
				return false;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "StateSet", new Type[1] { fieldType }, (Type[])null);
			if (methodInfo == null)
			{
				Plugin.Log.LogWarning((object)"[ArenaCompat] FERAL crown victory could not find Arena.StateSet(States).");
				return false;
			}
			object obj = Enum.ToObject(fieldType, 8);
			_crownGameOverRequested = true;
			methodInfo.Invoke(arena, new object[1] { obj });
			Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL crown victory -> vanilla Arena GameOver requested | previousState=" + num + " | targetState=8."));
			return true;
		}
		catch (Exception ex)
		{
			_crownGameOverRequested = false;
			Exception ex2 = ((ex is TargetInvocationException && ex.InnerException != null) ? ex.InnerException : ex);
			Plugin.Log.LogWarning((object)("[ArenaCompat] FERAL crown victory GameOver transition failed: " + ex2.GetType().Name + ": " + ex2.Message));
			return false;
		}
	}

	private static bool TryInvokeArenaMethod(object arena, string methodName)
	{
		if (arena == null)
		{
			return false;
		}
		try
		{
			MethodInfo methodInfo = AccessTools.Method(arena.GetType(), methodName, Type.EmptyTypes, (Type[])null);
			if (methodInfo == null)
			{
				return false;
			}
			methodInfo.Invoke(arena, null);
			return true;
		}
		catch (Exception ex)
		{
			Exception ex2 = ((ex is TargetInvocationException && ex.InnerException != null) ? ex.InnerException : ex);
			Plugin.Log.LogWarning((object)("[ArenaCompat] FERAL vanilla Arena." + methodName + " failed: " + ex2.GetType().Name + ": " + ex2.Message));
			return false;
		}
	}

	private static bool IsUnityObjectDestroyed(object value)
	{
		Object val = (Object)((value is Object) ? value : null);
		if (object.ReferenceEquals(val, null))
		{
			return false;
		}
		return !Object.op_Implicit(val);
	}

	private static int GetRuntimeObjectId(object value)
	{
		Object val = (Object)((value is Object) ? value : null);
		if (val != (Object)null)
		{
			return val.GetInstanceID();
		}
		return value?.GetHashCode() ?? 0;
	}

	private static int GetPlayerViewId(PlayerAvatar player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return 0;
		}
		object member = GetMember(player, "photonView");
		if (member == null)
		{
			member = GetMember(player, "PhotonView");
		}
		object member2 = GetMember(member, "ViewID");
		if (member2 is int)
		{
			return (int)member2;
		}
		try
		{
			return (member2 != null) ? Convert.ToInt32(member2) : 0;
		}
		catch
		{
			return 0;
		}
	}

	private static bool IsEnemyVisionPlayerRegistered(object enemy, int viewId)
	{
		object member = GetMember(enemy, "HasVision");
		if (member is bool && !(bool)member)
		{
			return true;
		}
		object member2 = GetMember(enemy, "Vision");
		if (member2 == null)
		{
			return true;
		}
		if (DictionaryContainsKey(GetMember(member2, "VisionsTriggered"), viewId))
		{
			return DictionaryContainsKey(GetMember(member2, "VisionTriggered"), viewId);
		}
		return false;
	}

	private static bool IsEnemyOnScreenPlayerRegistered(object enemy, int viewId)
	{
		object member = GetMember(enemy, "HasOnScreen");
		if (member is bool && !(bool)member)
		{
			return true;
		}
		object member2 = GetMember(enemy, "OnScreen");
		if (member2 == null)
		{
			return true;
		}
		if (DictionaryContainsKey(GetMember(member2, "OnScreenPlayer"), viewId))
		{
			return DictionaryContainsKey(GetMember(member2, "CulledPlayer"), viewId);
		}
		return false;
	}

	private static bool DictionaryContainsKey(object dictionary, int key)
	{
		if (dictionary == null)
		{
			return false;
		}
		if (dictionary is IDictionary dictionary2)
		{
			return dictionary2.Contains(key);
		}
		try
		{
			MethodInfo methodInfo = AccessTools.Method(dictionary.GetType(), "ContainsKey", new Type[1] { typeof(int) }, (Type[])null);
			if (methodInfo != null)
			{
				object obj = methodInfo.Invoke(dictionary, new object[1] { key });
				if (obj is bool)
				{
					return (bool)obj;
				}
			}
		}
		catch
		{
		}
		return false;
	}

	internal static bool IsCustomArenaActive()
	{
		try
		{
			if (!IsDisposalArenaLevel())
			{
				return false;
			}
			GameObject val = GameObject.Find("Start Room - Arena(Clone)") ?? GameObject.Find("Start Room - Arena");
			return (Object)(object)val != (Object)null;
		}
		catch
		{
			return false;
		}
	}

	internal static bool IsInsideCustomArena(Transform transform)
	{
		Transform val = transform;
		while ((Object)(object)val != (Object)null)
		{
			string text = ((Object)val).name ?? "";
			if (text.StartsWith("Start Room - Arena", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			val = val.parent;
		}
		return false;
	}

	internal static bool IsDisposalArenaLevel()
	{
		try
		{
			if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)RunManager.instance.levelCurrent == (Object)null)
			{
				return false;
			}
			string a = ((Object)RunManager.instance.levelCurrent).name ?? "";
			return string.Equals(a, "Level - Arena Fight", StringComparison.OrdinalIgnoreCase);
		}
		catch
		{
			return false;
		}
	}

	internal static AudioSource GetFeralMusicSource(object feralPlugin)
	{
		object memberValue = GetMemberValue(feralPlugin, "musicSource");
		return (AudioSource)((memberValue is AudioSource) ? memberValue : null);
	}

	internal static void ResetFeralSceneState(object feralPlugin)
	{
		if (feralPlugin == null)
		{
			return;
		}
		try
		{
			RemoveFeralNavMesh();
			DestroyCrownVisibilityMarker();
			DestroyCrownSafeRoot();
			_currentFeralArena = null;
			_currentTrueCrown = null;
			_crownInteractionReady = false;
			_crownInteractionPrepared = false;
			_crownGrabForwardInProgress = false;
			_crownGameOverRequested = false;
			_preparationArmed = false;
			_preparationWaitingForRoundStart = false;
			_preparationReleased = true;
			_preparationReleaseLogged = false;
			_preparationReleaseAt = -1f;
			FeralPreparationOnScreenGuard.ResetLogState();
			AudioSource feralMusicSource = GetFeralMusicSource(feralPlugin);
			if ((Object)(object)feralMusicSource != (Object)null && feralMusicSource.isPlaying)
			{
				feralMusicSource.Stop();
			}
			SetMember(feralPlugin, "musicTriggered", false);
			SetMember(feralPlugin, "floorDoor", null);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("[ArenaCompat] FERAL scene-state reset failed: " + ex.Message));
		}
	}

	private static bool TryBuildFeralNavMesh(GameObject arenaRoot)
	{
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0239: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0278: Unknown result type (might be due to invalid IL or missing references)
		//IL_027d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0282: Unknown result type (might be due to invalid IL or missing references)
		//IL_028f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_031f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0324: Unknown result type (might be due to invalid IL or missing references)
		//IL_033e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0358: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Unknown result type (might be due to invalid IL or missing references)
		//IL_0366: Unknown result type (might be due to invalid IL or missing references)
		//IL_0368: Unknown result type (might be due to invalid IL or missing references)
		//IL_036d: Unknown result type (might be due to invalid IL or missing references)
		//IL_039c: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)arenaRoot == (Object)null)
		{
			return false;
		}
		try
		{
			if (_feralNavMeshAdded && ((NavMeshDataInstance)(ref _feralNavMeshInstance)).valid)
			{
				return true;
			}
			Renderer val = null;
			Collider val2 = null;
			Renderer[] componentsInChildren = arenaRoot.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren)
			{
				if (!((Object)(object)val3 == (Object)null) && string.Equals(((Object)((Component)val3).gameObject).name, "Arena_Ground", StringComparison.OrdinalIgnoreCase))
				{
					val = val3;
					break;
				}
			}
			Collider[] componentsInChildren2 = arenaRoot.GetComponentsInChildren<Collider>(true);
			foreach (Collider val4 in componentsInChildren2)
			{
				if (!((Object)(object)val4 == (Object)null) && string.Equals(((Object)((Component)val4).gameObject).name, "Arena_Ground", StringComparison.OrdinalIgnoreCase))
				{
					val2 = val4;
					break;
				}
			}
			Bounds bounds;
			if ((Object)(object)val != (Object)null)
			{
				bounds = val.bounds;
			}
			else
			{
				if (!((Object)(object)val2 != (Object)null))
				{
					Plugin.Log.LogWarning((object)"[ArenaCompat] FERAL NavMesh: Arena_Ground renderer/collider not found.");
					return false;
				}
				bounds = val2.bounds;
			}
			_feralArenaGroundBounds = bounds;
			_feralArenaGroundBoundsValid = true;
			float y = ((Bounds)(ref bounds)).max.y;
			Bounds playableBounds = bounds;
			foreach (Renderer val5 in componentsInChildren)
			{
				if (!((Object)(object)val5 == (Object)null))
				{
					EncapsulatePlayableBounds(ref playableBounds, val5.bounds, bounds);
				}
			}
			foreach (Collider val6 in componentsInChildren2)
			{
				if (!((Object)(object)val6 == (Object)null) && !val6.isTrigger)
				{
					EncapsulatePlayableBounds(ref playableBounds, val6.bounds, bounds);
				}
			}
			bool flag = false;
			try
			{
				if ((Object)(object)PlayerController.instance != (Object)null && (Object)(object)PlayerController.instance.playerAvatarScript != (Object)null)
				{
					Vector3 position = ((Component)PlayerController.instance.playerAvatarScript).transform.position;
					Vector3 val7 = default(Vector3);
					((Vector3)(ref val7))..ctor(position.x, ((Bounds)(ref bounds)).center.y, position.z);
					((Bounds)(ref playableBounds)).Encapsulate(val7);
					flag = true;
				}
			}
			catch
			{
			}
			float num = Mathf.Max(8f, ((Bounds)(ref playableBounds)).size.x + 12f);
			float num2 = Mathf.Max(8f, ((Bounds)(ref playableBounds)).size.z + 12f);
			Vector3 val8 = default(Vector3);
			((Vector3)(ref val8))..ctor(((Bounds)(ref playableBounds)).center.x, ((Bounds)(ref bounds)).center.y, ((Bounds)(ref playableBounds)).center.z);
			_feralPlayableBounds = new Bounds(new Vector3(val8.x, y + 2f, val8.z), new Vector3(num, 12f, num2));
			_feralPlayableBoundsValid = true;
			NavMeshBuildSource item = default(NavMeshBuildSource);
			((NavMeshBuildSource)(ref item)).shape = (NavMeshBuildSourceShape)2;
			((NavMeshBuildSource)(ref item)).area = 0;
			((NavMeshBuildSource)(ref item)).size = new Vector3(num, 0.2f, num2);
			((NavMeshBuildSource)(ref item)).transform = Matrix4x4.TRS(new Vector3(val8.x, y - 0.1f, val8.z), Quaternion.identity, Vector3.one);
			List<NavMeshBuildSource> list = new List<NavMeshBuildSource>();
			list.Add(item);
			int settingsCount = NavMesh.GetSettingsCount();
			if (settingsCount <= 0)
			{
				Plugin.Log.LogWarning((object)"[ArenaCompat] FERAL NavMesh: no NavMesh build settings available.");
				return false;
			}
			NavMeshBuildSettings settingsByIndex = NavMesh.GetSettingsByIndex(0);
			Bounds val9 = default(Bounds);
			((Bounds)(ref val9))..ctor(new Vector3(val8.x, y + 2f, val8.z), new Vector3(num + 4f, 12f, num2 + 4f));
			NavMeshData val10 = NavMeshBuilder.BuildNavMeshData(settingsByIndex, list, val9, Vector3.zero, Quaternion.identity);
			if ((Object)(object)val10 == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[ArenaCompat] FERAL NavMesh: BuildNavMeshData returned null.");
				return false;
			}
			_feralNavMeshInstance = NavMesh.AddNavMeshData(val10);
			_feralNavMeshAdded = ((NavMeshDataInstance)(ref _feralNavMeshInstance)).valid;
			ManualLogSource log = Plugin.Log;
			object[] array = new object[17]
			{
				"[ArenaCompat] FERAL expanded fallback NavMesh built | floorCenter=", null, null, null, null, null, null, null, null, null,
				null, null, null, null, null, null, null
			};
			Vector3 center = ((Bounds)(ref bounds)).center;
			array[1] = ((Vector3)(ref center)).ToString("F2");
			array[2] = " | floorSize=";
			Vector3 size = ((Bounds)(ref bounds)).size;
			array[3] = ((Vector3)(ref size)).ToString("F2");
			array[4] = " | navCenter=";
			array[5] = ((Vector3)(ref val8)).ToString("F2");
			array[6] = " | navSize=(";
			array[7] = num.ToString("F2");
			array[8] = ", ";
			array[9] = num2.ToString("F2");
			array[10] = ") | playerIncluded=";
			array[11] = flag;
			array[12] = " | agentType=";
			array[13] = ((NavMeshBuildSettings)(ref settingsByIndex)).agentTypeID;
			array[14] = " | valid=";
			array[15] = _feralNavMeshAdded;
			array[16] = ".";
			log.LogInfo((object)string.Concat(array));
			return _feralNavMeshAdded;
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("[ArenaCompat] FERAL fallback NavMesh build failed: " + ex));
			return false;
		}
	}

	private static void EncapsulatePlayableBounds(ref Bounds playableBounds, Bounds candidate, Bounds floorBounds)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		if (!(((Bounds)(ref candidate)).size.x <= 0.01f) || !(((Bounds)(ref candidate)).size.z <= 0.01f))
		{
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(((Bounds)(ref floorBounds)).center.x, ((Bounds)(ref floorBounds)).center.z);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(((Bounds)(ref candidate)).center.x, ((Bounds)(ref candidate)).center.z);
			if (!(Vector2.Distance(val, val2) > 80f) && !(((Bounds)(ref candidate)).size.x > 120f) && !(((Bounds)(ref candidate)).size.z > 120f))
			{
				Vector3 min = ((Bounds)(ref candidate)).min;
				Vector3 max = ((Bounds)(ref candidate)).max;
				((Bounds)(ref playableBounds)).Encapsulate(new Vector3(min.x, ((Bounds)(ref floorBounds)).center.y, min.z));
				((Bounds)(ref playableBounds)).Encapsulate(new Vector3(max.x, ((Bounds)(ref floorBounds)).center.y, max.z));
			}
		}
	}

	private static IEnumerator RepairFeralAgentsDelayed()
	{
		float[] waits = new float[3] { 1f, 2f, 3f };
		for (int pass = 0; pass < waits.Length; pass++)
		{
			yield return (object)new WaitForSeconds(waits[pass]);
			if (IsCustomArenaActive())
			{
				RepairFeralAgentsAndLog(pass + 1);
				continue;
			}
			break;
		}
	}

	private static void RepairFeralAgentsAndLog(int pass)
	{
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Expected O, but got Unknown
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Invalid comparison between Unknown and I4
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		NavMeshAgent[] array = Object.FindObjectsOfType<NavMeshAgent>();
		NavMeshHit val2 = default(NavMeshHit);
		foreach (NavMeshAgent val in array)
		{
			if ((Object)(object)val == (Object)null || !((Behaviour)val).enabled || !((Component)val).gameObject.activeInHierarchy || (_feralPlayableBoundsValid && !InsidePlayableXZ(((Component)val).transform.position, _feralPlayableBounds, 12f)))
			{
				continue;
			}
			num++;
			bool flag = false;
			try
			{
				flag = val.isOnNavMesh;
			}
			catch
			{
			}
			if (flag)
			{
				num2++;
				continue;
			}
			if (NavMesh.SamplePosition(((Component)val).transform.position, ref val2, 10f, -1))
			{
				try
				{
					if (val.Warp(((NavMeshHit)(ref val2)).position))
					{
						num3++;
						continue;
					}
				}
				catch
				{
				}
			}
			num4++;
		}
		bool flag2 = false;
		bool flag3 = false;
		Vector3 val3 = Vector3.zero;
		Vector3 val4 = Vector3.zero;
		try
		{
			if ((Object)(object)PlayerController.instance != (Object)null && (Object)(object)PlayerController.instance.playerAvatarScript != (Object)null)
			{
				PlayerAvatar playerAvatarScript = PlayerController.instance.playerAvatarScript;
				val3 = ((Component)playerAvatarScript).transform.position;
				NavMeshHit val5 = default(NavMeshHit);
				flag2 = NavMesh.SamplePosition(val3, ref val5, 6f, -1);
				if (flag2)
				{
					val4 = ((NavMeshHit)(ref val5)).position;
				}
				if (flag2)
				{
					foreach (NavMeshAgent val6 in array)
					{
						if ((Object)(object)val6 == (Object)null || !((Behaviour)val6).enabled)
						{
							continue;
						}
						bool flag4 = false;
						try
						{
							flag4 = val6.isOnNavMesh;
						}
						catch
						{
						}
						if (flag4)
						{
							NavMeshPath val7 = new NavMeshPath();
							if (NavMesh.CalculatePath(((Component)val6).transform.position, val4, -1, val7))
							{
								flag3 = (int)val7.status == 0;
							}
							break;
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("[ArenaCompat] FERAL NavMesh player diagnostic failed: " + ex.Message));
		}
		Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL NavMesh agent pass " + pass + " | agents=" + num + " | onMesh=" + num2 + " | warped=" + num3 + " | unresolved=" + num4 + " | playerCurrent=" + ((Vector3)(ref val3)).ToString("F2") + " | currentOnNav=" + flag2 + " | sampleEnemyToPlayerPathComplete=" + flag3 + "."));
	}

	private static bool InsidePlayableXZ(Vector3 position, Bounds bounds, float padding)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		Vector3 min = ((Bounds)(ref bounds)).min;
		Vector3 max = ((Bounds)(ref bounds)).max;
		if (position.x >= min.x - padding && position.x <= max.x + padding && position.z >= min.z - padding)
		{
			return position.z <= max.z + padding;
		}
		return false;
	}

	private static void SnapArenaLevelPointsToNavMesh(GameObject arenaRoot)
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)arenaRoot == (Object)null)
		{
			return;
		}
		Type type = AccessTools.TypeByName("LevelPoint");
		if (type == null || !typeof(Component).IsAssignableFrom(type))
		{
			Plugin.Log.LogWarning((object)"[ArenaCompat] FERAL NavMesh: LevelPoint type not found; spawn-point snap skipped.");
			return;
		}
		Component[] componentsInChildren = arenaRoot.GetComponentsInChildren(type, true);
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		NavMeshHit