using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; using System.Threading; using AIGraph; using Agents; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using ChainedPuzzles; using GTFO.API; using GTFO.API.Extensions; using GTFO.API.Utilities; using GameData; using HarmonyLib; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Text; using LevelGeneration; using Localization; using MTFO.API; using Microsoft.CodeAnalysis; using Player; using ScanPosOverride.Component; using ScanPosOverride.JSON; using ScanPosOverride.JSON.Extensions; using ScanPosOverride.JSON.PData; using ScanPosOverride.Managers; using ScanPosOverride.PuzzleOverrideData; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("ScanPosOverride")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ScanPosOverride")] [assembly: AssemblyTitle("ScanPosOverride")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ScanPosOverride { internal static class SPOLogger { private static readonly ManualLogSource logger = Logger.CreateLogSource("ScanPosOverride"); public static void Log(string format, params object[] args) { Log(string.Format(format, args)); } public static void Log(string str) { if (logger != null) { logger.Log((LogLevel)8, (object)str); } } public static void Warning(string format, params object[] args) { Warning(string.Format(format, args)); } public static void Warning(string str) { if (logger != null) { logger.Log((LogLevel)4, (object)str); } } public static void Error(string format, params object[] args) { Error(string.Format(format, args)); } public static void Error(string str) { if (logger != null) { logger.Log((LogLevel)2, (object)str); } } public static void Debug(string format, params object[] args) { Debug(string.Format(format, args)); } public static void Debug(string str) { if (logger != null) { logger.Log((LogLevel)32, (object)str); } } public static void Log(BepInExDebugLogInterpolatedStringHandler logHandler) { logger.LogDebug(logHandler); } } [BepInPlugin("ScanPositionOverride", "ScanPositionOverride", "1.6.10")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] internal sealed class Plugin : BasePlugin { [CompilerGenerated] private static class <>O { public static LiveEditEventHandler <0>__LiveEdit_FileChanged; } private static Dictionary> PuzzleOverrides = new Dictionary>(); public static readonly string OVERRIDE_SCAN_POS_PATH = Path.Combine(MTFOPathAPI.CustomPath, "ScanPositionOverrides"); private static LiveEditListener listener = null; private static Harmony m_Harmony = null; public override void Load() { //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Expected O, but got Unknown //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Expected O, but got Unknown SPOLogger.Error(OVERRIDE_SCAN_POS_PATH); if (!Directory.Exists(OVERRIDE_SCAN_POS_PATH)) { Directory.CreateDirectory(OVERRIDE_SCAN_POS_PATH); StreamWriter streamWriter = File.CreateText(Path.Combine(OVERRIDE_SCAN_POS_PATH, "Template.json")); streamWriter.WriteLine(Json.Serialize(new PuzzleOverrideJsonFile())); streamWriter.Flush(); streamWriter.Close(); return; } foreach (string item in Directory.EnumerateFiles(OVERRIDE_SCAN_POS_PATH, "*.json", SearchOption.AllDirectories)) { Json.Load(item, out var config); if (PuzzleOverrides.ContainsKey(config.MainLevelLayout)) { SPOLogger.Warning("Duplicate MainLevelLayout {0}, won't load.", config.MainLevelLayout); continue; } Dictionary dictionary = new Dictionary(); foreach (PuzzleOverride puzzle in config.Puzzles) { if (dictionary.ContainsKey(puzzle.Index)) { SPOLogger.Error("Duplicate Puzzle Override found. MainLevelLayout {0}, Index {1}.", config.MainLevelLayout, puzzle.Index); continue; } puzzle.EventsOnBioscanProgress.RemoveAll((BioscanProgressEvent e) => e.Progress <= 0f); puzzle.EventsOnBioscanProgress.Sort((BioscanProgressEvent e1, BioscanProgressEvent e2) => Mathf.RoundToInt(e1.Progress - e2.Progress)); dictionary.Add(puzzle.Index, puzzle); } PuzzleOverrides.Add(config.MainLevelLayout, dictionary); } listener = LiveEdit.CreateListener(OVERRIDE_SCAN_POS_PATH, "*.json", true); LiveEditListener obj = listener; object obj2 = <>O.<0>__LiveEdit_FileChanged; if (obj2 == null) { LiveEditEventHandler val = LiveEdit_FileChanged; <>O.<0>__LiveEdit_FileChanged = val; obj2 = (object)val; } obj.FileChanged += (LiveEditEventHandler)obj2; m_Harmony = new Harmony("ScanPosOverride.Patches"); m_Harmony.PatchAll(); } private static void LiveEdit_FileChanged(LiveEditEventArgs e) { SPOLogger.Warning("LiveEdit File Changed: " + e.FullPath + "."); LiveEdit.TryReadFileContent(e.FullPath, (Action)delegate(string content) { PuzzleOverrideJsonFile puzzleOverrideJsonFile = Json.Deserialize(content); if (!PuzzleOverrides.ContainsKey(puzzleOverrideJsonFile.MainLevelLayout)) { SPOLogger.Warning("MainLevelLayout not found, which is now not supported. Will not replace."); } else { Dictionary dictionary = PuzzleOverrides[puzzleOverrideJsonFile.MainLevelLayout]; dictionary.Clear(); foreach (PuzzleOverride puzzle in puzzleOverrideJsonFile.Puzzles) { if (dictionary.ContainsKey(puzzle.Index)) { SPOLogger.Error("Duplicate Puzzle Override found. MainLevelLayout {0}, Index {1}.", puzzleOverrideJsonFile.MainLevelLayout, puzzle.Index); } else { puzzle.EventsOnBioscanProgress.Sort((BioscanProgressEvent e1, BioscanProgressEvent e2) => Mathf.RoundToInt(e1.Progress - e2.Progress)); dictionary.Add(puzzle.Index, puzzle); } } SPOLogger.Warning("Replaced Override Puzzle with MainLevelLayout {0}", puzzleOverrideJsonFile.MainLevelLayout); } }); } internal static PuzzleOverride GetOverride(uint mainLevelLayout, uint puzzleIndex) { if (!PuzzleOverrides.ContainsKey(mainLevelLayout)) { return null; } Dictionary dictionary = PuzzleOverrides[mainLevelLayout]; if (!dictionary.ContainsKey(puzzleIndex)) { return null; } return dictionary[puzzleIndex]; } } public static class Utils { } } namespace ScanPosOverride.PuzzleOverrideData { internal sealed class PuzzleOverrideJsonFile { public uint MainLevelLayout { get; set; } public List Puzzles { get; set; } = new List { new PuzzleOverride() }; } public class BioscanProgressEvent { public float Progress { get; set; } = -1f; public List Events { get; set; } = new List(); } public class ClusterProgressEvent { public int Count { get; set; } = -1; public List Events { get; set; } = new List(); } public class PuzzleOverride { public uint Index { get; set; } public Vec3 Position { get; set; } = new Vec3(); public Vec3 Rotation { get; set; } = new Vec3(); public bool HideSpline { get; set; } = false; public Vec3 PrevPosOverride { get; set; } = new Vec3(); public uint PrevPosOverrideIndex { get; set; } = 0u; public bool ConcurrentCluster { get; set; } = false; public HashSet PrerequiredScanIndices { get; set; } = new HashSet(); public float TMoveSpeedMulti { get; set; } = -1f; public List EventsOnBioscanProgress { get; set; } = new List { new BioscanProgressEvent() }; public List EventsOnClusterProgress { get; set; } = new List { new ClusterProgressEvent() }; public List TPositions { get; set; } = new List { new Vec3() }; public List RequiredItemsIndices { get; set; } = new List { 0 }; public List EventsOnPuzzleSolved { get; set; } = new List(); } public class Vec3 { public float x { get; set; } public float y { get; set; } public float z { get; set; } public Vector3 ToVector3() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(x, y, z); } public Quaternion ToQuaternion() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return Quaternion.Euler(x, y, z); } } } namespace ScanPosOverride.Patches { [HarmonyPatch] internal static class Patch_CP_BasicMovable_TryGetNextIndex { } [HarmonyPatch] internal static class Patch_CP_Bioscan_Core_OnSyncStateChange { private static Dictionary EOPIndex; static Patch_CP_Bioscan_Core_OnSyncStateChange() { EOPIndex = new Dictionary(); LevelAPI.OnBuildStart += EOPIndex.Clear; LevelAPI.OnLevelCleanup += EOPIndex.Clear; } [HarmonyPostfix] [HarmonyPatch(typeof(CP_Bioscan_Core), "OnSyncStateChange")] private static void Post_OnSyncStateChanged_CheckEOPAndEventsOnPuzzleSolved(CP_Bioscan_Core __instance, float progress, eBioscanStatus status, List playersInScan, bool isDropinState) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Invalid comparison between Unknown and I4 if ((int)status == 4 && !isDropinState) { uint bioscanCoreOverrideIndex = PuzzleOverrideManager.Current.GetBioscanCoreOverrideIndex(__instance); PuzzleOverrideManager.CompletedScans.Add(bioscanCoreOverrideIndex); SPOLogger.Warning($"OnSyncStateChange: scan {bioscanCoreOverrideIndex} completed, updated completed Scans - {string.Join(",", PuzzleOverrideManager.CompletedScans)}"); } uint bioscanCoreOverrideIndex2 = PuzzleOverrideManager.Current.GetBioscanCoreOverrideIndex(__instance); PuzzleOverride def = Plugin.GetOverride(PuzzleOverrideManager.MainLevelLayout, bioscanCoreOverrideIndex2); if (def != null) { if (def.EventsOnBioscanProgress.Count > 0) { CheckBioscanEventsOnProgress(); } if ((int)status == 4 && !isDropinState && def.EventsOnPuzzleSolved.Count > 0) { WardenObjectiveManager.CheckAndExecuteEventsOnTrigger(ListExtensions.ToIl2Cpp(def.EventsOnPuzzleSolved), (eWardenObjectiveEventTrigger)0, true, 0f, (Il2CppStructArray)null); } } void CheckBioscanEventsOnProgress() { if (!EOPIndex.ContainsKey(((Il2CppObjectBase)__instance).Pointer)) { EOPIndex[((Il2CppObjectBase)__instance).Pointer] = 0; } int num = EOPIndex[((Il2CppObjectBase)__instance).Pointer]; if (isDropinState) { for (num = 0; num < def.EventsOnBioscanProgress.Count; num++) { BioscanProgressEvent bioscanProgressEvent = def.EventsOnBioscanProgress[num]; if (bioscanProgressEvent.Progress > progress) { break; } } EOPIndex[((Il2CppObjectBase)__instance).Pointer] = num; } else if (num < def.EventsOnBioscanProgress.Count) { BioscanProgressEvent bioscanProgressEvent2 = def.EventsOnBioscanProgress[num]; if (bioscanProgressEvent2.Progress < progress) { WardenObjectiveManager.CheckAndExecuteEventsOnTrigger(ListExtensions.ToIl2Cpp(def.EventsOnBioscanProgress[num].Events), (eWardenObjectiveEventTrigger)0, true, 0f, (Il2CppStructArray)null); EOPIndex[((Il2CppObjectBase)__instance).Pointer] = num + 1; } } } } [HarmonyPostfix] [HarmonyPatch(typeof(CP_Bioscan_Core), "OnSyncStateChange")] private static void Post_OnSyncStateChanged_CheckPrereqsAndConcurrentCluster(CP_Bioscan_Core __instance, float progress, eBioscanStatus status, List playersInScan, bool isDropinState) { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Invalid comparison between Unknown and I4 //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Invalid comparison between Unknown and I4 //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Invalid comparison between Unknown and I4 //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Invalid comparison between Unknown and I4 //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Invalid comparison between Unknown and I4 //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_037d: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Invalid comparison between Unknown and I4 //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Invalid comparison between Unknown and I4 //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_05e8: Unknown result type (might be due to invalid IL or missing references) //IL_05ee: Invalid comparison between Unknown and I4 //IL_04fb: Unknown result type (might be due to invalid IL or missing references) //IL_0501: Invalid comparison between Unknown and I4 //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Unknown result type (might be due to invalid IL or missing references) //IL_041e: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: Unknown result type (might be due to invalid IL or missing references) bool flag = PlayerScannerManager.Current.IsConcurrentCluster(__instance); uint bioscanCoreOverrideIndex = PuzzleOverrideManager.Current.GetBioscanCoreOverrideIndex(__instance); PuzzleOverride @override = Plugin.GetOverride(PuzzleOverrideManager.MainLevelLayout, bioscanCoreOverrideIndex); if (@override == null) { return; } bool flag2 = false; if (@override != null && @override.PrerequiredScanIndices.Count > 0) { foreach (uint prerequiredScanIndex in @override.PrerequiredScanIndices) { if (!PuzzleOverrideManager.CompletedScans.Contains(prerequiredScanIndex)) { flag2 = true; break; } } } if (flag && __instance.m_reqItemsEnabled) { SPOLogger.Warning($"OnSyncStateChange: status - {status}, playersInScan - {playersInScan.Count}, progress: {progress}"); } if (flag2) { SPOLogger.Warning($"OnSyncStateChange: scan - {bioscanCoreOverrideIndex}, completede scans: {string.Join(",", PuzzleOverrideManager.CompletedScans)}, prerequired scans: {string.Join(",", @override.PrerequiredScanIndices)}"); } if ((int)status != 3) { if (flag) { if ((int)status == 4) { CP_Cluster_Core val = ((Il2CppObjectBase)__instance.Owner).TryCast(); if ((Object)(object)val == (Object)null) { SPOLogger.Error("Cannot find parent cluster core! The concurrent cluster may fail!"); } else { PlayerScannerManager.Current.CompleteConcurrentCluster(val, __instance); } } else { PlayerScannerManager.Current.CCShouldProgress(__instance, IsThisScanShouldProgress: false); } } if (__instance.m_reqItemsEnabled) { __instance.m_graphics.SetColorMode((eChainedPuzzleGraphicsColorMode)((!__instance.m_hasAlarm) ? 1 : 4)); } } else { if (!__instance.IsMovable && !flag && !__instance.m_reqItemsEnabled && @override.PrerequiredScanIndices.Count <= 0) { return; } SPOLogger.Warning($"OnSyncStateChange: processing scan - {bioscanCoreOverrideIndex}"); CP_PlayerScanner cacheScanner = PlayerScannerManager.Current.GetCacheScanner(__instance); if ((Object)(object)cacheScanner == (Object)null) { return; } int count = playersInScan.Count; List playerAgentsInLevel = PlayerManager.PlayerAgentsInLevel; float num = 0f; float[] cacheOriginalScanSpeed = PlayerScannerManager.Current.GetCacheOriginalScanSpeed(__instance); if ((int)__instance.m_playerScanner.ScanPlayersRequired == 0) { num = ((count <= 0) ? 0f : cacheOriginalScanSpeed[count - 1]); } else if (((int)cacheScanner.m_playerRequirement == 1 && count == playerAgentsInLevel.Count) || ((int)cacheScanner.m_playerRequirement == 2 && count == 1)) { num = cacheOriginalScanSpeed[0]; } bool flag3 = num > 0f; if (flag3) { if (cacheScanner.m_reqItemsEnabled) { for (int i = 0; i < ((Il2CppArrayBase)(object)cacheScanner.m_reqItems).Length; i++) { Vector3 val2 = Vector3.zero; if ((int)((Il2CppArrayBase)(object)cacheScanner.m_reqItems)[i].PickupItemStatus == 0) { val2 = ((Il2CppArrayBase)(object)cacheScanner.m_reqItems)[i].transform.position; } else if ((int)((Il2CppArrayBase)(object)cacheScanner.m_reqItems)[i].PickupItemStatus == 1) { if ((Object)(object)((Il2CppArrayBase)(object)cacheScanner.m_reqItems)[i].PickedUpByPlayer != (Object)null) { val2 = ((Agent)((Il2CppArrayBase)(object)cacheScanner.m_reqItems)[i].PickedUpByPlayer).Position; } else { Debug.LogError(Object.op_Implicit("Playerscanner is looking for an item that has ePickupItemStatus.PickedUp but null player, how come!?")); } } Vector3 val3 = ((Component)cacheScanner).transform.position - val2; if (((Vector3)(ref val3)).sqrMagnitude >= cacheScanner.m_scanRadiusSqr) { flag3 = false; break; } } } if (flag2) { flag3 = false; } } if (flag) { if (flag3) { flag3 = PlayerScannerManager.Current.CCShouldProgress(__instance, IsThisScanShouldProgress: true); } else { PlayerScannerManager.Current.CCShouldProgress(__instance, IsThisScanShouldProgress: false); } } if (flag3) { if (flag) { CP_Cluster_Core parent = ((Il2CppObjectBase)__instance.Owner).Cast(); PlayerScannerManager.Current.RestoreCCScanSpeed(parent); } if (__instance.IsMovable) { __instance.m_movingComp.ResumeMovement(); } if (cacheScanner.m_reqItemsEnabled) { if ((int)cacheScanner.m_playerRequirement == 0) { ((Il2CppArrayBase)(object)cacheScanner.m_scanSpeeds)[0] = ((count > 0) ? cacheOriginalScanSpeed[count - 1] : 0f); } __instance.m_graphics.SetColorMode((eChainedPuzzleGraphicsColorMode)(__instance.m_hasAlarm ? 5 : 2)); } if (@override.PrerequiredScanIndices.Count > 0) { ((Il2CppArrayBase)(object)cacheScanner.m_scanSpeeds)[0] = ((count > 0) ? cacheOriginalScanSpeed[count - 1] : 0f); __instance.m_graphics.SetColorMode((eChainedPuzzleGraphicsColorMode)(__instance.m_hasAlarm ? 5 : 2)); } return; } if (flag) { CP_Cluster_Core parent2 = ((Il2CppObjectBase)__instance.Owner).Cast(); PlayerScannerManager.Current.ZeroCCScanSpeed(parent2); } if (__instance.IsMovable) { __instance.m_movingComp.PauseMovement(); } if (cacheScanner.m_reqItemsEnabled) { if ((int)cacheScanner.m_playerRequirement == 0) { PlayerScannerManager.Current.GetCacheOriginalScanSpeed(__instance); ((Il2CppArrayBase)(object)cacheScanner.m_scanSpeeds)[0] = 0f; } __instance.m_graphics.SetColorMode((eChainedPuzzleGraphicsColorMode)((!__instance.m_hasAlarm) ? 1 : 4)); } if (flag2) { ((Il2CppArrayBase)(object)cacheScanner.m_scanSpeeds)[0] = 0f; SPOLogger.Warning($"OnSyncStateChange: scan - {bioscanCoreOverrideIndex} paused"); __instance.m_graphics.SetColorMode((eChainedPuzzleGraphicsColorMode)((!__instance.m_hasAlarm) ? 1 : 4)); } } } } [HarmonyPatch] internal class Patch_CP_Bioscan_Core_Setup { [HarmonyPrefix] [HarmonyPatch(typeof(CP_Bioscan_Core), "Setup")] private static void Pre_CP_Bioscan_Core_Setup(CP_Bioscan_Core __instance, int puzzleIndex, iChainedPuzzleOwner owner, ref Vector3 prevPuzzlePos, ref bool revealWithHoloPath, ref bool onlyShowHUDWhenPlayerIsClose) { //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_0418: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_0530: Unknown result type (might be due to invalid IL or missing references) //IL_0555: Unknown result type (might be due to invalid IL or missing references) ChainedPuzzleInstance val = ((Il2CppObjectBase)owner).TryCast(); uint num = PuzzleOverrideManager.Current.Register(__instance); PuzzleOverride @override = Plugin.GetOverride(PuzzleOverrideManager.MainLevelLayout, num); if ((Object)(object)val != (Object)null) { bool flag = false; if (@override != null) { if (@override.PrevPosOverride.ToVector3() != Vector3.zero) { prevPuzzlePos = @override.PrevPosOverride.ToVector3(); flag = true; } else if (@override.PrevPosOverrideIndex != 0) { CP_Bioscan_Core bioscanCore = PuzzleOverrideManager.Current.GetBioscanCore(@override.PrevPosOverrideIndex); ? val2; if (bioscanCore == null) { CP_Cluster_Core clusterCore = PuzzleOverrideManager.Current.GetClusterCore(@override.PrevPosOverrideIndex); val2 = ((clusterCore != null) ? ((Component)clusterCore).transform.position : Vector3.zero); } else { val2 = bioscanCore.m_position; } Vector3 val3 = (Vector3)val2; if (val3 == Vector3.zero) { SPOLogger.Error($"PuzzleOverrideIndex: {num} - trying to use 'PrevPosOverrideIndex' ({@override.PrevPosOverrideIndex}) but the puzzle is not found."); SPOLogger.Error($"The puzzle is probably yet registered. NOTE: 'PrevPosOverrideIndex' could only be a integer that is less than PuzzleOverrideIndex({num})"); flag = false; } else { prevPuzzlePos = val3; flag = true; } } } if (!flag && puzzleIndex != 0) { CP_Bioscan_Core val4 = ((Il2CppObjectBase)((Il2CppArrayBase)(object)val.m_chainedPuzzleCores)[puzzleIndex - 1]).TryCast(); if ((Object)(object)val4 != (Object)null) { prevPuzzlePos = ((Component)val4).transform.position; } else { CP_Cluster_Core val5 = ((Il2CppObjectBase)((Il2CppArrayBase)(object)val.m_chainedPuzzleCores)[puzzleIndex - 1]).TryCast(); if ((Object)(object)val5 == (Object)null) { SPOLogger.Error($"Cannot cast m_chainedPuzzleCores[{puzzleIndex - 1}] to neither CP_Bioscan_Core or CP_Cluster_Core! WTF???"); } else { prevPuzzlePos = ((Component)val5).transform.position; } } } } else { CP_Cluster_Core val6 = ((Il2CppObjectBase)owner).Cast(); if (@override != null && @override.PrevPosOverride.ToVector3() != Vector3.zero) { prevPuzzlePos = @override.PrevPosOverride.ToVector3(); } else if (@override != null && @override.PrevPosOverrideIndex != 0) { CP_Bioscan_Core bioscanCore2 = PuzzleOverrideManager.Current.GetBioscanCore(@override.PrevPosOverrideIndex); ? val7; if (bioscanCore2 == null) { CP_Cluster_Core clusterCore2 = PuzzleOverrideManager.Current.GetClusterCore(@override.PrevPosOverrideIndex); val7 = ((clusterCore2 != null) ? ((Component)clusterCore2).transform.position : Vector3.zero); } else { val7 = bioscanCore2.m_position; } Vector3 val8 = (Vector3)val7; if (val8 == Vector3.zero) { SPOLogger.Error($"PuzzleOverrideIndex: {num} - trying to use 'PrevPosOverrideIndex' ({@override.PrevPosOverrideIndex}) but the puzzle is not found."); SPOLogger.Error($"The puzzle is probably yet registered. NOTE: 'PrevPosOverrideIndex' could only be a integer that is less than PuzzleOverrideIndex({num})"); prevPuzzlePos = ((Component)val6).transform.position; } else { prevPuzzlePos = val8; } } else { prevPuzzlePos = ((Component)val6).transform.position; } val = ((Il2CppObjectBase)val6.m_owner).Cast(); if (val.Data.OnlyShowHUDWhenPlayerIsClose) { onlyShowHUDWhenPlayerIsClose = true; } } if (@override != null) { if (@override.Position.ToVector3() != Vector3.zero || @override.Rotation.ToVector3() != Vector3.zero) { ((Component)__instance).transform.SetPositionAndRotation(@override.Position.ToVector3(), @override.Rotation.ToQuaternion()); } if (@override.HideSpline || ((Object)(object)__instance.m_movingComp != (Object)null && __instance.m_movingComp.IsMoveConfigured)) { revealWithHoloPath = false; } if (@override.RequiredItemsIndices != null && @override.RequiredItemsIndices.Count > 0) { PuzzleReqItemManager.Current.QueueForAddingReqItems(__instance, @override.RequiredItemsIndices); } SPOLogger.Warning("Overriding CP_Bioscan_Core." + (((Object)(object)val == (Object)null) ? "" : $"Zone {val.m_sourceArea.m_zone.Alias}, Layer {val.m_sourceArea.m_zone.Layer.m_type}, Dim {val.m_sourceArea.m_zone.DimensionIndex}")); } } } [HarmonyPatch] internal class Patch_ChainedPuzzleInstance_SetupMovement { [HarmonyPrefix] [HarmonyPatch(typeof(ChainedPuzzleInstance), "SetupMovement")] private static bool Pre_SetupMovement(ChainedPuzzleInstance __instance, GameObject gameObject) { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) iChainedPuzzleMovable movingComp = gameObject.GetComponent(); if (movingComp == null || !movingComp.UsingStaticBioscanPoints) { return true; } CP_BasicMovable val = ((Il2CppObjectBase)movingComp).Cast(); iChainedPuzzleCore component = gameObject.GetComponent(); CP_Bioscan_Core core = ((Il2CppObjectBase)component).Cast(); uint bioscanCoreOverrideIndex = PuzzleOverrideManager.Current.GetBioscanCoreOverrideIndex(core); if (bioscanCoreOverrideIndex == 0) { SPOLogger.Error("Did not find registered movable override for this movable scan."); return true; } PuzzleOverride @override = Plugin.GetOverride(PuzzleOverrideManager.MainLevelLayout, bioscanCoreOverrideIndex); if (@override == null || @override.TPositions.Count < 1) { SPOLogger.Error("No Override for this T-Scan, falling back to vanilla impl."); return true; } @override.TPositions.ForEach(delegate(Vec3 pos) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) movingComp.ScanPositions.Add(pos.ToVector3()); }); gameObject.transform.position = @override.TPositions[0].ToVector3(); val.m_amountOfPositions = @override.TPositions.Count; if (@override.TMoveSpeedMulti > 0f) { val.m_movementSpeed *= @override.TMoveSpeedMulti; } SPOLogger.Warning("Overriding T-Scan pos!"); return false; } } [HarmonyPatch] internal class Patch_CarryItemPickup_Core_Setup { [HarmonyPostfix] [HarmonyPatch(typeof(CarryItemPickup_Core), "Setup")] private static void Post_CarryItemPickup_Core_Setup(CarryItemPickup_Core __instance) { PuzzleReqItemManager.Current.Register(__instance); } } [HarmonyPatch] internal static class Patch_CP_Cluster_Core_OnSyncStateChange { [HarmonyPostfix] [HarmonyPatch(typeof(CP_Cluster_Core), "OnSyncStateChange")] private static void Post_CheckEventsOnPuzzleSolved(CP_Cluster_Core __instance, eClusterStatus newStatus, bool isDropinState) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)newStatus == 3) { if (!isDropinState) { uint clusterCoreOverrideIndex = PuzzleOverrideManager.Current.GetClusterCoreOverrideIndex(__instance); PuzzleOverrideManager.CompletedScans.Add(clusterCoreOverrideIndex); SPOLogger.Warning($"OnSyncStateChange: scan {clusterCoreOverrideIndex} completed, updated completed scans - {PuzzleOverrideManager.CompletedScans}"); } uint clusterCoreOverrideIndex2 = PuzzleOverrideManager.Current.GetClusterCoreOverrideIndex(__instance); PuzzleOverride @override = Plugin.GetOverride(PuzzleOverrideManager.MainLevelLayout, clusterCoreOverrideIndex2); if (@override != null && @override.EventsOnPuzzleSolved.Count > 0 && !isDropinState) { WardenObjectiveManager.CheckAndExecuteEventsOnTrigger(ListExtensions.ToIl2Cpp(@override.EventsOnPuzzleSolved), (eWardenObjectiveEventTrigger)0, true, 0f, (Il2CppStructArray)null); } } } } [HarmonyPatch] internal class Patch_CP_Cluster_Core_Setup { [HarmonyPrefix] [HarmonyPatch(typeof(CP_Cluster_Core), "Setup")] private static void Pre_CP_Cluster_Core_Setup(CP_Cluster_Core __instance, int puzzleIndex, iChainedPuzzleOwner owner, ref Vector3 prevPuzzlePos, ref bool revealWithHoloPath) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0263: 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_027a: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: 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_016b: Unknown result type (might be due to invalid IL or missing references) uint num = PuzzleOverrideManager.Current.Register(__instance); PuzzleOverride @override = Plugin.GetOverride(PuzzleOverrideManager.MainLevelLayout, num); ChainedPuzzleInstance val = ((Il2CppObjectBase)owner).Cast(); bool flag = false; if (@override != null) { if (@override.PrevPosOverride.ToVector3() != Vector3.zero) { prevPuzzlePos = @override.PrevPosOverride.ToVector3(); flag = true; } else if (@override.PrevPosOverrideIndex != 0) { CP_Bioscan_Core bioscanCore = PuzzleOverrideManager.Current.GetBioscanCore(@override.PrevPosOverrideIndex); ? val2; if (bioscanCore == null) { CP_Cluster_Core clusterCore = PuzzleOverrideManager.Current.GetClusterCore(@override.PrevPosOverrideIndex); val2 = ((clusterCore != null) ? ((Component)clusterCore).transform.position : Vector3.zero); } else { val2 = bioscanCore.m_position; } Vector3 val3 = (Vector3)val2; if (val3 == Vector3.zero) { SPOLogger.Error($"PuzzleOverrideIndex: {num} - trying to use 'PrevPosOverrideIndex' ({@override.PrevPosOverrideIndex}) but the puzzle is not found."); SPOLogger.Error($"The puzzle is probably yet registered. NOTE: 'PrevPosOverrideIndex' could only be a integer that is less than PuzzleOverrideIndex({num})"); flag = false; } else { prevPuzzlePos = val3; flag = true; } } } if (!flag && puzzleIndex != 0) { CP_Bioscan_Core val4 = ((Il2CppObjectBase)((Il2CppArrayBase)(object)val.m_chainedPuzzleCores)[puzzleIndex - 1]).TryCast(); if ((Object)(object)val4 != (Object)null) { prevPuzzlePos = ((Component)val4).transform.position; } else { CP_Cluster_Core val5 = ((Il2CppObjectBase)((Il2CppArrayBase)(object)val.m_chainedPuzzleCores)[puzzleIndex - 1]).TryCast(); if ((Object)(object)val5 == (Object)null) { SPOLogger.Error($"Cannot cast m_chainedPuzzleCores[{puzzleIndex - 1}] to neither CP_Bioscan_Core or CP_Cluster_Core! WTF???"); } else { prevPuzzlePos = ((Component)val5).transform.position; } } } if (@override != null) { if (@override.Position.ToVector3() != Vector3.zero || @override.Rotation.ToVector3() != Vector3.zero) { ((Component)__instance).transform.SetPositionAndRotation(@override.Position.ToVector3(), @override.Rotation.ToQuaternion()); } if (@override.RequiredItemsIndices != null && @override.RequiredItemsIndices.Count > 0) { PuzzleReqItemManager.Current.QueueForAddingReqItems(__instance, @override.RequiredItemsIndices); } if (@override.HideSpline) { revealWithHoloPath = false; } SPOLogger.Warning("Overriding CP_Cluster_Core!"); } } [HarmonyPostfix] [HarmonyPatch(typeof(CP_Cluster_Core), "Setup")] private static void Post_CP_Cluster_Core_Setup(CP_Cluster_Core __instance) { ChainedPuzzleInstance val = ((Il2CppObjectBase)__instance.m_owner).Cast(); foreach (iChainedPuzzleCore item in (Il2CppArrayBase)(object)__instance.m_childCores) { if (item.IsMovable && PuzzleOverrideManager.Current.GetBioscanCoreOverrideIndex(((Il2CppObjectBase)item).Pointer) != 0) { val.SetupMovement(((Component)((Il2CppObjectBase)item).Cast()).gameObject, val.m_sourceArea); } } uint clusterCoreOverrideIndex = PuzzleOverrideManager.Current.GetClusterCoreOverrideIndex(__instance); if (clusterCoreOverrideIndex == 0) { return; } PuzzleOverride def = Plugin.GetOverride(PuzzleOverrideManager.MainLevelLayout, clusterCoreOverrideIndex); if (def == null) { return; } if (def.ConcurrentCluster) { if (2 <= ((Il2CppArrayBase)(object)__instance.m_childCores).Count && ((Il2CppArrayBase)(object)__instance.m_childCores).Count <= 4) { CP_Cluster_Hud val2 = ((Il2CppObjectBase)__instance.m_hud).Cast(); ConcurrentClusterHud concurrentClusterHud = ((Component)val2).gameObject.AddComponent(); concurrentClusterHud.parent = __instance; concurrentClusterHud.parentHud = ((Il2CppObjectBase)val2.m_hud).Cast(); concurrentClusterHud.def = def; if (concurrentClusterHud.Setup()) { PlayerScannerManager.Current.RegisterConcurrentCluster(__instance); SPOLogger.Warning("Setting up CP_Cluster_Core as Concurrent Cluster!"); } else { SPOLogger.Warning("Concurrent Cluster: failed to setup"); } } else { SPOLogger.Error("Trying to setup concurrent cluster, " + $"but the cluster scan has {((Il2CppArrayBase)(object)__instance.m_childCores).Count}, which is senseless or is impossible for 4 players to complete"); } } if (def.EventsOnClusterProgress.Count <= 0) { return; } foreach (iChainedPuzzleCore item2 in (Il2CppArrayBase)(object)__instance.m_childCores) { item2.OnPuzzleDone += Action.op_Implicit((Action)CheckEventsOnClusterProgress); } void CheckEventsOnClusterProgress(int puzzleIndex) { int num = 0; for (int i = 0; i < ((Il2CppArrayBase)(object)__instance.m_childCores).Length; i++) { if (((Il2CppArrayBase)(object)__instance.m_childCores)[i].IsFinished()) { num++; } } foreach (ClusterProgressEvent item3 in def.EventsOnClusterProgress) { if (item3.Count == num) { WardenObjectiveManager.CheckAndExecuteEventsOnTrigger(ListExtensions.ToIl2Cpp(item3.Events), (eWardenObjectiveEventTrigger)0, true, 0f, (Il2CppStructArray)null); } } } } } [HarmonyPatch] internal class Patches_CP_Cluster_Hud_ReqItems { private static Dictionary> childrenReqItemEnabled { get; } private static Dictionary> clustersChildrenReqItemNames { get; } private static Dictionary>> clustersChildrenReqItemsStatus { get; } [HarmonyPostfix] [HarmonyPatch(typeof(CP_Bioscan_Core), "AddRequiredItems")] private static void Post_CP_Bioscan_Core_AddRequiredItems(CP_Bioscan_Core __instance, Il2CppReferenceArray requiredItems) { CP_Cluster_Core val = ((Il2CppObjectBase)__instance.Owner).TryCast(); if ((Object)(object)val == (Object)null) { return; } if (__instance.m_hud == null) { SPOLogger.Error("CP_Cluster_Hud_ReqItems: replacement Cluster_hud is null."); return; } CP_Cluster_Hud val2 = ((Il2CppObjectBase)__instance.m_hud).Cast(); string[] array = new string[((Il2CppArrayBase)(object)requiredItems).Count]; for (int i = 0; i < __instance.m_reqItems.Count; i++) { if (__instance.m_reqItems[i] != null) { array[i] = __instance.m_reqItems[i].PublicName; } else { SPOLogger.Error("Post_CP_Bioscan_Core_AddRequiredItems: CP_Bioscan_Core " + ((Object)__instance).name + " has a missing m_reqItem! " + i); } } List list; List list2; if (childrenReqItemEnabled.ContainsKey(((Il2CppObjectBase)val2).Pointer)) { list = childrenReqItemEnabled[((Il2CppObjectBase)val2).Pointer]; list2 = clustersChildrenReqItemNames[((Il2CppObjectBase)val2).Pointer]; } else { list = Enumerable.Repeat(element: false, val.NRofPuzzles()).ToList(); list2 = Enumerable.Repeat(new string[0], val.NRofPuzzles()).ToList(); childrenReqItemEnabled.Add(((Il2CppObjectBase)val2).Pointer, list); clustersChildrenReqItemNames.Add(((Il2CppObjectBase)val2).Pointer, list2); } list[__instance.m_puzzleIndex] = __instance.m_reqItemsEnabled; list2[__instance.m_puzzleIndex] = array; } [HarmonyPrefix] [HarmonyPatch(typeof(CP_Cluster_Hud), "SetRequiredItemData")] private static bool Pre_CP_Cluster_Hud_SetRequiredItemData(CP_Cluster_Hud __instance, int puzzleIndex, Il2CppStructArray reqItemStatus) { List> list; if (!clustersChildrenReqItemsStatus.ContainsKey(((Il2CppObjectBase)__instance).Pointer)) { list = Enumerable.Repeat>(null, __instance.m_clusterSize).ToList(); clustersChildrenReqItemsStatus.Add(((Il2CppObjectBase)__instance).Pointer, list); } else { list = clustersChildrenReqItemsStatus[((Il2CppObjectBase)__instance).Pointer]; } list[puzzleIndex] = reqItemStatus; return false; } [HarmonyPostfix] [HarmonyPatch(typeof(CP_Cluster_Hud), "UpdateDataFor")] private static void Post_CP_Cluster_Hud_UpdateDataFor(CP_Cluster_Hud __instance, int index) { if (clustersChildrenReqItemsStatus.ContainsKey(((Il2CppObjectBase)__instance).Pointer)) { if (!childrenReqItemEnabled.ContainsKey(((Il2CppObjectBase)__instance).Pointer) || !clustersChildrenReqItemNames.ContainsKey(((Il2CppObjectBase)__instance).Pointer)) { SPOLogger.Error("CP_Cluster_Hud_UpdateDataFor: Found registered reqItemStatus but ReqItemEnabled or ReqItemNames is missing!"); return; } Il2CppStructArray val = clustersChildrenReqItemsStatus[((Il2CppObjectBase)__instance).Pointer][index]; __instance.m_hud.SetupRequiredItems(childrenReqItemEnabled[((Il2CppObjectBase)__instance).Pointer][index], Il2CppStringArray.op_Implicit(clustersChildrenReqItemNames[((Il2CppObjectBase)__instance).Pointer][index])); __instance.m_hud.SetRequiredItemData(__instance.m_puzzleIndex, val); } } private static void Clear() { clustersChildrenReqItemsStatus.Clear(); clustersChildrenReqItemNames.Clear(); childrenReqItemEnabled.Clear(); } static Patches_CP_Cluster_Hud_ReqItems() { childrenReqItemEnabled = new Dictionary>(); clustersChildrenReqItemNames = new Dictionary>(); clustersChildrenReqItemsStatus = new Dictionary>>(); LevelAPI.OnLevelCleanup += Clear; } } } namespace ScanPosOverride.Managers { public class PlayerScannerManager { private static readonly float[] ZERO_SCAN_SPEED; private Mutex CCStateMutex = null; private Dictionary ChildScanners = new Dictionary(); public static PlayerScannerManager Current { get; } private Dictionary> CCCores { get; } = new Dictionary>(); private Dictionary> CCChildren { get; } = new Dictionary>(); private Dictionary> CCChildrenState { get; } = new Dictionary>(); private Dictionary OriginalClusterScanSpeeds { get; } = new Dictionary(); private Dictionary OriginalScanSpeed { get; } = new Dictionary(); internal bool RegisterConcurrentCluster(CP_Cluster_Core core) { if (CCCores.ContainsKey(((Il2CppObjectBase)core).Pointer)) { return false; } List list = Enumerable.Repeat(null, core.m_amountOfPuzzles).ToList(); HashSet hashSet = new HashSet(); for (int i = 0; i < ((Il2CppArrayBase)(object)core.m_childCores).Count; i++) { if ((Object)(object)list[i] != (Object)null) { SPOLogger.Error("SetupConcurrentClusterScanners: Duplicate child scanner for child scan. ??"); continue; } iChainedPuzzleCore val = ((Il2CppArrayBase)(object)core.m_childCores)[i]; CP_Bioscan_Core val2 = ((Il2CppObjectBase)val).TryCast(); if ((Object)(object)val2 == (Object)null) { SPOLogger.Error("SetupConcurrentClusterScanners: Failed to cast child to CP_Bioscan_Core"); continue; } CP_PlayerScanner val3 = ((Il2CppObjectBase)val2.PlayerScanner).TryCast(); if ((Object)(object)val3 == (Object)null) { SPOLogger.Error("SetupConcurrentClusterScanners: Failed to cast CP_Bioscan_Core.PlayerScanner to CP_PlayerScanner"); continue; } list[i] = val3; ChildScanners.Add(((Il2CppObjectBase)val).Pointer, val3); hashSet.Add(((Il2CppObjectBase)val2).Pointer); if (!OriginalClusterScanSpeeds.ContainsKey(((Il2CppObjectBase)core).Pointer)) { Il2CppStructArray scanSpeeds = val3.m_scanSpeeds; float[] array = new float[((Il2CppArrayBase)(object)scanSpeeds).Length]; Array.Copy(Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)scanSpeeds), array, ((Il2CppArrayBase)(object)scanSpeeds).Length); OriginalClusterScanSpeeds.Add(((Il2CppObjectBase)core).Pointer, array); } } CCCores.Add(((Il2CppObjectBase)core).Pointer, list); CCChildren.Add(((Il2CppObjectBase)core).Pointer, hashSet); CCChildrenState.Add(((Il2CppObjectBase)core).Pointer, new HashSet()); return true; } internal bool IsConcurrentCluster(CP_Cluster_Core core) { return CCCores.ContainsKey(((Il2CppObjectBase)core).Pointer); } internal bool IsConcurrentCluster(CP_Bioscan_Core core) { return CCCores.ContainsKey(((Il2CppObjectBase)core.Owner).Pointer); } internal void ZeroCCScanSpeed(CP_Cluster_Core parent) { if (!CCCores.ContainsKey(((Il2CppObjectBase)parent).Pointer)) { return; } foreach (CP_PlayerScanner item in CCCores[((Il2CppObjectBase)parent).Pointer]) { bool flag = true; for (int i = 0; i < 4; i++) { flag = flag && ((Il2CppArrayBase)(object)item.m_scanSpeeds)[i] == 0f; ((Il2CppArrayBase)(object)item.m_scanSpeeds)[i] = 0f; } if (flag) { break; } } } internal void RestoreCCScanSpeed(CP_Cluster_Core parent) { if (!CCCores.ContainsKey(((Il2CppObjectBase)parent).Pointer) || !OriginalClusterScanSpeeds.ContainsKey(((Il2CppObjectBase)parent).Pointer)) { return; } float[] array = OriginalClusterScanSpeeds[((Il2CppObjectBase)parent).Pointer]; foreach (CP_PlayerScanner item in CCCores[((Il2CppObjectBase)parent).Pointer]) { bool flag = false; for (int i = 0; i < 4; i++) { flag = flag || ((Il2CppArrayBase)(object)item.m_scanSpeeds)[i] != 0f; ((Il2CppArrayBase)(object)item.m_scanSpeeds)[i] = array[i]; } if (flag) { break; } } } internal float[] GetCacheOriginalScanSpeed(CP_Bioscan_Core core) { if (IsConcurrentCluster(core)) { return CCCores.ContainsKey(((Il2CppObjectBase)core.Owner).Pointer) ? OriginalClusterScanSpeeds[((Il2CppObjectBase)core.Owner).Pointer] : ZERO_SCAN_SPEED; } if (OriginalScanSpeed.ContainsKey(((Il2CppObjectBase)core).Pointer)) { return OriginalScanSpeed[((Il2CppObjectBase)core).Pointer]; } CP_PlayerScanner cacheScanner = GetCacheScanner(core); if ((Object)(object)cacheScanner == (Object)null) { SPOLogger.Error("GetCacheOriginalScanSpeed: cannot get scanner for this CP_Bioscan_Core"); return ZERO_SCAN_SPEED; } float[] array = new float[4]; Array.Copy(Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)cacheScanner.m_scanSpeeds), array, array.Length); OriginalScanSpeed.Add(((Il2CppObjectBase)core).Pointer, array); return array; } public CP_PlayerScanner GetCacheScanner(CP_Bioscan_Core core) { if (ChildScanners.ContainsKey(((Il2CppObjectBase)core).Pointer)) { return ChildScanners[((Il2CppObjectBase)core).Pointer]; } CP_PlayerScanner val = ((Il2CppObjectBase)core.PlayerScanner).TryCast(); if ((Object)(object)val == (Object)null) { return null; } ChildScanners.Add(((Il2CppObjectBase)core).Pointer, val); return val; } internal bool CCShouldProgress(CP_Bioscan_Core child, bool IsThisScanShouldProgress) { if (CCStateMutex == null) { CCStateMutex = new Mutex(); } if (CCStateMutex.WaitOne(2000)) { if (!CCCores.ContainsKey(((Il2CppObjectBase)child.Owner).Pointer)) { SPOLogger.Error("ConcurrentClusterShouldProgress: failed to find cluster parent!"); CCStateMutex.ReleaseMutex(); return false; } CP_Cluster_Core val = ((Il2CppObjectBase)child.Owner).Cast(); if (!CCChildrenState.ContainsKey(((Il2CppObjectBase)val).Pointer)) { SPOLogger.Error("ConcurrentClusterShouldProgress: ConcurrentClusterChildScanState initialization error!"); CCStateMutex.ReleaseMutex(); return false; } HashSet hashSet = CCChildrenState[((Il2CppObjectBase)val).Pointer]; bool result; if (IsThisScanShouldProgress) { hashSet.Add(((Il2CppObjectBase)child).Pointer); result = hashSet.Count == val.m_amountOfPuzzles; } else { hashSet.Remove(((Il2CppObjectBase)child).Pointer); result = false; } CCStateMutex.ReleaseMutex(); return result; } SPOLogger.Debug("ConcurrentCluster: Failed to acquire scan mutex."); return false; } internal void CompleteConcurrentCluster(CP_Cluster_Core parent, CP_Bioscan_Core child) { if (CCChildren.ContainsKey(((Il2CppObjectBase)parent).Pointer)) { HashSet hashSet = CCChildren[((Il2CppObjectBase)parent).Pointer]; hashSet.Remove(((Il2CppObjectBase)child).Pointer); if (hashSet.Count < 1) { CCChildren.Remove(((Il2CppObjectBase)parent).Pointer); } } } public List GetCCChildrenScanner(CP_Cluster_Core parent) { return CCCores.ContainsKey(((Il2CppObjectBase)parent).Pointer) ? CCCores[((Il2CppObjectBase)parent).Pointer] : null; } public void Clear() { CCCores.Clear(); CCChildren.Clear(); CCChildrenState.Clear(); OriginalClusterScanSpeeds.Clear(); ChildScanners.Clear(); OriginalScanSpeed.Clear(); if (CCStateMutex != null) { CCStateMutex.Dispose(); } CCStateMutex = null; } static PlayerScannerManager() { ZERO_SCAN_SPEED = new float[4]; Current = new PlayerScannerManager(); LevelAPI.OnLevelCleanup += Current.Clear; } private PlayerScannerManager() { } } public class PuzzleReqItemManager { public static readonly PuzzleReqItemManager Current; private Dictionary BigPickupItemsInLevel = new Dictionary(); private int itemIndexCounter = 1; private List<(CP_Bioscan_Core, List)> bioscanCoresToAddReqItems = new List<(CP_Bioscan_Core, List)>(); private List<(CP_Cluster_Core, List)> clusterCoresToAddReqItems = new List<(CP_Cluster_Core, List)>(); private Dictionary movableScansWithReqItems = new Dictionary(); internal int Register(CarryItemPickup_Core item) { int num = itemIndexCounter; itemIndexCounter++; BigPickupItemsInLevel.Add(num, item); return num; } internal void QueueForAddingReqItems(CP_Bioscan_Core core, List itemsIndices) { bioscanCoresToAddReqItems.Add((core, itemsIndices)); } internal void QueueForAddingReqItems(CP_Cluster_Core core, List itemsIndices) { clusterCoresToAddReqItems.Add((core, itemsIndices)); } internal CP_Bioscan_Core GetMovableCoreWithReqItem(CP_PlayerScanner scanner) { return movableScansWithReqItems.ContainsKey(((Il2CppObjectBase)scanner).Pointer) ? movableScansWithReqItems[((Il2CppObjectBase)scanner).Pointer] : null; } public CarryItemPickup_Core GetBigPickupItem(int bigPickupInLevelIndex) { return BigPickupItemsInLevel.ContainsKey(bigPickupInLevelIndex) ? BigPickupItemsInLevel[bigPickupInLevelIndex] : null; } public bool AddReqItems(CP_Bioscan_Core puzzle, int itemIndex) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown if ((Object)(object)puzzle == (Object)null || (long)itemIndex == 0) { return false; } if (!BigPickupItemsInLevel.ContainsKey(itemIndex)) { SPOLogger.Error($"Unregistered BigPickup Item with index {itemIndex}"); return false; } CarryItemPickup_Core val = BigPickupItemsInLevel[itemIndex]; puzzle.AddRequiredItems(Il2CppReferenceArray.op_Implicit((iWardenObjectiveItem[])(object)new iWardenObjectiveItem[1] { new iWardenObjectiveItem(((Il2CppObjectBase)val).Pointer) })); return true; } public bool AddReqItems(CP_Cluster_Core puzzle, int itemIndex) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown if ((Object)(object)puzzle == (Object)null || (long)itemIndex == 0) { return false; } if (!BigPickupItemsInLevel.ContainsKey(itemIndex)) { SPOLogger.Error($"Unregistered BigPickup Item with index {itemIndex}"); return false; } CarryItemPickup_Core val = BigPickupItemsInLevel[itemIndex]; foreach (iChainedPuzzleCore item in (Il2CppArrayBase)(object)puzzle.m_childCores) { item.AddRequiredItems(Il2CppReferenceArray.op_Implicit((iWardenObjectiveItem[])(object)new iWardenObjectiveItem[1] { new iWardenObjectiveItem(((Il2CppObjectBase)val).Pointer) })); } return true; } public bool AddReqItems(CP_Bioscan_Core puzzle, List itemsIndices) { if ((Object)(object)puzzle == (Object)null || itemsIndices == null || itemsIndices.Count < 1) { return false; } bool flag = false; foreach (int item in itemsIndices.ToHashSet()) { flag |= AddReqItems(puzzle, item); } if (puzzle.IsMovable && flag) { movableScansWithReqItems.Add(((Il2CppObjectBase)puzzle.m_playerScanner).Pointer, puzzle); } return flag; } public void RemoveReqItem(CP_Bioscan_Core puzzle, int itemIndex) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown if (!((Object)(object)puzzle == (Object)null)) { if (!BigPickupItemsInLevel.ContainsKey(itemIndex) && (long)itemIndex != 0) { SPOLogger.Error($"Unregistered BigPickup Item with index {itemIndex}"); } else { CarryItemPickup_Core val = BigPickupItemsInLevel[itemIndex]; puzzle.RemoveRequiredItems((iWardenObjectiveItem[])(object)new iWardenObjectiveItem[1] { new iWardenObjectiveItem(((Il2CppObjectBase)val).Pointer) }); } } } public void RemoveReqItem(CP_Cluster_Core puzzle, int itemIndex) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown if ((Object)(object)puzzle == (Object)null) { return; } if (!BigPickupItemsInLevel.ContainsKey(itemIndex) && (long)itemIndex != 0) { SPOLogger.Error($"Unregistered BigPickup Item with index {itemIndex}"); return; } CarryItemPickup_Core val = BigPickupItemsInLevel[itemIndex]; foreach (iChainedPuzzleCore item in (Il2CppArrayBase)(object)puzzle.m_childCores) { item.RemoveRequiredItems((iWardenObjectiveItem[])(object)new iWardenObjectiveItem[1] { new iWardenObjectiveItem(((Il2CppObjectBase)val).Pointer) }); } } private void AddQueuedReqItems() { foreach (var (puzzle, itemsIndices) in bioscanCoresToAddReqItems) { AddReqItems(puzzle, itemsIndices); } foreach (var (val, itemsIndices2) in clusterCoresToAddReqItems) { foreach (iChainedPuzzleCore item in (Il2CppArrayBase)(object)val.m_childCores) { CP_Bioscan_Core val2 = ((Il2CppObjectBase)item).TryCast(); if ((Object)(object)val2 == (Object)null) { SPOLogger.Error("Failed to cast child core to CP_Bioscan_Core"); } else { AddReqItems(val2, itemsIndices2); } } } } public void OutputLevelBigPickupInfo() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0114: 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) StringBuilder val = new StringBuilder(); val.AppendLine(); List list = new List(BigPickupItemsInLevel.Values); list.Sort(delegate(CarryItemPickup_Core b1, CarryItemPickup_Core b2) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_008a: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) AIG_CourseNode spawnNode = b1.SpawnNode; AIG_CourseNode spawnNode2 = b2.SpawnNode; if (spawnNode.m_dimension.DimensionIndex != spawnNode2.m_dimension.DimensionIndex) { return (spawnNode.m_dimension.DimensionIndex > spawnNode2.m_dimension.DimensionIndex) ? 1 : (-1); } if (spawnNode.LayerType != spawnNode2.LayerType) { return (spawnNode.LayerType >= spawnNode2.LayerType) ? 1 : (-1); } return (spawnNode.m_zone.LocalIndex != spawnNode2.m_zone.LocalIndex) ? ((spawnNode.m_zone.LocalIndex >= spawnNode2.m_zone.LocalIndex) ? 1 : (-1)) : 0; }); Dictionary dictionary = new Dictionary(); foreach (int key in BigPickupItemsInLevel.Keys) { dictionary.Add(BigPickupItemsInLevel[key], key); } foreach (CarryItemPickup_Core item in list) { val.AppendLine("Item Name: " + ((Item)item).ItemDataBlock.publicName); val.AppendLine($"Zone {item.SpawnNode.m_zone.Alias}, {item.SpawnNode.LayerType}, Dim {item.SpawnNode.m_dimension.DimensionIndex}"); val.AppendLine($"Item Index: {dictionary[item]}"); val.AppendLine(); } SPOLogger.Debug(((Object)val).ToString()); } internal void OnEnterLevel() { AddQueuedReqItems(); OutputLevelBigPickupInfo(); } public void Clear() { BigPickupItemsInLevel.Clear(); itemIndexCounter = 1; bioscanCoresToAddReqItems.Clear(); clusterCoresToAddReqItems.Clear(); movableScansWithReqItems.Clear(); } static PuzzleReqItemManager() { Current = new PuzzleReqItemManager(); LevelAPI.OnLevelCleanup += Current.Clear; LevelAPI.OnEnterLevel += Current.OnEnterLevel; } private PuzzleReqItemManager() { } } public class PuzzleOverrideManager { public static readonly PuzzleOverrideManager Current; public static HashSet CompletedScans; private uint puzzleOverrideIndex = 1u; public static uint MainLevelLayout => RundownManager.ActiveExpedition.LevelLayoutData; private Dictionary bioscanIndex { get; } = new Dictionary(); private Dictionary clusterIndex { get; } = new Dictionary(); private Dictionary index2Bioscan { get; } = new Dictionary(); private Dictionary index2Cluster { get; } = new Dictionary(); public uint Register(CP_Bioscan_Core __instance) { if ((Object)(object)__instance == (Object)null) { return 0u; } uint num = puzzleOverrideIndex; puzzleOverrideIndex++; if (!bioscanIndex.ContainsKey(((Il2CppObjectBase)__instance).Pointer)) { bioscanIndex.Add(((Il2CppObjectBase)__instance).Pointer, num); index2Bioscan.Add(num, __instance); return num; } return GetBioscanCoreOverrideIndex(__instance); } public uint Register(CP_Cluster_Core __instance) { if ((Object)(object)__instance == (Object)null) { return 0u; } uint num = puzzleOverrideIndex; puzzleOverrideIndex++; if (!clusterIndex.ContainsKey(((Il2CppObjectBase)__instance).Pointer)) { clusterIndex.Add(((Il2CppObjectBase)__instance).Pointer, num); index2Cluster.Add(num, __instance); return num; } return GetClusterCoreOverrideIndex(__instance); } public void OutputLevelPuzzleInfo() { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_049c: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Enumerator enumerator = ChainedPuzzleManager.Current.m_instances.GetEnumerator(); while (enumerator.MoveNext()) { ChainedPuzzleInstance current = enumerator.Current; list.Add(current); } list.Sort(delegate(ChainedPuzzleInstance c1, ChainedPuzzleInstance c2) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0084: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) LG_Zone zone2 = c1.m_sourceArea.m_zone; LG_Zone zone3 = c2.m_sourceArea.m_zone; if (zone2.DimensionIndex != zone3.DimensionIndex) { return (zone2.DimensionIndex >= zone3.DimensionIndex) ? 1 : (-1); } return (zone2.Layer.m_type != zone3.Layer.m_type) ? ((zone2.Layer.m_type >= zone3.Layer.m_type) ? 1 : (-1)) : ((zone2.LocalIndex >= zone3.LocalIndex) ? 1 : (-1)); }); StringBuilder stringBuilder = new StringBuilder(); foreach (ChainedPuzzleInstance item in list) { LG_Zone zone = item.m_sourceArea.m_zone; StringBuilder stringBuilder2 = stringBuilder; StringBuilder stringBuilder3 = stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(15, 3, stringBuilder2); handler.AppendLiteral("\nZone "); handler.AppendFormatted(zone.Alias); handler.AppendLiteral(", "); handler.AppendFormatted(zone.m_layer.m_type); handler.AppendLiteral(", Dim "); handler.AppendFormatted(zone.DimensionIndex); handler.AppendLiteral("\n"); stringBuilder3.Append(ref handler); stringBuilder2 = stringBuilder; StringBuilder stringBuilder4 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(14, 1, stringBuilder2); handler.AppendLiteral("Alarm name: "); handler.AppendFormatted(item.Data.PublicAlarmName); handler.AppendLiteral(":\n"); stringBuilder4.Append(ref handler); for (int i = 0; i < ((Il2CppArrayBase)(object)item.m_chainedPuzzleCores).Count; i++) { iChainedPuzzleCore val = ((Il2CppArrayBase)(object)item.m_chainedPuzzleCores)[i]; if (bioscanIndex.ContainsKey(((Il2CppObjectBase)val).Pointer)) { uint value = bioscanIndex[((Il2CppObjectBase)val).Pointer]; stringBuilder2 = stringBuilder; StringBuilder stringBuilder5 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(15, 1, stringBuilder2); handler.AppendLiteral("puzzle index: "); handler.AppendFormatted(i); handler.AppendLiteral("\n"); stringBuilder5.Append(ref handler); stringBuilder.Append("type: CP_Bioscan_Core\n"); stringBuilder2 = stringBuilder; StringBuilder stringBuilder6 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(22, 1, stringBuilder2); handler.AppendLiteral("PuzzleOverrideIndex: "); handler.AppendFormatted(value); handler.AppendLiteral("\n"); stringBuilder6.Append(ref handler); CP_Bioscan_Core val2 = ((Il2CppObjectBase)val).Cast(); CP_PlayerScanner val3 = ((Il2CppObjectBase)val2.PlayerScanner).Cast(); stringBuilder2 = stringBuilder; StringBuilder stringBuilder7 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2); handler.AppendLiteral("Position: "); handler.AppendFormatted(val2.m_position); handler.AppendLiteral("\n"); stringBuilder7.Append(ref handler); stringBuilder2 = stringBuilder; StringBuilder stringBuilder8 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2); handler.AppendLiteral("Radius: "); handler.AppendFormatted(val3.Radius); handler.AppendLiteral("\n"); stringBuilder8.Append(ref handler); } else if (clusterIndex.ContainsKey(((Il2CppObjectBase)val).Pointer)) { uint value2 = clusterIndex[((Il2CppObjectBase)val).Pointer]; CP_Cluster_Core val4 = ((Il2CppObjectBase)val).Cast(); stringBuilder2 = stringBuilder; StringBuilder stringBuilder9 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(15, 1, stringBuilder2); handler.AppendLiteral("puzzle index: "); handler.AppendFormatted(i); handler.AppendLiteral("\n"); stringBuilder9.Append(ref handler); stringBuilder.Append("type: CP_Cluster_Core\n"); stringBuilder2 = stringBuilder; StringBuilder stringBuilder10 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(22, 1, stringBuilder2); handler.AppendLiteral("PuzzleOverrideIndex: "); handler.AppendFormatted(value2); handler.AppendLiteral("\n"); stringBuilder10.Append(ref handler); stringBuilder.Append("=== Clustered puzzles info: ===\n"); for (int j = 0; j < val4.m_amountOfPuzzles; j++) { iChainedPuzzleCore val5 = ((Il2CppArrayBase)(object)val4.m_childCores)[j]; if (!bioscanIndex.ContainsKey(((Il2CppObjectBase)val5).Pointer)) { SPOLogger.Error("Unregistered clustered iChainedPuzzleCore found..."); continue; } uint value3 = bioscanIndex[((Il2CppObjectBase)val5).Pointer]; stringBuilder2 = stringBuilder; StringBuilder stringBuilder11 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(15, 1, stringBuilder2); handler.AppendLiteral("puzzle index: "); handler.AppendFormatted(j); handler.AppendLiteral("\n"); stringBuilder11.Append(ref handler); stringBuilder.Append("type: CP_Bioscan_Core\n"); stringBuilder2 = stringBuilder; StringBuilder stringBuilder12 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(22, 1, stringBuilder2); handler.AppendLiteral("PuzzleOverrideIndex: "); handler.AppendFormatted(value3); handler.AppendLiteral("\n"); stringBuilder12.Append(ref handler); CP_Bioscan_Core val6 = ((Il2CppObjectBase)val5).Cast(); CP_PlayerScanner val7 = ((Il2CppObjectBase)val6.PlayerScanner).Cast(); stringBuilder2 = stringBuilder; StringBuilder stringBuilder13 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(11, 1, stringBuilder2); handler.AppendLiteral("Position: "); handler.AppendFormatted(val6.m_position); handler.AppendLiteral("\n"); stringBuilder13.Append(ref handler); stringBuilder2 = stringBuilder; StringBuilder stringBuilder14 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2); handler.AppendLiteral("Radius: "); handler.AppendFormatted(val7.Radius); handler.AppendLiteral("\n"); stringBuilder14.Append(ref handler); } stringBuilder.Append("=== Clustered puzzles END ===\n"); } else { SPOLogger.Error("Unregistered iChainedPuzzleCore found..."); } } stringBuilder.Append('\n'); } SPOLogger.Debug(stringBuilder.ToString()); } public uint GetBioscanCoreOverrideIndex(CP_Bioscan_Core core) { return bioscanIndex.ContainsKey(((Il2CppObjectBase)core).Pointer) ? bioscanIndex[((Il2CppObjectBase)core).Pointer] : 0u; } public uint GetClusterCoreOverrideIndex(CP_Cluster_Core core) { return clusterIndex.ContainsKey(((Il2CppObjectBase)core).Pointer) ? clusterIndex[((Il2CppObjectBase)core).Pointer] : 0u; } public uint GetBioscanCoreOverrideIndex(IntPtr pointer) { return bioscanIndex.ContainsKey(pointer) ? bioscanIndex[pointer] : 0u; } public uint GetClusterCoreOverrideIndex(IntPtr pointer) { return clusterIndex.ContainsKey(pointer) ? clusterIndex[pointer] : 0u; } public CP_Bioscan_Core GetBioscanCore(uint puzzleOverrideIndex) { return index2Bioscan.ContainsKey(puzzleOverrideIndex) ? index2Bioscan[puzzleOverrideIndex] : null; } public CP_Cluster_Core GetClusterCore(uint puzzleOverrideIndex) { return index2Cluster.ContainsKey(puzzleOverrideIndex) ? index2Cluster[puzzleOverrideIndex] : null; } public void Clear() { puzzleOverrideIndex = 1u; bioscanIndex.Clear(); clusterIndex.Clear(); index2Bioscan.Clear(); index2Cluster.Clear(); CompletedScans.Clear(); } private PuzzleOverrideManager() { } static PuzzleOverrideManager() { CompletedScans = new HashSet(); Current = new PuzzleOverrideManager(); LevelAPI.OnEnterLevel += Current.OutputLevelPuzzleInfo; LevelAPI.OnBuildStart += Current.Clear; LevelAPI.OnLevelCleanup += Current.Clear; } public iChainedPuzzleOwner ChainedPuzzleInstanceOwner(CP_Bioscan_Core bioscanCore) { if ((Object)(object)bioscanCore == (Object)null) { return null; } iChainedPuzzleOwner owner = bioscanCore.Owner; ChainedPuzzleInstance val = ((Il2CppObjectBase)owner).TryCast(); if ((Object)(object)val != (Object)null) { return owner; } CP_Cluster_Core val2 = ((Il2CppObjectBase)owner).TryCast(); if ((Object)(object)val2 != (Object)null) { return val2.m_owner; } SPOLogger.Error("Failed to find CP_BioScan_Core owner (instance of ChainedPuzzleInstance)."); return null; } } } namespace ScanPosOverride.JSON { public static class InjectLibUtil { public const string PLUGIN_GUID = "GTFO.InjectLib"; public static JsonConverter InjectLibConnector { get; private set; } public static bool IsLoaded { get; private set; } static InjectLibUtil() { InjectLibConnector = null; IsLoaded = false; if (!((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("GTFO.InjectLib", out var value)) { return; } try { Assembly assembly = ((value == null) ? null : value.Instance?.GetType()?.Assembly) ?? null; if ((object)assembly == null) { throw new Exception("Assembly is Missing!"); } Type[] types = assembly.GetTypes(); Type type = types.First((Type t) => t.Name == "InjectLibConnector"); if ((object)type == null) { throw new Exception("Unable to Find InjectLibConnector Class"); } InjectLibConnector = (JsonConverter)Activator.CreateInstance(type); IsLoaded = true; } catch (Exception value2) { SPOLogger.Error($"Exception thrown while reading data from GTFO.AWO: {value2}"); } } } internal class LocalizedTextConverter : JsonConverter { public override bool HandleNull => false; public override LocalizedText Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown switch (reader.TokenType) { case JsonTokenType.String: { string @string = reader.GetString(); return new LocalizedText { Id = 0u, UntranslatedText = @string }; } case JsonTokenType.Number: return new LocalizedText { Id = reader.GetUInt32(), UntranslatedText = null }; default: throw new JsonException($"LocalizedTextJson type: {reader.TokenType} is not implemented!"); } } public override void Write(Utf8JsonWriter writer, LocalizedText value, JsonSerializerOptions options) { JsonSerializer.Serialize(writer, value, options); } } public sealed class MyVector3Converter : JsonConverter { public override bool HandleNull => false; public override Vector3 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { //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_014d: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) Vector3 vector = Vector3.zero; switch (reader.TokenType) { case JsonTokenType.StartObject: { int currentDepth = reader.CurrentDepth; while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject && reader.CurrentDepth == currentDepth) { SPOLogger.Warning($"Parsed Vector3 : {vector}"); return vector; } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected PropertyName token"); } string @string = reader.GetString(); reader.Read(); switch (@string.ToLowerInvariant()) { case "x": vector.x = reader.GetSingle(); break; case "y": vector.y = reader.GetSingle(); break; case "z": vector.z = reader.GetSingle(); break; } } throw new JsonException("Expected EndObject token"); } case JsonTokenType.String: { string text = reader.GetString().Trim(); if (TryParseVector3(text, out vector)) { return vector; } throw new JsonException("Vector3 format is not right: " + text); } default: throw new JsonException($"Vector3Json type: {reader.TokenType} is not implemented!"); } } private static bool TryParseVector3(string input, out Vector3 vector) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) float[] array = default(float[]); if (!RegexUtils.TryParseVectorString(input, ref array)) { vector = Vector3.zero; return false; } if (array.Length < 3) { vector = Vector3.zero; return false; } vector = new Vector3(array[0], array[1], array[2]); return true; } public override void Write(Utf8JsonWriter writer, Vector3 value, JsonSerializerOptions options) { //IL_001a: 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_0050: Unknown result type (might be due to invalid IL or missing references) writer.WriteStringValue($"({value.x} {value.y} {value.z})"); } } public sealed class WritableLocalizedTextConverter : JsonConverter { public static WritableLocalizedTextConverter Converter { get; } = new WritableLocalizedTextConverter(); public override bool HandleNull => false; public override LocalizedText Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (MTFOPartialDataUtil.LocalizedTextConverter != null) { return ((JsonConverter)MTFOPartialDataUtil.LocalizedTextConverter).Read(ref reader, typeToConvert, options); } throw new NotImplementedException(); } public override void Write(Utf8JsonWriter writer, LocalizedText value, JsonSerializerOptions options) { if (value.Id != 0) { JsonSerializer.Serialize(writer, value.Id, options); } else { JsonSerializer.Serialize(writer, value.UntranslatedText, options); } } } internal static class Json { private static readonly JsonSerializerOptions _setting; static Json() { _setting = new JsonSerializerOptions { ReadCommentHandling = JsonCommentHandling.Skip, IncludeFields = false, PropertyNameCaseInsensitive = true, WriteIndented = true, IgnoreReadOnlyProperties = true }; _setting.Converters.Add(new JsonStringEnumConverter()); _setting.Converters.Add(new MyVector3Converter()); if (MTFOPartialDataUtil.IsLoaded && InjectLibUtil.IsLoaded) { _setting.Converters.Add(InjectLibUtil.InjectLibConnector); _setting.Converters.Add(new LocalizedTextConverter()); SPOLogger.Log("InjectLib (AWO) && PartialData support found!"); return; } if (MTFOPartialDataUtil.IsLoaded) { _setting.Converters.Add(MTFOPartialDataUtil.PersistentIDConverter); _setting.Converters.Add(WritableLocalizedTextConverter.Converter); SPOLogger.Log("PartialData support found!"); return; } if (InjectLibUtil.IsLoaded) { _setting.Converters.Add(InjectLibUtil.InjectLibConnector); SPOLogger.Log("InjectLib (AWO) support found!"); } _setting.Converters.Add(new LocalizedTextConverter()); } public static T Deserialize(string json) { return JsonSerializer.Deserialize(json, _setting); } public static object Deserialize(Type type, string json) { return JsonSerializer.Deserialize(json, type, _setting); } public static string Serialize(T value) { return JsonSerializer.Serialize(value, _setting); } public static void Load(string file, out T config) where T : new() { if (file.Length < ".json".Length) { config = default(T); return; } if (file.Substring(file.Length - ".json".Length) != ".json") { file += ".json"; } string path = Path.Combine(Plugin.OVERRIDE_SCAN_POS_PATH, file); file = File.ReadAllText(path); config = Deserialize(file); } } public static class MTFOUtil { public const string PLUGIN_GUID = "com.dak.MTFO"; public const BindingFlags PUBLIC_STATIC = BindingFlags.Static | BindingFlags.Public; public static string GameDataPath { get; private set; } public static string CustomPath { get; private set; } public static bool HasCustomContent { get; private set; } public static bool IsLoaded { get; private set; } static MTFOUtil() { GameDataPath = string.Empty; CustomPath = string.Empty; HasCustomContent = false; IsLoaded = false; if (!((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("com.dak.MTFO", out var value)) { return; } try { Assembly assembly = ((value == null) ? null : value.Instance?.GetType()?.Assembly) ?? null; if ((object)assembly == null) { throw new Exception("Assembly is Missing!"); } Type[] types = assembly.GetTypes(); Type type = types.First((Type t) => t.Name == "ConfigManager"); if ((object)type == null) { throw new Exception("Unable to Find ConfigManager Class"); } FieldInfo field = type.GetField("GameDataPath", BindingFlags.Static | BindingFlags.Public); FieldInfo field2 = type.GetField("CustomPath", BindingFlags.Static | BindingFlags.Public); FieldInfo field3 = type.GetField("HasCustomContent", BindingFlags.Static | BindingFlags.Public); if ((object)field == null) { throw new Exception("Unable to Find Field: GameDataPath"); } if ((object)field2 == null) { throw new Exception("Unable to Find Field: CustomPath"); } if ((object)field3 == null) { throw new Exception("Unable to Find Field: HasCustomContent"); } GameDataPath = (string)field.GetValue(null); CustomPath = (string)field2.GetValue(null); HasCustomContent = (bool)field3.GetValue(null); IsLoaded = true; } catch (Exception value2) { SPOLogger.Error($"Exception thrown while reading path from DataDumper (MTFO): \n{value2}"); } } } } namespace ScanPosOverride.JSON.PData { public class PDataGUID { public string GUID { get; set; } public uint ID { get; set; } } public static class MTFOPartialDataUtil { public const string PLUGIN_GUID = "MTFO.Extension.PartialBlocks"; public const string ID_FILE_NAME = "_persistentID.json"; private static Dictionary pdataGUID; public static JsonConverter PersistentIDConverter { get; private set; } public static JsonConverter LocalizedTextConverter { get; private set; } public static bool IsLoaded { get; private set; } public static bool Initialized { get; private set; } public static string PartialDataPath { get; private set; } public static string ConfigPath { get; private set; } static MTFOPartialDataUtil() { PersistentIDConverter = null; LocalizedTextConverter = null; IsLoaded = false; Initialized = false; PartialDataPath = string.Empty; ConfigPath = string.Empty; pdataGUID = null; if (!((BaseChainloader)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("MTFO.Extension.PartialBlocks", out var value)) { return; } try { Assembly assembly = ((value == null) ? null : value.Instance?.GetType()?.Assembly) ?? null; if ((object)assembly == null) { throw new Exception("Assembly is Missing!"); } Type[] types = assembly.GetTypes(); Type type = types.First((Type t) => t.Name == "PersistentIDConverter"); if ((object)type == null) { throw new Exception("Unable to Find PersistentIDConverter Class"); } Type type2 = types.First((Type t) => t.Name == "PartialDataManager"); if ((object)type2 == null) { throw new Exception("Unable to Find PartialDataManager Class"); } Type type3 = types.First((Type t) => t.Name == "LocalizedTextConverter"); if ((object)type3 == null) { throw new Exception("Unable to Find LocalizedTextConverter Class"); } PropertyInfo property = type2.GetProperty("Initialized", BindingFlags.Static | BindingFlags.Public); PropertyInfo property2 = type2.GetProperty("PartialDataPath", BindingFlags.Static | BindingFlags.Public); PropertyInfo property3 = type2.GetProperty("ConfigPath", BindingFlags.Static | BindingFlags.Public); if ((object)property == null) { throw new Exception("Unable to Find Property: Initialized"); } if ((object)property2 == null) { throw new Exception("Unable to Find Property: PartialDataPath"); } if ((object)property3 == null) { throw new Exception("Unable to Find Field: ConfigPath"); } Initialized = (bool)property.GetValue(null); PartialDataPath = (string)property2.GetValue(null); ConfigPath = (string)property3.GetValue(null); PersistentIDConverter = (JsonConverter)Activator.CreateInstance(type); LocalizedTextConverter = (JsonConverter)Activator.CreateInstance(type3); IsLoaded = true; } catch (Exception value2) { SPOLogger.Error($"Exception thrown while reading data from MTFO_Extension_PartialData:\n{value2}"); } } internal static void ReadPDataGUID() { //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown if (pdataGUID != null) { return; } if (!IsLoaded) { SPOLogger.Error("ReadPDataGUID: invoked when not loaded, which is a broken operation"); return; } string path = Path.Combine(PartialDataPath, "_persistentID.json"); if (!File.Exists(path)) { SPOLogger.Error("ReadPDataGUID: PartialData GUID file not found"); return; } string json = File.ReadAllText(path); List list = Json.Deserialize>(json); pdataGUID = new Dictionary(); foreach (PDataGUID item in list) { if (!pdataGUID.TryAdd(item.GUID, item.ID)) { SPOLogger.Error("ReadPDataGUID: cannot add '" + item.GUID + "', probably there's a duplicate"); } } bool flag = default(bool); BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(33, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ReadPDataGUID: Loaded "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(pdataGUID.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" PData GUID"); } SPOLogger.Log(val); } public static bool TryGetID(string guid, out uint id) { id = 0u; return pdataGUID?.TryGetValue(guid, out id) ?? false; } public static string ConvertAllGUID(string json) { if (!IsLoaded) { SPOLogger.Error("MTFOPartialDataUtil.ConvertAllGUID: partial data is not loaded"); return json; } JsonNode jsonNode = JsonNode.Parse(json, default(JsonNodeOptions), new JsonDocumentOptions { CommentHandling = JsonCommentHandling.Skip }); foreach (var item in (from i in jsonNode.DescendantItemsAndSelf() where i.name != null && i.node is JsonValue select i).ToList()) { if (item.Item1.GetValue().ValueKind == JsonValueKind.String && item.Item3 != null && TryGetID(item.Item1.ToString(), out var id) && id != 0) { JsonObject jsonObject = (JsonObject)item.Item4; jsonObject.Remove(item.Item3); jsonObject.Add(item.Item3, (JsonNode)id); } } return jsonNode.ToString(); } } } namespace ScanPosOverride.JSON.Extensions { public static class JsonExtensions { public static IEnumerable Descendants(this JsonNode? root) { return root.DescendantsAndSelf(includeSelf: false); } public static IEnumerable DescendantsAndSelf(this JsonNode? root, bool includeSelf = true) { return from i in root.DescendantItemsAndSelf(includeSelf) select i.node; } public static IEnumerable<(JsonNode? node, int? index, string? name, JsonNode? parent)> DescendantItemsAndSelf(this JsonNode? root, bool includeSelf = true) { return RecursiveEnumerableExtensions.Traverse<(JsonNode, int?, string, JsonNode)>((root, null, null, null), delegate((JsonNode node, int? index, string name, JsonNode parent) i) { JsonNode item2 = i.node; if (1 == 0) { } IEnumerable<(JsonNode, int?, string, JsonNode)> result = (IEnumerable<(JsonNode, int?, string, JsonNode)>)((item2 is JsonObject o) ? (from p in o.AsDictionary() select (p.Value, null, p.Key.AsNullableReference(), i.node.AsNullableReference())) : ((!(item2 is JsonArray source)) ? ((IEnumerable)i.ToEmptyEnumerable()) : ((IEnumerable)((IEnumerable)source).Select((Func)((JsonNode item, int index) => (item, index.AsNullableValue(), null, i.node.AsNullableReference())))))); if (1 == 0) { } return result; }, includeSelf); } private static IEnumerable ToEmptyEnumerable(this T item) { return Enumerable.Empty(); } private static T? AsNullableReference(this T item) where T : class { return item; } private static T? AsNullableValue(this T item) where T : struct { return item; } private static IDictionary AsDictionary(this JsonObject o) { return o; } } public static class RecursiveEnumerableExtensions { [CompilerGenerated] private sealed class d__0 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private T <>2__current; private int <>l__initialThreadId; private T root; public T <>3__root; private Func> children; public Func> <>3__children; private bool includeSelf; public bool <>3__includeSelf; private Stack> 5__1; private IEnumerator 5__2; private Stack>.Enumerator <>s__3; private IEnumerator 5__4; T IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 2) { try { } finally { <>m__Finally1(); } } 5__1 = null; 5__2 = null; <>s__3 = default(Stack>.Enumerator); 5__4 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (includeSelf) { <>2__current = root; <>1__state = 1; return true; } goto IL_005e; case 1: <>1__state = -1; goto IL_005e; case 2: { <>1__state = -3; 5__1.Push(children(5__2.Current).GetEnumerator()); goto IL_0126; } IL_0126: 5__2 = null; goto IL_012e; IL_005e: 5__1 = new Stack>(); <>1__state = -3; 5__1.Push(children(root).GetEnumerator()); goto IL_012e; IL_012e: if (5__1.Count != 0) { 5__2 = 5__1.Peek(); if (!5__2.MoveNext()) { 5__1.Pop(); 5__2.Dispose(); goto IL_0126; } <>2__current = 5__2.Current; <>1__state = 2; return true; } <>m__Finally1(); return false; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; <>s__3 = 5__1.GetEnumerator(); try { while (<>s__3.MoveNext()) { 5__4 = <>s__3.Current; 5__4.Dispose(); 5__4 = null; } } finally { ((IDisposable)<>s__3).Dispose(); } <>s__3 = default(Stack>.Enumerator); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__0 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__0(0); } d__.root = <>3__root; d__.children = <>3__children; d__.includeSelf = <>3__includeSelf; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [IteratorStateMachine(typeof(d__0<>))] public static IEnumerable Traverse(T root, Func> children, bool includeSelf = true) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__0(-2) { <>3__root = root, <>3__children = children, <>3__includeSelf = includeSelf }; } } } namespace ScanPosOverride.Component { internal class ConcurrentClusterHud : MonoBehaviour { public enum PlayerCountRequirement { INVALID, ANY, SOLO, DUO } private StringBuilder displayText = new StringBuilder(); private bool m_isValid = false; private List children; private float childRadius = -1f; private int[] playerInScanCount; private readonly string[] ROMAN = new string[4] { "I", "II", "III", "IV" }; internal CP_Cluster_Core parent { get; set; } internal CP_Bioscan_Hud parentHud { get; set; } internal PuzzleOverride def { get; set; } public PlayerCountRequirement playerCountReq { get; private set; } = PlayerCountRequirement.INVALID; private PlayerCountRequirement ReqPlayerCount(iChainedPuzzleCore child) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_003c: Expected I4, but got Unknown CP_Bioscan_Core val = ((Il2CppObjectBase)child).Cast(); CP_PlayerScanner val2 = ((Il2CppObjectBase)val.m_playerScanner).Cast(); PlayerRequirement playerRequirement = val2.m_playerRequirement; Il2CppStructArray scanSpeeds = val2.m_scanSpeeds; PlayerRequirement val3 = playerRequirement; PlayerRequirement val4 = val3; switch ((int)val4) { case 2: return (((Il2CppArrayBase)(object)scanSpeeds)[0] > 0f) ? PlayerCountRequirement.SOLO : PlayerCountRequirement.INVALID; case 0: { int i; for (i = 0; i < ((Il2CppArrayBase)(object)scanSpeeds).Count && ((Il2CppArrayBase)(object)scanSpeeds)[i] == 0f; i++) { } if (i >= 2) { return PlayerCountRequirement.INVALID; } if (i == 1) { return PlayerCountRequirement.DUO; } return (((Il2CppArrayBase)(object)scanSpeeds)[i + 1] > 0f) ? PlayerCountRequirement.ANY : PlayerCountRequirement.SOLO; } default: return PlayerCountRequirement.INVALID; } } internal bool Setup() { if (((Il2CppArrayBase)(object)parent.m_childCores).Count < 2 || ((Il2CppArrayBase)(object)parent.m_childCores).Count > 4) { SPOLogger.Error($"ConcurrentClusterHud: got cluster scan with {((Il2CppArrayBase)(object)parent.m_childCores).Count} children, which is invalid for concurrent cluster"); return false; } playerCountReq = ReqPlayerCount(((Il2CppArrayBase)(object)parent.m_childCores)[0]); if (playerCountReq == PlayerCountRequirement.INVALID) { SPOLogger.Error($"ConcurrentCluster setup: playerRequirement is {1}, which is invalid for concurrent cluster"); return false; } switch (((Il2CppArrayBase)(object)parent.m_childCores).Count) { case 2: switch (playerCountReq) { case PlayerCountRequirement.ANY: case PlayerCountRequirement.SOLO: m_isValid = true; break; case PlayerCountRequirement.DUO: m_isValid = true; break; } break; case 4: { PlayerCountRequirement playerCountRequirement3 = playerCountReq; PlayerCountRequirement playerCountRequirement4 = playerCountRequirement3; if ((uint)(playerCountRequirement4 - 1) <= 1u) { m_isValid = true; } break; } case 3: { PlayerCountRequirement playerCountRequirement = playerCountReq; PlayerCountRequirement playerCountRequirement2 = playerCountRequirement; if ((uint)(playerCountRequirement2 - 1) <= 1u) { m_isValid = true; } break; } } if (!m_isValid) { SPOLogger.Error($"ConcurrentCluster setup: Something went wrong! PlayerCountRequirement: {playerCountReq}, children num: {((Il2CppArrayBase)(object)parent.m_childCores).Count}"); return false; } playerInScanCount = new int[((Il2CppArrayBase)(object)parent.m_childCores).Count]; Array.Fill(playerInScanCount, 0); children = ((IEnumerable)parent.m_childCores).ToList().ConvertAll((iChainedPuzzleCore c) => ((Il2CppObjectBase)c).Cast()); childRadius = ((Il2CppObjectBase)((Il2CppObjectBase)((Il2CppArrayBase)(object)parent.m_childCores)[0]).Cast().m_playerScanner).Cast().Radius; return true; } private void LateUpdate() { //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) if (!m_isValid || !parentHud.m_visible || !parentHud.m_isClosestToPlayer) { return; } displayText.Clear(); displayText.AppendLine().Append(""); for (int i = 0; i < children.Count; i++) { int num = 0; CP_Bioscan_Core val = children[i]; Enumerator enumerator = PlayerManager.PlayerAgentsInLevel.GetEnumerator(); while (enumerator.MoveNext()) { PlayerAgent current = enumerator.Current; Vector3 val2 = ((Agent)current).Position - ((Component)val).transform.position; if (((Vector3)(ref val2)).magnitude < childRadius) { num++; } } playerInScanCount[i] = num; string value = string.Empty; string value2 = string.Empty; switch (playerCountReq) { case PlayerCountRequirement.ANY: switch (num) { case 0: value = " "; break; case 1: value = "A"; break; case 2: value = "A,B"; break; case 3: value = "A,B,C"; break; case 4: value = "A,B,C,D"; break; } value2 = ((num > 0) ? "white" : "orange"); break; case PlayerCountRequirement.SOLO: switch (num) { case 0: value = " "; value2 = "orange"; break; case 1: value = "A"; value2 = "white"; break; case 2: value = "A,B"; value2 = "orange"; break; case 3: value = "A,B,C"; value2 = "orange"; break; case 4: value = "A,B,C,D"; value2 = "orange"; break; } break; case PlayerCountRequirement.DUO: switch (num) { case 0: value = " , "; value2 = "orange"; break; case 1: value = "A, "; value2 = "orange"; break; case 2: value = "A,B"; value2 = "white"; break; case 3: value = "A,B,C"; value2 = "orange"; break; case 4: value = "A,B,C,D"; value2 = "orange"; break; } break; } StringBuilder stringBuilder = displayText; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder); handler.AppendLiteral(""); StringBuilder stringBuilder2 = stringBuilder.Append(ref handler).Append(ROMAN[i]).Append(": ") .Append("[") .Append(value) .Append("]"); StringBuilder.AppendInterpolatedStringHandler handler2 = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2); handler2.AppendLiteral(""); stringBuilder2.Append(ref handler2); if (i != children.Count - 1) { displayText.Append(" | "); } } displayText.Append(""); parentHud.m_msgCharBuffer.Add(displayText.ToString()); GuiManager.InteractionLayer.SetMessage(parentHud.m_msgCharBuffer, parentHud.m_msgStyle, 0); } private void OnDestroy() { parent = null; parentHud = null; def = null; children.Clear(); children = null; m_isValid = false; playerInScanCount = null; displayText = null; } static ConcurrentClusterHud() { ClassInjector.RegisterTypeInIl2Cpp(); } } }