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 FeralMusicVolume; internal static ConfigEntry 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("Feral Arena", "MusicVolume", 0.05f, "Volume de la musique Gladiator/Feral Arena. 0 = muet, 1 = volume original."); FeralPreparationDelaySeconds = ((BaseUnityPlugin)this).Config.Bind("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 list = new List(); 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 : "") + "'.")); } } 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 _feralRuntimeInstanceIds = new HashSet(); 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 handledPairs = new HashSet(); 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 : ""); string text2 = (((Object)(object)val2 != (Object)null && (Object)(object)val2.parent != (Object)null) ? ((Object)((Component)val2.parent).gameObject).name : ""); 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(); foreach (GameObject val3 in array) { if (!((Object)(object)val3 == (Object)null) && string.Equals(((Object)val3).name, "Arena_Ground", StringComparison.OrdinalIgnoreCase)) { Renderer component = val3.GetComponent(); Collider component2 = val3.GetComponent(); 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 hashSet = new HashSet(); object member = GetMember(arena, "crownTransform"); Transform val2 = (Transform)((member is Transform) ? member : null); if ((Object)(object)val2 != (Object)null) { Renderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren(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 hashSet = new HashSet(); 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(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(); 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(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Renderer component2 = val.GetComponent(); 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(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Renderer component2 = val2.GetComponent(); if ((Object)(object)component2 != (Object)null) { try { component2.material.color = new Color(1f, 0.72f, 0.08f, 1f); } catch { } } Light val3 = val2.AddComponent(); 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(); if ((Object)(object)component3 != (Object)null) { Object.Destroy((Object)(object)component3); } Renderer component4 = val4.GetComponent(); 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(true) : val.GetComponentsInChildren(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(); if ((Object)(object)val6 == (Object)null) { val6 = _crownGrabProxy.AddComponent(); } 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(true) : val.GetComponentsInChildren(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 : ""); 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(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(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 list = new List(); 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(); 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 val2 = default(NavMeshHit); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { Vector3 position = val.transform.position; if (NavMesh.SamplePosition(position, ref val2, 0.75f, -1)) { num2++; } else if (NavMesh.SamplePosition(position, ref val2, 80f, -1)) { val.transform.position = ((NavMeshHit)(ref val2)).position; num++; ManualLogSource log = Plugin.Log; string[] array = new string[7] { "[ArenaCompat] FERAL NavMesh snapped LevelPoint '", ((Object)val.gameObject).name, "': ", ((Vector3)(ref position)).ToString("F2"), " -> ", null, null }; Vector3 position2 = ((NavMeshHit)(ref val2)).position; array[5] = ((Vector3)(ref position2)).ToString("F2"); array[6] = "."; log.LogInfo((object)string.Concat(array)); } else { num3++; } } } Plugin.Log.LogInfo((object)("[ArenaCompat] FERAL LevelPoint NavMesh snap complete | total=" + componentsInChildren.Length + " | moved=" + num + " | alreadyOnMesh=" + num2 + " | unresolved=" + num3 + ".")); } private static void RemoveFeralNavMesh() { _feralArenaGroundBoundsValid = false; _crownLifetimeGuardLogged = false; if (!_feralNavMeshAdded) { return; } try { if (((NavMeshDataInstance)(ref _feralNavMeshInstance)).valid) { ((NavMeshDataInstance)(ref _feralNavMeshInstance)).Remove(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ArenaCompat] FERAL fallback NavMesh cleanup failed: " + ex.Message)); } _feralNavMeshAdded = false; _feralPlayableBoundsValid = false; } private static object GetMemberValue(object target, string name) { if (target == null) { return null; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; Type type = target.GetType(); FieldInfo field = type.GetField(name, bindingAttr); if (field != null) { return field.GetValue(target); } PropertyInfo property = type.GetProperty(name, bindingAttr); if (!(property != null)) { return null; } return property.GetValue(target, null); } private static int RemoveStalePlayerDeathHeads(GameObject root) { int num = 0; MonoBehaviour[] componentsInChildren = root.GetComponentsInChildren(true); foreach (MonoBehaviour val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { Type type = ((object)val).GetType(); if (string.Equals(type.Name, "PlayerDeathHead", StringComparison.Ordinal)) { ((Behaviour)val).enabled = false; Object.Destroy((Object)(object)val); num++; } } } return num; } private static void EnsureArenaEnemyTrigger(GameObject root) { Type type = AccessTools.TypeByName("ArenaEnemyTrigger"); if (!(type == null) && typeof(Component).IsAssignableFrom(type)) { Component val = root.GetComponent(type); if ((Object)(object)val == (Object)null) { val = root.AddComponent(type); } SetMember(val, "spawnCount", 8); SetMember(val, "logger", Plugin.Log); } } private static IEnumerator InvokeCoroutine(object target, string methodName, object argument) { if (target == null) { return null; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; MethodInfo method = target.GetType().GetMethod(methodName, bindingAttr); if (method == null) { Plugin.Log.LogWarning((object)("[ArenaCompat] FERAL method not found: " + methodName + ".")); return null; } try { object obj = method.Invoke(target, new object[1] { argument }); return obj as IEnumerator; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ArenaCompat] FERAL method '" + methodName + "' invocation failed: " + ex)); return null; } } private static object GetStaticMember(Type type, string name) { if (type == null) { return null; } BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = type.GetField(name, bindingAttr); if (field != null) { return field.GetValue(null); } PropertyInfo property = type.GetProperty(name, bindingAttr); if (!(property != null)) { return null; } return property.GetValue(null, null); } private static object GetMember(object target, string name) { if (target == null) { return null; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; Type type = target.GetType(); FieldInfo field = type.GetField(name, bindingAttr); if (field != null) { return field.GetValue(target); } PropertyInfo property = type.GetProperty(name, bindingAttr); if (!(property != null)) { return null; } return property.GetValue(target, null); } private static void SetMember(object target, string name, object value) { if (target == null) { return; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; Type type = target.GetType(); FieldInfo field = type.GetField(name, bindingAttr); if (field != null) { field.SetValue(target, value); return; } PropertyInfo property = type.GetProperty(name, bindingAttr); if (property != null && property.CanWrite) { property.SetValue(target, value, null); } } } internal static class LevelGeneratorStartPatch { private sealed class ArenaSelection { internal GameObject Prefab; internal string ResourcePath; } private static LevelGenerator _lastArenaGenerator; private static bool _lastArenaUseCustom; private static bool _nextArenaUseCustom = false; internal static void Postfix(LevelGenerator __instance) { //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return; } try { if (!FeralRuntimeCompatibility.IsDisposalArenaLevel()) { return; } bool isNewDecision; bool flag = ShouldUseCustomArena(__instance, out isNewDecision); if (isNewDecision) { Plugin.Log.LogInfo((object)("[ArenaCompat] ARENA 50/50 ROTATION | selected=" + (flag ? "GLADIATOR" : "VANILLA") + " | next=" + (flag ? "VANILLA" : "GLADIATOR") + ".")); } if (!flag) { return; } ArenaSelection arenaSelection = SelectEnabledArena(); if (arenaSelection == null || (Object)(object)arenaSelection.Prefab == (Object)null) { Plugin.Log.LogWarning((object)"[ArenaCompat] Disposal Arena detected but no enabled registered custom arena was found."); return; } object staticMember = GetStaticMember(typeof(RunManager), "instance"); if (staticMember == null) { Plugin.Log.LogError((object)"[ArenaCompat] RunManager.instance is null."); return; } AddToMultiplayerResourceCache(staticMember, arenaSelection.ResourcePath, arenaSelection.Prefab); object member = GetMember(staticMember, "levelCurrent"); if (member == null) { Plugin.Log.LogError((object)"[ArenaCompat] RunManager.levelCurrent is null."); return; } object obj = CreatePrefabRef(((Object)arenaSelection.Prefab).name, arenaSelection.ResourcePath); if (obj == null) { Plugin.Log.LogError((object)"[ArenaCompat] Could not create PrefabRef."); return; } IList list = GetList(member, "StartRooms"); if (list == null) { Plugin.Log.LogError((object)"[ArenaCompat] Level.StartRooms was not found."); return; } list.Clear(); list.Add(obj); ClearList(member, "ModulesNormal1"); ClearList(member, "ModulesNormal2"); ClearList(member, "ModulesNormal3"); FieldInfo fieldInfo = AccessTools.Field(typeof(LevelGenerator), "ModuleRotations"); if (fieldInfo != null) { fieldInfo.SetValue(__instance, new Vector3[1] { Vector3.zero }); } Plugin.Log.LogInfo((object)("[ArenaCompat] ARENA INJECTED | prefab='" + ((Object)arenaSelection.Prefab).name + "' | resourcePath='" + arenaSelection.ResourcePath + "' | StartRooms=" + list.Count + ".")); } catch (Exception ex) { Plugin.Log.LogError((object)("[ArenaCompat] Arena injection failed: " + ex)); } } private static bool ShouldUseCustomArena(LevelGenerator generator, out bool isNewDecision) { isNewDecision = false; if ((Object)(object)generator == (Object)null) { return false; } if (object.ReferenceEquals(_lastArenaGenerator, generator)) { return _lastArenaUseCustom; } _lastArenaGenerator = generator; _lastArenaUseCustom = _nextArenaUseCustom; _nextArenaUseCustom = !_nextArenaUseCustom; isNewDecision = true; return _lastArenaUseCustom; } private static ArenaSelection SelectEnabledArena() { Type type = AccessTools.TypeByName("Empress_ArenaLoaderAPI.ArenaLoaderPlugin"); if (type == null) { return null; } FieldInfo fieldInfo = AccessTools.Field(type, "RegisteredArenas"); if (fieldInfo == null) { return null; } if (!(fieldInfo.GetValue(null) is IEnumerable enumerable)) { return null; } List list = new List(); foreach (object item in enumerable) { if (item == null) { continue; } object member = GetMember(item, "EnabledConfig"); bool flag = true; if (member != null) { object member2 = GetMember(member, "Value"); if (member2 is bool) { flag = (bool)member2; } } if (flag) { object member3 = GetMember(item, "Prefab"); GameObject val = (GameObject)((member3 is GameObject) ? member3 : null); string text = GetMember(item, "ResourcePath") as string; if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(text)) { list.Add(new ArenaSelection { Prefab = val, ResourcePath = text }); } } } if (list.Count == 0) { return null; } return list[Random.Range(0, list.Count)]; } private static void AddToMultiplayerResourceCache(object runManager, string resourcePath, GameObject prefab) { object member = GetMember(runManager, "multiplayerPool"); if (member == null) { Plugin.Log.LogWarning((object)"[ArenaCompat] multiplayerPool is null; resource cache injection skipped."); return; } object member2 = GetMember(member, "ResourceCache"); if (!(member2 is IDictionary dictionary)) { Plugin.Log.LogWarning((object)"[ArenaCompat] multiplayerPool.ResourceCache is unavailable."); } else if (!dictionary.Contains(resourcePath)) { dictionary.Add(resourcePath, prefab); } } private static object CreatePrefabRef(string prefabName, string resourcePath) { Type type = AccessTools.TypeByName("PrefabRef"); if (type == null) { return null; } object obj = Activator.CreateInstance(type); SetMember(obj, "prefabName", prefabName); SetMember(obj, "resourcePath", resourcePath); return obj; } private static void ClearList(object target, string name) { GetList(target, name)?.Clear(); } private static IList GetList(object target, string name) { return GetMember(target, name) as IList; } private static object GetStaticMember(Type type, string name) { FieldInfo fieldInfo = AccessTools.Field(type, name); if (fieldInfo != null) { return fieldInfo.GetValue(null); } PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (!(property != null)) { return null; } return property.GetValue(null, null); } private static object GetMember(object target, string name) { if (target == null) { return null; } Type type = target.GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = type.GetField(name, bindingAttr); if (field != null) { return field.GetValue(target); } PropertyInfo property = type.GetProperty(name, bindingAttr); if (!(property != null)) { return null; } return property.GetValue(target, null); } private static void SetMember(object target, string name, object value) { if (target == null) { return; } Type type = target.GetType(); FieldInfo fieldInfo = AccessTools.Field(type, name); if (fieldInfo != null) { fieldInfo.SetValue(target, value); return; } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanWrite) { property.SetValue(target, value, null); } } }