Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MoonsHaunted v1.0.6
BepInEx/plugins/MoonsHaunted/MoonsHaunted.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Mono.Cecil; using Mono.Cecil.Cil; using MonoMod.Cil; using MonoMod.RuntimeDetour; using RoR2; using RoR2.Items; using RoR2.Projectile; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace MoonsHaunted; [BepInPlugin("com.moonishaunted", "Moon's Haunted", "1.0.5")] public sealed class Plugin : BaseUnityPlugin { private delegate void OrigSetStack(CharacterBody body, ref BaseItemBodyBehavior behavior, Type behaviorType, int count); private delegate void SetStackHook(OrigSetStack original, CharacterBody body, ref BaseItemBodyBehavior behavior, Type behaviorType, int count); private Hook stackHook; private Hook hauntHook; private Hook sceneHook; private Hook targetHook; private Hook limitHook; private Hook attributesEnableHook; private Hook purchaseEnableHook; private ILHook triggerHook; private ILHook scheduleHook; private ILHook memoryHook; private ILHook expiryHook; private static readonly MethodInfo RefreshStacks = typeof(BaseItemBodyBehavior).GetMethod("UpdateBodyItemBehaviorStacks", BindingFlags.Static | BindingFlags.NonPublic); private static ManualLogSource log; private static readonly HashSet<int> activated = new HashSet<int>(); private static readonly HashSet<int> succeeded = new HashSet<int>(); private static readonly Dictionary<int, float> nextReport = new Dictionary<int, float>(); [ThreadStatic] private static bool moonPlayerHaunting; private float nextCheck; private string lastScene; private bool lastServer; private ConfigEntry<bool> startOnMoon; private static ConfigEntry<float> hauntFrequency; private float nextSync; private bool hauntingReady; private Run observedRun; private bool startOnMoonThisRun; private bool testWarpSent; private float firstStageReadyAt; private static bool OnMoon() { SceneDef sceneDefForCurrentScene = SceneCatalog.GetSceneDefForCurrentScene(); if (Object.op_Implicit((Object)(object)Run.instance) && Object.op_Implicit((Object)(object)sceneDefForCurrentScene)) { if (!(sceneDefForCurrentScene.baseSceneName == "moon2")) { return sceneDefForCurrentScene.baseSceneName == "moon"; } return true; } return false; } private static bool IsPlayer(CharacterBody body) { if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.master)) { return Object.op_Implicit((Object)(object)((Component)body.master).GetComponent<PlayerCharacterMasterController>()); } return false; } private void Awake() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Expected O, but got Unknown //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Expected O, but got Unknown //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Expected O, but got Unknown //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Expected O, but got Unknown //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Expected O, but got Unknown //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Expected O, but got Unknown //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Expected O, but got Unknown //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Expected O, but got Unknown log = ((BaseUnityPlugin)this).Logger; startOnMoon = ((BaseUnityPlugin)this).Config.Bind<bool>("Testing", "StartOnMoon", false, "Host lobby toggle: skip the first stage and travel immediately to Commencement for testing."); hauntFrequency = ((BaseUnityPlugin)this).Config.Bind<float>("Haunting", "FrequencyMultiplier", 10f, new ConfigDescription("Divide the moon haunting cooldown by this number. 10 means ten times as many opportunities to haunt. Keeps native animation and simultaneous-haunt cap.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), new object[0])); MoonTargets.Initialize(); try { stackHook = new Hook((MethodBase)typeof(BaseItemBodyBehavior).GetMethod("SetItemStack", BindingFlags.Static | BindingFlags.NonPublic), (Delegate)new SetStackHook(SetStack)); hauntHook = new Hook((MethodBase)typeof(HexHauntingBehaviour).GetMethod("TryHauntNearbyInteractable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Func<Func<HexHauntingBehaviour, bool>, HexHauntingBehaviour, bool>(Haunt)); sceneHook = new Hook((MethodBase)typeof(DLC4ProgressionController).GetMethod("SceneAllowsSpawningForPoltergeistOrMimics"), (Delegate)new Func<Func<DLC4ProgressionController, bool>, DLC4ProgressionController, bool>(AllowScene)); targetHook = new Hook((MethodBase)typeof(SpecialObjectAttributes).GetProperty("isTargetable").GetGetMethod(), (Delegate)new Func<Func<SpecialObjectAttributes, bool>, SpecialObjectAttributes, bool>(Targetable)); limitHook = new Hook((MethodBase)typeof(CharacterMaster).GetMethod("GetDeployableSameSlotLimit"), (Delegate)new Func<Func<CharacterMaster, DeployableSlot, int>, CharacterMaster, DeployableSlot, int>(DeployableLimit)); triggerHook = new ILHook((MethodBase)typeof(HauntedInteractable).GetMethod("OnTriggerStay", BindingFlags.Instance | BindingFlags.NonPublic), new Manipulator(PatchTrigger)); scheduleHook = new ILHook((MethodBase)typeof(HexHauntingBehaviour).GetMethod("StepHauntNextInteractable", BindingFlags.Instance | BindingFlags.NonPublic), new Manipulator(PatchCooldownCalls)); expiryHook = new ILHook((MethodBase)typeof(HexHauntingBehaviour).GetMethod("TryHauntNearbyInteractable", BindingFlags.Instance | BindingFlags.NonPublic), new Manipulator(PatchCooldownCalls)); memoryHook = new ILHook((MethodBase)typeof(HexHauntingBehaviour).GetMethod("ScheduleNextClearHauntMemory", BindingFlags.Instance | BindingFlags.NonPublic), new Manipulator(PatchCooldownCalls)); attributesEnableHook = new Hook((MethodBase)typeof(SpecialObjectAttributes).GetMethod("OnEnable", BindingFlags.Instance | BindingFlags.NonPublic), (Delegate)new Action<Action<SpecialObjectAttributes>, SpecialObjectAttributes>(AttributesEnabled)); purchaseEnableHook = new Hook((MethodBase)typeof(PurchaseInteraction).GetMethod("OnEnable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Action<Action<PurchaseInteraction>, PurchaseInteraction>(PurchaseEnabled)); Stage.onServerStageBegin += StageBegin; hauntingReady = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Moon's Haunted 1.0.5 loaded. Server activates five hidden haunting stacks per moon player."); } catch (Exception ex) { DisposeHooks(); ((BaseUnityPlugin)this).Logger.LogError((object)ex); MoonTargets.Shutdown(); hauntingReady = false; } } private static void SetStack(OrigSetStack original, CharacterBody body, ref BaseItemBodyBehavior behavior, Type behaviorType, int count) { bool flag = behaviorType == typeof(HexHauntingBehaviour) && NetworkServer.active && OnMoon() && IsPlayer(body); original(body, ref behavior, behaviorType, flag ? (count + 5) : count); if (flag && Object.op_Implicit((Object)(object)behavior) && activated.Add(((Object)body).GetInstanceID())) { log.LogInfo((object)("Activated hidden haunting for " + ((Object)body).name + ": native stacks=" + count + ", bonus=5, behavior stacks=" + behavior.stack)); } } private static bool Haunt(Func<HexHauntingBehaviour, bool> original, HexHauntingBehaviour behavior) { bool flag = moonPlayerHaunting; moonPlayerHaunting = NetworkServer.active && OnMoon() && IsPlayer(((BaseItemBodyBehavior)behavior).body); try { bool flag2 = original(behavior); if (moonPlayerHaunting) { int instanceID = ((Object)((BaseItemBodyBehavior)behavior).body).GetInstanceID(); if (flag2 && succeeded.Add(instanceID)) { log.LogInfo((object)("Haunting succeeded for " + ((Object)((BaseItemBodyBehavior)behavior).body).name + "; an interactable is now haunted.")); } if (!flag2 && (!nextReport.TryGetValue(instanceID, out var value) || Time.unscaledTime >= value)) { nextReport[instanceID] = Time.unscaledTime + 30f; log.LogInfo((object)("Haunting attempt unsuccessful for " + ((Object)((BaseItemBodyBehavior)behavior).body).name + "; stacks=" + ((BaseItemBodyBehavior)behavior).stack + ", DLC controller=" + Object.op_Implicit((Object)(object)DLC4ProgressionController.instance) + ", trigger prefab=" + ReadHauntPrefab("hauntInteractableTriggerPrefab") + ", ghost prefab=" + ReadHauntPrefab("poltergeistMasterPrefab") + ". Native haunting needs an eligible interactable within 120m; this message repeats at most every 30s per body.")); } } return flag2; } finally { moonPlayerHaunting = flag; } } private static void AttributesEnabled(Action<SpecialObjectAttributes> original, SpecialObjectAttributes attributes) { original(attributes); if (OnMoon()) { MoonTargets.QueueTarget(((Component)attributes).gameObject); } } private static void PurchaseEnabled(Action<PurchaseInteraction> original, PurchaseInteraction purchase) { original(purchase); if (OnMoon()) { MoonTargets.QueueTarget(((Component)purchase).gameObject); } } private static void PatchCooldownCalls(ILContext context) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(context); int num = 0; while (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { HauntTiming.IsCooldownRead })) { val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Func<float, HexHauntingBehaviour, float>>((Func<float, HexHauntingBehaviour, float>)ScaleCooldown); num++; } if (num == 0) { throw new InvalidOperationException("Native haunt scheduling changed; no cooldown call was found in " + ((MemberReference)context.Method).Name); } } private static float ScaleCooldown(float seconds, HexHauntingBehaviour behavior) { if (!NetworkServer.active || !OnMoon() || !IsPlayer(((BaseItemBodyBehavior)behavior).body)) { return seconds; } return seconds / hauntFrequency.Value; } private static bool ReadHauntPrefab(string name) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown PropertyInfo property = typeof(HexHauntingBehaviour).GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return Object.op_Implicit((Object)property.GetValue(null, null)); } return false; } private static void PatchTrigger(ILContext context) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(context); if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { delegate(Instruction instruction) { object operand = instruction.Operand; MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null); return val2 != null && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == "RoR2.Inventory" && ((MemberReference)val2).Name == "GetItemCountEffective"; } })) { throw new InvalidOperationException("HauntedInteractable inventory check changed; refusing to silently skip the trigger patch."); } val.Emit(OpCodes.Ldarg_1); val.EmitDelegate<Func<int, Collider, int>>((Func<int, Collider, int>)delegate(int count, Collider collider) { CharacterBody body = (Object.op_Implicit((Object)(object)collider) ? ((Component)collider).GetComponent<CharacterBody>() : null); return (!NetworkServer.active || !OnMoon() || !IsPlayer(body)) ? count : (count + 5); }); } private static bool Targetable(Func<SpecialObjectAttributes, bool> original, SpecialObjectAttributes attributes) { if (!moonPlayerHaunting || !Object.op_Implicit((Object)(object)((Component)attributes).GetComponent<MoonHauntTarget>())) { return original(attributes); } return true; } private static int DeployableLimit(Func<CharacterMaster, DeployableSlot, int> original, CharacterMaster master, DeployableSlot slot) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 int num = original(master, slot); if ((int)slot != 38 || !NetworkServer.active || !OnMoon() || !Object.op_Implicit((Object)(object)master) || !Object.op_Implicit((Object)(object)((Component)master).GetComponent<PlayerCharacterMasterController>())) { return num; } return num + 5; } private static bool AllowScene(Func<DLC4ProgressionController, bool> original, DLC4ProgressionController controller) { if (!moonPlayerHaunting) { return original(controller); } return true; } private void OnGUI() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) if (((Behaviour)this).enabled && NetworkServer.active && Object.op_Implicit((Object)(object)PreGameController.instance) && !Object.op_Implicit((Object)(object)Run.instance)) { float num = Mathf.Min(360f, (float)Screen.width - 24f); GUI.Box(new Rect(12f, 12f, num, 108f), "Moon's Haunted - Test Settings"); bool flag = GUI.Toggle(new Rect(24f, 42f, num - 24f, 26f), startOnMoon.Value, " Start on Moon (testing)"); if (flag != startOnMoon.Value) { startOnMoon.Value = flag; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Host lobby Start on Moon changed to " + flag)); } GUI.Label(new Rect(24f, 72f, num - 24f, 38f), "Next run skips directly to Commencement.\nNormal difficulty selection still applies."); } } private void CheckTestTravel() { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Invalid comparison between Unknown and I4 Run instance = Run.instance; if ((Object)(object)instance != (Object)(object)observedRun) { observedRun = instance; startOnMoonThisRun = startOnMoon.Value; testWarpSent = false; firstStageReadyAt = 0f; } if (!Object.op_Implicit((Object)(object)instance) || !NetworkServer.active || !startOnMoonThisRun || testWarpSent || OnMoon() || instance.stageClearCount != 0 || !Object.op_Implicit((Object)(object)Stage.instance)) { return; } SceneDef sceneDefForCurrentScene = SceneCatalog.GetSceneDefForCurrentScene(); if (!Object.op_Implicit((Object)(object)sceneDefForCurrentScene) || (int)sceneDefForCurrentScene.sceneType != 1) { return; } bool flag = false; foreach (PlayerCharacterMasterController instance2 in PlayerCharacterMasterController.instances) { if (Object.op_Implicit((Object)(object)instance2) && Object.op_Implicit((Object)(object)instance2.master) && Object.op_Implicit((Object)(object)instance2.master.GetBody())) { flag = true; break; } } if (!flag) { return; } if (firstStageReadyAt == 0f) { firstStageReadyAt = Time.unscaledTime + 3f; } else if (!(Time.unscaledTime < firstStageReadyAt)) { SceneDef val = SceneCatalog.FindSceneDef("moon2"); testWarpSent = true; if (!Object.op_Implicit((Object)(object)val)) { ((BaseUnityPlugin)this).Logger.LogError((object)"Testing travel failed: moon2 scene is unavailable."); return; } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Start on Moon testing enabled: host is advancing all players to moon2."); instance.AdvanceStage(val); } } private void Update() { CheckTestTravel(); if (hauntingReady && OnMoon()) { int num = MoonTargets.Prepare(); if (num > 0) { ((BaseUnityPlugin)this).Logger.LogDebug((object)("Prepared " + num + " more moon targets.")); } if (Time.unscaledTime >= nextSync) { nextSync = Time.unscaledTime + 0.2f; MoonTargets.Synchronize(); } } else { MoonTargets.Clear(); } if (Time.unscaledTime < nextCheck) { return; } nextCheck = Time.unscaledTime + 1f; SceneDef sceneDefForCurrentScene = SceneCatalog.GetSceneDefForCurrentScene(); string text = (Object.op_Implicit((Object)(object)sceneDefForCurrentScene) ? sceneDefForCurrentScene.baseSceneName : "<none>"); if (text != lastScene || NetworkServer.active != lastServer) { lastScene = text; lastServer = NetworkServer.active; activated.Clear(); succeeded.Clear(); nextReport.Clear(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Scene=" + text + "; role=" + (lastServer ? "server/host" : "client") + "; moon bonus=" + (OnMoon() && lastServer))); } if (!hauntingReady || !OnMoon() || !NetworkServer.active) { return; } foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) { if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance.master)) { continue; } CharacterBody body = instance.master.GetBody(); if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.inventory) || !Object.op_Implicit((Object)(object)Items.HexHaunting)) { continue; } HexHauntingBehaviour component = ((Component)body).GetComponent<HexHauntingBehaviour>(); int num2 = body.inventory.GetItemCountEffective(Items.HexHaunting) + 5; if (!Object.op_Implicit((Object)(object)component) || ((BaseItemBodyBehavior)component).stack != num2) { try { RefreshStacks.Invoke(null, new object[1] { body }); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); hauntingReady = false; DisposeHooks(); MoonTargets.Shutdown(); break; } } } } private static void StageBegin(Stage stage) { foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) { if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.master)) { CharacterBody body = instance.master.GetBody(); if (Object.op_Implicit((Object)(object)body)) { RefreshStacks.Invoke(null, new object[1] { body }); } } } } private void DisposeHooks() { if (expiryHook != null) { expiryHook.Dispose(); } if (scheduleHook != null) { scheduleHook.Dispose(); } if (memoryHook != null) { memoryHook.Dispose(); } if (attributesEnableHook != null) { attributesEnableHook.Dispose(); } if (purchaseEnableHook != null) { purchaseEnableHook.Dispose(); } if (triggerHook != null) { triggerHook.Dispose(); } if (targetHook != null) { targetHook.Dispose(); } if (limitHook != null) { limitHook.Dispose(); } if (sceneHook != null) { sceneHook.Dispose(); } if (hauntHook != null) { hauntHook.Dispose(); } if (stackHook != null) { stackHook.Dispose(); } } private void OnDestroy() { Stage.onServerStageBegin -= StageBegin; MoonTargets.Shutdown(); DisposeHooks(); activated.Clear(); succeeded.Clear(); nextReport.Clear(); } } public sealed class MoonHauntTarget : MonoBehaviour, IInteractable { public string key; public string GetContextString(Interactor interactor) { return "Haunted moon object"; } public Interactability GetInteractability(Interactor interactor) { return (Interactability)0; } public void OnInteractionBegin(Interactor interactor) { } public bool ShouldIgnoreSpherecastForInteractibility(Interactor interactor) { return true; } public bool ShouldShowOnScanner() { return false; } public bool ShouldProximityHighlight() { return false; } public int GetInteractablePriority(Interactor interactor) { return 0; } public bool ShouldSpawnLesserInteractionRewards(Interactor interactor) { return false; } } internal static class MoonTargets { internal sealed class Snapshot : MessageBase { internal string scene; internal readonly List<NetworkInstanceId> seats = new List<NetworkInstanceId>(); internal readonly List<string> keys = new List<string>(); public override void Serialize(NetworkWriter writer) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) writer.Write(scene); writer.Write((ushort)seats.Count); for (int i = 0; i < seats.Count; i++) { writer.Write(seats[i]); writer.Write(keys[i]); } } public override void Deserialize(NetworkReader reader) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) scene = reader.ReadString(); int num = reader.ReadUInt16(); for (int i = 0; i < num; i++) { seats.Add(reader.ReadNetworkId()); keys.Add(reader.ReadString()); } } } private const short SnapshotMessage = 28713; private static readonly Dictionary<string, GameObject> targets = new Dictionary<string, GameObject>(); private static readonly HashSet<NetworkClient> registeredClients = new HashSet<NetworkClient>(); private static readonly Dictionary<VehicleSeat, GameObject> mirroredPassengers = new Dictionary<VehicleSeat, GameObject>(); private static readonly Dictionary<VehicleSeat, MoonHauntTarget> occupiedSeats = new Dictionary<VehicleSeat, MoonHauntTarget>(); private static readonly Queue<GameObject> queuedTargets = new Queue<GameObject>(); private static readonly HashSet<int> queuedIds = new HashSet<int>(); private static readonly List<VehicleSeat> seatScratch = new List<VehicleSeat>(); private static readonly HashSet<VehicleSeat> activeMirrors = new HashSet<VehicleSeat>(); private static readonly MethodInfo SetPassenger = typeof(VehicleSeat).GetMethod("SetPassenger", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo[] AttributeFields = typeof(SpecialObjectAttributes).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static Snapshot pending; private static string currentScene; private static bool initialized; private static bool dirty; private static float nextHeartbeat; internal static void Initialize() { if (!initialized) { initialized = true; VehicleSeat.onPassengerEnterGlobal += PassengerEnter; VehicleSeat.onPassengerExitGlobal += PassengerExit; } } private static void PassengerEnter(VehicleSeat seat, GameObject passenger) { if (NetworkServer.active && currentScene != null && Object.op_Implicit((Object)(object)seat) && Object.op_Implicit((Object)(object)passenger)) { MoonHauntTarget component = passenger.GetComponent<MoonHauntTarget>(); if (Object.op_Implicit((Object)(object)component)) { RefreshKey(component); occupiedSeats[seat] = component; dirty = true; } } } private static void PassengerExit(VehicleSeat seat, GameObject passenger) { if (occupiedSeats.Remove(seat)) { dirty = true; } } internal static void QueueTarget(GameObject target) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)target) && currentScene != null) { Scene scene = target.scene; if (!(((Scene)(ref scene)).name != currentScene) && !Object.op_Implicit((Object)(object)target.GetComponent<MoonHauntTarget>()) && queuedIds.Add(((Object)target).GetInstanceID())) { queuedTargets.Enqueue(target); } } } internal static int Prepare() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) string cachedName = SceneCatalog.GetSceneDefForCurrentScene().cachedName; if (currentScene != cachedName) { Clear(); currentScene = cachedName; dirty = true; MonoBehaviour[] array = Object.FindObjectsOfType<MonoBehaviour>(true); foreach (MonoBehaviour val in array) { if (Object.op_Implicit((Object)(object)val)) { Scene scene = ((Component)val).gameObject.scene; if (!(((Scene)(ref scene)).name != cachedName) && (val is IInteractable || val is HoldoutZoneController || val is SpecialObjectAttributes || val is JumpVolume || val is SceneExitController || val is EscapeSequenceExtractionZone)) { QueueTarget(((Component)val).gameObject); } } } } int num = 0; for (int j = 0; j < 8 && queuedTargets.Count > 0; j++) { GameObject val2 = queuedTargets.Dequeue(); if (!Object.op_Implicit((Object)(object)val2)) { continue; } queuedIds.Remove(((Object)val2).GetInstanceID()); Scene scene2 = val2.scene; if (((Scene)(ref scene2)).name != cachedName || Object.op_Implicit((Object)(object)val2.GetComponentInParent<CharacterBody>()) || Object.op_Implicit((Object)(object)val2.GetComponentInParent<ProjectileController>()) || (Object.op_Implicit((Object)(object)val2.GetComponent<VehicleSeat>()) && !Object.op_Implicit((Object)(object)val2.GetComponent<EscapeSequenceExtractionZone>()) && !Object.op_Implicit((Object)(object)val2.GetComponent<HoldoutZoneController>()))) { continue; } NetworkIdentity componentInParent = val2.GetComponentInParent<NetworkIdentity>(); GameObject obj; if (Object.op_Implicit((Object)(object)componentInParent)) { Scene scene3 = ((Component)componentInParent).gameObject.scene; if (((Scene)(ref scene3)).name == cachedName) { obj = ((Component)componentInParent).gameObject; goto IL_0183; } } obj = val2; goto IL_0183; IL_0183: GameObject val3 = obj; if (Object.op_Implicit((Object)(object)val3.GetComponent<CharacterBody>()) || Object.op_Implicit((Object)(object)val3.GetComponent<ProjectileController>())) { continue; } MoonHauntTarget component = val3.GetComponent<MoonHauntTarget>(); if (Object.op_Implicit((Object)(object)component)) { RefreshKey(component); continue; } component = val3.AddComponent<MoonHauntTarget>(); component.key = MakeKey(val3.transform); targets[component.key] = val3; SpecialObjectAttributes val4 = val3.GetComponent<SpecialObjectAttributes>(); bool flag = !Object.op_Implicit((Object)(object)val4); if (flag) { val4 = val3.AddComponent<SpecialObjectAttributes>(); } FieldInfo[] attributeFields = AttributeFields; foreach (FieldInfo fieldInfo in attributeFields) { if (fieldInfo.FieldType.IsGenericType && fieldInfo.FieldType.GetGenericTypeDefinition() == typeof(List<>) && fieldInfo.GetValue(val4) == null) { fieldInfo.SetValue(val4, Activator.CreateInstance(fieldInfo.FieldType)); } } val4.grabbable = true; val4.locked = false; ((Behaviour)val4).enabled = true; if (flag) { val4.renderersToDisable.AddRange(val3.GetComponentsInChildren<Renderer>(true)); HashSet<GameObject> hashSet = new HashSet<GameObject>(); Collider[] componentsInChildren = val3.GetComponentsInChildren<Collider>(true); foreach (Collider val5 in componentsInChildren) { hashSet.Add(((Component)val5).gameObject); } val4.collisionToDisable.AddRange(hashSet); MonoBehaviour[] components = val3.GetComponents<MonoBehaviour>(); foreach (MonoBehaviour val6 in components) { if (Object.op_Implicit((Object)(object)val6) && (Object)(object)val6 != (Object)(object)component && (Object)(object)val6 != (Object)(object)val4 && (val6 is IInteractable || val6 is HoldoutZoneController)) { val4.behavioursToDisable.Add(val6); } } val4.maxDurability = 20; val4.bestName = ((Object)val3).name; } num++; } return num; } private static void RefreshKey(MoonHauntTarget marker) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) NetworkIdentity component = ((Component)marker).GetComponent<NetworkIdentity>(); if (!Object.op_Implicit((Object)(object)component)) { return; } NetworkInstanceId netId = component.netId; if (((NetworkInstanceId)(ref netId)).Value == 0) { return; } NetworkInstanceId netId2 = component.netId; string text = "net:" + ((NetworkInstanceId)(ref netId2)).Value; if (!(text == marker.key)) { if (marker.key != null) { targets.Remove(marker.key); } marker.key = text; targets[text] = ((Component)marker).gameObject; } } private static string MakeKey(Transform target) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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) NetworkIdentity component = ((Component)target).GetComponent<NetworkIdentity>(); if (Object.op_Implicit((Object)(object)component)) { NetworkInstanceId netId = component.netId; if (((NetworkInstanceId)(ref netId)).Value != 0) { NetworkInstanceId netId2 = component.netId; return "net:" + ((NetworkInstanceId)(ref netId2)).Value; } } List<string> list = new List<string>(); Transform val = target; while (Object.op_Implicit((Object)(object)val)) { int num = 0; if (Object.op_Implicit((Object)(object)val.parent)) { for (int i = 0; i < val.GetSiblingIndex(); i++) { if (((Object)val.parent.GetChild(i)).name == ((Object)val).name) { num++; } } } else { Scene scene = ((Component)val).gameObject.scene; GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); foreach (GameObject val2 in rootGameObjects) { if ((Object)(object)val2 == (Object)(object)((Component)val).gameObject) { break; } if (((Object)val2).name == ((Object)val).name) { num++; } } } list.Add(Uri.EscapeDataString(((Object)val).name) + "#" + num); val = val.parent; } list.Reverse(); Scene scene2 = ((Component)target).gameObject.scene; return "scene:" + ((Scene)(ref scene2)).name + "/" + string.Join("/", list.ToArray()); } private static void RegisterClients() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown foreach (NetworkClient allClient in NetworkClient.allClients) { if (allClient == null || !registeredClients.Add(allClient)) { continue; } allClient.RegisterHandler((short)28713, (NetworkMessageDelegate)delegate(NetworkMessage message) { if (!NetworkServer.active) { pending = message.ReadMessage<Snapshot>(); } }); } } internal static void Synchronize() { //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) RegisterClients(); if (NetworkServer.active) { if (!dirty && Time.unscaledTime < nextHeartbeat) { return; } Snapshot snapshot = new Snapshot(); snapshot.scene = currentScene; Snapshot snapshot2 = snapshot; seatScratch.Clear(); foreach (KeyValuePair<VehicleSeat, MoonHauntTarget> occupiedSeat in occupiedSeats) { VehicleSeat key = occupiedSeat.Key; MoonHauntTarget value = occupiedSeat.Value; if (!Object.op_Implicit((Object)(object)key) || !Object.op_Implicit((Object)(object)value) || !Object.op_Implicit((Object)(object)key.currentPassengerTransform) || (Object)(object)key.currentPassengerTransform != (Object)(object)((Component)value).transform) { seatScratch.Add(key); continue; } NetworkInstanceId netId = ((NetworkBehaviour)key).netId; if (((NetworkInstanceId)(ref netId)).Value != 0) { RefreshKey(value); snapshot2.seats.Add(((NetworkBehaviour)key).netId); snapshot2.keys.Add(value.key); } } foreach (VehicleSeat item in seatScratch) { occupiedSeats.Remove(item); } NetworkServer.SendToAll((short)28713, (MessageBase)(object)snapshot2); dirty = false; nextHeartbeat = Time.unscaledTime + 5f; } else { if (pending == null || !(pending.scene == currentScene)) { return; } activeMirrors.Clear(); bool flag = false; for (int i = 0; i < pending.seats.Count; i++) { GameObject val = ClientScene.FindLocalObject(pending.seats[i]); if (!targets.TryGetValue(pending.keys[i], out var value2) && pending.keys[i].StartsWith("net:", StringComparison.Ordinal) && uint.TryParse(pending.keys[i].Substring(4), out var result)) { value2 = ClientScene.FindLocalObject(new NetworkInstanceId(result)); } if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)value2) || !Object.op_Implicit((Object)(object)value2.GetComponent<MoonHauntTarget>())) { flag = true; continue; } VehicleSeat component = val.GetComponent<VehicleSeat>(); if (Object.op_Implicit((Object)(object)component)) { if ((Object)(object)component.currentPassengerTransform != (Object)(object)value2.transform) { SetPassenger.Invoke(component, new object[1] { value2 }); } mirroredPassengers[component] = value2; activeMirrors.Add(component); } } seatScratch.Clear(); foreach (KeyValuePair<VehicleSeat, GameObject> mirroredPassenger in mirroredPassengers) { if (!Object.op_Implicit((Object)(object)mirroredPassenger.Key) || !activeMirrors.Contains(mirroredPassenger.Key)) { seatScratch.Add(mirroredPassenger.Key); } } foreach (VehicleSeat item2 in seatScratch) { if (Object.op_Implicit((Object)(object)item2) && Object.op_Implicit((Object)(object)mirroredPassengers[item2]) && (Object)(object)item2.currentPassengerTransform == (Object)(object)mirroredPassengers[item2].transform) { MethodInfo setPassenger = SetPassenger; object[] parameters = new object[1]; setPassenger.Invoke(item2, parameters); } mirroredPassengers.Remove(item2); } if (!flag) { pending = null; } } } internal static void Clear() { if (currentScene == null && registeredClients.Count == 0 && queuedTargets.Count == 0) { return; } foreach (NetworkClient registeredClient in registeredClients) { if (registeredClient != null) { registeredClient.UnregisterHandler((short)28713); } } registeredClients.Clear(); targets.Clear(); mirroredPassengers.Clear(); occupiedSeats.Clear(); queuedTargets.Clear(); queuedIds.Clear(); seatScratch.Clear(); activeMirrors.Clear(); pending = null; currentScene = null; dirty = false; nextHeartbeat = 0f; } internal static void Shutdown() { if (initialized) { VehicleSeat.onPassengerEnterGlobal -= PassengerEnter; VehicleSeat.onPassengerExitGlobal -= PassengerExit; initialized = false; } Clear(); } } internal static class HauntTiming { internal static bool IsCooldownRead(Instruction instruction) { object operand = instruction.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); object operand2 = instruction.Operand; FieldReference val2 = (FieldReference)((operand2 is FieldReference) ? operand2 : null); if (val == null || !(((MemberReference)((MemberReference)val).DeclaringType).FullName == "RoR2.Items.HexHauntingBehaviour") || !(((MemberReference)val).Name == "GetCooldownValue")) { if (val2 != null && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == "RoR2.Items.HexHauntingBehaviour") { return ((MemberReference)val2).Name == "baseHauntCooldown"; } return false; } return true; } }