using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Logging; using DG.Tweening; using DG.Tweening.Core; using HarmonyLib; using Lamb.UI; using Lamb.UI.DeathScreen; using Lamb.UI.PauseMenu; using MMBiomeGeneration; using MMTools; using Microsoft.CodeAnalysis; using Rewired; using Spine; using Spine.Unity; using TMPro; using Unify; using Unify.Input; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ClassLibrary1")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ClassLibrary1")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("b05729a9-afdc-413c-b90e-c3a9f2cd0a2c")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 COTLMultiplayerExpansion { [BepInPlugin("com.cotlmp.multiplayerexpansion", "COTL Multiplayer Expansion", "2.20.14")] public class Plugin : BaseUnityPlugin { public static ManualLogSource Log; public const int MAX_PLAYERS = 4; public static readonly Color[] GoatColors = (Color[])(object)new Color[4] { Color.white, Color.white, new Color(0.4f, 0.7f, 1f, 1f), new Color(1f, 0.4f, 0.4f, 1f) }; public static readonly Color[] IndicatorColors = (Color[])(object)new Color[4] { new Color(0.9f, 0.2f, 0.2f, 1f), new Color(0.6f, 0.3f, 0.9f, 1f), new Color(1f, 0.6f, 0.1f, 1f), new Color(0.4f, 0.7f, 1f, 1f) }; private void Awake() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Expected O, but got Unknown //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Expected O, but got Unknown //IL_0205: Expected O, but got Unknown //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Expected O, but got Unknown //IL_027a: Expected O, but got Unknown //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Expected O, but got Unknown //IL_02ed: Expected O, but got Unknown //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Expected O, but got Unknown //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Expected O, but got Unknown //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Expected O, but got Unknown //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Expected O, but got Unknown //IL_0420: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Expected O, but got Unknown //IL_0456: Unknown result type (might be due to invalid IL or missing references) //IL_0463: Expected O, but got Unknown //IL_048c: Unknown result type (might be due to invalid IL or missing references) //IL_0499: Expected O, but got Unknown //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04cf: Expected O, but got Unknown //IL_04f8: Unknown result type (might be due to invalid IL or missing references) //IL_0505: Expected O, but got Unknown //IL_053f: Unknown result type (might be due to invalid IL or missing references) //IL_054d: Expected O, but got Unknown //IL_0576: Unknown result type (might be due to invalid IL or missing references) //IL_0583: Expected O, but got Unknown //IL_05ae: Unknown result type (might be due to invalid IL or missing references) //IL_05b9: Expected O, but got Unknown //IL_05e4: Unknown result type (might be due to invalid IL or missing references) //IL_05ef: Expected O, but got Unknown //IL_061a: Unknown result type (might be due to invalid IL or missing references) //IL_0625: Expected O, but got Unknown //IL_06b0: Unknown result type (might be due to invalid IL or missing references) //IL_06c5: Unknown result type (might be due to invalid IL or missing references) //IL_06d0: Expected O, but got Unknown //IL_06d0: Expected O, but got Unknown //IL_070a: Unknown result type (might be due to invalid IL or missing references) //IL_0720: Unknown result type (might be due to invalid IL or missing references) //IL_0735: Unknown result type (might be due to invalid IL or missing references) //IL_0740: Expected O, but got Unknown //IL_0740: Expected O, but got Unknown //IL_0740: Expected O, but got Unknown //IL_077a: Unknown result type (might be due to invalid IL or missing references) //IL_0791: Unknown result type (might be due to invalid IL or missing references) //IL_079c: Expected O, but got Unknown //IL_079c: Expected O, but got Unknown //IL_07d0: Unknown result type (might be due to invalid IL or missing references) //IL_07e7: Unknown result type (might be due to invalid IL or missing references) //IL_07f2: Expected O, but got Unknown //IL_07f2: Expected O, but got Unknown //IL_066c: Unknown result type (might be due to invalid IL or missing references) //IL_0677: Expected O, but got Unknown //IL_0846: Unknown result type (might be due to invalid IL or missing references) //IL_085d: Unknown result type (might be due to invalid IL or missing references) //IL_0868: Expected O, but got Unknown //IL_0868: Expected O, but got Unknown //IL_08bc: Unknown result type (might be due to invalid IL or missing references) //IL_08d2: Unknown result type (might be due to invalid IL or missing references) //IL_08e7: Unknown result type (might be due to invalid IL or missing references) //IL_08f2: Expected O, but got Unknown //IL_08f2: Expected O, but got Unknown //IL_08f2: Expected O, but got Unknown //IL_0946: Unknown result type (might be due to invalid IL or missing references) //IL_095d: Unknown result type (might be due to invalid IL or missing references) //IL_0968: Expected O, but got Unknown //IL_0968: Expected O, but got Unknown //IL_09bc: Unknown result type (might be due to invalid IL or missing references) //IL_09d3: Unknown result type (might be due to invalid IL or missing references) //IL_09de: Expected O, but got Unknown //IL_09de: Expected O, but got Unknown //IL_0a36: Unknown result type (might be due to invalid IL or missing references) //IL_0a4b: Unknown result type (might be due to invalid IL or missing references) //IL_0a56: Expected O, but got Unknown //IL_0a56: Expected O, but got Unknown //IL_0a8e: Unknown result type (might be due to invalid IL or missing references) //IL_0aa3: Unknown result type (might be due to invalid IL or missing references) //IL_0aae: Expected O, but got Unknown //IL_0aae: Expected O, but got Unknown //IL_0b3d: Unknown result type (might be due to invalid IL or missing references) //IL_0b54: Unknown result type (might be due to invalid IL or missing references) //IL_0b5f: Expected O, but got Unknown //IL_0b5f: Expected O, but got Unknown //IL_0ba6: Unknown result type (might be due to invalid IL or missing references) //IL_0bb4: Expected O, but got Unknown //IL_0bee: Unknown result type (might be due to invalid IL or missing references) //IL_0c05: Unknown result type (might be due to invalid IL or missing references) //IL_0c10: Expected O, but got Unknown //IL_0c10: Expected O, but got Unknown //IL_0c38: Unknown result type (might be due to invalid IL or missing references) //IL_0c4e: Unknown result type (might be due to invalid IL or missing references) //IL_0c63: Unknown result type (might be due to invalid IL or missing references) //IL_0c6e: Expected O, but got Unknown //IL_0c6e: Expected O, but got Unknown //IL_0c6e: Expected O, but got Unknown //IL_0ca8: Unknown result type (might be due to invalid IL or missing references) //IL_0cb6: Expected O, but got Unknown //IL_0ae6: Unknown result type (might be due to invalid IL or missing references) //IL_0afb: Unknown result type (might be due to invalid IL or missing references) //IL_0b06: Expected O, but got Unknown //IL_0b06: Expected O, but got Unknown //IL_0cea: Unknown result type (might be due to invalid IL or missing references) //IL_0d00: Unknown result type (might be due to invalid IL or missing references) //IL_0d15: Unknown result type (might be due to invalid IL or missing references) //IL_0d20: Expected O, but got Unknown //IL_0d20: Expected O, but got Unknown //IL_0d20: Expected O, but got Unknown //IL_0d7a: Unknown result type (might be due to invalid IL or missing references) //IL_0d91: Unknown result type (might be due to invalid IL or missing references) //IL_0d9c: Expected O, but got Unknown //IL_0d9c: Expected O, but got Unknown //IL_0dc4: Unknown result type (might be due to invalid IL or missing references) //IL_0dda: Unknown result type (might be due to invalid IL or missing references) //IL_0def: Unknown result type (might be due to invalid IL or missing references) //IL_0dfa: Expected O, but got Unknown //IL_0dfa: Expected O, but got Unknown //IL_0dfa: Expected O, but got Unknown //IL_0e2e: Unknown result type (might be due to invalid IL or missing references) //IL_0e44: Unknown result type (might be due to invalid IL or missing references) //IL_0e59: Unknown result type (might be due to invalid IL or missing references) //IL_0e64: Expected O, but got Unknown //IL_0e64: Expected O, but got Unknown //IL_0e64: Expected O, but got Unknown //IL_0ebe: Unknown result type (might be due to invalid IL or missing references) //IL_0ed5: Unknown result type (might be due to invalid IL or missing references) //IL_0ee0: Expected O, but got Unknown //IL_0ee0: Expected O, but got Unknown //IL_0f08: Unknown result type (might be due to invalid IL or missing references) //IL_0f1e: Unknown result type (might be due to invalid IL or missing references) //IL_0f33: Unknown result type (might be due to invalid IL or missing references) //IL_0f3e: Expected O, but got Unknown //IL_0f3e: Expected O, but got Unknown //IL_0f3e: Expected O, but got Unknown //IL_0f72: Unknown result type (might be due to invalid IL or missing references) //IL_0f88: Unknown result type (might be due to invalid IL or missing references) //IL_0f9d: Unknown result type (might be due to invalid IL or missing references) //IL_0fa8: Expected O, but got Unknown //IL_0fa8: Expected O, but got Unknown //IL_0fa8: Expected O, but got Unknown //IL_1002: Unknown result type (might be due to invalid IL or missing references) //IL_1019: Unknown result type (might be due to invalid IL or missing references) //IL_1024: Expected O, but got Unknown //IL_1024: Expected O, but got Unknown //IL_104c: Unknown result type (might be due to invalid IL or missing references) //IL_1062: Unknown result type (might be due to invalid IL or missing references) //IL_1077: Unknown result type (might be due to invalid IL or missing references) //IL_1082: Expected O, but got Unknown //IL_1082: Expected O, but got Unknown //IL_1082: Expected O, but got Unknown //IL_10b6: Unknown result type (might be due to invalid IL or missing references) //IL_10cc: Unknown result type (might be due to invalid IL or missing references) //IL_10e1: Unknown result type (might be due to invalid IL or missing references) //IL_10ec: Expected O, but got Unknown //IL_10ec: Expected O, but got Unknown //IL_10ec: Expected O, but got Unknown //IL_1134: Unknown result type (might be due to invalid IL or missing references) //IL_1142: Expected O, but got Unknown //IL_116b: Unknown result type (might be due to invalid IL or missing references) //IL_1178: Expected O, but got Unknown //IL_11b3: Unknown result type (might be due to invalid IL or missing references) //IL_11c0: Expected O, but got Unknown //IL_11ed: Unknown result type (might be due to invalid IL or missing references) //IL_11fa: Expected O, but got Unknown //IL_1269: Unknown result type (might be due to invalid IL or missing references) //IL_1276: Expected O, but got Unknown //IL_12cf: Unknown result type (might be due to invalid IL or missing references) //IL_12dc: Expected O, but got Unknown //IL_1328: Unknown result type (might be due to invalid IL or missing references) //IL_1335: Expected O, but got Unknown //IL_1370: Unknown result type (might be due to invalid IL or missing references) //IL_137d: Expected O, but got Unknown //IL_13aa: Unknown result type (might be due to invalid IL or missing references) //IL_13b7: Expected O, but got Unknown //IL_13f1: Unknown result type (might be due to invalid IL or missing references) //IL_1406: Unknown result type (might be due to invalid IL or missing references) //IL_1413: Expected O, but got Unknown //IL_1413: Expected O, but got Unknown //IL_143c: Unknown result type (might be due to invalid IL or missing references) //IL_1449: Expected O, but got Unknown //IL_1471: Unknown result type (might be due to invalid IL or missing references) //IL_147f: Expected O, but got Unknown //IL_14a7: Unknown result type (might be due to invalid IL or missing references) //IL_14b5: Expected O, but got Unknown //IL_14dd: Unknown result type (might be due to invalid IL or missing references) //IL_14eb: Expected O, but got Unknown //IL_1525: Unknown result type (might be due to invalid IL or missing references) //IL_1533: Expected O, but got Unknown //IL_156d: Unknown result type (might be due to invalid IL or missing references) //IL_157b: Expected O, but got Unknown //IL_15a3: Unknown result type (might be due to invalid IL or missing references) //IL_15b1: Expected O, but got Unknown //IL_1605: Unknown result type (might be due to invalid IL or missing references) //IL_1613: Expected O, but got Unknown //IL_165a: Unknown result type (might be due to invalid IL or missing references) //IL_1668: Expected O, but got Unknown //IL_1690: Unknown result type (might be due to invalid IL or missing references) //IL_169e: Expected O, but got Unknown //IL_16e5: Unknown result type (might be due to invalid IL or missing references) //IL_16f3: Expected O, but got Unknown //IL_173a: Unknown result type (might be due to invalid IL or missing references) //IL_174f: Unknown result type (might be due to invalid IL or missing references) //IL_175c: Expected O, but got Unknown //IL_175c: Expected O, but got Unknown //IL_1796: Unknown result type (might be due to invalid IL or missing references) //IL_17ad: Unknown result type (might be due to invalid IL or missing references) //IL_17b8: Expected O, but got Unknown //IL_17b8: Expected O, but got Unknown //IL_17f2: Unknown result type (might be due to invalid IL or missing references) //IL_1809: Unknown result type (might be due to invalid IL or missing references) //IL_1814: Expected O, but got Unknown //IL_1814: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"COTL Multiplayer Expansion loading..."); Harmony val = new Harmony("com.cotlmp.multiplayerexpansion"); val.Patch((MethodBase)AccessTools.Method(typeof(CoopManager), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "CoopManager_Awake", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(CoopManager), "OnControllerConnected", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "OnControllerConnected", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(CoopManager), "AddPlayerFromMenu", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "AddPlayerFromMenu", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(UICoopAssignController), "ConfirmSpawnButtonPress", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "ConfirmSpawnButtonPress", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(CoopManager), "RemovePlayerFromMenu", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "RemovePlayerFromMenu", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_TempleAltar), "OnInteract", new Type[1] { typeof(StateMachine) }, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "TempleAltar_Finalizer", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_TempleAltar), "DoCancel", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "TempleAltar_Finalizer", (Type[])null), (HarmonyMethod)null); MethodInfo method = typeof(Interaction_TempleAltar).GetMethod("TryOnboardSin", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { val.Patch((MethodBase)method, new HarmonyMethod(typeof(Patches), "TempleAltar_TryOnboardSin_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "TempleAltar_Finalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched Interaction_TempleAltar.TryOnboardSin coop-safe guard"); } else { Log.LogWarning((object)"[MP] Skipped patch: Interaction_TempleAltar.TryOnboardSin not found"); } MethodInfo methodInfo = AccessTools.Method(typeof(Interaction_TempleAltar), "b__68_1", (Type[])null, (Type[])null); if (methodInfo != null) { val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "TempleAltar_CancelCleanup_Postfix", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "TempleAltar_Finalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched Interaction_TempleAltar.DoCancel cleanup callback finalizer"); } else { Log.LogWarning((object)"[MP] Skipped patch: Interaction_TempleAltar.DoCancel cleanup callback not found"); } MethodInfo methodInfo2 = Patches.FindNestedMoveNext(typeof(Interaction_TempleAltar), "DelayMenu"); if (methodInfo2 != null) { val.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(Patches), "TempleAltarTwoPlayerScope_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "TempleAltarTwoPlayerScope_Finalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched Interaction_TempleAltar.DelayMenu player presentation scope"); } else { Log.LogWarning((object)"[MP] Skipped patch: Interaction_TempleAltar.DelayMenu MoveNext not found"); } val.Patch((MethodBase)AccessTools.Method(typeof(PlayerFarming), "OnEnable", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerFarming_OnEnable_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(CoopManager), "SpawnCoopPlayer", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "SpawnCoopPlayer_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(PlayerFarming), "SetSkin", new Type[1] { typeof(bool) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "SetSkin_Recolor", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(UIPauseMenuController), "OnCoopButtonPressed", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "OnCoopButtonPressed", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(UIPauseMenuController), "RefreshCoopText", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "RefreshCoopText", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(HUD_Manager), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "HUD_Update", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(CoopManager), "RefreshCoopPlayerRewired", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "RefreshCoopPlayerRewired", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(PlayerFarming), "RefreshPlayersCount", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "RefreshPlayersCount_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(CoopIndicatorIcon), "SetUsername", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "SetUsername_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(CoopIndicatorIcon), "AnimateDamageOnIcons", new Type[1] { typeof(PlayerFarming) }, (Type[])null), new HarmonyMethod(typeof(Patches), "CoopIndicatorIcon_AnimateDamageOnIcons_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(PlayerFarming), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerFarming_Update_Camera", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_DLCShrine), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "SilentFinalizer", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_DLCShrine), "OnDisable", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "SilentFinalizer", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(CoopManager), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "SilentFinalizer", (Type[])null), (HarmonyMethod)null); Type type = AccessTools.TypeByName("SkeletonAnimationLODGlobalManager"); if (type != null) { MethodInfo methodInfo3 = AccessTools.Method(type, "Update", (Type[])null, (Type[])null); if (methodInfo3 != null) { val.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "SilentFinalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched SkeletonAnimationLODGlobalManager.Update finalizer"); } } val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_Fishing), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerCount_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "FishingBounds_Finalizer", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_Fishing), "UpdatePlayer", new Type[1] { typeof(int) }, (Type[])null), new HarmonyMethod(typeof(Patches), "FishingTwoPlayerScope_Prefix", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerCount_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "FishingTwoPlayerScope_Finalizer", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_Fishing), "OnInteract", new Type[1] { typeof(StateMachine) }, (Type[])null), new HarmonyMethod(typeof(Patches), "InteractionFishing_BlockExtraPlayers_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "FishingBounds_Finalizer", (Type[])null), (HarmonyMethod)null); MethodInfo methodInfo4 = Patches.FindNestedMoveNext(typeof(Interaction_Fishing), "WaitForPlayersToArriveIE"); if (methodInfo4 != null) { val.Patch((MethodBase)methodInfo4, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerScope_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerScope_Finalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched Interaction_Fishing.WaitForPlayersToArriveIE two-player scope"); } else { Log.LogWarning((object)"[MP] Skipped patch: Interaction_Fishing.WaitForPlayersToArriveIE MoveNext not found"); } MethodInfo methodInfo5 = Patches.FindNestedMoveNext(typeof(Interaction_Fishing), "BeganFishingIE"); if (methodInfo5 != null) { val.Patch((MethodBase)methodInfo5, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerScope_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerScope_Finalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched Interaction_Fishing.BeganFishingIE two-player scope"); } else { Log.LogWarning((object)"[MP] Skipped patch: Interaction_Fishing.BeganFishingIE MoveNext not found"); } MethodInfo methodInfo6 = Patches.FindNestedMoveNext(typeof(Interaction_Fishing), "CastLineIE"); if (methodInfo6 != null) { val.Patch((MethodBase)methodInfo6, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerScope_Prefix", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerCount_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "FishingTwoPlayerScope_Finalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched Interaction_Fishing.CastLineIE two-player scope"); } else { Log.LogWarning((object)"[MP] Skipped patch: Interaction_Fishing.CastLineIE MoveNext not found"); } MethodInfo methodInfo7 = Patches.FindNestedMoveNext(typeof(Interaction_Fishing), "FishCaughtIE"); if (methodInfo7 != null) { val.Patch((MethodBase)methodInfo7, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerScope_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerScope_Finalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched Interaction_Fishing.FishCaughtIE two-player scope"); } else { Log.LogWarning((object)"[MP] Skipped patch: Interaction_Fishing.FishCaughtIE MoveNext not found"); } MethodInfo methodInfo8 = Patches.FindNestedMoveNext(typeof(Interaction_Fishing), "NoCatch"); if (methodInfo8 != null) { val.Patch((MethodBase)methodInfo8, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerScope_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerScope_Finalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched Interaction_Fishing.NoCatch two-player scope"); } else { Log.LogWarning((object)"[MP] Skipped patch: Interaction_Fishing.NoCatch MoveNext not found"); } MethodInfo methodInfo9 = AccessTools.Method(typeof(Fishable), "Update", (Type[])null, (Type[])null); if (methodInfo9 != null) { val.Patch((MethodBase)methodInfo9, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerCount_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "FishingBounds_Finalizer", (Type[])null), (HarmonyMethod)null); } MethodInfo methodInfo10 = AccessTools.Method(typeof(Fishable), "HookLanded", (Type[])null, (Type[])null); if (methodInfo10 != null) { val.Patch((MethodBase)methodInfo10, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "FishingTwoPlayerCount_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "FishingBounds_Finalizer", (Type[])null), (HarmonyMethod)null); } MethodInfo methodInfo11 = AccessTools.Method(typeof(BiomeConstants), "BiomeGenerator_OnBiomeChangeRoom", (Type[])null, (Type[])null); if (methodInfo11 != null) { val.Patch((MethodBase)methodInfo11, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "BiomeConstants_BiomeGenerator_OnBiomeChangeRoom_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "SilentFinalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched BiomeConstants.BiomeGenerator_OnBiomeChangeRoom (safe particle-clear transpiler)"); } val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_BaseTeleporter), "HandleAnimationStateEvent", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "TeleporterAnimEvent_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "TeleporterAnimEvent_Finalizer", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_BaseTeleporter), "SpawnPlayerIE", new Type[2] { typeof(PlayerFarming), typeof(Vector3) }, (Type[])null), new HarmonyMethod(typeof(Patches), "SpawnPlayerIE_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_PlayerClearRubble), "OnInteract", new Type[1] { typeof(StateMachine) }, (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerClearRubble_OnInteract_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerClearRubble_Finalizer", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_PlayerClearRubble), "Update", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerClearRubble_Update_Prefix", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerClearRubblePlayerIndex_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerClearRubble_Finalizer", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_PlayerClearRubble), "DoBuild", new Type[1] { typeof(PlayerFarming) }, (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerClearRubble_DoBuild_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo12 = Patches.FindNestedMoveNext(typeof(Interaction_PlayerClearRubble), "DoBuild"); if (methodInfo12 != null) { val.Patch((MethodBase)methodInfo12, new HarmonyMethod(typeof(Patches), "PlayerClearRubble_DoBuildMoveNext_Prefix", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerClearRubblePlayerIndex_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerClearRubble_Finalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched Interaction_PlayerClearRubble.DoBuild MoveNext safety"); } else { Log.LogWarning((object)"[MP] Skipped patch: Interaction_PlayerClearRubble.DoBuild MoveNext not found"); } val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_Woodcutting), "OnInteract", new Type[1] { typeof(StateMachine) }, (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerWork_OnInteract_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerWork_Finalizer", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_Woodcutting), "Update", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerWork_Update_Prefix", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerClearRubblePlayerIndex_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerWork_Finalizer", (Type[])null), (HarmonyMethod)null); MethodInfo methodInfo13 = Patches.FindNestedMoveNext(typeof(Interaction_Woodcutting), "DoWoodCutting"); if (methodInfo13 != null) { val.Patch((MethodBase)methodInfo13, new HarmonyMethod(typeof(Patches), "PlayerWork_MoveNext_Prefix", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerClearRubblePlayerIndex_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerWork_Finalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched Interaction_Woodcutting.DoWoodCutting MoveNext safety"); } else { Log.LogWarning((object)"[MP] Skipped patch: Interaction_Woodcutting.DoWoodCutting MoveNext not found"); } val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_WoodcuttingRubble), "OnInteract", new Type[1] { typeof(StateMachine) }, (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerWork_OnInteract_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerWork_Finalizer", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_WoodcuttingRubble), "Update", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerWork_Update_Prefix", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerClearRubblePlayerIndex_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerWork_Finalizer", (Type[])null), (HarmonyMethod)null); MethodInfo methodInfo14 = Patches.FindNestedMoveNext(typeof(Interaction_WoodcuttingRubble), "DoWoodCutting"); if (methodInfo14 != null) { val.Patch((MethodBase)methodInfo14, new HarmonyMethod(typeof(Patches), "PlayerWork_MoveNext_Prefix", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerClearRubblePlayerIndex_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerWork_Finalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched Interaction_WoodcuttingRubble.DoWoodCutting MoveNext safety"); } else { Log.LogWarning((object)"[MP] Skipped patch: Interaction_WoodcuttingRubble.DoWoodCutting MoveNext not found"); } val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_Berries), "OnInteract", new Type[1] { typeof(StateMachine) }, (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerWork_OnInteract_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerWork_Finalizer", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_Berries), "Update", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerWork_Update_Prefix", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerClearRubblePlayerIndex_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerWork_Finalizer", (Type[])null), (HarmonyMethod)null); MethodInfo methodInfo15 = Patches.FindNestedMoveNext(typeof(Interaction_Berries), "PickBerries"); if (methodInfo15 != null) { val.Patch((MethodBase)methodInfo15, new HarmonyMethod(typeof(Patches), "PlayerWork_MoveNext_Prefix", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "PlayerClearRubblePlayerIndex_Transpiler", (Type[])null), new HarmonyMethod(typeof(Patches), "PlayerWork_Finalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)"[MP] Patched Interaction_Berries.PickBerries MoveNext safety"); } else { Log.LogWarning((object)"[MP] Skipped patch: Interaction_Berries.PickBerries MoveNext not found"); } val.Patch((MethodBase)AccessTools.Method(typeof(GameManager), "NewRun", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "NewRun_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(CoopManager), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "CoopManager_Start_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(CoopManager), "WakeAllKnockedOutPlayersWithHealth", new Type[1] { typeof(float) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "CoopManager_WakeAllKnockedOutPlayersWithHealth_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(CoopManager), "WakeAllKnockedOutPlayers", Type.EmptyTypes, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "CoopManager_WakeAllKnockedOutPlayers_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(CoopManager), "WakeKnockedOutPlayer", new Type[5] { typeof(PlayerFarming), typeof(float), typeof(PlayerFarming), typeof(HeartPickupType), typeof(bool) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "CoopManager_WakeKnockedOutPlayer_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo method2 = typeof(CoopManager).GetMethod("ResetMainPlayerOnConversationEnd", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[2] { typeof(bool), typeof(bool) }, null); if (method2 != null) { val.Patch((MethodBase)method2, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "CoopManager_ResetMainPlayerOnConversationEnd_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Log.LogWarning((object)"[MP] Skipped patch: CoopManager.ResetMainPlayerOnConversationEnd(bool,bool) not found"); } val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_WeaponSelectionPodium), "SetWeapon", new Type[1] { typeof(int) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "WeaponPodium_SetWeapon_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_WeaponSelectionPodium), "SetCurse", new Type[1] { typeof(int) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "WeaponPodium_SetCurse_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_WeaponSelectionPodium), "OnEnable", Type.EmptyTypes, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "WeaponPodium_OnEnable_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Interaction_WeaponSelectionPodium), "OnInteract", new Type[1] { typeof(StateMachine) }, (Type[])null), new HarmonyMethod(typeof(Patches), "WeaponPodium_OnInteract_Prefix", (Type[])null), new HarmonyMethod(typeof(Patches), "WeaponPodium_OnInteract_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)typeof(UICoopAssignController).GetMethod("OnShowStarted", BindingFlags.Instance | BindingFlags.NonPublic), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "CoopAssign_OnShowStarted", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(Health_Manager), "Init", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "HealthManager_Init", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(HUD_Hearts), "SetWeapon", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "HUDHearts_SetWeapon_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(HUD_Hearts), "SetCurse", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "HUDHearts_SetCurse_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(HUD_Hearts), "OnHPUpdated", new Type[1] { typeof(HealthPlayer) }, (Type[])null), new HarmonyMethod(typeof(Patches), "HUDHearts_OnHPUpdated_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(HUD_Hearts), "OnTotalHPUpdated", new Type[1] { typeof(HealthPlayer) }, (Type[])null), new HarmonyMethod(typeof(Patches), "HUDHearts_OnTotalHPUpdated_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(HUD_Hearts), "OnEnable", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "HUDHearts_OnEnable_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(HUD_Heart), "SetSprite", new Type[3] { typeof(HeartState), typeof(bool), typeof(HeartType) }, (Type[])null), new HarmonyMethod(typeof(Patches), "HUDHeart_SetSprite_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(HUD_Heart), "Activate", new Type[2] { typeof(bool), typeof(bool) }, (Type[])null), new HarmonyMethod(typeof(Patches), "HUDHeart_Activate_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(FaithAmmo), "OnEnable", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "FaithAmmo_OnEnable_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(FaithAmmo), "OnGetSoul", new Type[2] { typeof(int), typeof(PlayerFarming) }, (Type[])null), new HarmonyMethod(typeof(Patches), "FaithAmmo_OnGetSoul_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(FaithAmmo), "UseAmmo", new Type[2] { typeof(float), typeof(bool) }, (Type[])null), new HarmonyMethod(typeof(Patches), "FaithAmmo_UseAmmo_Prefix", (Type[])null), new HarmonyMethod(typeof(Patches), "FaithAmmo_UseAmmo_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(HUD_ActiveTrinketsCoOp), "OnTrinketsChanged", new Type[1] { typeof(PlayerFarming) }, (Type[])null), new HarmonyMethod(typeof(Patches), "HUDActiveTrinketsCoOp_OnTrinketsChanged_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "SilentFinalizer", (Type[])null), (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.Method(typeof(HUD_ActiveTrinketsCoOp), "OnRomanNumeralSettingChanged", new Type[1] { typeof(bool) }, (Type[])null), new HarmonyMethod(typeof(Patches), "HUDActiveTrinketsCoOp_OnRomanNumeralSettingChanged_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "SilentFinalizer", (Type[])null), (HarmonyMethod)null); Log.LogInfo((object)("All patches applied. MAX_PLAYERS = " + 4)); } } public static class Patches { private sealed class PlayerListScopeState { public int SavedPlayersCount; public List HiddenPlayers; } private static bool _removingPlayer = false; private static bool _manualRemoveRequested = false; private static float _autoRemoveSuppressedUntil = 0f; private const float AutoRemoveSuppressSeconds = 8f; private static int _savedExtraSlotCount = 0; private static bool _autoRespawnRoutineRunning = false; private static float _nextAutoRespawnAttemptAt = 0f; private static float _nextAutoRespawnHeartbeatAt = 0f; private static float _nextControllerHealHeartbeatAt = 0f; private static float _nextRumbleCleanupAt = 0f; private static readonly HashSet _pendingSpawnSlots = new HashSet(); private static readonly Dictionary _pendingSpawnUseAnimation = new Dictionary(); private static readonly Dictionary _pendingSpawnFirstSeenAt = new Dictionary(); private static readonly HashSet _desiredExtraSlots = new HashSet(); private static int _startupExtraRespawnDepth = 0; private static float _dungeonIntroProtectUntil = 0f; private static float _nextPendingBlockLogAt = 0f; private static string _lastLoggedDungeonRoomPath = null; private static bool _p2EntranceGuardRunning = false; private static bool _dungeonRoomStabilizeRunning = false; private static int _lastStabilizedDungeonRoomId = int.MinValue; private static float _nextDungeonRoomStabilizeCheckAt = 0f; private static float _roomEntryDistanceRepositionGraceUntil = 0f; private static readonly HashSet _warnedOrphanSlotObjects = new HashSet(); private static readonly HashSet _postReviveHardResetSlots = new HashSet(); private static float _lastObservedWakeHealth = 2f; private static float _lastObservedSacrificialWakeHealth = 2f; private static float _sacrificialReviveWindowUntil = 0f; private const float SacrificialReviveWindowSeconds = 7f; private const float BoostedWakeHealthThreshold = 2.01f; private static readonly Dictionary _nextExtraFalseDownedWatchdogAt = new Dictionary(); private static readonly Dictionary _postReviveRaceGuardUntil = new Dictionary(); private static readonly Dictionary _nextPostReviveForceApplyAt = new Dictionary(); private static float _nextPostReviveRaceGuardHeartbeatAt = 0f; private const float PostReviveRaceGuardSeconds = 4f; private const float PostReviveRaceGuardPollInterval = 0.18f; private static Image _p2Widget; private static Image _p3Widget; private static Image _p4Widget; private static RectTransform _p2Arrow; private static RectTransform _p3Arrow; private static RectTransform _p4Arrow; private static readonly Dictionary _cachedSprites = new Dictionary(); private static readonly Dictionary _cachedTextImages = new Dictionary(); private static readonly Dictionary _cachedHaloSR = new Dictionary(); private static readonly HashSet _haloLogged = new HashSet(); private static readonly Dictionary _cachedHaloSprites = new Dictionary(); private static readonly Dictionary _haloSpriteNames = new Dictionary { { 2, "halo_orange.png" }, { 3, "halo_blue.png" } }; private static int _podiumExtraCount = 0; private static readonly Vector3[] SpawnOffsets = (Vector3[])(object)new Vector3[4] { Vector3.zero, new Vector3(1.5f, 0f, 0f), new Vector3(0f, 1.5f, 0f), new Vector3(0f, -1.5f, 0f) }; private static readonly FieldInfo _playerControllerUntouchableTimerField = AccessTools.Field(typeof(PlayerController), "untouchableTimer"); private static readonly FieldInfo _playerControllerInvincibleTimerField = AccessTools.Field(typeof(PlayerController), "invincibleTimer"); private static readonly FieldInfo _playerControllerImmuneToProjectilesTimerField = AccessTools.Field(typeof(PlayerController), "immuneToProjectilesTimer"); private static readonly FieldInfo _playerControllerUntouchableTimerFlashField = AccessTools.Field(typeof(PlayerController), "untouchableTimerFlash"); private static Type _cachedHealthReflectionType; private static FieldInfo _healthInvincibleField; private static FieldInfo _healthUntouchableField; private static FieldInfo _healthIgnoreProjectilesField; private static FieldInfo _healthMaxHpField; private static FieldInfo _healthTotalHpField; private static PropertyInfo _healthIgnoreProjectilesProperty; private static PropertyInfo _healthMaxHpProperty; private static PropertyInfo _healthTotalHpProperty; private static MethodInfo _healthClearAllStasisEffectsMethod; private static bool _faithAmmoDumped = false; private static bool _delayedRespawnAfterReviveQueued = false; private const float DelayedReviveRespawnInitialDelay = 0.35f; private const float DelayedReviveRespawnPollInterval = 0.2f; private const float DelayedReviveRespawnMaxDuration = 15f; private static readonly Vector3[] _teleporterOffsets = (Vector3[])(object)new Vector3[4] { new Vector3(-0.75f, 0f, 0f), new Vector3(0.75f, 0f, 0f), new Vector3(-1.5f, 0f, 0f), new Vector3(1.5f, 0f, 0f) }; private static readonly FieldInfo _teleporterStencilField = typeof(Interaction_BaseTeleporter).GetField("PlayerStencilRT", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo _clearRubbleButtonDownField = typeof(Interaction_PlayerClearRubble).GetField("buttonDown", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo _clearRubbleActivatingPlayersField = typeof(Interaction_PlayerClearRubble).GetField("activatingPlayers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo _templeAltarActivatedField = typeof(Interaction_TempleAltar).GetField("Activated", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo _templeAltarActivatingField = typeof(Interaction_TempleAltar).GetField("Activating", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo _templeAltarCoopPlayerFrozenField = typeof(Interaction_TempleAltar).GetField("CoopPlayerFrozen", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo _templeAltarInteractedField = typeof(Interaction_TempleAltar).GetField("k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo _templeAltarColliderField = typeof(Interaction_TempleAltar).GetField("Collider", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo _templeAltarForceRitualField = typeof(Interaction_TempleAltar).GetField("forceRitual", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static bool _templeExtraReleaseQueued = false; private static bool _loggedFishingBoundsSuppressed = false; private static readonly Stack _twoPlayerListScopes = new Stack(); private static bool _spawnedExtraWeaponPodiums = false; private static bool _spawnedExtraSpellPodiums = false; private static readonly FieldInfo _twinPodiumField = typeof(Interaction_WeaponSelectionPodium).GetField("TwinPodium", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly Dictionary> _podiumClones = new Dictionary>(); private static readonly Dictionary _podiumOwnerSlotByInstanceId = new Dictionary(); private static bool _positioningDeferred = false; private static readonly Dictionary _extraHeartBars = new Dictionary(); private static readonly HashSet _suppressedHeartEffectLogs = new HashSet(); private static readonly HashSet _suppressedFaithAmmoLogs = new HashSet(); private static readonly HashSet _suppressedTrinketHudLogs = new HashSet(); private static readonly HashSet _missingDamageIconLogs = new HashSet(); private static readonly MethodInfo _hudHeartsClearHealthEvents = typeof(HUD_Hearts).GetMethod("ClearHealthEvents", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo _faithAmmoUpdateBar = typeof(FaithAmmo).GetMethod("UpdateBar", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo _coopIndicatorAnimateOnDamagedField = typeof(CoopIndicatorIcon).GetField("animateIconOnDamaged", BindingFlags.Instance | BindingFlags.NonPublic); private static bool _reroutingFaithAmmoUse = false; private static int _safeBiomeClearPatchCountLog = -1; private static readonly Dictionary _digitBitmaps = new Dictionary { { '1', new int[35] { 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0 } }, { '2', new int[35] { 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1 } }, { '3', new int[35] { 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0 } }, { '4', new int[35] { 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0 } } }; public static void CoopManager_Awake() { GameObject[] allPlayerGameObjects = CoopManager.AllPlayerGameObjects; if (allPlayerGameObjects.Length < 4) { GameObject[] array = (GameObject[])(object)new GameObject[4]; for (int i = 0; i < allPlayerGameObjects.Length; i++) { array[i] = allPlayerGameObjects[i]; } typeof(CoopManager).GetField("AllPlayerGameObjects", BindingFlags.Static | BindingFlags.Public).SetValue(null, array); Plugin.Log.LogInfo((object)$"AllPlayerGameObjects expanded to {4}"); } } public static void OnControllerConnected(ControllerStatusChangedEventArgs args) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown if (!CoopManager.CoopActive || PlayerFarming.playersCount >= 4 || (Object)CoopManager.Instance == (Object)null || CoopManager.Instance.IsSpawningOrRemovingPlayer) { return; } Joystick val = null; foreach (Joystick joystick in ReInput.controllers.Joysticks) { if (((Controller)joystick).id == args.controllerId) { val = joystick; break; } } if (val == null) { return; } for (int i = 0; i < 4; i++) { Player player = RewiredInputManager.GetPlayer(i); if (player != null && player.controllers.ContainsController((Controller)val)) { Plugin.Log.LogInfo((object)$"OnControllerConnected: already assigned to slot {i}, skipping"); return; } } int playersCount = PlayerFarming.playersCount; Plugin.Log.LogInfo((object)$"OnControllerConnected: auto-assigning to slot {playersCount}"); for (int j = 0; j < 4; j++) { RewiredInputManager.GetPlayer(j).controllers.RemoveController((Controller)val); } RewiredInputManager.GetPlayer(playersCount).controllers.AddController((Controller)val, true); MarkDesiredExtraSlot(playersCount, desired: true); if (playersCount >= 2) { _pendingSpawnSlots.Add(playersCount); } CoopManager.Instance.SpawnCoopPlayer(playersCount, true, -1f); CoopManager.CoopActive = true; CoopManager.RefreshCoopPlayerRewired(); TryStopAllRumble("OnControllerConnected"); Plugin.Log.LogInfo((object)$"Auto-spawned goat at slot {playersCount}"); } public static bool AddPlayerFromMenu() { if (PlayerFarming.playersCount < 4) { Plugin.Log.LogInfo((object)$"AddPlayerFromMenu: players={PlayerFarming.playersCount}, opening assign menu"); UICoopAssignController val = MonoSingleton.Instance.ShowCoopAssignMenu(); ((UIMenuBase)val).OnHidden = (Action)Delegate.Combine(((UIMenuBase)val).OnHidden, (Action)delegate { if (CoopManager.CoopActive) { CoopManager.AddtionalUser = UserHelper.GetPlayer(1); } }); } return false; } public static bool OnCoopButtonPressed(UIPauseMenuController __instance) { Plugin.Log.LogInfo((object)$"OnCoopButtonPressed: players={PlayerFarming.playersCount}, coopActive={CoopManager.CoopActive}"); if (PlayerFarming.playersCount < 4) { ((UIMenuBase)__instance).Hide(true); CoopManager.AddPlayerFromMenu(); return false; } if (CoopManager.CoopActive) { ((UIMenuBase)__instance).Hide(false); _manualRemoveRequested = true; CoopManager.RemovePlayerFromMenu(); return false; } return true; } public static void RefreshCoopText(UIPauseMenuController __instance) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown FieldInfo field = typeof(UIPauseMenuController).GetField("_coopButtonText", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = typeof(UIPauseMenuController).GetField("_coopButton", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field3 = typeof(UIPauseMenuController).GetField("DenyCoop", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null || field2 == null) { return; } object value = field.GetValue(__instance); TextMeshProUGUI val = (TextMeshProUGUI)((value is TextMeshProUGUI) ? value : null); object value2 = field2.GetValue(__instance); MMButton val2 = (MMButton)((value2 is MMButton) ? value2 : null); bool flag = field3 != null && (bool)field3.GetValue(__instance); if (!((Object)val == (Object)null || (Object)val2 == (Object)null || flag)) { if (PlayerFarming.playersCount < 4) { ((TMP_Text)val).text = $"Add Player ({PlayerFarming.playersCount}/{4})"; val2.Interactable = true; } else { ((TMP_Text)val).text = $"Remove Player ({PlayerFarming.playersCount}/{4})"; val2.Interactable = true; } } } public static bool ConfirmSpawnButtonPress(UICoopAssignController __instance) { //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Expected O, but got Unknown //IL_0584: Unknown result type (might be due to invalid IL or missing references) //IL_058f: Expected O, but got Unknown //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown //IL_04ac: Unknown result type (might be due to invalid IL or missing references) //IL_04b6: Expected O, but got Unknown //IL_05e5: Unknown result type (might be due to invalid IL or missing references) //IL_05ef: Expected O, but got Unknown //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Expected O, but got Unknown //IL_04df: Unknown result type (might be due to invalid IL or missing references) //IL_04e9: Expected O, but got Unknown //IL_0501: Unknown result type (might be due to invalid IL or missing references) //IL_050b: Expected O, but got Unknown //IL_051a: Unknown result type (might be due to invalid IL or missing references) //IL_0525: Expected O, but got Unknown //IL_06ad: Unknown result type (might be due to invalid IL or missing references) //IL_06b7: Expected O, but got Unknown //IL_06d0: Unknown result type (might be due to invalid IL or missing references) //IL_06db: Expected O, but got Unknown //IL_0651: Unknown result type (might be due to invalid IL or missing references) //IL_065c: Expected O, but got Unknown //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Expected O, but got Unknown //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Expected O, but got Unknown //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Expected O, but got Unknown //IL_042b: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Expected O, but got Unknown FieldInfo field = typeof(UICoopAssignController).GetField("displayedConnectedGamepads", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field2 = typeof(UICoopAssignController).GetField("keyboardInputOption", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field3 = typeof(UICoopAssignController).GetField("preventSpawnBufferTime", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field4 = typeof(UICoopAssignController).GetField("confirmLock", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || field2 == null) { Plugin.Log.LogError((object)"Reflection failed"); return true; } if (field3 != null) { float num = (float)field3.GetValue(__instance); if (Time.realtimeSinceStartup < num + 0.25f) { return false; } } if (field4 != null) { if ((bool)field4.GetValue(__instance)) { return false; } field4.SetValue(__instance, true); } if (!(field.GetValue(__instance) is CoopAssignInputOption[] array)) { return true; } int num2 = PlayerFarming.playersCount; if (num2 < 1) { num2 = 1; } Plugin.Log.LogInfo((object)$"ConfirmSpawnButtonPress: nextSlot={num2}, players={PlayerFarming.playersCount}"); EnforceKeyboardOwnership(); List list = new List(ReInput.controllers.Joysticks); for (int i = 0; i < array.Length && i < list.Count; i++) { CoopAssignInputOption val = array[i]; if ((Object)val == (Object)null || !((Component)val).gameObject.activeSelf || val.selection != -1) { continue; } Joystick val2 = list[i]; if (val2 == null) { continue; } for (int j = 1; j < 4; j++) { if (!RewiredInputManager.GetPlayer(j).controllers.ContainsController((Controller)val2)) { continue; } PlayerFarming val3 = null; foreach (PlayerFarming player2 in PlayerFarming.players) { if (!player2.isLamb && player2.playerID == j && ((Component)player2).gameObject.activeSelf) { val3 = player2; break; } } if ((Object)val3 == (Object)null) { continue; } Plugin.Log.LogInfo((object)$"Joystick [{i}] moved to Lamb side — removing goat slot {j} (dropout)"); int playerID = val3.playerID; MarkDesiredExtraSlot(playerID, desired: false); _pendingSpawnSlots.Remove(playerID); _pendingSpawnUseAnimation.Remove(playerID); if (_cachedSprites.ContainsKey(playerID)) { _cachedSprites.Remove(playerID); } if (_cachedTextImages.ContainsKey(playerID)) { _cachedTextImages.Remove(playerID); } if (_cachedHaloSR.ContainsKey(playerID)) { _cachedHaloSR.Remove(playerID); } if (_cachedHaloSprites.ContainsKey(playerID)) { _cachedHaloSprites.Remove(playerID); } _haloLogged.Remove(playerID); _removingPlayer = true; CoopManager.AddtionalUser = null; UnhookVanillaCoopDelegates(); CoopManager.Instance.RemoveCoopPlayer(val3, true, false, true); if (_extraHeartBars.TryGetValue(playerID, out var value) && (Object)value != (Object)null) { Object.Destroy((Object)value); } _extraHeartBars.Remove(playerID); if (PlayerFarming.playersCount > 1 && (Object)HUD_Manager.Instance != (Object)null) { foreach (PlayerFarming player3 in PlayerFarming.players) { if (!player3.isLamb) { HUD_Manager.Instance.healthManager.Init(player3); } } } int num3 = 0; foreach (PlayerFarming player4 in PlayerFarming.players) { if (!player4.isLamb) { num3++; } } if (num3 <= 0) { UICoopAssignController.SetInputForSoloPlay(); UserHelper.DisengagePlayer(1); CoopManager.CoopActive = false; CoopManager.EnableCoopBlockers(false, true); DifficultyManager.LoadCurrentDifficulty(); } else { Player player = RewiredInputManager.GetPlayer(playerID); if (player != null) { foreach (Joystick item in new List(player.controllers.Joysticks)) { player.controllers.RemoveController((Controller)item); } } EnforceKeyboardOwnership(); CoopManager.RefreshCoopPlayerRewired(); } GameManager.GetInstance().WaitForSeconds(2f, (Action)delegate { _removingPlayer = false; Plugin.Log.LogInfo((object)"Dropout remove guard released"); }); break; } bool flag = false; for (int num4 = 1; num4 < 4; num4++) { if (RewiredInputManager.GetPlayer(num4).controllers.ContainsController((Controller)val2)) { flag = true; break; } } if (!flag) { for (int num5 = 1; num5 < 4; num5++) { RewiredInputManager.GetPlayer(num5).controllers.RemoveController((Controller)val2); } if (!RewiredInputManager.GetPlayer(0).controllers.ContainsController((Controller)val2)) { RewiredInputManager.GetPlayer(0).controllers.AddController((Controller)val2, true); } Plugin.Log.LogInfo((object)$"Joystick [{i}] assigned to Lamb (slot 0)"); } } num2 = PlayerFarming.playersCount; if (num2 < 1) { num2 = 1; } for (int num6 = 0; num6 < array.Length && num6 < list.Count; num6++) { if (num2 >= 4) { break; } CoopAssignInputOption val4 = array[num6]; if ((Object)val4 == (Object)null || !((Component)val4).gameObject.activeSelf || val4.selection != 1) { continue; } val4.inputLock = false; Joystick val5 = list[num6]; if (val5 == null) { continue; } bool flag2 = false; for (int num7 = 1; num7 < 4; num7++) { if (!RewiredInputManager.GetPlayer(num7).controllers.ContainsController((Controller)val5)) { continue; } PlayerFarming val6 = null; foreach (PlayerFarming player5 in PlayerFarming.players) { if (!player5.isLamb && player5.playerID == num7 && ((Component)player5).gameObject.activeSelf) { val6 = player5; break; } } if ((Object)val6 != (Object)null) { flag2 = true; Plugin.Log.LogInfo((object)$"Joystick [{num6}] already active goat slot {num7}, skipping"); break; } } if (!flag2) { for (int num8 = 0; num8 < 4; num8++) { RewiredInputManager.GetPlayer(num8).controllers.RemoveController((Controller)val5); } RewiredInputManager.GetPlayer(num2).controllers.AddController((Controller)val5, true); Plugin.Log.LogInfo((object)$"Joystick [{num6}] -> new goat slot {num2}"); MarkDesiredExtraSlot(num2, desired: true); if (num2 >= 2) { _pendingSpawnSlots.Add(num2); } CoopManager.Instance.SpawnCoopPlayer(num2, true, -1f); CoopManager.CoopActive = true; num2++; } } Plugin.Log.LogInfo((object)"Spawn complete"); ((UIMenuBase)__instance).Hide(false); return false; } public static void CoopAssign_OnShowStarted(UICoopAssignController __instance) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown if (!CoopManager.CoopActive) { return; } FieldInfo field = typeof(UICoopAssignController).GetField("displayedConnectedGamepads", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field2 = typeof(UICoopAssignController).GetField("keyboardInputOption", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || field2 == null) { return; } CoopAssignInputOption[] array = field.GetValue(__instance) as CoopAssignInputOption[]; object value = field2.GetValue(__instance); CoopAssignInputOption val = (CoopAssignInputOption)((value is CoopAssignInputOption) ? value : null); if (array == null) { return; } FieldInfo field3 = typeof(UICoopAssignController).GetField("keyboardInputOptionPreviousSelection", BindingFlags.Static | BindingFlags.NonPublic); if ((Object)val != (Object)null) { int num = ((!RewiredInputManager.GetPlayer(0).controllers.hasKeyboard) ? 1 : (-1)); field3?.SetValue(null, num); val.SetSelection(num, true); } List list = new List(ReInput.controllers.Joysticks); for (int i = 0; i < array.Length && i < list.Count; i++) { Joystick val2 = list[i]; int num2 = -1; for (int j = 0; j < 4; j++) { Player player = RewiredInputManager.GetPlayer(j); if (player != null && player.controllers.ContainsController((Controller)val2)) { num2 = j; break; } } int num3 = ((num2 != 0) ? 1 : (-1)); UICoopAssignController.displayedConnectedGamepadsPreviousSelection[i] = num3; array[i].SetSelection(num3, true); Plugin.Log.LogInfo((object)$"CoopAssign_OnShowStarted: joystick[{i}] ownerSlot={num2} → selection={num3}"); } } public static bool RemovePlayerFromMenu() { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Expected O, but got Unknown //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Expected O, but got Unknown //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Expected O, but got Unknown if (_removingPlayer) { Plugin.Log.LogInfo((object)"Remove guard active, skipping"); return false; } if (PlayerFarming.playersCount > 1 && CoopManager.CoopActive) { bool manualRemoveRequested = _manualRemoveRequested; _manualRemoveRequested = false; if (!manualRemoveRequested && Time.unscaledTime < _autoRemoveSuppressedUntil) { float num = Math.Max(0f, _autoRemoveSuppressedUntil - Time.unscaledTime); Plugin.Log.LogInfo((object)$"Auto remove suppressed ({num:0.00}s left)"); return false; } PlayerFarming val = null; for (int num2 = PlayerFarming.players.Count - 1; num2 >= 0; num2--) { PlayerFarming val2 = PlayerFarming.players[num2]; if (!((Object)val2 == (Object)null) && !val2.isLamb && !((Object)((Component)val2).gameObject == (Object)null) && ((Component)val2).gameObject.activeSelf) { if (manualRemoveRequested) { val = val2; break; } int playerID = val2.playerID; if (playerID > 0 && playerID < 4 && !SlotHasJoystick(playerID)) { val = val2; break; } } } if ((Object)val == (Object)null) { if (!manualRemoveRequested) { Plugin.Log.LogInfo((object)"Auto remove ignored: no goat slot lost joystick ownership"); } else { Plugin.Log.LogWarning((object)"No Goat found to remove"); } return false; } _removingPlayer = true; CoopManager.AddtionalUser = null; int playerID2 = val.playerID; MarkDesiredExtraSlot(playerID2, desired: false); _pendingSpawnSlots.Remove(playerID2); _pendingSpawnUseAnimation.Remove(playerID2); if (_cachedSprites.ContainsKey(playerID2)) { _cachedSprites.Remove(playerID2); } if (_cachedTextImages.ContainsKey(playerID2)) { _cachedTextImages.Remove(playerID2); } if (_cachedHaloSR.ContainsKey(playerID2)) { _cachedHaloSR.Remove(playerID2); } if (_cachedHaloSprites.ContainsKey(playerID2)) { _cachedHaloSprites.Remove(playerID2); } _haloLogged.Remove(playerID2); Plugin.Log.LogInfo((object)string.Format("Removing playerID {0} ({1})", playerID2, manualRemoveRequested ? "manual" : "auto-disconnect")); UnhookVanillaCoopDelegates(); CoopManager.Instance.RemoveCoopPlayer(val, true, false, true); if (_extraHeartBars.TryGetValue(playerID2, out var value) && (Object)value != (Object)null) { Object.Destroy((Object)value); } _extraHeartBars.Remove(playerID2); int num3 = 0; foreach (PlayerFarming player2 in PlayerFarming.players) { if (!player2.isLamb) { num3++; } } if (num3 <= 0) { _desiredExtraSlots.Clear(); UICoopAssignController.SetInputForSoloPlay(); UserHelper.DisengagePlayer(1); } else { Player player = RewiredInputManager.GetPlayer(playerID2); if (player != null) { foreach (Joystick item in new List(player.controllers.Joysticks)) { player.controllers.RemoveController((Controller)item); } } EnforceKeyboardOwnership(); CoopManager.RefreshCoopPlayerRewired(); } if (PlayerFarming.playersCount <= 1) { CoopManager.CoopActive = false; CoopManager.EnableCoopBlockers(false, true); DifficultyManager.LoadCurrentDifficulty(); } TryStopAllRumble($"RemovePlayerFromMenu(slot={playerID2})"); if (!manualRemoveRequested) { _autoRemoveSuppressedUntil = Time.unscaledTime + 8f; Plugin.Log.LogInfo((object)$"Auto remove cooldown armed for {8f:0.0}s"); } GameManager.GetInstance().WaitForSeconds(2f, (Action)delegate { _removingPlayer = false; Plugin.Log.LogInfo((object)"Remove guard released"); }); } return false; } public static void PlayerFarming_OnEnable_Prefix(PlayerFarming __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_001f: 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) //IL_003c: Expected O, but got Unknown //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) //IL_007f: Expected O, but got Unknown //IL_007f: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown if ((Object)__instance == (Object)null || __instance.isLamb || __instance.playerID <= 1 || !GameManager.IsDungeon(PlayerFarming.Location) || (Object)__instance.Spine == (Object)null) { return; } int num = __instance.playerID; if (num < 2 || num >= 4) { for (int i = 2; i < 4; i++) { if (CoopManager.AllPlayerGameObjects != null && i < CoopManager.AllPlayerGameObjects.Length && (Object)CoopManager.AllPlayerGameObjects[i] == (Object)((Component)__instance).gameObject) { num = i; break; } } } if (num < 2 || num >= 4) { return; } bool value = false; _pendingSpawnUseAnimation.TryGetValue(num, out value); if (value) { Plugin.Log.LogInfo((object)$"[MP] PlayerFarming_OnEnable_Prefix: keeping mesh visible for animated spawn slot {num}"); return; } MeshRenderer component = ((Component)__instance.Spine).GetComponent(); if ((Object)component != (Object)null) { ((Renderer)component).enabled = false; } Plugin.Log.LogInfo((object)$"[MP] PlayerFarming_OnEnable_Prefix: hid mesh for slot {num}"); } public static void SpawnCoopPlayer_Postfix(int slot) { if (slot < 2) { _pendingSpawnSlots.Remove(slot); _pendingSpawnUseAnimation.Remove(slot); } else { MarkDesiredExtraSlot(slot, desired: true); ((MonoBehaviour)CoopManager.Instance).StartCoroutine(ApplyVisualDelayed(slot)); } } private static IEnumerator RespawnExtraSlots(int count) { _startupExtraRespawnDepth++; try { bool inDungeon = GameManager.IsDungeon(PlayerFarming.Location); float timeout = 30f; float waited; for (waited = 0f; waited < timeout; waited += 0.25f) { if ((Object)PlayerFarming.Instance != (Object)null && ((Component)PlayerFarming.Instance).gameObject.activeSelf && PlayerFarming.playersCount >= 1 && (Object)PlayerFarming.Instance.state != (Object)null && (inDungeon || (int)PlayerFarming.Instance.state.CURRENT_STATE != 13)) { break; } yield return (object)new WaitForSeconds(0.25f); } if (waited >= timeout) { Plugin.Log.LogWarning((object)"RespawnExtraSlots: timed out waiting for PlayerFarming.Instance"); yield break; } if (inDungeon) { _dungeonIntroProtectUntil = Time.unscaledTime + 8f; } yield return (object)new WaitForSeconds(1f); for (int s = 2; s < 2 + count && s < 4; s++) { if (_pendingSpawnSlots.Contains(s)) { Plugin.Log.LogInfo((object)$"RespawnExtraSlots: slot {s} already pending, skipping duplicate startup spawn"); continue; } if ((Object)FindActivePlayerBySlot(s) != (Object)null) { Plugin.Log.LogInfo((object)$"RespawnExtraSlots: slot {s} already active, skipping startup spawn"); continue; } if (CoopManager.AllPlayerGameObjects != null && s < CoopManager.AllPlayerGameObjects.Length && (Object)CoopManager.AllPlayerGameObjects[s] != (Object)null && CoopManager.AllPlayerGameObjects[s].activeInHierarchy) { Plugin.Log.LogInfo((object)$"RespawnExtraSlots: slot {s} already has active gameobject, skipping startup spawn"); continue; } Player player = RewiredInputManager.GetPlayer(s); if (player == null || player.controllers == null || player.controllers.Joysticks == null || player.controllers.Joysticks.Count <= 0) { Plugin.Log.LogWarning((object)$"RespawnExtraSlots: slot {s} has no joystick, skipping"); continue; } Plugin.Log.LogInfo((object)$"RespawnExtraSlots: spawning slot {s}"); float spawnWait = 0f; while ((Object)CoopManager.Instance != (Object)null && CoopManager.Instance.IsSpawningOrRemovingPlayer && spawnWait < 10f) { yield return (object)new WaitForSeconds(0.1f); spawnWait += 0.1f; } if (_pendingSpawnSlots.Contains(s)) { Plugin.Log.LogInfo((object)$"RespawnExtraSlots: slot {s} became pending during wait, skipping duplicate startup spawn"); continue; } if ((Object)FindActivePlayerBySlot(s) != (Object)null) { Plugin.Log.LogInfo((object)$"RespawnExtraSlots: slot {s} became active during wait, skipping duplicate startup spawn"); continue; } _pendingSpawnSlots.Add(s); bool flag = false; _pendingSpawnUseAnimation[s] = flag; Plugin.Log.LogInfo((object)$"RespawnExtraSlots: slot {s} spawn mode animated={flag}"); try { CoopManager.Instance.SpawnCoopPlayer(s, flag, -1f); } catch (Exception ex) { _pendingSpawnSlots.Remove(s); _pendingSpawnUseAnimation.Remove(s); Plugin.Log.LogWarning((object)$"RespawnExtraSlots: failed spawning slot {s}: {ex.GetType().Name}: {ex.Message}"); } yield return (object)new WaitForSeconds(1f); } } finally { _startupExtraRespawnDepth = Math.Max(0, _startupExtraRespawnDepth - 1); } } public static void NewRun_Prefix() { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown _spawnedExtraWeaponPodiums = false; _spawnedExtraSpellPodiums = false; _podiumClones.Clear(); _podiumOwnerSlotByInstanceId.Clear(); int num = 0; foreach (PlayerFarming player in PlayerFarming.players) { if (!player.isLamb && player.playerID >= 2) { num++; } } if (num > 0) { _savedExtraSlotCount = num; Plugin.Log.LogInfo((object)$"NewRun_Prefix: saved {num} extra slot(s) for dungeon respawn"); } _cachedHaloSR.Clear(); _cachedHaloSprites.Clear(); _cachedTextImages.Clear(); _cachedSprites.Clear(); _haloLogged.Clear(); foreach (KeyValuePair extraHeartBar in _extraHeartBars) { if ((Object)extraHeartBar.Value != (Object)null) { Object.Destroy((Object)extraHeartBar.Value); } } _extraHeartBars.Clear(); _positioningDeferred = false; _podiumExtraCount = 0; _autoRespawnRoutineRunning = false; _nextAutoRespawnAttemptAt = 0f; _nextAutoRespawnHeartbeatAt = 0f; _pendingSpawnSlots.Clear(); _pendingSpawnUseAnimation.Clear(); _pendingSpawnFirstSeenAt.Clear(); _nextPendingBlockLogAt = 0f; _delayedRespawnAfterReviveQueued = false; _lastObservedWakeHealth = 2f; _lastObservedSacrificialWakeHealth = 2f; _sacrificialReviveWindowUntil = 0f; _nextExtraFalseDownedWatchdogAt.Clear(); _postReviveRaceGuardUntil.Clear(); _nextPostReviveForceApplyAt.Clear(); _nextPostReviveRaceGuardHeartbeatAt = 0f; _lastLoggedDungeonRoomPath = null; _p2EntranceGuardRunning = false; _dungeonRoomStabilizeRunning = false; _lastStabilizedDungeonRoomId = int.MinValue; _nextDungeonRoomStabilizeCheckAt = 0f; _roomEntryDistanceRepositionGraceUntil = 0f; Plugin.Log.LogInfo((object)"NewRun_Prefix: all visual caches cleared"); } public static void CoopManager_Start_Postfix() { CoopManager_Start_Postfix_Inner(); } public static void CoopManager_Start_Postfix_Inner() { //IL_0033: 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_004f: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) RefreshDesiredExtraSlotsFromActivePlayers(); _spawnedExtraWeaponPodiums = false; _spawnedExtraSpellPodiums = false; _delayedRespawnAfterReviveQueued = false; _nextAutoRespawnHeartbeatAt = 0f; _nextDungeonRoomStabilizeCheckAt = 0f; if (!CoopManager.CoopActive) { return; } if (GameManager.IsDungeon(PlayerFarming.Location) && (Object)CoopManager.Instance != (Object)null && !_p2EntranceGuardRunning) { ((MonoBehaviour)CoopManager.Instance).StartCoroutine(EnsureP2DungeonEntranceNotStuckRoutine()); } int savedExtraSlotCount = _savedExtraSlotCount; if (savedExtraSlotCount > 0) { if (GameManager.IsDungeon(PlayerFarming.Location)) { _dungeonIntroProtectUntil = Time.unscaledTime + 8f; } _podiumExtraCount = savedExtraSlotCount; _savedExtraSlotCount = 0; Plugin.Log.LogInfo((object)$"CoopManager_Start_Postfix: scheduling respawn of {savedExtraSlotCount} extra slot(s)"); ((MonoBehaviour)CoopManager.Instance).StartCoroutine(RespawnExtraSlots(savedExtraSlotCount)); _nextAutoRespawnAttemptAt = Time.unscaledTime + 5f; } else { TryAutoRespawnMissingExtraSlots("CoopManager.Start"); } } private static IEnumerator ApplyVisualDelayed(int slot) { if (slot < 2) { _pendingSpawnSlots.Remove(slot); _pendingSpawnUseAnimation.Remove(slot); yield break; } PlayerFarming player = null; float waited = 0f; while ((Object)player == (Object)null && waited < 10f) { foreach (PlayerFarming player2 in PlayerFarming.players) { if ((Object)player2 != (Object)null && player2.playerID == slot) { player = player2; break; } } if ((Object)player == (Object)null) { yield return (object)new WaitForSeconds(0.2f); waited += 0.2f; } } if ((Object)player == (Object)null) { Plugin.Log.LogWarning((object)$"ApplyVisualDelayed: gave up waiting for playerID={slot}"); _pendingSpawnSlots.Remove(slot); _pendingSpawnUseAnimation.Remove(slot); yield break; } bool useAnimatedSpawn = false; _pendingSpawnUseAnimation.TryGetValue(slot, out useAnimatedSpawn); bool inDungeon = GameManager.IsDungeon(PlayerFarming.Location); MeshRenderer meshR = null; if (slot >= 2 && (Object)player.Spine != (Object)null) { meshR = ((Component)player.Spine).GetComponent(); if (!useAnimatedSpawn && (Object)meshR != (Object)null && ((Renderer)meshR).enabled) { ((Renderer)meshR).enabled = false; } } if (slot >= 2 && (Object)PlayerFarming.Instance != (Object)null && slot < SpawnOffsets.Length && (!useAnimatedSpawn || !inDungeon)) { ((Component)player).transform.position = ((Component)PlayerFarming.Instance).transform.position + SpawnOffsets[slot]; } if (slot >= 2 && inDungeon) { float waitLimit = 8f; for (float w = 0f; w < waitLimit; w += 0.1f) { if (!((Object)player.state != (Object)null)) { break; } if (!player.state.LockStateChanges && (int)player.state.CURRENT_STATE != 13 && (int)player.state.CURRENT_STATE != 49) { break; } yield return (object)new WaitForSeconds(0.1f); } yield return null; if ((!useAnimatedSpawn || !inDungeon) && (Object)PlayerFarming.Instance != (Object)null && slot < SpawnOffsets.Length) { ((Component)player).transform.position = ((Component)PlayerFarming.Instance).transform.position + SpawnOffsets[slot]; } } else { for (float waitLimit = 0f; waitLimit < 2f; waitLimit += 0.1f) { if (!((Object)PlayerFarming.Instance == (Object)null) && !((Object)PlayerFarming.Instance.state == (Object)null) && (int)PlayerFarming.Instance.state.CURRENT_STATE != 13) { break; } yield return (object)new WaitForSeconds(0.1f); } yield return null; if (slot < SpawnOffsets.Length && (Object)PlayerFarming.Instance != (Object)null) { ((Component)player).transform.position = ((Component)PlayerFarming.Instance).transform.position + SpawnOffsets[slot]; } } if (slot >= 2 && (Object)meshR != (Object)null && !((Renderer)meshR).enabled) { ((Renderer)meshR).enabled = true; } if (slot < Plugin.GoatColors.Length && (Object)player.Spine != (Object)null && ((SkeletonRenderer)player.Spine).skeleton != null) { ((SkeletonRenderer)player.Spine).skeleton.R = Plugin.GoatColors[slot].r; ((SkeletonRenderer)player.Spine).skeleton.G = Plugin.GoatColors[slot].g; ((SkeletonRenderer)player.Spine).skeleton.B = Plugin.GoatColors[slot].b; ((SkeletonRenderer)player.Spine).skeleton.A = Plugin.GoatColors[slot].a; } if ((Object)GameManager.GetInstance() != (Object)null) { GameManager.GetInstance().AddToCamera(player.CameraBone, 0.1f); } EnsurePlayerAwakeAfterRespawn(player, $"ApplyVisualDelayed(slot={slot})"); if (slot >= 2) { EnsureExtraSpawnStateUnlocked(player, $"ApplyVisualDelayed(slot={slot})"); } if (_podiumClones.TryGetValue(slot, out var value)) { foreach (Interaction_WeaponSelectionPodium item in value) { if ((Object)item != (Object)null) { EnsurePodiumCloneOwner(item, slot, player, forceInteractable: true); Plugin.Log.LogInfo((object)$"[MP] Refreshed podium clone state for slot {slot} on {((Object)item).name}"); } } } HUD_Hearts val = player.hudHearts; if ((Object)val != (Object)null && (Object)val.playerFarming != (Object)player) { Plugin.Log.LogWarning((object)$"[MP] ApplyVisualDelayed: stale hudHearts owner for slot {slot}, skipping direct faithAmmo init"); val = null; } if ((Object)val == (Object)null && _extraHeartBars.TryGetValue(slot, out var value2) && (Object)value2 != (Object)null) { HUD_Hearts component = value2.GetComponent(); if ((Object)component != (Object)null && (Object)component.playerFarming == (Object)player) { val = component; player.hudHearts = component; } } if (slot >= 2 && (Object)val != (Object)null) { SyncFaithAmmoForOwner(player, val, $"ApplyVisualDelayed(slot={slot})", forceReinit: true); } _pendingSpawnSlots.Remove(slot); _pendingSpawnUseAnimation.Remove(slot); Plugin.Log.LogInfo((object)$"ApplyVisualDelayed done for slot {slot}"); } private static bool IsDungeonContextLikely() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (GameManager.IsDungeon(PlayerFarming.Location)) { return true; } try { Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (!string.IsNullOrEmpty(name) && name.IndexOf("Dungeon", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } catch { } return false; } private unsafe static bool IsReviveDesyncState(State st) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Invalid comparison between Unknown and I4 //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Invalid comparison between Unknown and I4 if ((int)st != 13 && (int)st != 49 && (int)st != 24 && (int)st != 16 && !string.Equals(((object)(*(State*)(&st))/*cast due to .constrained prefix*/).ToString(), "CoopReviving", StringComparison.Ordinal) && (int)st != 63 && (int)st != 35 && (int)st != 56 && (int)st != 41 && (int)st != 42 && (int)st != 32 && (int)st != 33 && (int)st != 52) { return (int)st == 62; } return true; } private unsafe static bool IsHardDownedOrReviveState(State st) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 if ((int)st != 63 && !string.Equals(((object)(*(State*)(&st))/*cast due to .constrained prefix*/).ToString(), "CoopReviving", StringComparison.Ordinal) && (int)st != 35 && (int)st != 56 && (int)st != 32 && (int)st != 33 && (int)st != 52) { return (int)st == 62; } return true; } private static bool IsFalseDownedVisualStateForExtra(PlayerFarming player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if ((Object)player == (Object)null || player.isLamb || player.playerID < 2) { return false; } try { if ((Object)player.health == (Object)null || ((Health)player.health).CurrentHP <= 0f) { return false; } } catch { return false; } try { if (Health.team2 != null && Health.team2.Count > 0) { return false; } } catch { } if (IsLikelyLegitDownedState(player)) { return false; } bool flag = false; try { flag = player.IsKnockedOut; } catch { } if (!flag) { try { flag = (Object)player.state != (Object)null && (int)player.state.CURRENT_STATE == 63; } catch { } } return flag; } private static bool IsLikelyLegitDownedState(PlayerFarming player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown if ((Object)player == (Object)null) { return false; } bool flag = false; try { Interaction_CoopRevive component = ((Component)player).GetComponent(); flag = (Object)component != (Object)null && ((Behaviour)component).enabled; } catch { } bool flag2 = false; State val = (State)0; try { if ((Object)player.state != (Object)null) { val = player.state.CURRENT_STATE; flag2 = true; } } catch { } if (flag2 && IsHardDownedOrReviveState(val)) { return true; } bool flag3 = false; try { flag3 = player.IsKnockedOut; } catch { } if (!flag3) { return false; } if (flag) { return true; } if (flag2 && (int)val == 49) { return true; } try { if ((Object)player.health != (Object)null && ((Health)player.health).CurrentHP <= 0f) { return true; } } catch { } return false; } private static bool ShouldForceIdleForSpawnUnlock(State st) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return IsHardDownedOrReviveState(st); } private static bool IsLikelyReviveDesyncState(PlayerFarming player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) if ((Object)player == (Object)null || (Object)player.health == (Object)null || ((Health)player.health).CurrentHP <= 0f) { return false; } if (player.IsKnockedOut) { return true; } try { if ((Object)player.state != (Object)null && IsReviveDesyncState(player.state.CURRENT_STATE)) { return true; } } catch { } return false; } private static bool NeedsWakeRecovery(PlayerFarming player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) if ((Object)player == (Object)null || (Object)player.health == (Object)null) { return false; } bool flag = ((Health)player.health).CurrentHP <= 0f; bool isKnockedOut = player.IsKnockedOut; bool flag2 = false; bool flag3 = false; try { Interaction_CoopRevive component = ((Component)player).GetComponent(); flag2 = (Object)component != (Object)null && ((Behaviour)component).enabled; } catch { } try { if ((Object)player.state != (Object)null) { flag3 = IsHardDownedOrReviveState(player.state.CURRENT_STATE); } } catch { } return flag || isKnockedOut || flag2 || flag3; } private static bool AnyNonLambPlayerNeedsWakeRecovery() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown if (PlayerFarming.players == null) { return false; } foreach (PlayerFarming player in PlayerFarming.players) { if (!((Object)player == (Object)null) && !player.isLamb && !((Object)((Component)player).gameObject == (Object)null) && ((Component)player).gameObject.activeInHierarchy && NeedsWakeRecovery(player)) { return true; } } return false; } private static float GetReviveWakeHealth(PlayerFarming player, string reason) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown bool flag = IsWakeAllRespawnReason(reason); bool num = IsSacrificialReviveFlowReason(reason); float num2 = _lastObservedWakeHealth; if (num) { float lastObservedSacrificialWakeHealth = _lastObservedSacrificialWakeHealth; if (!float.IsNaN(lastObservedSacrificialWakeHealth) && lastObservedSacrificialWakeHealth > 0f) { num2 = lastObservedSacrificialWakeHealth; } } if (float.IsNaN(num2) || num2 <= 0f) { num2 = 1f; } if (!num) { if (flag) { return 1f; } return Mathf.Clamp(num2, 1f, 2f); } if ((Object)player == (Object)null || player.isLamb || player.playerID < 2) { return Mathf.Max(2f, num2); } float num3 = Mathf.Max(2f, num2); try { PlayerFarming val = FindActivePlayerBySlot(1); if ((Object)val != (Object)null && (Object)val.health != (Object)null) { float currentHP = ((Health)val.health).CurrentHP; if (currentHP > num3) { num3 = currentHP; } } } catch { } return Mathf.Max(2f, num3); } private static void EnsurePlayerAwakeAfterRespawn(PlayerFarming player, string reason) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown if ((Object)player == (Object)null) { return; } bool flag = IsSacrificialReviveFlowReason(reason); bool flag2 = NeedsWakeRecovery(player); if (!flag2 && !flag) { return; } float reviveWakeHealth = GetReviveWakeHealth(player, reason); if (flag2) { try { CoopManager.WakeKnockedOutPlayer(player, reviveWakeHealth, (PlayerFarming)null, (HeartPickupType)0, false); } catch { } } try { if ((Object)player.health != (Object)null) { if (flag) { TryRaiseHealthCapacity(player.health, reviveWakeHealth); } if (((Health)player.health).CurrentHP < reviveWakeHealth) { ((Health)player.health).HP = reviveWakeHealth; } if (flag && player.playerID >= 2 && ((Health)player.health).CurrentHP + 0.01f < reviveWakeHealth) { Plugin.Log.LogWarning((object)$"[MP] Sacrificial wake health clamp suspected for playerID={player.playerID}: hp={((Health)player.health).CurrentHP:0.00}, target={reviveWakeHealth:0.00} ({reason})"); } } } catch { } player.IsKnockedOut = false; EnsureExtraSpawnStateUnlocked(player, reason); QueuePostReviveHardReset(player, reason); Plugin.Log.LogInfo((object)$"[MP] Cleared downed state for playerID={player.playerID} ({reason})"); } private static void QueuePostReviveHardReset(PlayerFarming player, string reason) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown if (!((Object)player == (Object)null) && !player.isLamb && player.playerID >= 1 && player.playerID < 4 && !((Object)CoopManager.Instance == (Object)null)) { int playerID = player.playerID; ArmPostReviveRaceGuard(playerID); if (!_postReviveHardResetSlots.Contains(playerID)) { _postReviveHardResetSlots.Add(playerID); Plugin.Log.LogInfo((object)$"[MP] Queued post-revive hard reset for playerID={playerID} ({reason})"); ((MonoBehaviour)CoopManager.Instance).StartCoroutine(PostReviveHardResetRoutine(playerID, reason)); } } } private static void QueuePostReviveHardResetForAll(string reason) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if (PlayerFarming.players == null) { return; } foreach (PlayerFarming player in PlayerFarming.players) { if (!((Object)player == (Object)null) && !player.isLamb && !((Object)((Component)player).gameObject == (Object)null) && ((Component)player).gameObject.activeInHierarchy) { QueuePostReviveHardReset(player, reason); } } } private static void ArmPostReviveRaceGuard(int slot) { if (slot >= 1 && slot < 4) { float num = Time.unscaledTime + 4f; if (!_postReviveRaceGuardUntil.TryGetValue(slot, out var value) || !(value > num)) { _postReviveRaceGuardUntil[slot] = Mathf.Max(value, num); } } } private static bool IsLikelyStaleDownedPresentation(PlayerFarming player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0075: 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) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Invalid comparison between Unknown and I4 if ((Object)player == (Object)null) { return false; } try { if ((Object)player.health == (Object)null || ((Health)player.health).CurrentHP <= 0f) { return false; } } catch { return false; } if (IsLikelyLegitDownedState(player)) { return false; } if (IsFalseKnockedOutState(player)) { return true; } try { if ((Object)player.state != (Object)null) { State cURRENT_STATE = player.state.CURRENT_STATE; if (IsHardDownedOrReviveState(cURRENT_STATE)) { return true; } if (((int)cURRENT_STATE == 49 || (int)cURRENT_STATE == 16) && !MMConversation.isPlaying && !LetterBox.IsPlaying) { return true; } } } catch { } try { Interaction_CoopRevive component = ((Component)player).GetComponent(); if ((Object)component != (Object)null && ((Behaviour)component).enabled) { return true; } } catch { } return false; } private static void ProcessPostReviveRaceGuards(string reason) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Expected O, but got Unknown //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Invalid comparison between Unknown and I4 //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Invalid comparison between Unknown and I4 //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown if ((Object)CoopManager.Instance == (Object)null || !CoopManager.CoopActive || _postReviveRaceGuardUntil.Count == 0) { return; } float unscaledTime = Time.unscaledTime; for (int i = 1; i < 4; i++) { if (!_postReviveRaceGuardUntil.TryGetValue(i, out var value)) { continue; } if (unscaledTime > value) { _postReviveRaceGuardUntil.Remove(i); _nextPostReviveForceApplyAt.Remove(i); } else if (!GameManager.IsDungeon(PlayerFarming.Location)) { _postReviveRaceGuardUntil.Remove(i); _nextPostReviveForceApplyAt.Remove(i); } else if (MMConversation.isPlaying || LetterBox.IsPlaying) { _nextExtraFalseDownedWatchdogAt[i] = unscaledTime + 0.35f; } else { if ((_nextExtraFalseDownedWatchdogAt.TryGetValue(i, out var value2) && unscaledTime < value2) || (_nextPostReviveForceApplyAt.TryGetValue(i, out var value3) && unscaledTime < value3)) { continue; } PlayerFarming val = FindActivePlayerBySlot(i); if ((Object)val == (Object)null || (Object)((Component)val).gameObject == (Object)null || !((Component)val).gameObject.activeInHierarchy) { continue; } if (!IsLikelyStaleDownedPresentation(val)) { _nextExtraFalseDownedWatchdogAt[i] = unscaledTime + 0.2f; _nextPostReviveForceApplyAt.Remove(i); continue; } string text = $"RaceGuard:{reason}(slot={i})"; bool flag = false; bool flag2 = false; bool flag3 = false; bool flag4 = false; bool flag5 = false; try { flag5 = IsFalseKnockedOutState(val); } catch { } try { flag3 = val.IsKnockedOut; } catch { } try { if ((Object)val.state != (Object)null) { State cURRENT_STATE = val.state.CURRENT_STATE; flag = IsHardDownedOrReviveState(cURRENT_STATE); flag2 = (int)cURRENT_STATE == 49 || (int)cURRENT_STATE == 16; } } catch { } try { Interaction_CoopRevive component = ((Component)val).GetComponent(); flag4 = (Object)component != (Object)null && ((Behaviour)component).enabled; } catch { } bool flag6 = flag5 || flag3 || flag || flag2 || flag4; ForceReviveVisualState(val, text + (flag6 ? ".hard" : ".soft")); if (flag6) { SnapSpawnedPlayerToAwakeIdle(val, text); QueuePostReviveHardReset(val, text); _postReviveRaceGuardUntil[i] = Mathf.Max(value, unscaledTime + 1.25f); _nextExtraFalseDownedWatchdogAt[i] = unscaledTime + 0.9f; _nextPostReviveForceApplyAt[i] = unscaledTime + 1.1f; } else { _nextExtraFalseDownedWatchdogAt[i] = unscaledTime + 0.35f; _nextPostReviveForceApplyAt[i] = unscaledTime + 0.5f; } float num = 0f; try { if ((Object)val.health != (Object)null) { num = ((Health)val.health).CurrentHP; } } catch { } Plugin.Log.LogWarning((object)$"[MP] Post-revive race guard corrected stale downed presentation for playerID={i} ({reason}, hp={num:0.00}, hardReset={flag6})"); } } } private static FieldInfo FindBoolFieldOnTypeChain(Type t, params string[] names) { while (t != null) { foreach (string name in names) { FieldInfo field = t.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); if (field != null && field.FieldType == typeof(bool)) { return field; } } t = t.BaseType; } return null; } private static PropertyInfo FindBoolPropertyOnTypeChain(Type t, params string[] names) { while (t != null) { foreach (string name in names) { PropertyInfo property = t.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); if (property != null && property.PropertyType == typeof(bool)) { return property; } } t = t.BaseType; } return null; } private static bool IsNumericType(Type t) { if (!(t == typeof(float)) && !(t == typeof(int))) { return t == typeof(double); } return true; } private static FieldInfo FindNumericFieldOnTypeChain(Type t, params string[] names) { while (t != null) { foreach (string name in names) { FieldInfo field = t.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); if (field != null && IsNumericType(field.FieldType)) { return field; } } t = t.BaseType; } return null; } private static PropertyInfo FindNumericPropertyOnTypeChain(Type t, params string[] names) { while (t != null) { foreach (string name in names) { PropertyInfo property = t.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); if (property != null && property.CanWrite && IsNumericType(property.PropertyType)) { return property; } } t = t.BaseType; } return null; } private static void EnsureHealthReflection(object health) { if (health != null) { Type type = health.GetType(); if (!(type == _cachedHealthReflectionType)) { _cachedHealthReflectionType = type; _healthInvincibleField = FindBoolFieldOnTypeChain(type, "invincible"); _healthUntouchableField = FindBoolFieldOnTypeChain(type, "untouchable"); _healthIgnoreProjectilesField = FindBoolFieldOnTypeChain(type, "IgnoreProjectiles", "ignoreProjectiles"); _healthMaxHpField = FindNumericFieldOnTypeChain(type, "MaxHP", "maxHP", "MaxHealth", "maxHealth"); _healthTotalHpField = FindNumericFieldOnTypeChain(type, "TotalHP", "totalHP", "TotalHealth", "totalHealth"); _healthIgnoreProjectilesProperty = FindBoolPropertyOnTypeChain(type, "IgnoreProjectiles", "ignoreProjectiles"); _healthMaxHpProperty = FindNumericPropertyOnTypeChain(type, "MaxHP", "maxHP", "MaxHealth", "maxHealth"); _healthTotalHpProperty = FindNumericPropertyOnTypeChain(type, "TotalHP", "totalHP", "TotalHealth", "totalHealth"); _healthClearAllStasisEffectsMethod = AccessTools.Method(type, "ClearAllStasisEffects", (Type[])null, (Type[])null); } } } private static void TryRaiseNumericField(FieldInfo fi, object instance, float target) { try { if (fi == null || instance == null) { return; } object value = fi.GetValue(instance); if (!(((value == null) ? 0f : Convert.ToSingle(value)) >= target)) { if (fi.FieldType == typeof(float)) { fi.SetValue(instance, target); } else if (fi.FieldType == typeof(int)) { fi.SetValue(instance, Mathf.CeilToInt(target)); } else if (fi.FieldType == typeof(double)) { fi.SetValue(instance, (double)target); } } } catch { } } private static void TryRaiseNumericProperty(PropertyInfo pi, object instance, float target) { try { if (pi == null || instance == null || !pi.CanWrite) { return; } object obj = null; try { obj = pi.GetValue(instance, null); } catch { } if (!(((obj == null) ? 0f : Convert.ToSingle(obj)) >= target)) { if (pi.PropertyType == typeof(float)) { pi.SetValue(instance, target, null); } else if (pi.PropertyType == typeof(int)) { pi.SetValue(instance, Mathf.CeilToInt(target), null); } else if (pi.PropertyType == typeof(double)) { pi.SetValue(instance, (double)target, null); } } } catch { } } private static void TryRaiseHealthCapacity(object health, float targetHp) { if (health != null && !(targetHp <= 0f)) { EnsureHealthReflection(health); TryRaiseNumericField(_healthMaxHpField, health, targetHp); TryRaiseNumericField(_healthTotalHpField, health, targetHp); TryRaiseNumericProperty(_healthMaxHpProperty, health, targetHp); TryRaiseNumericProperty(_healthTotalHpProperty, health, targetHp); } } private static void TrySetFloatField(FieldInfo fi, object instance, float value) { try { if (fi != null && instance != null && fi.FieldType == typeof(float)) { fi.SetValue(instance, value); } } catch { } } private static void TrySetIntField(FieldInfo fi, object instance, int value) { try { if (fi != null && instance != null && fi.FieldType == typeof(int)) { fi.SetValue(instance, value); } } catch { } } private static void TrySetBoolField(FieldInfo fi, object instance, bool value) { try { if (fi != null && instance != null && fi.FieldType == typeof(bool)) { fi.SetValue(instance, value); } } catch { } } private static void TrySetBoolProperty(PropertyInfo pi, object instance, bool value) { try { if (pi != null && instance != null && pi.CanWrite && pi.PropertyType == typeof(bool)) { pi.SetValue(instance, value, null); } } catch { } } private static void ForceReviveVisualState(PlayerFarming player, string reason) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Expected O, but got Unknown //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Expected O, but got Unknown //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Invalid comparison between Unknown and I4 //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Invalid comparison between Unknown and I4 //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) if ((Object)player == (Object)null) { return; } bool flag = !string.IsNullOrEmpty(reason) && reason.IndexOf("PostRevive:", StringComparison.Ordinal) >= 0; bool flag2 = false; bool flag3 = false; bool flag4 = false; try { if ((Object)player.state != (Object)null) { flag2 = ShouldForceIdleForSpawnUnlock(player.state.CURRENT_STATE); } } catch { } try { flag3 = player.IsKnockedOut; } catch { } try { if ((Object)player.health != (Object)null) { EnsureHealthReflection(player.health); float reviveWakeHealth = GetReviveWakeHealth(player, reason); if (IsSacrificialReviveFlowReason(reason)) { TryRaiseHealthCapacity(player.health, reviveWakeHealth); } if (((Health)player.health).CurrentHP < reviveWakeHealth) { ((Health)player.health).HP = reviveWakeHealth; } ((Behaviour)player.health).enabled = true; TrySetBoolField(_healthInvincibleField, player.health, value: false); TrySetBoolField(_healthUntouchableField, player.health, value: false); TrySetBoolField(_healthIgnoreProjectilesField, player.health, value: false); TrySetBoolProperty(_healthIgnoreProjectilesProperty, player.health, value: false); if (_healthClearAllStasisEffectsMethod != null) { try { _healthClearAllStasisEffectsMethod.Invoke(player.health, null); } catch { } } } } catch { } try { player.IsKnockedOut = false; } catch { } try { Interaction_CoopRevive component = ((Component)player).GetComponent(); flag4 = (Object)component != (Object)null && ((Behaviour)component).enabled; if (flag4) { ((Behaviour)component).enabled = false; } } catch { } try { if ((Object)player.playerController != (Object)null) { TrySetFloatField(_playerControllerInvincibleTimerField, player.playerController, 0f); TrySetFloatField(_playerControllerUntouchableTimerField, player.playerController, 0f); TrySetFloatField(_playerControllerImmuneToProjectilesTimerField, player.playerController, 0f); TrySetIntField(_playerControllerUntouchableTimerFlashField, player.playerController, 0); if (flag2 || flag3 || flag4 || flag) { player.playerController.ResetSpecificMovementAnimations(); } } } catch { } try { if ((Object)player.state != (Object)null) { player.state.LockStateChanges = false; State cURRENT_STATE = player.state.CURRENT_STATE; bool flag5 = (int)cURRENT_STATE == 49 || (int)cURRENT_STATE == 16; if (flag2 || (flag && flag5)) { player.state.CURRENT_STATE = (State)0; } } } catch { } bool flag6 = true; if (!string.IsNullOrEmpty(reason) && reason.IndexOf(".soft", StringComparison.Ordinal) >= 0 && reason.IndexOf("PostRevive:", StringComparison.Ordinal) < 0 && reason.IndexOf("Watchdog", StringComparison.Ordinal) < 0 && reason.IndexOf("WakeKnockedOutPlayer", StringComparison.Ordinal) < 0) { flag6 = false; } if (flag6) { try { player.SetSkin(false); } catch { try { player.SetSkin(); } catch { } } } try { if ((Object)player.Spine != (Object)null) { player.Spine.timeScale = 1f; player.Spine.UseDeltaTime = true; MeshRenderer component2 = ((Component)player.Spine).GetComponent(); if ((Object)component2 != (Object)null && !((Renderer)component2).enabled) { ((Renderer)component2).enabled = true; } if (((SkeletonRenderer)player.Spine).skeleton != null && player.Spine.AnimationState != null) { player.Spine.AnimationState.Apply(((SkeletonRenderer)player.Spine).skeleton, true); } } } catch { } EnsureExtraSpawnStateUnlocked(player, reason); } private static void SnapSpawnedPlayerToAwakeIdle(PlayerFarming player, string reason) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown if ((Object)player == (Object)null || (Object)player.state == (Object)null) { return; } try { player.IsKnockedOut = false; } catch { } try { player.state.LockStateChanges = false; player.state.CURRENT_STATE = (State)0; } catch { } try { if ((Object)player.playerController != (Object)null) { player.playerController.ResetSpecificMovementAnimations(); } } catch { } try { if ((Object)player.Spine != (Object)null) { player.Spine.timeScale = 1f; player.Spine.UseDeltaTime = true; if (player.Spine.AnimationState != null && ((SkeletonRenderer)player.Spine).skeleton != null) { player.Spine.AnimationState.Apply(((SkeletonRenderer)player.Spine).skeleton, true); } } } catch { } Plugin.Log.LogInfo((object)$"[MP] Spawn visual snap to Idle for playerID={player.playerID} ({reason})"); } private static IEnumerator PostReviveHardResetRoutine(int slot, string reason) { try { int settledTicks = 0; for (int i = 0; i < 18; i++) { if ((Object)CoopManager.Instance == (Object)null) { break; } if (!CoopManager.CoopActive) { break; } PlayerFarming val = FindActivePlayerBySlot(slot); if ((Object)val == (Object)null) { yield return (object)new WaitForSeconds(0.1f); continue; } bool num = NeedsWakeRecovery(val) || IsFalseKnockedOutState(val); bool flag = !num && i < 6; if (num || i < 2 || flag) { ForceReviveVisualState(val, $"PostRevive:{reason}.tick{i}"); } if (!num) { settledTicks++; if (settledTicks >= 6 && i >= 8) { break; } } else { settledTicks = 0; } yield return (object)new WaitForSeconds((i < 6) ? 0.12f : 0.18f); } } finally { _postReviveHardResetSlots.Remove(slot); } } private static void EnsureExtraSpawnStateUnlocked(PlayerFarming player, string reason) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_004c: 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_0030: Expected O, but got Unknown if ((Object)player == (Object)null || player.isLamb || player.playerID < 1 || (Object)player.state == (Object)null) { return; } try { player.state.LockStateChanges = false; } catch { } try { if (ShouldForceIdleForSpawnUnlock(player.state.CURRENT_STATE)) { player.state.CURRENT_STATE = (State)0; Plugin.Log.LogInfo((object)$"[MP] Restored spawn state to Idle for playerID={player.playerID} ({reason})"); } } catch { } } private static void EnsureAllExtraPlayersUnlocked(string reason) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown if (PlayerFarming.players == null) { return; } foreach (PlayerFarming player in PlayerFarming.players) { if (!((Object)player == (Object)null) && !((Object)((Component)player).gameObject == (Object)null) && ((Component)player).gameObject.activeInHierarchy) { EnsureExtraSpawnStateUnlocked(player, reason); } } } private static bool IsFalseKnockedOutState(PlayerFarming player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Invalid comparison between Unknown and I4 if ((Object)player == (Object)null) { return false; } try { if ((Object)player.health == (Object)null || ((Health)player.health).CurrentHP <= 0f) { return false; } if (IsLikelyLegitDownedState(player)) { return false; } if (player.IsKnockedOut) { return true; } if ((Object)player.state != (Object)null && (int)player.state.CURRENT_STATE == 63) { return true; } return false; } catch { return false; } } private static void ClearFalseKnockedOutState(PlayerFarming player, string reason) { if (IsFalseKnockedOutState(player)) { player.IsKnockedOut = false; EnsureExtraSpawnStateUnlocked(player, reason); QueuePostReviveHardReset(player, reason); Plugin.Log.LogInfo((object)$"[MP] Cleared false downed flag for playerID={player.playerID} ({reason})"); } } private static void ClearFalseKnockedOutStatesForAll(string reason) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown if (PlayerFarming.players == null) { return; } foreach (PlayerFarming player in PlayerFarming.players) { if (!((Object)player == (Object)null) && !((Object)((Component)player).gameObject == (Object)null) && ((Component)player).gameObject.activeInHierarchy) { ClearFalseKnockedOutState(player, reason); } } } public static void SetSkin_Recolor(PlayerFarming __instance) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown if (__instance.isLamb) { return; } int playerID = __instance.playerID; if (playerID > 0) { if (playerID < Plugin.GoatColors.Length && (Object)__instance.Spine != (Object)null && ((SkeletonRenderer)__instance.Spine).skeleton != null) { ((SkeletonRenderer)__instance.Spine).skeleton.R = Plugin.GoatColors[playerID].r; ((SkeletonRenderer)__instance.Spine).skeleton.G = Plugin.GoatColors[playerID].g; ((SkeletonRenderer)__instance.Spine).skeleton.B = Plugin.GoatColors[playerID].b; ((SkeletonRenderer)__instance.Spine).skeleton.A = Plugin.GoatColors[playerID].a; } ApplyIndicator(__instance, playerID); } } private static void ApplyIndicator(PlayerFarming player, int slot) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_0037: Expected O, but got Unknown //IL_05fb: Unknown result type (might be due to invalid IL or missing references) //IL_0606: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_004f: Expected O, but got Unknown //IL_06af: Unknown result type (might be due to invalid IL or missing references) //IL_06be: Unknown result type (might be due to invalid IL or missing references) //IL_060d: Unknown result type (might be due to invalid IL or missing references) //IL_0618: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_06e0: Unknown result type (might be due to invalid IL or missing references) //IL_06e7: Unknown result type (might be due to invalid IL or missing references) //IL_06f1: Expected O, but got Unknown //IL_06f1: Expected O, but got Unknown //IL_0622: Unknown result type (might be due to invalid IL or missing references) //IL_0627: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_06fe: Unknown result type (might be due to invalid IL or missing references) //IL_0639: Unknown result type (might be due to invalid IL or missing references) //IL_0644: Expected O, but got Unknown //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_064e: Unknown result type (might be due to invalid IL or missing references) //IL_0653: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Expected O, but got Unknown //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Expected O, but got Unknown //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Expected O, but got Unknown //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_043a: 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_046a: Expected O, but got Unknown //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Expected O, but got Unknown //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_04ff: Expected O, but got Unknown //IL_04b5: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Expected O, but got Unknown //IL_052e: Unknown result type (might be due to invalid IL or missing references) //IL_0539: Expected O, but got Unknown //IL_0513: Unknown result type (might be due to invalid IL or missing references) //IL_051e: Expected O, but got Unknown //IL_0593: Unknown result type (might be due to invalid IL or missing references) //IL_059e: Expected O, but got Unknown if (slot >= Plugin.IndicatorColors.Length) { return; } Color val = Plugin.IndicatorColors[slot]; string text = (slot + 1).ToString(); HUD_Hearts val2 = player.hudHearts; if ((Object)val2 != (Object)null && (Object)val2.playerFarming != (Object)player) { val2 = null; } if ((Object)val2 != (Object)null && (Object)val2.coopIndicatorIcon != (Object)null) { CoopIndicatorIcon coopIndicatorIcon = val2.coopIndicatorIcon; if ((Object)coopIndicatorIcon.GoatImage != (Object)null) { ((Graphic)coopIndicatorIcon.GoatImage).color = val; } if ((Object)coopIndicatorIcon.UserName != (Object)null) { coopIndicatorIcon.UserName.text = text; } } Image[] componentsInChildren2; if (slot >= 2 && (Object)val2 != (Object)null && (Object)val2.faithAmmo != (Object)null) { Color color = Color.Lerp(val, Color.white, 0.05f); Transform[] componentsInChildren; if (!_faithAmmoDumped) { _faithAmmoDumped = true; componentsInChildren = ((Component)val2.faithAmmo).GetComponentsInChildren(true); foreach (Transform val3 in componentsInChildren) { Image component = ((Component)val3).GetComponent(); Plugin.Log.LogInfo((object)string.Format("[FaithAmmo] child: '{0}' hasImage={1} color={2}", ((Object)((Component)val3).gameObject).name, (Object)component != (Object)null, ((Object)component != (Object)null) ? ((object)((Graphic)component).color).ToString() : "n/a")); } } Transform val4 = null; componentsInChildren = ((Component)val2.faithAmmo).GetComponentsInChildren(true); foreach (Transform val5 in componentsInChildren) { if (((Object)((Component)val5).gameObject).name == "FaithBarContainer") { val4 = val5; break; } } if ((Object)val4 != (Object)null) { componentsInChildren2 = ((Component)val4).GetComponentsInChildren(true); foreach (Image val6 in componentsInChildren2) { switch (((Object)((Component)val6).gameObject).name) { case "Glow": case "Goop": case "LoseFaithFeedback": case "GainFaithFeedback": case "RedGlow": case "FaithProgressBar": case "FaithProgressBar (1)": case "White flash": continue; } ((Graphic)val6).color = color; } } componentsInChildren = ((Component)val2.faithAmmo).GetComponentsInChildren(true); foreach (Transform val7 in componentsInChildren) { if (((Object)((Component)val7).gameObject).name == "Goat") { Image component2 = ((Component)val7).GetComponent(); if ((Object)component2 != (Object)null) { ((Graphic)component2).color = color; } } } } if (slot < 2 || (Object)player.CoopIndicatorGoat == (Object)null) { return; } componentsInChildren2 = player.CoopIndicatorGoat.GetComponentsInChildren(true); foreach (Image val8 in componentsInChildren2) { if (((Object)((Component)val8).gameObject).name != "Text (1)") { ((Graphic)val8).color = val; } } SpriteRenderer[] componentsInChildren3 = player.CoopIndicatorGoat.GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren3.Length; j++) { componentsInChildren3[j].color = val; } SkeletonGraphic[] componentsInChildren4 = player.CoopIndicatorGoat.GetComponentsInChildren(true); for (int k = 0; k < componentsInChildren4.Length; k++) { ((Graphic)componentsInChildren4[k]).color = val; } if (!_cachedTextImages.TryGetValue(slot, out var value) || (Object)value == (Object)null) { _cachedTextImages.Remove(slot); Transform[] componentsInChildren = player.CoopIndicatorGoat.GetComponentsInChildren(true); foreach (Transform val9 in componentsInChildren) { if (((Object)((Component)val9).gameObject).name.Contains("Text")) { Image component3 = ((Component)val9).GetComponent(); if ((Object)component3 != (Object)null) { _cachedTextImages[slot] = component3; value = component3; break; } } } } if (!_cachedTextImages.TryGetValue(slot, out var value2) || (Object)value2 == (Object)null) { return; } if (!_cachedSprites.TryGetValue(slot, out var value3) || (Object)value3 == (Object)null) { Sprite sprite = value2.sprite; float num = (((Object)sprite != (Object)null) ? sprite.pixelsPerUnit : 100f) * 0.12f; string text2 = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), text + ".png"); Texture2D val10 = null; if (File.Exists(text2)) { try { val10 = LoadPNG(text2); if ((Object)val10 != (Object)null) { Plugin.Log.LogInfo((object)$"[MP] Loaded PNG sprite: {text2} {((Texture)val10).width}x{((Texture)val10).height}"); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MP] Failed to load PNG " + text2 + ": " + ex.Message)); val10 = null; } } if ((Object)val10 == (Object)null) { int num2; Rect rect; if (!((Object)sprite != (Object)null)) { num2 = 32; } else { rect = sprite.rect; num2 = (int)((Rect)(ref rect)).width; } int num3 = num2; int num4; if (!((Object)sprite != (Object)null)) { num4 = 32; } else { rect = sprite.rect; num4 = (int)((Rect)(ref rect)).height; } int num5 = num4; val10 = BuildNumberTexture(text, num3, num5); Plugin.Log.LogInfo((object)$"[MP] Using generated texture {num3}x{num5} (no PNG found at {text2})"); } value3 = Sprite.Create(val10, new Rect(0f, 0f, (float)((Texture)val10).width, (float)((Texture)val10).height), new Vector2(0.5f, 0.5f), num); _cachedSprites[slot] = value3; } if ((Object)value2.sprite != (Object)value3) { value2.sprite = value3; ((Graphic)value2).color = Color.white; ((Behaviour)value2).enabled = true; } } private static SpriteRenderer FindHaloSR(PlayerFarming player, int slot) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown if (_cachedHaloSR.TryGetValue(slot, out var value) && (Object)value != (Object)null) { return value; } if ((Object)player.CoopIndicatorGoat == (Object)null) { return null; } SpriteRenderer component = player.CoopIndicatorGoat.GetComponent(); if ((Object)component != (Object)null) { _cachedHaloSR[slot] = component; Plugin.Log.LogInfo((object)$"[MP] Found halo SR on CoopIndicatorGoat root, slot={slot}"); } return component; } private static Sprite GetHaloSprite(int slot) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown //IL_00ad: 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) if (_cachedHaloSprites.TryGetValue(slot, out var value) && (Object)value != (Object)null) { return value; } if (!_haloSpriteNames.TryGetValue(slot, out var value2)) { return null; } string text = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), value2); if (!File.Exists(text)) { Plugin.Log.LogWarning((object)("[MP] Halo PNG not found: " + text)); return null; } try { Texture2D val = LoadPNG(text); if ((Object)val == (Object)null) { return null; } float num = 100f; Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), num); _cachedHaloSprites[slot] = val2; Plugin.Log.LogInfo((object)$"[MP] Loaded halo sprite: {value2} {((Texture)val).width}x{((Texture)val).height} ppu={num}"); return val2; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MP] Failed to load halo PNG " + text + ": " + ex.Message)); return null; } } public static void HUD_Update(HUD_Manager __instance) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) if (PlayerFarming.playersCount < 3 || LetterBox.IsPlaying) { return; } FieldInfo field = typeof(HUD_Manager).GetField("_playerTwoWidget", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = typeof(HUD_Manager).GetField("_playerTwoArrow", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null || field2 == null) { return; } object value = field.GetValue(__instance); Image val = (Image)((value is Image) ? value : null); object value2 = field2.GetValue(__instance); RectTransform val2 = (RectTransform)((value2 is RectTransform) ? value2 : null); if (!((Object)val == (Object)null) && !((Object)val2 == (Object)null)) { ((Component)val).gameObject.SetActive(false); if ((Object)_p2Widget == (Object)null) { _p2Widget = Object.Instantiate(val, ((Component)val).transform.parent); _p2Arrow = Object.Instantiate(val2, ((Component)val2).transform.parent); ((Graphic)_p2Widget).color = Plugin.IndicatorColors[1]; ((Component)_p2Widget).gameObject.SetActive(false); } if ((Object)_p3Widget == (Object)null) { _p3Widget = Object.Instantiate(val, ((Component)val).transform.parent); _p3Arrow = Object.Instantiate(val2, ((Component)val2).transform.parent); ((Graphic)_p3Widget).color = Plugin.IndicatorColors[2]; ((Component)_p3Widget).gameObject.SetActive(false); } if ((Object)_p4Widget == (Object)null && PlayerFarming.playersCount >= 4) { _p4Widget = Object.Instantiate(val, ((Component)val).transform.parent); _p4Arrow = Object.Instantiate(val2, ((Component)val2).transform.parent); ((Graphic)_p4Widget).color = Plugin.IndicatorColors[3]; ((Component)_p4Widget).gameObject.SetActive(false); } UpdateExtraPlayerWidget(_p2Widget, _p2Arrow, 1); UpdateExtraPlayerWidget(_p3Widget, _p3Arrow, 2); if (PlayerFarming.playersCount >= 4) { UpdateExtraPlayerWidget(_p4Widget, _p4Arrow, 3); } } } private static void UpdateExtraPlayerWidget(Image widget, RectTransform arrow, int slot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: 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_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Expected O, but got Unknown //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) if ((Object)widget == (Object)null || (Object)arrow == (Object)null) { return; } PlayerFarming val = null; foreach (PlayerFarming player in PlayerFarming.players) { if ((Object)player != (Object)null && player.playerID == slot) { val = player; break; } } if ((Object)val == (Object)null) { ((Component)widget).gameObject.SetActive(false); return; } Vector3 val2 = CameraManager.instance.CameraRef.WorldToScreenPoint(((Component)val).transform.position); bool flag = val2.z < 0f || val2.x < 0f || val2.x > (float)Screen.width || val2.y < 0f || val2.y > (float)Screen.height; if (!flag && (Object)PlayerFarming.Instance != (Object)null && Vector3.Distance(((Component)PlayerFarming.Instance).transform.position, ((Component)val).transform.position) > 15f) { flag = true; } ((Component)widget).gameObject.SetActive(flag); if (flag) { if (val2.z < 0f) { val2.x = (float)Screen.width - val2.x; val2.y = (float)Screen.height - val2.y; } int num = 60; ((Transform)((Graphic)widget).rectTransform).position = new Vector3(Mathf.Clamp(val2.x, (float)num, (float)(Screen.width - num)), Mathf.Clamp(val2.y, (float)num, (float)(Screen.height - num)), 0f); ((Transform)arrow).up = ((Component)arrow).transform.position - val2; if ((Object)PlayerFarming.Instance != (Object)null) { float num2 = Vector3.Distance(((Component)PlayerFarming.Instance).transform.position, ((Component)val).transform.position); float num3 = Mathf.Lerp(1f, 0.5f, Mathf.Clamp01(num2 / 30f)); ((Transform)((Graphic)widget).rectTransform).localScale = Vector3.one * num3; } } } private static void UnhookVanillaCoopDelegates() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown MethodInfo method = typeof(CoopManager).GetMethod("OnPlayerUserChanged", BindingFlags.Static | BindingFlags.NonPublic); if (method != null) { Delegate obj = Delegate.CreateDelegate(typeof(PlayerUserChangedDelegate), method, throwOnBindFailure: false); PlayerUserChangedDelegate val = (PlayerUserChangedDelegate)((obj is PlayerUserChangedDelegate) ? obj : null); if (val != null) { UserHelper.OnPlayerUserChanged = (PlayerUserChangedDelegate)Delegate.Remove((Delegate)(object)UserHelper.OnPlayerUserChanged, (Delegate)(object)val); } } MethodInfo method2 = typeof(CoopManager).GetMethod("OnPlayerGamePadChanged", BindingFlags.Static | BindingFlags.NonPublic); if (method2 != null) { Delegate obj2 = Delegate.CreateDelegate(typeof(PlayerGamePadChangedDelegate), method2, throwOnBindFailure: false); PlayerGamePadChangedDelegate val2 = (PlayerGamePadChangedDelegate)((obj2 is PlayerGamePadChangedDelegate) ? obj2 : null); if (val2 != null) { UserHelper.OnPlayerGamePadChanged = (PlayerGamePadChangedDelegate)Delegate.Remove((Delegate)(object)UserHelper.OnPlayerGamePadChanged, (Delegate)(object)val2); } } } public static void RefreshCoopPlayerRewired() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown EnforceKeyboardOwnership(); if (ReInput.controllers == null) { return; } for (int i = 0; i < PlayerFarming.players.Count; i++) { PlayerFarming val = PlayerFarming.players[i]; if (!((Object)val == (Object)null) && ((Component)val).gameObject.activeSelf) { Player player = RewiredInputManager.GetPlayer((!val.isLamb) ? val.playerID : 0); if (player != null) { val.rewiredPlayer = player; val.canUseKeyboard = player.controllers.hasKeyboard; } } } RefreshDesiredExtraSlotsFromActivePlayers(); TryAutoRespawnMissingExtraSlots("RefreshCoopPlayerRewired"); StopOrphanedRumbleHeartbeat("RefreshCoopPlayerRewired"); } private static void MarkDesiredExtraSlot(int slot, bool desired) { if (slot >= 2 && slot < 4) { if (desired) { _desiredExtraSlots.Add(slot); } else { _desiredExtraSlots.Remove(slot); } } } private static void RefreshDesiredExtraSlotsFromActivePlayers() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (!CoopManager.CoopActive) { _desiredExtraSlots.Clear(); return; } foreach (PlayerFarming player in PlayerFarming.players) { if (!((Object)player == (Object)null) && !player.isLamb && ((Component)player).gameObject.activeSelf) { MarkDesiredExtraSlot(player.playerID, desired: true); } } } private static void PrunePendingSpawnSlots() { //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Expected O, but got Unknown //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Expected O, but got Unknown if (_pendingSpawnSlots.Count > 0) { _pendingSpawnSlots.RemoveWhere((int slot) => slot < 2 || slot >= 4); } if (_pendingSpawnUseAnimation.Count > 0) { List list = null; foreach (int key in _pendingSpawnUseAnimation.Keys) { if (key < 2 || key >= 4) { if (list == null) { list = new List(); } list.Add(key); } } if (list != null) { foreach (int item in list) { _pendingSpawnUseAnimation.Remove(item); } } } if (_pendingSpawnFirstSeenAt.Count > 0) { List list2 = null; foreach (int key2 in _pendingSpawnFirstSeenAt.Keys) { if (!_pendingSpawnSlots.Contains(key2)) { if (list2 == null) { list2 = new List(); } list2.Add(key2); } } if (list2 != null) { foreach (int item2 in list2) { _pendingSpawnFirstSeenAt.Remove(item2); } } } if (_pendingSpawnSlots.Count == 0) { return; } bool flag = (Object)CoopManager.Instance != (Object)null && CoopManager.Instance.IsSpawningOrRemovingPlayer; float unscaledTime = Time.unscaledTime; List list3 = null; List list4 = null; foreach (int pendingSpawnSlot in _pendingSpawnSlots) { bool num = (Object)FindActivePlayerBySlot(pendingSpawnSlot) != (Object)null; bool flag2 = CoopManager.AllPlayerGameObjects != null && pendingSpawnSlot < CoopManager.AllPlayerGameObjects.Length && (Object)CoopManager.AllPlayerGameObjects[pendingSpawnSlot] != (Object)null && CoopManager.AllPlayerGameObjects[pendingSpawnSlot].activeInHierarchy; if (num) { if (list3 == null) { list3 = new List(); } list3.Add(pendingSpawnSlot); continue; } if (flag) { _pendingSpawnFirstSeenAt.Remove(pendingSpawnSlot); continue; } if (!_pendingSpawnFirstSeenAt.TryGetValue(pendingSpawnSlot, out var value)) { _pendingSpawnFirstSeenAt[pendingSpawnSlot] = unscaledTime; continue; } float num2 = (flag2 ? 6f : 12f); if (!(unscaledTime - value < num2)) { if (list4 == null) { list4 = new List(); } list4.Add(pendingSpawnSlot); } } if (list3 != null) { foreach (int item3 in list3) { _pendingSpawnSlots.Remove(item3); _pendingSpawnUseAnimation.Remove(item3); _pendingSpawnFirstSeenAt.Remove(item3); } } if (list4 == null || list4.Count == 0) { return; } foreach (int item4 in list4) { _pendingSpawnSlots.Remove(item4); _pendingSpawnUseAnimation.Remove(item4); _pendingSpawnFirstSeenAt.Remove(item4); Plugin.Log.LogWarning((object)$"[MP] Cleared stale pending spawn slot {item4} after timeout"); } } private static bool SlotHasJoystick(int slot) { Player player = RewiredInputManager.GetPlayer(slot); if (player != null && player.controllers != null && player.controllers.Joysticks != null) { return player.controllers.Joysticks.Count > 0; } return false; } private static int FindJoystickOwnerSlot(Joystick joystick) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (joystick == null) { return -1; } for (int i = 0; i < 4; i++) { Player player = RewiredInputManager.GetPlayer(i); if (player != null && player.controllers != null && player.controllers.ContainsController((Controller)joystick)) { return i; } } return -1; } private static bool IsSlotExpectedToKeepJoystick(int slot, HashSet activeGoatSlots) { if (slot <= 0 || slot >= 4) { return false; } if (activeGoatSlots != null && activeGoatSlots.Contains(slot)) { return true; } if (_desiredExtraSlots.Contains(slot)) { return true; } if (slot == 1 && PlayerFarming.playersCount > 1) { return true; } return false; } private static void AggressiveControllerOwnershipHeartbeat(string reason) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Expected O, but got Unknown //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Expected O, but got Unknown if (!CoopManager.CoopActive || (Object)CoopManager.Instance == (Object)null || ReInput.controllers == null || CoopManager.Instance.IsSpawningOrRemovingPlayer || _removingPlayer) { return; } EnforceKeyboardOwnership(); RefreshDesiredExtraSlotsFromActivePlayers(); List list = new List(ReInput.controllers.Joysticks); if (list.Count == 0) { return; } HashSet hashSet = new HashSet(); foreach (PlayerFarming player3 in PlayerFarming.players) { if (!((Object)player3 == (Object)null) && !player3.isLamb && ((Component)player3).gameObject.activeSelf && player3.playerID >= 1 && player3.playerID < 4) { hashSet.Add(player3.playerID); } } List list2 = new List(); for (int i = 1; i < 4; i++) { if (IsSlotExpectedToKeepJoystick(i, hashSet) && !SlotHasJoystick(i)) { list2.Add(i); } } if (list2.Count == 0) { return; } HashSet hashSet2 = new HashSet(); bool flag = false; foreach (int item in list2) { Player player = RewiredInputManager.GetPlayer(item); if (player == null || player.controllers == null) { continue; } Joystick val = null; int num = -1; Joystick val2 = null; foreach (Joystick item2 in list) { if (item2 != null && !hashSet2.Contains(((Controller)item2).id)) { int num2 = FindJoystickOwnerSlot(item2); if (num2 < 0 || !IsSlotExpectedToKeepJoystick(num2, hashSet)) { val = item2; num = num2; break; } if (num2 == 0 && val2 == null) { val2 = item2; } } } if (val == null && val2 != null) { val = val2; num = 0; } if (val == null) { continue; } for (int j = 0; j < 4; j++) { Player player2 = RewiredInputManager.GetPlayer(j); if (player2 != null && player2.controllers != null) { player2.controllers.RemoveController((Controller)val); } } player.controllers.AddController((Controller)val, true); hashSet2.Add(((Controller)val).id); if (item >= 2) { MarkDesiredExtraSlot(item, desired: true); } flag = true; Plugin.Log.LogInfo((object)$"[MP] Controller-heal ({reason}): joystick id={((Controller)val).id} owner={num} -> slot {item}"); } if (flag) { try { CoopManager.RefreshCoopPlayerRewired(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MP] Controller-heal refresh failed (" + reason + "): " + ex.GetType().Name + ": " + ex.Message)); } TryAutoRespawnMissingExtraSlots("ControllerHeal:" + reason); StopOrphanedRumbleHeartbeat("ControllerHeal:" + reason); } } private static void TryStopAllRumble(string reason) { try { MMVibrate.StopRumble((PlayerFarming)null); Plugin.Log.LogInfo((object)("[MP] Forced rumble stop (" + reason + ")")); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MP] Failed to stop rumble (" + reason + "): " + ex.GetType().Name + ": " + ex.Message)); } } private static void StopOrphanedRumbleHeartbeat(string reason) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown if (Time.unscaledTime < _nextRumbleCleanupAt) { return; } _nextRumbleCleanupAt = Time.unscaledTime + 0.5f; if (ReInput.controllers == null) { return; } bool flag = false; for (int i = 1; i < 4; i++) { bool num = SlotHasJoystick(i); bool flag2 = (Object)FindActivePlayerBySlot(i) != (Object)null; bool flag3 = _pendingSpawnSlots.Contains(i); if (num && !flag2 && !flag3) { flag = true; break; } } if (flag) { TryStopAllRumble(reason + ":orphan-slot"); } } private static List GetMissingSpawnableExtraSlots() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown List list = new List(); for (int i = 2; i < 4; i++) { if (_pendingSpawnSlots.Contains(i)) { continue; } if ((Object)FindActivePlayerBySlot(i) != (Object)null) { _warnedOrphanSlotObjects.Remove(i); continue; } if (CoopManager.AllPlayerGameObjects != null && i < CoopManager.AllPlayerGameObjects.Length && (Object)CoopManager.AllPlayerGameObjects[i] != (Object)null && CoopManager.AllPlayerGameObjects[i].activeInHierarchy) { if ((Object)CoopManager.Instance != (Object)null && CoopManager.Instance.IsSpawningOrRemovingPlayer) { continue; } if (_warnedOrphanSlotObjects.Add(i)) { Plugin.Log.LogWarning((object)$"[MP] Slot {i} has active player object but no active PlayerFarming; treating as missing."); } } else { _warnedOrphanSlotObjects.Remove(i); } Player player = RewiredInputManager.GetPlayer(i); if ((player != null && player.controllers != null && player.controllers.Joysticks != null && player.controllers.Joysticks.Count > 0) || _desiredExtraSlots.Contains(i)) { list.Add(i); } } return list; } private static bool IsReviveOrCutsceneFlowActive() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Invalid comparison between Unknown and I4 //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Invalid comparison between Unknown and I4 //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Invalid comparison between Unknown and I4 //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown if ((Object)UIDeathScreenOverlayController.Instance != (Object)null && (Object)((Component)UIDeathScreenOverlayController.Instance).gameObject != (Object)null && ((Component)UIDeathScreenOverlayController.Instance).gameObject.activeInHierarchy) { return true; } if (MMConversation.isPlaying || LetterBox.IsPlaying) { return true; } if ((Object)PlayerFarming.Instance == (Object)null || (Object)PlayerFarming.Instance.state == (Object)null) { return true; } State cURRENT_STATE = PlayerFarming.Instance.state.CURRENT_STATE; if ((int)cURRENT_STATE == 13 || (int)cURRENT_STATE == 49 || (int)cURRENT_STATE == 24 || (int)cURRENT_STATE == 16) { return true; } string name = ((Object)PlayerFarming.Instance).name; if (!string.IsNullOrEmpty(name) && name.IndexOf("TempPlayer", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } foreach (PlayerFarming player in PlayerFarming.players) { if (!((Object)player == (Object)null)) { if (IsFalseKnockedOutState(player)) { ClearFalseKnockedOutState(player, "IsReviveOrCutsceneFlowActive"); } else if (player.IsKnockedOut || IsLikelyReviveDesyncState(player)) { return true; } } } return false; } private static IEnumerator DelayedRespawnAfterReviveRoutine(string reason) { try { if ((Object)CoopManager.Instance == (Object)null) { yield break; } bool allowDuringReviveFlow = IsWakeAllRespawnReason(reason) || IsSacrificialReviveFlowReason(reason); float num = (allowDuringReviveFlow ? 0.05f : 0.35f); yield return (object)new WaitForSeconds(num); float deadline = Time.unscaledTime + 15f; int attempts = 0; while (Time.unscaledTime < deadline) { if ((Object)CoopManager.Instance == (Object)null || !CoopManager.CoopActive) { yield break; } _nextAutoRespawnAttemptAt = 0f; TryAutoRespawnMissingExtraSlots($"{reason}.poll{attempts}"); if ((reason.StartsWith("WakeAllKnockedOutPlayers", StringComparison.Ordinal) || IsSacrificialReviveFlowReason(reason)) && AnyNonLambPlayerNeedsWakeRecovery()) { EnsureAllPlayersAwake(reason + ".DelayedRespawnAfterReviveRoutine"); EnsureAllExtraPlayersUnlocked(reason + ".DelayedRespawnAfterReviveRoutine"); QueuePostReviveHardResetForAll(reason + ".DelayedRespawnAfterReviveRoutine"); } PrunePendingSpawnSlots(); List missingSpawnableExtraSlots = GetMissingSpawnableExtraSlots(); bool flag = _pendingSpawnSlots.Count > 0; bool isSpawningOrRemovingPlayer = CoopManager.Instance.IsSpawningOrRemovingPlayer; bool flag2 = IsReviveOrCutsceneFlowActive(); if (missingSpawnableExtraSlots.Count == 0 && !flag && !isSpawningOrRemovingPlayer && (!flag2 || allowDuringReviveFlow)) { if (attempts > 0) { Plugin.Log.LogInfo((object)$"[MP] Delayed revive respawn settled after {attempts} poll(s) ({reason})"); } break; } if (attempts % 8 == 0) { Plugin.Log.LogInfo((object)$"[MP] Delayed revive respawn polling ({reason}): missing={missingSpawnableExtraSlots.Count}, pending={_pendingSpawnSlots.Count}, blocked={flag2}, spawning={isSpawningOrRemovingPlayer}"); } attempts++; yield return (object)new WaitForSeconds(0.2f); } _nextAutoRespawnAttemptAt = 0f; TryAutoRespawnMissingExtraSlots(reason + ".final"); if (!reason.StartsWith("WakeAllKnockedOutPlayers", StringComparison.Ordinal) && !IsSacrificialReviveFlowReason(reason)) { yield break; } if (AnyNonLambPlayerNeedsWakeRecovery()) { EnsureAllPlayersAwake(reason + ".DelayedRespawnAfterReviveRoutine.final"); EnsureAllExtraPlayersUnlocked(reason + ".DelayedRespawnAfterReviveRoutine.final"); QueuePostReviveHardResetForAll(reason + ".DelayedRespawnAfterReviveRoutine.final"); } for (int i = 0; i < 8; i++) { if ((Object)CoopManager.Instance == (Object)null) { break; } if (!CoopManager.CoopActive) { break; } yield return (object)new WaitForSeconds(0.25f); if (AnyNonLambPlayerNeedsWakeRecovery()) { EnsureAllPlayersAwake(reason + ".DelayedRespawnAfterReviveRoutine.stabilize"); EnsureAllExtraPlayersUnlocked(reason + ".DelayedRespawnAfterReviveRoutine.stabilize"); QueuePostReviveHardResetForAll(reason + ".DelayedRespawnAfterReviveRoutine.stabilize"); } } } finally { _delayedRespawnAfterReviveQueued = false; } } private static void EnsureAllPlayersAwake(string reason) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown if (PlayerFarming.players == null) { return; } foreach (PlayerFarming player in PlayerFarming.players) { if (!((Object)player == (Object)null) && !player.isLamb && ((Component)player).gameObject.activeInHierarchy) { EnsurePlayerAwakeAfterRespawn(player, reason); } } } private static void QueueDelayedRespawnAfterRevive(string reason) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!((Object)CoopManager.Instance == (Object)null) && !_delayedRespawnAfterReviveQueued) { if (GameManager.IsDungeon(PlayerFarming.Location) && Time.unscaledTime < _dungeonIntroProtectUntil) { Plugin.Log.LogInfo((object)("[MP] Suppressed delayed respawn during dungeon intro window (" + reason + ")")); return; } _delayedRespawnAfterReviveQueued = true; ((MonoBehaviour)CoopManager.Instance).StartCoroutine(DelayedRespawnAfterReviveRoutine(reason)); } } private static bool IsDungeonAutoRespawnReasonAllowed(string reason) { if (string.IsNullOrEmpty(reason)) { return false; } if (!reason.StartsWith("WakeAllKnockedOutPlayers", StringComparison.Ordinal) && !reason.StartsWith("WakeKnockedOutPlayer", StringComparison.Ordinal) && !reason.StartsWith("ResetMainPlayerOnConversationEnd", StringComparison.Ordinal) && !reason.StartsWith("CoopManager.Start", StringComparison.Ordinal)) { return reason.StartsWith("LambHeartbeat", StringComparison.Ordinal); } return true; } private static bool IsWakeAllRespawnReason(string reason) { if (!string.IsNullOrEmpty(reason)) { return reason.IndexOf("WakeAllKnockedOutPlayers", StringComparison.Ordinal) >= 0; } return false; } private static bool IsWakeAllWithHealthRespawnReason(string reason) { if (!string.IsNullOrEmpty(reason)) { return reason.IndexOf("WakeAllKnockedOutPlayersWithHealth", StringComparison.Ordinal) >= 0; } return false; } private static bool IsSacrificialReviveFlowReason(string reason) { if (IsWakeAllWithHealthRespawnReason(reason)) { return true; } try { return Time.unscaledTime <= _sacrificialReviveWindowUntil; } catch { return false; } } private static void OpenSacrificialReviveWindow(string reason) { try { float num = Time.unscaledTime + 7f; if (num > _sacrificialReviveWindowUntil) { _sacrificialReviveWindowUntil = num; } Plugin.Log.LogInfo((object)$"[MP] Opened sacrificial revive window ({reason}) until t={_sacrificialReviveWindowUntil:0.00}"); } catch { _sacrificialReviveWindowUntil = 7f; } } public static void CoopManager_WakeAllKnockedOutPlayers_Postfix() { QueueDelayedRespawnAfterRevive("WakeAllKnockedOutPlayers"); } public static void CoopManager_WakeAllKnockedOutPlayersWithHealth_Postfix(float wakeUpHealth) { if (wakeUpHealth > 0f) { _lastObservedWakeHealth = wakeUpHealth; _lastObservedSacrificialWakeHealth = wakeUpHealth; } OpenSacrificialReviveWindow("WakeAllKnockedOutPlayersWithHealth"); QueueDelayedRespawnAfterRevive("WakeAllKnockedOutPlayersWithHealth"); } public static void CoopManager_WakeKnockedOutPlayer_Postfix(PlayerFarming playerFarming, float wakeUpHealth, PlayerFarming playerWhoIsReviving) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown if (wakeUpHealth > 0f) { _lastObservedWakeHealth = wakeUpHealth; } if ((Object)playerFarming == (Object)null || (Object)((Component)playerFarming).gameObject == (Object)null || !((Component)playerFarming).gameObject.activeInHierarchy || (!NeedsWakeRecovery(playerFarming) && !IsFalseKnockedOutState(playerFarming))) { return; } float num = 0f; try { if ((Object)playerFarming.health != (Object)null) { num = ((Health)playerFarming.health).CurrentHP; } } catch { } float num2 = Mathf.Max(wakeUpHealth, num); bool flag = (Object)playerWhoIsReviving == (Object)null; bool flag2 = false; try { flag2 = GameManager.IsDungeon(PlayerFarming.Location) && IsReviveOrCutsceneFlowActive(); } catch { } bool flag3 = flag && flag2; if (num2 > 2.01f || flag3) { float num3 = num2; if (flag3 && num3 < 6f) { num3 = 6f; } _lastObservedSacrificialWakeHealth = num3; OpenSacrificialReviveWindow(string.Format("WakeKnockedOutPlayer(hp={0:0.##},reviver={1})", num3, ((Object)playerWhoIsReviving != (Object)null) ? playerWhoIsReviving.playerID.ToString() : "none")); Plugin.Log.LogInfo((object)string.Format("[MP] Detected sacrificial/system WakeKnockedOutPlayer health={0:0.##} (raw={1:0.##}, reviver={2}, cutsceneFlow={3}); treating as sacrificial revive flow.", num3, num2, ((Object)playerWhoIsReviving != (Object)null) ? playerWhoIsReviving.playerID.ToString() : "none", flag2)); } ForceReviveVisualState(playerFarming, "WakeKnockedOutPlayer.Postfix"); if (!playerFarming.isLamb && playerFarming.playerID >= 1 && playerFarming.playerID < 4) { MarkDesiredExtraSlot(playerFarming.playerID, desired: true); QueuePostReviveHardReset(playerFarming, "WakeKnockedOutPlayer.Postfix"); _nextAutoRespawnAttemptAt = 0f; TryAutoRespawnMissingExtraSlots("WakeKnockedOutPlayer"); QueueDelayedRespawnAfterRevive("WakeKnockedOutPlayer"); } } public static void CoopManager_ResetMainPlayerOnConversationEnd_Postfix(bool SetPlayerToIdle, bool ShowHUD) { QueueDelayedRespawnAfterRevive("ResetMainPlayerOnConversationEnd"); } private static void TryAutoRespawnMissingExtraSlots(string reason) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) if ((Object)CoopManager.Instance == (Object)null || !CoopManager.CoopActive || _autoRespawnRoutineRunning || (_startupExtraRespawnDepth > 0 && (string.IsNullOrEmpty(reason) || !reason.StartsWith("CoopManager.Start", StringComparison.Ordinal)))) { return; } PrunePendingSpawnSlots(); if (_pendingSpawnSlots.Count > 0) { if (Time.unscaledTime >= _nextPendingBlockLogAt) { _nextPendingBlockLogAt = Time.unscaledTime + 3f; Plugin.Log.LogInfo((object)("[MP] Auto-respawn blocked by pending slots (" + reason + "): [" + string.Join(",", _pendingSpawnSlots) + "]")); } } else { if (CoopManager.Instance.IsSpawningOrRemovingPlayer || CoopManager.Instance.LockedAddRemoveCoopPlayer || Time.unscaledTime < _nextAutoRespawnAttemptAt || (Object)PlayerFarming.Instance == (Object)null || (Object)((Component)PlayerFarming.Instance).gameObject == (Object)null || !((Component)PlayerFarming.Instance).gameObject.activeInHierarchy || (GameManager.IsDungeon(PlayerFarming.Location) && Time.unscaledTime < _dungeonIntroProtectUntil && (string.IsNullOrEmpty(reason) || !reason.StartsWith("CoopManager.Start", StringComparison.Ordinal))) || (GameManager.IsDungeon(PlayerFarming.Location) && !IsDungeonAutoRespawnReasonAllowed(reason))) { return; } bool flag = IsWakeAllRespawnReason(reason) || IsSacrificialReviveFlowReason(reason); if ((!IsReviveOrCutsceneFlowActive() || flag) && PlayerFarming.playersCount >= 1) { List missingSpawnableExtraSlots = GetMissingSpawnableExtraSlots(); if (missingSpawnableExtraSlots.Count != 0) { _nextAutoRespawnAttemptAt = Time.unscaledTime + 1f; ((MonoBehaviour)CoopManager.Instance).StartCoroutine(AutoRespawnMissingSlotsRoutine(missingSpawnableExtraSlots, reason)); } } } } private static IEnumerator AutoRespawnMissingSlotsRoutine(List missingSlots, string reason) { _autoRespawnRoutineRunning = true; bool allowDuringReviveFlow = IsWakeAllRespawnReason(reason) || IsSacrificialReviveFlowReason(reason); float interSpawnDelay = (allowDuringReviveFlow ? 0.15f : 0.75f); yield return (object)new WaitForSeconds(0.35f); foreach (int slot in missingSlots) { if ((Object)CoopManager.Instance == (Object)null || !CoopManager.CoopActive) { break; } if (_pendingSpawnSlots.Contains(slot) || (Object)FindActivePlayerBySlot(slot) != (Object)null) { continue; } Player player = RewiredInputManager.GetPlayer(slot); if (((player == null || player.controllers == null || player.controllers.Joysticks == null || player.controllers.Joysticks.Count <= 0) && !_desiredExtraSlots.Contains(slot)) || (Object)PlayerFarming.Instance == (Object)null || (Object)PlayerFarming.Instance.state == (Object)null || (IsReviveOrCutsceneFlowActive() && !allowDuringReviveFlow)) { continue; } float spawnWait = 0f; while (CoopManager.Instance.IsSpawningOrRemovingPlayer && spawnWait < 10f) { yield return (object)new WaitForSeconds(0.1f); spawnWait += 0.1f; } if (!_pendingSpawnSlots.Contains(slot) && !((Object)FindActivePlayerBySlot(slot) != (Object)null)) { Plugin.Log.LogInfo((object)$"[MP] Auto-respawn ({reason}): spawning missing slot {slot}"); _pendingSpawnSlots.Add(slot); bool flag = false; Plugin.Log.LogInfo((object)$"[MP] Auto-respawn spawn mode slot {slot}: animated={flag}"); _pendingSpawnUseAnimation[slot] = flag; try { CoopManager.Instance.SpawnCoopPlayer(slot, flag, -1f); } catch (Exception ex) { _pendingSpawnSlots.Remove(slot); _pendingSpawnUseAnimation.Remove(slot); Plugin.Log.LogWarning((object)$"[MP] Auto-respawn failed for slot {slot}: {ex.GetType().Name}: {ex.Message}"); } yield return (object)new WaitForSeconds(interSpawnDelay); } } _autoRespawnRoutineRunning = false; _nextAutoRespawnAttemptAt = Time.unscaledTime + 1.5f; } public static void PlayerFarming_Update_Camera(PlayerFarming __instance) { //IL_0012: 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_00ec: Expected O, but got Unknown //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Expected O, but got Unknown //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Expected O, but got Unknown //IL_0244: Expected O, but got Unknown //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Expected O, but got Unknown //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Expected O, but got Unknown //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Expected O, but got Unknown //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Expected O, but got Unknown //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Expected O, but got Unknown //IL_02b1: Expected O, but got Unknown //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Expected O, but got Unknown //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Expected O, but got Unknown //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Expected O, but got Unknown //IL_0461: Unknown result type (might be due to invalid IL or missing references) //IL_046c: Expected O, but got Unknown //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Expected O, but got Unknown //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_047f: Expected O, but got Unknown //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_04dd: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Unknown result type (might be due to invalid IL or missing references) //IL_0501: Unknown result type (might be due to invalid IL or missing references) if (__instance.isLamb) { if (CoopManager.CoopActive && GameManager.IsDungeon(PlayerFarming.Location)) { LogDungeonRoomTypeIfChanged(); TryQueueDungeonRoomStabilize("LambHeartbeat"); } if (CoopManager.CoopActive && Time.unscaledTime >= _nextControllerHealHeartbeatAt) { _nextControllerHealHeartbeatAt = Time.unscaledTime + 0.5f; ClearFalseKnockedOutStatesForAll("LambHeartbeat"); AggressiveControllerOwnershipHeartbeat("LambHeartbeat"); } if (CoopManager.CoopActive && Time.unscaledTime >= _nextPostReviveRaceGuardHeartbeatAt) { _nextPostReviveRaceGuardHeartbeatAt = Time.unscaledTime + 0.18f; ProcessPostReviveRaceGuards("LambHeartbeat"); } if (CoopManager.CoopActive && Time.unscaledTime >= _nextAutoRespawnHeartbeatAt) { _nextAutoRespawnHeartbeatAt = Time.unscaledTime + 1f; RefreshDesiredExtraSlotsFromActivePlayers(); TryAutoRespawnMissingExtraSlots("LambHeartbeat"); } return; } int playerID = __instance.playerID; if (playerID < 2 || !((Component)__instance).gameObject.activeSelf || (Object)GameManager.GetInstance() == (Object)null) { return; } if (CoopManager.CoopActive) { if (!_nextExtraFalseDownedWatchdogAt.TryGetValue(playerID, out var value)) { value = 0f; } if (Time.unscaledTime >= value) { if (IsFalseDownedVisualStateForExtra(__instance)) { _nextExtraFalseDownedWatchdogAt[playerID] = Time.unscaledTime + 0.75f; ForceReviveVisualState(__instance, $"PlayerUpdate.Watchdog(slot={playerID})"); SnapSpawnedPlayerToAwakeIdle(__instance, $"PlayerUpdate.Watchdog(slot={playerID})"); QueuePostReviveHardReset(__instance, $"PlayerUpdate.Watchdog(slot={playerID})"); Plugin.Log.LogWarning((object)$"[MP] Watchdog cleared false downed state for playerID={playerID} (HP={((Health)__instance.health).CurrentHP:0.00})"); } else { _nextExtraFalseDownedWatchdogAt[playerID] = Time.unscaledTime + 0.2f; } } } if (!LetterBox.IsPlaying && !MMConversation.isPlaying && !GameManager.GetInstance().CameraContains(__instance.CameraBone)) { GameManager.GetInstance().AddToCamera(__instance.CameraBone, 0.1f); } if (playerID >= Plugin.IndicatorColors.Length) { return; } Color val = Plugin.IndicatorColors[playerID]; string text = (playerID + 1).ToString(); HUD_Hearts val2 = __instance.hudHearts; if ((Object)val2 != (Object)null && (Object)val2.playerFarming != (Object)__instance) { val2 = null; } if ((Object)val2 != (Object)null) { SyncFaithAmmoForOwner(__instance, val2, "PlayerUpdateSync", forceReinit: false); } ApplyIndicator(__instance, playerID); SpriteRenderer val3 = FindHaloSR(__instance, playerID); if ((Object)val3 != (Object)null) { Sprite haloSprite = GetHaloSprite(playerID); if ((Object)haloSprite != (Object)null && (Object)val3.sprite != (Object)haloSprite) { val3.sprite = haloSprite; } val3.color = Color.white; } if ((Object)val2 != (Object)null && (Object)val2.coopIndicatorIcon != (Object)null) { CoopIndicatorIcon coopIndicatorIcon = val2.coopIndicatorIcon; if ((Object)coopIndicatorIcon.GoatImage != (Object)null) { ((Graphic)coopIndicatorIcon.GoatImage).color = val; } if ((Object)coopIndicatorIcon.UserName != (Object)null) { coopIndicatorIcon.UserName.text = text; } } if (playerID < Plugin.GoatColors.Length && (Object)__instance.Spine != (Object)null && ((SkeletonRenderer)__instance.Spine).skeleton != null) { ((SkeletonRenderer)__instance.Spine).skeleton.R = Plugin.GoatColors[playerID].r; ((SkeletonRenderer)__instance.Spine).skeleton.G = Plugin.GoatColors[playerID].g; ((SkeletonRenderer)__instance.Spine).skeleton.B = Plugin.GoatColors[playerID].b; ((SkeletonRenderer)__instance.Spine).skeleton.A = Plugin.GoatColors[playerID].a; } if ((Object)__instance.CoopIndicatorGoat != (Object)null) { SkeletonGraphic[] componentsInChildren = __instance.CoopIndicatorGoat.GetComponentsInChildren(true); foreach (SkeletonGraphic val4 in componentsInChildren) { if (val4.Skeleton != null) { val4.Skeleton.R = val.r; val4.Skeleton.G = val.g; val4.Skeleton.B = val.b; } } } if (!((Object)val2 != (Object)null) || !((Object)val2.faithAmmo != (Object)null)) { return; } Transform[] componentsInChildren2 = ((Component)val2.faithAmmo).GetComponentsInChildren(true); foreach (Transform val5 in componentsInChildren2) { if (!((Object)((Component)val5).gameObject).name.StartsWith("CoopIndicatorIcon")) { continue; } SkeletonGraphic[] componentsInChildren = ((Component)val5).GetComponentsInChildren(true); foreach (SkeletonGraphic val6 in componentsInChildren) { if (val6.Skeleton != null) { val6.Skeleton.R = val.r; val6.Skeleton.G = val.g; val6.Skeleton.B = val.b; } } } } private static void EnforceKeyboardOwnership() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown Keyboard keyboard = ReInput.controllers.Keyboard; Mouse mouse = ReInput.controllers.Mouse; for (int i = 1; i < 4; i++) { Player player = RewiredInputManager.GetPlayer(i); if (player != null) { if (keyboard != null) { player.controllers.RemoveController((Controller)keyboard); } if (mouse != null) { player.controllers.RemoveController((Controller)mouse); } player.controllers.hasKeyboard = false; player.controllers.hasMouse = false; } } Player player2 = RewiredInputManager.GetPlayer(0); if (player2 != null) { if (keyboard != null && !player2.controllers.ContainsController((Controller)keyboard)) { player2.controllers.AddController((Controller)keyboard, true); } if (mouse != null && !player2.controllers.ContainsController((Controller)mouse)) { player2.controllers.AddController((Controller)mouse, true); } player2.controllers.hasKeyboard = true; player2.controllers.hasMouse = true; } } private static bool ShouldAnimateIndicatorOnDamage(CoopIndicatorIcon icon) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)icon == (Object)null) { return false; } if (_coopIndicatorAnimateOnDamagedField == null) { return true; } try { object value = _coopIndicatorAnimateOnDamagedField.GetValue(icon); if (value is bool) { return (bool)value; } } catch { } return true; } private static CoopIndicatorIcon ResolveCanonicalIndicatorIcon(PlayerFarming owner) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_007b: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown if ((Object)owner == (Object)null) { return null; } if ((Object)owner.hudHearts != (Object)null && (Object)owner.hudHearts.coopIndicatorIcon != (Object)null) { return owner.hudHearts.coopIndicatorIcon; } foreach (PlayerFarming player in PlayerFarming.players) { if (!((Object)player == (Object)null) && !((Object)player != (Object)owner) && (Object)player.hudHearts != (Object)null && (Object)player.hudHearts.coopIndicatorIcon != (Object)null) { return player.hudHearts.coopIndicatorIcon; } } return null; } private static void AnimateIndicatorDamageSingle(CoopIndicatorIcon icon) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_009a: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0154: 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_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown if ((Object)icon == (Object)null || !ShouldAnimateIndicatorOnDamage(icon)) { return; } try { ShortcutExtensions.DOKill((Component)((Component)icon).transform, false); } catch { } if (icon.isLambIcon) { if ((Object)icon.LambImage != (Object)null) { try { ShortcutExtensions.DOKill((Component)icon.LambImage, false); } catch { } ((Graphic)icon.LambImage).color = Color.red; DOTween.To((DOGetter)(() => ((Graphic)icon.LambImage).color), (DOSetter)delegate(Color c) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) ((Graphic)icon.LambImage).color = c; }, Color.white, 0.5f); } } else if ((Object)icon.GoatImage != (Object)null) { try { ShortcutExtensions.DOKill((Component)icon.GoatImage, false); } catch { } ((Graphic)icon.GoatImage).color = Color.red; DOTween.To((DOGetter)(() => ((Graphic)icon.GoatImage).color), (DOSetter)delegate(Color c) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) ((Graphic)icon.GoatImage).color = c; }, Color.white, 0.5f); } ((Component)icon).transform.localScale = Vector3.one * 1.5f; Tween val = (Tween)ShortcutExtensions.DOScale(((Component)icon).transform, Vector3.one, 0.25f); if (val != null) { TweenSettingsExtensions.SetEase(val, (Ease)27); TweenSettingsExtensions.SetUpdate(val, true); } } public static bool CoopIndicatorIcon_AnimateDamageOnIcons_Prefix(PlayerFarming playerFarming) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if ((Object)playerFarming == (Object)null) { return true; } CoopIndicatorIcon val = ResolveCanonicalIndicatorIcon(playerFarming); if ((Object)val == (Object)null) { int playerID = playerFarming.playerID; if (_missingDamageIconLogs.Add(playerID)) { Plugin.Log.LogWarning((object)$"[MP] Damage icon unresolved for playerID={playerID}; suppressing shared bounce fallback"); } if (!playerFarming.isLamb) { return false; } return true; } AnimateIndicatorDamageSingle(val); return false; } public static void SetUsername_Postfix(CoopIndicatorIcon __instance, int playernumber) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0035: 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_0045: Expected O, but got Unknown //IL_0045: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) PlayerFarming val = null; foreach (PlayerFarming player in PlayerFarming.players) { if ((Object)player.hudHearts != (Object)null && (Object)player.hudHearts.coopIndicatorIcon == (Object)__instance) { val = player; break; } } if ((Object)val == (Object)null) { return; } int playerID = val.playerID; if (playerID >= 2 && playerID < Plugin.IndicatorColors.Length) { Color color = Plugin.IndicatorColors[playerID]; string text = (playerID + 1).ToString(); if ((Object)__instance.GoatImage != (Object)null) { ((Graphic)__instance.GoatImage).color = color; } if ((Object)__instance.UserName != (Object)null) { __instance.UserName.text = text; } ApplyIndicator(val, playerID); } } public static void RefreshPlayersCount_Postfix() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown for (int i = 2; i < PlayerFarming.players.Count; i++) { PlayerFarming val = PlayerFarming.players[i]; if ((Object)val == (Object)null) { continue; } int playerID = val.playerID; if (playerID >= 2) { if (playerID < Plugin.GoatColors.Length && (Object)val.Spine != (Object)null && ((SkeletonRenderer)val.Spine).skeleton != null) { ((SkeletonRenderer)val.Spine).skeleton.R = Plugin.GoatColors[playerID].r; ((SkeletonRenderer)val.Spine).skeleton.G = Plugin.GoatColors[playerID].g; ((SkeletonRenderer)val.Spine).skeleton.B = Plugin.GoatColors[playerID].b; ((SkeletonRenderer)val.Spine).skeleton.A = Plugin.GoatColors[playerID].a; } ApplyIndicator(val, playerID); } } } private static int ResolveTeleporterSlot(PlayerFarming playerFarming) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)playerFarming == (Object)null) { return -1; } int num = ((!playerFarming.isLamb) ? playerFarming.playerID : 0); if (num >= 0 && num < _teleporterOffsets.Length) { return num; } int num2 = PlayerFarming.players.IndexOf(playerFarming); if (num2 >= 0 && num2 < _teleporterOffsets.Length) { return num2; } return -1; } public static bool TeleporterAnimEvent_Prefix(Interaction_BaseTeleporter __instance, TrackEntry trackEntry, Event e) { if (e == null || e.Data == null) { return true; } EnsureTeleporterStencilCapacity(__instance); return true; } public static Exception TeleporterAnimEvent_Finalizer(Exception __exception, Interaction_BaseTeleporter __instance) { if (__exception == null) { return null; } if (!(__exception is IndexOutOfRangeException)) { return __exception; } EnsureTeleporterStencilCapacity(__instance); RecoverTeleporterPlayerState("[MP] Recovered teleporter player state after stencil bounds exception"); return null; } private static void EnsureTeleporterStencilCapacity(Interaction_BaseTeleporter teleporter) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)teleporter == (Object)null || _teleporterStencilField == null || !(_teleporterStencilField.GetValue(teleporter) is Material[] array) || array.Length == 0) { return; } int num = 4; if (PlayerFarming.players != null) { num = Mathf.Max(num, PlayerFarming.players.Count); } num = Mathf.Max(num, PlayerFarming.playersCount); if (array.Length < num) { Material[] array2 = (Material[])(object)new Material[num]; for (int i = 0; i < array2.Length; i++) { array2[i] = array[Mathf.Clamp(i, 0, array.Length - 1)]; } _teleporterStencilField.SetValue(teleporter, array2); Plugin.Log.LogInfo((object)$"[MP] Expanded PlayerStencilRT to {array2.Length} for teleporter safety"); } } private static void RecoverTeleporterPlayerState(string reason) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown if (PlayerFarming.players == null) { return; } for (int i = 0; i < PlayerFarming.players.Count; i++) { PlayerFarming val = PlayerFarming.players[i]; if ((Object)val == (Object)null) { continue; } try { if ((Object)val.Spine != (Object)null) { ((SkeletonRenderer)val.Spine).CustomMaterialOverride?.Clear(); MeshRenderer component = ((Component)val.Spine).GetComponent(); if ((Object)component != (Object)null) { ((Renderer)component).enabled = true; } } if ((Object)val.state != (Object)null) { val.state.LockStateChanges = false; } } catch { } } Plugin.Log.LogWarning((object)reason); } public static IEnumerable FishingTwoPlayerCount_Transpiler(IEnumerable instructions) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown List list = new List(instructions); MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(List), "Count"); MethodInfo methodInfo2 = AccessTools.Method(typeof(Patches), "GetFishingParticipantCount", (Type[])null, (Type[])null); FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerFarming), "playersCount"); MethodInfo methodInfo3 = AccessTools.Method(typeof(Patches), "GetFishingParticipantStaticCount", (Type[])null, (Type[])null); for (int i = 0; i < list.Count; i++) { CodeInstruction val = list[i]; if (methodInfo != null && methodInfo2 != null && CodeInstructionExtensions.Calls(val, methodInfo)) { list[i] = new CodeInstruction(OpCodes.Call, (object)methodInfo2); } else if (fieldInfo != null && methodInfo3 != null && val.opcode == OpCodes.Ldsfld && object.Equals(val.operand, fieldInfo)) { list[i] = new CodeInstruction(OpCodes.Call, (object)methodInfo3); } } return list; } public static int GetFishingParticipantCount(List players) { if (players == null) { return 0; } return Mathf.Min(players.Count, 2); } public static int GetFishingParticipantStaticCount() { int num = PlayerFarming.playersCount; if (PlayerFarming.players != null) { num = Mathf.Max(num, PlayerFarming.players.Count); } return Mathf.Min(num, 2); } public static void FishingTwoPlayerScope_Prefix() { BeginTwoPlayerListScope("fishing"); } public static Exception FishingTwoPlayerScope_Finalizer(Exception __exception) { EndTwoPlayerListScope(); return FishingBounds_Finalizer(__exception); } public static void TempleAltarTwoPlayerScope_Prefix() { BeginTwoPlayerListScope("temple altar"); } public static Exception TempleAltarTwoPlayerScope_Finalizer(Exception __exception) { EndTwoPlayerListScope(); if (__exception == null) { return null; } Plugin.Log.LogWarning((object)("[MP] Suppressed temple altar presentation exception: " + __exception.GetType().Name + ": " + __exception.Message)); return null; } private static void BeginTwoPlayerListScope(string reason) { PlayerListScopeState playerListScopeState = new PlayerListScopeState { SavedPlayersCount = PlayerFarming.playersCount }; try { if (PlayerFarming.players != null && PlayerFarming.players.Count > 2) { playerListScopeState.HiddenPlayers = new List(); for (int i = 2; i < PlayerFarming.players.Count; i++) { playerListScopeState.HiddenPlayers.Add(PlayerFarming.players[i]); } PlayerFarming.players.RemoveRange(2, PlayerFarming.players.Count - 2); } if (PlayerFarming.playersCount > 2) { PlayerFarming.playersCount = 2; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MP] Failed to limit " + reason + " player list: " + ex.Message)); } _twoPlayerListScopes.Push(playerListScopeState); } private static void EndTwoPlayerListScope() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown if (_twoPlayerListScopes.Count <= 0) { return; } PlayerListScopeState playerListScopeState = _twoPlayerListScopes.Pop(); try { if (PlayerFarming.players != null && playerListScopeState.HiddenPlayers != null) { for (int i = 0; i < playerListScopeState.HiddenPlayers.Count; i++) { PlayerFarming val = playerListScopeState.HiddenPlayers[i]; if ((Object)val != (Object)null && !PlayerFarming.players.Contains(val)) { PlayerFarming.players.Add(val); } } } PlayerFarming.playersCount = playerListScopeState.SavedPlayersCount; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MP] Failed to restore scoped player list: " + ex.Message)); } } public static bool InteractionFishing_BlockExtraPlayers_Prefix(StateMachine state) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown PlayerFarming val = null; try { val = (((Object)state != (Object)null) ? ((Component)state).GetComponent() : null); } catch { } if ((Object)val == (Object)null || PlayerFarming.players == null) { return true; } int num = PlayerFarming.players.IndexOf(val); if (num < 2 && val.playerID < 2) { return true; } Plugin.Log.LogInfo((object)$"[MP] Ignored fishing interaction for unsupported playerID={val.playerID} index={num}"); return false; } public static Exception FishingBounds_Finalizer(Exception __exception) { if (__exception == null) { return null; } if (!(__exception is IndexOutOfRangeException)) { return __exception; } if (!_loggedFishingBoundsSuppressed) { _loggedFishingBoundsSuppressed = true; Plugin.Log.LogWarning((object)"[MP] Suppressed fishing two-slot bounds exception"); } return null; } public static void TempleAltar_OnInteract_Postfix(Interaction_TempleAltar __instance) { QueueTempleExtraRelease(__instance, "OnInteract"); } public static bool TempleAltar_TryOnboardSin_Prefix(Interaction_TempleAltar __instance, Action callback, ref IEnumerator __result) { if (!ShouldUseCoopSafeSinOnboarding()) { return true; } __result = TempleAltarCoopSafeSinOnboardingRoutine(__instance, callback); Plugin.Log.LogWarning((object)"[MP] Replaced temple sin onboarding cinematic for 3+ player coop"); return false; } private unsafe static IEnumerator TempleAltarCoopSafeSinOnboardingRoutine(Interaction_TempleAltar altar, Action callback) { yield return (object)new WaitForEndOfFrame(); while (MMConversation.isPlaying) { yield return null; } if (!WillTempleSinOnboardingRun()) { callback?.Invoke(); yield break; } try { Time.timeScale = 1f; SimulationManager.UnPause(); MonoSingleton.Instance.ForceBlockPause = false; MonoSingleton.Instance.ForceBlockMenus = true; DataManager.Instance.PleasureRevealed = true; DataManager.Instance.PleasureDoctrineEnabled = true; Type val = (Type)(UpgradeSystem.GetUnlocked((Type)267) ? 267 : 268); UpgradeSystem.ClearCooldown(val); if (_templeAltarForceRitualField != null && (Object)altar != (Object)null) { _templeAltarForceRitualField.SetValue(altar, val); } Plugin.Log.LogWarning((object)("[MP] Skipped fragile sin onboarding cinematic; opening forced ritual " + ((object)(*(Type*)(&val))/*cast due to .constrained prefix*/).ToString())); if ((Object)altar != (Object)null) { altar.DoRitual(); } else { callback?.Invoke(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MP] Coop-safe sin onboarding handoff failed: " + ex.GetType().Name + ": " + ex.Message)); callback?.Invoke(); } } private static bool ShouldUseCoopSafeSinOnboarding() { if (!CoopManager.CoopActive) { return false; } int num = PlayerFarming.playersCount; if (PlayerFarming.players != null) { num = Mathf.Max(num, PlayerFarming.players.Count); } return num > 2; } public static void TempleAltar_DoCancel_Postfix(Interaction_TempleAltar __instance) { QueueTempleCancelExitCheck(__instance, "DoCancel"); } public static void TempleAltar_CancelCleanup_Postfix(Interaction_TempleAltar __instance) { QueueTemplePresentationNormalize(__instance, "DoCancel.cleanup"); } public static Exception TempleAltar_Finalizer(Exception __exception, Interaction_TempleAltar __instance) { if (__exception == null) { return null; } RecoverTempleAltarExitState(__instance, "exception:" + __exception.GetType().Name); Plugin.Log.LogWarning((object)("[MP] Suppressed temple altar exception: " + __exception.GetType().Name + ": " + __exception.Message)); return null; } private static void QueueTempleExtraRelease(Interaction_TempleAltar altar, string reason) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)altar == (Object)null || _templeExtraReleaseQueued || !HasExtraTemplePlayers()) { return; } try { ((MonoBehaviour)altar).StartCoroutine(TempleExtraReleaseRoutine(reason)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MP] Failed to queue temple extra-player release: " + ex.Message)); } } private static IEnumerator TempleExtraReleaseRoutine(string reason) { _templeExtraReleaseQueued = true; yield return (object)new WaitForSecondsRealtime(0.35f); ReleaseTempleExtraPlayers(reason + ".stage"); yield return (object)new WaitForSecondsRealtime(0.45f); ReleaseTempleExtraPlayers(reason + ".settle"); _templeExtraReleaseQueued = false; } private static void QueueTempleCancelExitCheck(Interaction_TempleAltar altar, string reason) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)altar == (Object)null) { return; } try { ((MonoBehaviour)altar).StartCoroutine(TempleCancelExitCheckRoutine(altar, reason)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MP] Failed to queue temple cancel exit check: " + ex.Message)); } } private static IEnumerator TempleCancelExitCheckRoutine(Interaction_TempleAltar altar, string reason) { yield return (object)new WaitForSecondsRealtime(0.25f); ReleaseTempleExtraPlayers(reason + ".early"); yield return (object)new WaitForSecondsRealtime(2f); if (!IsTempleSinOrConversationFlowActive() && NeedsTempleExitRecovery(altar)) { RecoverTempleAltarExitState(altar, reason + ".delayed"); } } private static void QueueTemplePresentationNormalize(Interaction_TempleAltar altar, string reason) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)altar == (Object)null) { return; } try { ((MonoBehaviour)altar).StartCoroutine(TemplePresentationNormalizeRoutine(reason)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MP] Failed to queue temple presentation normalize: " + ex.Message)); } } private static IEnumerator TemplePresentationNormalizeRoutine(string reason) { yield return (object)new WaitForSecondsRealtime(0.35f); NormalizeTemplePresentation(reason + ".early"); yield return (object)new WaitForSecondsRealtime(1.25f); NormalizeTemplePresentation(reason + ".late"); } private static void NormalizeTemplePresentation(string reason) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Invalid comparison between Unknown and I4 //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown if (PlayerFarming.players == null || IsTempleSinOrConversationFlowActive()) { return; } bool flag = false; for (int i = 0; i < PlayerFarming.players.Count; i++) { PlayerFarming playerFarming = PlayerFarming.players[i]; if ((Object)playerFarming == (Object)null || !((Component)playerFarming).gameObject.activeInHierarchy) { continue; } try { if ((Object)playerFarming.Spine != (Object)null) { playerFarming.Spine.UseDeltaTime = true; playerFarming.Spine.timeScale = 1f; } } catch { } if (!IsStuckTempleAnimation(playerFarming)) { continue; } try { if ((Object)playerFarming.state != (Object)null && !playerFarming.state.LockStateChanges && ((int)playerFarming.state.CURRENT_STATE == 0 || (int)playerFarming.state.CURRENT_STATE == 49)) { playerFarming.state.CURRENT_STATE = (State)0; } } catch { } try { string currentSpineAnimationName = GetCurrentSpineAnimationName(playerFarming); if (!string.IsNullOrEmpty(currentSpineAnimationName) && currentSpineAnimationName.IndexOf("sermons/second-player", StringComparison.OrdinalIgnoreCase) >= 0) { playerFarming.CustomAnimationWithCallback("sermons/second-player-stop", false, (Action)delegate { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown try { if ((Object)playerFarming.state != (Object)null) { playerFarming.state.LockStateChanges = false; playerFarming.state.CURRENT_STATE = (State)0; } } catch { } }); flag = true; } else if ((Object)playerFarming.state != (Object)null) { playerFarming.state.LockStateChanges = false; playerFarming.state.CURRENT_STATE = (State)0; flag = true; } } catch { } } if (flag) { Plugin.Log.LogInfo((object)("[MP] Normalized stuck temple player animation (" + reason + ")")); } } private static string GetCurrentSpineAnimationName(PlayerFarming player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown try { if ((Object)player == (Object)null || (Object)player.Spine == (Object)null || player.Spine.AnimationState == null) { return null; } TrackEntry current = player.Spine.AnimationState.GetCurrent(0); object result; if (current == null) { result = null; } else { Animation animation = current.Animation; result = ((animation != null) ? animation.Name : null); } return (string)result; } catch { return null; } } private static bool IsStuckTempleAnimation(PlayerFarming player) { try { string currentSpineAnimationName = GetCurrentSpineAnimationName(player); if (string.IsNullOrEmpty(currentSpineAnimationName)) { return false; } return currentSpineAnimationName.IndexOf("sermons/second-player", StringComparison.OrdinalIgnoreCase) >= 0 || currentSpineAnimationName.IndexOf("rituals/sin-onboarding", StringComparison.OrdinalIgnoreCase) >= 0; } catch { return false; } } private static bool HasExtraTemplePlayers() { if (PlayerFarming.players == null) { return false; } for (int i = 0; i < PlayerFarming.players.Count; i++) { if (IsExtraTemplePlayer(PlayerFarming.players[i])) { return true; } } return false; } private static bool IsExtraTemplePlayer(PlayerFarming player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)player != (Object)null && !player.isLamb) { return player.playerID >= 2; } return false; } private static void ReleaseTempleExtraPlayers(string reason) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Invalid comparison between Unknown and I4 //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Invalid comparison between Unknown and I4 //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Invalid comparison between Unknown and I4 //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Invalid comparison between Unknown and I4 //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Invalid comparison between Unknown and I4 if (PlayerFarming.players == null) { return; } bool flag = false; for (int i = 0; i < PlayerFarming.players.Count; i++) { PlayerFarming val = PlayerFarming.players[i]; if (!IsExtraTemplePlayer(val) || !((Component)val).gameObject.activeInHierarchy) { continue; } bool flag2 = false; try { if (val.GoToAndStopping) { val.GoToAndStopping = false; flag2 = true; } } catch { } try { if ((Object)val.Spine != (Object)null) { val.Spine.UseDeltaTime = true; val.Spine.timeScale = 1f; } } catch { } try { if ((Object)val.state != (Object)null) { if (val.state.LockStateChanges) { val.state.LockStateChanges = false; flag2 = true; } State cURRENT_STATE = val.state.CURRENT_STATE; if ((int)cURRENT_STATE == 49 || (int)cURRENT_STATE == 16 || (int)cURRENT_STATE == 13 || (int)cURRENT_STATE == 24 || (int)cURRENT_STATE == 49) { val.state.CURRENT_STATE = (State)0; flag2 = true; } } } catch { } flag = flag || flag2; } if (flag) { Plugin.Log.LogInfo((object)("[MP] Released P3/P4 from temple staging state (" + reason + ")")); } } private static bool IsTempleSinOrConversationFlowActive() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown try { if (MMConversation.isPlaying || LetterBox.IsPlaying) { return true; } } catch { } try { UIManager instance = MonoSingleton.Instance; if ((Object)instance != (Object)null && instance.ForceBlockPause) { return true; } } catch { } return false; } private static bool WillTempleSinOnboardingRun() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown try { if ((Object)DataManager.Instance == (Object)null) { return false; } bool unlocked = UpgradeSystem.GetUnlocked((Type)267); bool unlocked2 = UpgradeSystem.GetUnlocked((Type)268); bool flag = DataManager.Instance.PleasureRevealed && (unlocked || unlocked2); if (DataManager.Instance.BossesCompleted == null || DataManager.Instance.BossesCompleted.Count < 3) { return false; } if (flag) { return false; } if (Ritual.FollowerToAttendSermon == null || Ritual.FollowerToAttendSermon.Count <= 0) { return false; } return UpgradeSystem.GetUnlocked((Type)229); } catch { return false; } } private static bool NeedsTempleExitRecovery(Interaction_TempleAltar altar) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown try { if (Mathf.Approximately(Time.timeScale, 0f)) { return true; } } catch { } try { UIManager instance = MonoSingleton.Instance; if ((Object)instance != (Object)null && (instance.ForceBlockMenus || instance.ForceDisableSaving)) { return true; } } catch { } try { GameManager instance2 = GameManager.GetInstance(); if ((Object)instance2 != (Object)null && (Object)instance2.CamFollowTarget != (Object)null && instance2.CamFollowTarget.DisablePlayerLook) { return true; } } catch { } if (GetBoolField(_templeAltarActivatedField, altar) || GetBoolField(_templeAltarActivatingField, altar) || GetBoolField(_templeAltarCoopPlayerFrozenField, altar)) { return true; } return HasLockedExtraTemplePlayer(); } private static bool HasLockedExtraTemplePlayer() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown if (PlayerFarming.players == null) { return false; } for (int i = 0; i < PlayerFarming.players.Count; i++) { PlayerFarming val = PlayerFarming.players[i]; if (!IsExtraTemplePlayer(val)) { continue; } try { if (val.GoToAndStopping) { return true; } if ((Object)val.state != (Object)null && val.state.LockStateChanges) { return true; } } catch { } } return false; } private static void RecoverTempleAltarExitState(Interaction_TempleAltar altar, string reason) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown //IL_0071: 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_00ed: Expected O, but got Unknown try { Time.timeScale = 1f; SimulationManager.UnPause(); } catch { } try { UIManager instance = MonoSingleton.Instance; if ((Object)instance != (Object)null) { instance.ForceBlockMenus = false; instance.ForceDisableSaving = false; } } catch { } try { GameManager instance2 = GameManager.GetInstance(); if ((Object)instance2 != (Object)null) { if ((Object)instance2.CamFollowTarget != (Object)null) { instance2.CamFollowTarget.DisablePlayerLook = false; } instance2.CameraSetOffset(Vector3.zero); instance2.OnConversationEnd(true, true); } } catch { } if ((Object)altar != (Object)null) { SetBoolField(_templeAltarActivatedField, altar, value: false); SetBoolField(_templeAltarActivatingField, altar, value: false); SetBoolField(_templeAltarCoopPlayerFrozenField, altar, value: false); SetBoolField(_templeAltarInteractedField, altar, value: false); try { object? obj4 = _templeAltarColliderField?.GetValue(altar); Collider2D val = (Collider2D)((obj4 is Collider2D) ? obj4 : null); if ((Object)val != (Object)null) { ((Behaviour)val).enabled = true; } } catch { } try { if ((Object)altar.Menu != (Object)null) { altar.Menu.SetActive(false); } ((Interaction)altar).HasChanged = true; if ((Object)((Interaction)altar).state != (Object)null) { ((Interaction)altar).state.CURRENT_STATE = (State)0; } AccessTools.Method(typeof(Interaction_TempleAltar), "ResetSprite", new Type[1] { typeof(bool) }, (Type[])null)?.Invoke(altar, new object[1] { false }); } catch { } } ReleaseTempleExtraPlayers(reason); Plugin.Log.LogWarning((object)("[MP] Temple altar exit recovery applied (" + reason + ")")); } private static bool GetBoolField(FieldInfo field, object instance) { if (field == null || instance == null) { return false; } try { object value = field.GetValue(instance); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static void SetBoolField(FieldInfo field, object instance, bool value) { if (field == null || instance == null) { return; } try { field.SetValue(instance, value); } catch { } } public static bool SpawnPlayerIE_Prefix(PlayerFarming playerFarming, ref Vector3 positionOffset) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if ((Object)playerFarming == (Object)null) { return true; } if (PlayerFarming.players.Count <= 1) { return true; } if (playerFarming.isLamb || playerFarming.playerID <= 1) { return true; } int num = playerFarming.playerID; if (num < 2 || num >= _teleporterOffsets.Length) { num = ResolveTeleporterSlot(playerFarming); } if (num <= 1) { return true; } if (num < 0 || num >= _teleporterOffsets.Length) { return true; } positionOffset = _teleporterOffsets[num]; return true; } public static void PlayerClearRubble_OnInteract_Prefix(Interaction_PlayerClearRubble __instance, StateMachine state) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown PlayerFarming player = (((Object)state != (Object)null) ? ((Component)state).GetComponent() : null); EnsurePlayerClearRubbleCapacity(__instance, player); } public static void PlayerClearRubble_Update_Prefix(Interaction_PlayerClearRubble __instance) { EnsurePlayerClearRubbleCapacity(__instance, null); } public static void PlayerClearRubble_DoBuild_Prefix(Interaction_PlayerClearRubble __instance, PlayerFarming player) { EnsurePlayerClearRubbleCapacity(__instance, player); } public static void PlayerClearRubble_DoBuildMoveNext_Prefix(object __instance) { Interaction_PlayerClearRubble interaction = ResolveClearRubbleFromStateMachine(__instance); PlayerFarming player = ResolveClearRubblePlayerFromStateMachine(__instance); EnsurePlayerClearRubbleCapacity(interaction, player); } public static IEnumerable PlayerClearRubblePlayerIndex_Transpiler(IEnumerable instructions) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown List list = new List(instructions); MethodInfo methodInfo = AccessTools.Method(typeof(List), "IndexOf", new Type[1] { typeof(PlayerFarming) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Patches), "GetClearRubblePlayerIndex", (Type[])null, (Type[])null); for (int i = 0; i < list.Count; i++) { if (methodInfo != null && methodInfo2 != null && CodeInstructionExtensions.Calls(list[i], methodInfo)) { list[i] = new CodeInstruction(OpCodes.Call, (object)methodInfo2); } } return list; } public static int GetClearRubblePlayerIndex(List players, PlayerFarming player) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown int num = -1; if (players != null && (Object)player != (Object)null) { num = players.IndexOf(player); } if (num >= 0) { return num; } if ((Object)player == (Object)null) { return -1; } int playerID = player.playerID; if (playerID >= 0 && playerID < 4) { return playerID; } return -1; } public static Exception PlayerClearRubble_Finalizer(Exception __exception, object __instance) { if (__exception == null) { return null; } if (!(__exception is IndexOutOfRangeException)) { return __exception; } object interaction = ((__instance is Interaction_PlayerClearRubble) ? __instance : null) ?? ResolveClearRubbleFromStateMachine(__instance); PlayerFarming player = ResolveClearRubblePlayerFromStateMachine(__instance); EnsurePlayerClearRubbleCapacity((Interaction_PlayerClearRubble)interaction, player); RecoverClearRubblePlayer(player); Plugin.Log.LogWarning((object)"[MP] Suppressed Interaction_PlayerClearRubble player-slot bounds exception"); return null; } public static void PlayerWork_OnInteract_Prefix(object __instance, StateMachine state) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown PlayerFarming player = (((Object)state != (Object)null) ? ((Component)state).GetComponent() : null); EnsurePlayerWorkButtonCapacity(__instance, player); } public static void PlayerWork_Update_Prefix(object __instance) { EnsurePlayerWorkButtonCapacity(__instance, null); } public static void PlayerWork_MoveNext_Prefix(object __instance) { object interaction = ResolveCoroutineOwner(__instance); PlayerFarming player = ResolveCoroutinePlayer(__instance); EnsurePlayerWorkButtonCapacity(interaction, player); } public static Exception PlayerWork_Finalizer(Exception __exception, object __instance) { if (__exception == null) { return null; } if (!(__exception is IndexOutOfRangeException)) { return __exception; } object obj = __instance; if (!(obj is Interaction_Woodcutting) && !(obj is Interaction_WoodcuttingRubble) && !(obj is Interaction_Berries)) { obj = ResolveCoroutineOwner(__instance); } PlayerFarming player = ResolveCoroutinePlayer(__instance); EnsurePlayerWorkButtonCapacity(obj, player); RecoverPlayerWorkPlayer(player); Plugin.Log.LogWarning((object)"[MP] Suppressed player work interaction slot bounds exception"); return null; } public static MethodInfo FindNestedMoveNext(Type ownerType, string methodName) { if (ownerType == null || string.IsNullOrEmpty(methodName)) { return null; } Type[] nestedTypes = ownerType.GetNestedTypes(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (Type type in nestedTypes) { if (type != null && type.Name.IndexOf("<" + methodName + ">", StringComparison.Ordinal) >= 0) { MethodInfo method = type.GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { return method; } } } return null; } private static void EnsurePlayerClearRubbleCapacity(Interaction_PlayerClearRubble interaction, PlayerFarming player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)interaction == (Object)null || _clearRubbleButtonDownField == null) { return; } PruneClearRubbleActivatingPlayers(interaction); int num = 4; if (PlayerFarming.players != null) { num = Mathf.Max(num, PlayerFarming.players.Count); } num = Mathf.Max(num, PlayerFarming.playersCount); int playerListIndex = GetPlayerListIndex(player); if (playerListIndex >= 0) { num = Mathf.Max(num, playerListIndex + 1); } bool[] array = _clearRubbleButtonDownField.GetValue(interaction) as bool[]; if (array == null || array.Length < num) { bool[] array2 = new bool[num]; if (array != null) { Array.Copy(array, array2, Mathf.Min(array.Length, array2.Length)); } _clearRubbleButtonDownField.SetValue(interaction, array2); Plugin.Log.LogInfo((object)$"[MP] Expanded Interaction_PlayerClearRubble.buttonDown to {array2.Length}"); } } private static void EnsurePlayerWorkButtonCapacity(object interaction, PlayerFarming player) { if (interaction == null) { return; } Type type = interaction.GetType(); FieldInfo field = type.GetField("buttonDown", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return; } PrunePlayerWorkActivatingPlayers(interaction); int num = 4; if (PlayerFarming.players != null) { num = Mathf.Max(num, PlayerFarming.players.Count); } num = Mathf.Max(num, PlayerFarming.playersCount); int clearRubblePlayerIndex = GetClearRubblePlayerIndex(PlayerFarming.players, player); if (clearRubblePlayerIndex >= 0) { num = Mathf.Max(num, clearRubblePlayerIndex + 1); } bool[] array = field.GetValue(interaction) as bool[]; if (array == null || array.Length < num) { bool[] array2 = new bool[num]; if (array != null) { Array.Copy(array, array2, Mathf.Min(array.Length, array2.Length)); } field.SetValue(interaction, array2); Plugin.Log.LogInfo((object)("[MP] Expanded " + type.Name + ".buttonDown to " + array2.Length)); } } private static void PrunePlayerWorkActivatingPlayers(object interaction) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown if (interaction == null || !(interaction.GetType().GetField("activatingPlayers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(interaction) is List { Count: not 0 } list)) { return; } for (int num = list.Count - 1; num >= 0; num--) { PlayerFarming val = list[num]; if ((Object)val == (Object)null || GetClearRubblePlayerIndex(PlayerFarming.players, val) < 0) { list.RemoveAt(num); } } } private static void PruneClearRubbleActivatingPlayers(Interaction_PlayerClearRubble interaction) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown if ((Object)interaction == (Object)null || _clearRubbleActivatingPlayersField == null || !(_clearRubbleActivatingPlayersField.GetValue(interaction) is List { Count: not 0 } list)) { return; } for (int num = list.Count - 1; num >= 0; num--) { PlayerFarming val = list[num]; if ((Object)val == (Object)null || GetPlayerListIndex(val) < 0) { list.RemoveAt(num); } } } private static int GetPlayerListIndex(PlayerFarming player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)player == (Object)null || PlayerFarming.players == null) { return -1; } return GetClearRubblePlayerIndex(PlayerFarming.players, player); } private static Interaction_PlayerClearRubble ResolveClearRubbleFromStateMachine(object stateMachine) { object obj = ResolveCoroutineOwner(stateMachine); return (Interaction_PlayerClearRubble)((obj is Interaction_PlayerClearRubble) ? obj : null); } private static PlayerFarming ResolveClearRubblePlayerFromStateMachine(object stateMachine) { return ResolveCoroutinePlayer(stateMachine); } private static object ResolveCoroutineOwner(object stateMachine) { return stateMachine?.GetType().GetField("<>4__this", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(stateMachine); } private static PlayerFarming ResolveCoroutinePlayer(object stateMachine) { if (stateMachine == null) { return null; } object? obj = stateMachine.GetType().GetField("player", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(stateMachine); return (PlayerFarming)((obj is PlayerFarming) ? obj : null); } private static void RecoverClearRubblePlayer(PlayerFarming player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 if ((Object)player == (Object)null) { return; } try { if ((Object)player.state != (Object)null && (int)player.state.CURRENT_STATE == 49) { player.state.CURRENT_STATE = (State)0; } player.OnCrownReturn?.Invoke(); } catch { } } private static void RecoverPlayerWorkPlayer(PlayerFarming player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 if ((Object)player == (Object)null) { return; } try { if ((Object)player.state != (Object)null && ((int)player.state.CURRENT_STATE == 49 || (int)player.state.CURRENT_STATE == 16)) { player.state.CURRENT_STATE = (State)0; } player.OnCrownReturn?.Invoke(); } catch { } } public static void WeaponPodium_SetWeapon_Postfix(Interaction_WeaponSelectionPodium __instance) { FieldInfo field = typeof(Interaction_WeaponSelectionPodium).GetField("isCoopPodium", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || !(bool)field.GetValue(__instance) || _spawnedExtraWeaponPodiums) { return; } List activeExtraSlotsForPodiums = GetActiveExtraSlotsForPodiums(); if (activeExtraSlotsForPodiums.Count == 0 && _podiumExtraCount > 0) { for (int i = 2; i < 2 + _podiumExtraCount && i < 4; i++) { activeExtraSlotsForPodiums.Add(i); } } if (activeExtraSlotsForPodiums.Count != 0) { _spawnedExtraWeaponPodiums = true; Plugin.Log.LogInfo((object)("WeaponPodium_SetWeapon_Postfix: spawning weapon podiums for slots [" + string.Join(",", activeExtraSlotsForPodiums) + "]")); SpawnExtraPodiumsOfType(__instance, activeExtraSlotsForPodiums, field, "Weapon"); } } public static void WeaponPodium_SetCurse_Postfix(Interaction_WeaponSelectionPodium __instance) { FieldInfo field = typeof(Interaction_WeaponSelectionPodium).GetField("isCoopPodium", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || !(bool)field.GetValue(__instance) || _spawnedExtraSpellPodiums) { return; } List activeExtraSlotsForPodiums = GetActiveExtraSlotsForPodiums(); if (activeExtraSlotsForPodiums.Count == 0 && _podiumExtraCount > 0) { for (int i = 2; i < 2 + _podiumExtraCount && i < 4; i++) { activeExtraSlotsForPodiums.Add(i); } } if (activeExtraSlotsForPodiums.Count != 0) { _spawnedExtraSpellPodiums = true; Plugin.Log.LogInfo((object)("WeaponPodium_SetCurse_Postfix: spawning spell podiums for slots [" + string.Join(",", activeExtraSlotsForPodiums) + "]")); SpawnExtraPodiumsOfType(__instance, activeExtraSlotsForPodiums, field, "Spell"); } } private static List GetActiveExtraSlotsForPodiums() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown List list = new List(); foreach (PlayerFarming player in PlayerFarming.players) { if (!((Object)player == (Object)null) && !player.isLamb && player.playerID >= 2 && player.playerID < 4 && !list.Contains(player.playerID)) { list.Add(player.playerID); } } list.Sort(); return list; } private static PlayerFarming FindActivePlayerBySlot(int slot) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown foreach (PlayerFarming player in PlayerFarming.players) { if ((Object)player != (Object)null && !player.isLamb && player.playerID == slot && ((Component)player).gameObject.activeSelf) { return player; } } return null; } private static IEnumerator EnsureP2DungeonEntranceNotStuckRoutine() { if (_p2EntranceGuardRunning) { yield break; } _p2EntranceGuardRunning = true; try { if (!GameManager.IsDungeon(PlayerFarming.Location)) { yield break; } yield return (object)new WaitForSeconds(1.8f); for (float waited = 0f; waited < 3f; waited += 0.2f) { if (!GameManager.IsDungeon(PlayerFarming.Location)) { break; } PlayerFarming instance = PlayerFarming.Instance; PlayerFarming val = FindActivePlayerBySlot(1); if ((Object)instance != (Object)null && (Object)val != (Object)null && (Object)((Component)instance).gameObject != (Object)null && (Object)((Component)val).gameObject != (Object)null && ((Component)instance).gameObject.activeInHierarchy && ((Component)val).gameObject.activeInHierarchy) { Vector3 val2 = ((Component)val).transform.position - ((Component)instance).transform.position; float magnitude = ((Vector3)(ref val2)).magnitude; bool flag = val2.y < -2.8f && Mathf.Abs(val2.x) < 4.5f && magnitude > 3.2f; bool flag2 = false; bool flag3 = IsFalseKnockedOutState(val); try { if ((Object)val.state != (Object)null) { State cURRENT_STATE = val.state.CURRENT_STATE; flag2 = val.state.LockStateChanges || (int)cURRENT_STATE == 13 || (int)cURRENT_STATE == 49 || (int)cURRENT_STATE == 24 || (int)cURRENT_STATE == 16; } } catch { } if (flag && (flag2 || flag3)) { Vector3 position = ((Component)instance).transform.position + new Vector3(1.25f, -0.1f, 0f); ((Component)val).transform.position = position; try { if ((Object)val.state != (Object)null) { val.state.LockStateChanges = false; val.state.CURRENT_STATE = (State)0; } } catch { } try { if ((Object)val.health != (Object)null && ((Health)val.health).CurrentHP <= 0f) { ((Health)val.health).HP = 2f; } } catch { } val.IsKnockedOut = false; Plugin.Log.LogWarning((object)$"[MP] P2 entrance unstuck applied (dy={val2.y:0.00}, dist={magnitude:0.00}, stateLocked={flag2}, falseDowned={flag3})"); break; } } yield return (object)new WaitForSeconds(0.2f); } } finally { _p2EntranceGuardRunning = false; } } private static bool TryInferPodiumOwnerSlotFromName(Interaction_WeaponSelectionPodium podium, out int slot) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown slot = -1; if ((Object)podium == (Object)null || string.IsNullOrEmpty(((Object)podium).name)) { return false; } int num = ((Object)podium).name.LastIndexOf("_P", StringComparison.OrdinalIgnoreCase); if (num < 0) { return false; } int i = num + 2; int num2 = 0; bool flag = false; for (; i < ((Object)podium).name.Length && char.IsDigit(((Object)podium).name[i]); i++) { flag = true; num2 = num2 * 10 + (((Object)podium).name[i] - 48); } if (!flag) { return false; } int num3 = num2 - 1; if (num3 < 2 || num3 >= 4) { return false; } slot = num3; return true; } private static bool TryGetPodiumOwnerSlot(Interaction_WeaponSelectionPodium podium, out int slot) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown slot = -1; if ((Object)podium == (Object)null) { return false; } int instanceID = ((Object)podium).GetInstanceID(); if (_podiumOwnerSlotByInstanceId.TryGetValue(instanceID, out slot)) { return true; } if (!TryInferPodiumOwnerSlotFromName(podium, out slot)) { return false; } _podiumOwnerSlotByInstanceId[instanceID] = slot; Plugin.Log.LogInfo((object)$"[MP] Inferred podium owner slot {slot} from clone name '{((Object)podium).name}'"); return true; } private static void RelaxPodiumAffinityFor3PlusPlayers(Interaction_WeaponSelectionPodium podium) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown if (!((Object)podium == (Object)null) && PlayerFarming.players != null && PlayerFarming.players.Count > 2) { ((Interaction)podium).LambOnly = false; ((Interaction)podium).GoatOnly = false; Interaction_WeaponSelectionPodium val = null; try { object obj = _twinPodiumField?.GetValue(podium); val = (Interaction_WeaponSelectionPodium)((obj is Interaction_WeaponSelectionPodium) ? obj : null); } catch { val = null; } if ((Object)val != (Object)null) { ((Interaction)val).LambOnly = false; ((Interaction)val).GoatOnly = false; } } } private static void EnsurePodiumCloneOwner(Interaction_WeaponSelectionPodium podium, int slot, PlayerFarming owner, bool forceInteractable) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)podium == (Object)null || slot < 2) { return; } FieldInfo field = typeof(Interaction).GetField("playerFarming", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field2 = typeof(Interaction_WeaponSelectionPodium).GetField("activated", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(podium, null); } else { ((Interaction)podium).playerFarming = null; } ((Interaction)podium).LambOnly = false; ((Interaction)podium).GoatOnly = false; RelaxPodiumAffinityFor3PlusPlayers(podium); if (forceInteractable && !podium.WeaponTaken) { if (field2 != null) { field2.SetValue(podium, false); } ((Interaction)podium).Interactable = true; ((Interaction)podium).SecondaryInteractable = true; ((Behaviour)podium).enabled = true; ((Interaction)podium).HasChanged = true; } } private static IEnumerator DeferredEnsurePodiumOwner(Interaction_WeaponSelectionPodium podium, int slot) { float waited = 0f; while (waited < 3f && !((Object)podium == (Object)null)) { if (!((Component)podium).gameObject.activeInHierarchy) { yield return (object)new WaitForSeconds(0.1f); waited += 0.1f; continue; } PlayerFarming val = FindActivePlayerBySlot(slot); EnsurePodiumCloneOwner(podium, slot, val, forceInteractable: true); if (!((Object)val != (Object)null)) { yield return (object)new WaitForSeconds(0.1f); waited += 0.1f; continue; } break; } } public static void WeaponPodium_OnEnable_Postfix(Interaction_WeaponSelectionPodium __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if (!((Object)__instance == (Object)null)) { RelaxPodiumAffinityFor3PlusPlayers(__instance); if (TryGetPodiumOwnerSlot(__instance, out var slot)) { PlayerFarming owner = FindActivePlayerBySlot(slot); EnsurePodiumCloneOwner(__instance, slot, owner, forceInteractable: true); } } } public static bool WeaponPodium_OnInteract_Prefix(Interaction_WeaponSelectionPodium __instance, StateMachine state) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown if ((Object)__instance == (Object)null) { return true; } RelaxPodiumAffinityFor3PlusPlayers(__instance); if (!TryGetPodiumOwnerSlot(__instance, out var slot)) { return true; } if ((Object)state == (Object)null) { return true; } PlayerFarming component = ((Component)state).GetComponent(); if ((Object)component == (Object)null) { return true; } EnsurePodiumCloneOwner(__instance, slot, component, forceInteractable: true); return true; } public static void WeaponPodium_OnInteract_Postfix(Interaction_WeaponSelectionPodium __instance, StateMachine state) { RelaxPodiumAffinityFor3PlusPlayers(__instance); } private static void SpawnExtraPodiumsOfType(Interaction_WeaponSelectionPodium sourcePodium, List extraSlots, FieldInfo isCoopField, string podLabel) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Expected O, but got Unknown //IL_03bf: Unknown result type (might be due to invalid IL or missing references) if (extraSlots == null || extraSlots.Count == 0) { return; } FieldInfo field = typeof(Interaction).GetField("playerFarming", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field2 = typeof(Interaction_WeaponSelectionPodium).GetField("Used", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field3 = typeof(Interaction_WeaponSelectionPodium).GetField("activated", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field4 = typeof(Interaction_WeaponSelectionPodium).GetField("k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field5 = typeof(Interaction_WeaponSelectionPodium).GetField("CoopPodium", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field6 = typeof(Interaction_WeaponSelectionPodium).GetField("TwinPodium", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field7 = typeof(Interaction_WeaponSelectionPodium).GetField("initialDungeonEnter", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field8 = typeof(Interaction_WeaponSelectionPodium).GetField("coopInitialDungeonEnterSet", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field9 = typeof(Interaction_WeaponSelectionPodium).GetField("otherWeaponOptions", BindingFlags.Instance | BindingFlags.NonPublic); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(0f, 1.5f, 0f); Vector3 position = ((Component)sourcePodium).transform.position; foreach (int extraSlot in extraSlots) { int num = Mathf.Max(1, extraSlot - 1); Vector3 val2 = position + val * (float)num; if (!_podiumClones.TryGetValue(extraSlot, out var value)) { value = new List(); _podiumClones[extraSlot] = value; } for (int num2 = value.Count - 1; num2 >= 0; num2--) { Interaction_WeaponSelectionPodium val3 = value[num2]; if ((Object)val3 == (Object)null) { value.RemoveAt(num2); } else if (((Object)val3).name.StartsWith(podLabel + "Podium_", StringComparison.Ordinal)) { _podiumOwnerSlotByInstanceId.Remove(((Object)val3).GetInstanceID()); Object.Destroy((Object)((Component)val3).gameObject); value.RemoveAt(num2); } } GameObject val4 = Object.Instantiate(((Component)sourcePodium).gameObject, ((Component)sourcePodium).transform.parent); val4.transform.position = val2; val4.transform.rotation = ((Component)sourcePodium).transform.rotation; ((Object)val4).name = $"{podLabel}Podium_P{extraSlot + 1}"; Renderer[] componentsInChildren = val4.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = true; } Interaction_WeaponSelectionPodium component = val4.GetComponent(); isCoopField.SetValue(component, false); component.DestroyOtherWeaponInCoop = false; field?.SetValue(component, null); if (field2 != null) { field2.SetValue(component, false); } if (field3 != null) { field3.SetValue(component, false); } if (field4 != null) { field4.SetValue(component, false); } if (field5 != null) { field5.SetValue(component, null); } if (field6 != null) { field6.SetValue(component, null); } if (field7 != null) { field7.SetValue(component, false); } if (field8 != null) { field8.SetValue(component, false); } if (field9 != null) { field9.SetValue(component, new Interaction_WeaponSelectionPodium[0]); } ((Interaction)component).LambOnly = false; ((Interaction)component).GoatOnly = false; if (!component.WeaponTaken) { ((Interaction)component).Interactable = true; ((Interaction)component).SecondaryInteractable = true; ((Behaviour)component).enabled = true; } ((Interaction)component).HasChanged = true; value.Add(component); _podiumOwnerSlotByInstanceId[((Object)component).GetInstanceID()] = extraSlot; EnsurePodiumCloneOwner(component, extraSlot, null, forceInteractable: true); Plugin.Log.LogInfo((object)$"Extra {podLabel} podium P{extraSlot + 1} at {val2} (free interact)"); } } public static void ResetPodiumFlag() { _spawnedExtraWeaponPodiums = false; _spawnedExtraSpellPodiums = false; _podiumOwnerSlotByInstanceId.Clear(); } public static bool PositionAllPlayers_Prefix(Vector3 pos, bool increment) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) LogDungeonRoomTypeIfChanged(); if (_savedExtraSlotCount <= 0) { return true; } if (_positioningDeferred) { return true; } if (!GameManager.IsDungeon(PlayerFarming.Location)) { return true; } int num = 1 + _savedExtraSlotCount + 1; if (PlayerFarming.playersCount >= num) { return true; } _positioningDeferred = true; Plugin.Log.LogInfo((object)$"PositionAllPlayers deferred — waiting for {num} players (have {PlayerFarming.playersCount})"); if ((Object)CoopManager.Instance != (Object)null) { ((MonoBehaviour)CoopManager.Instance).StartCoroutine(DeferredPositionAllPlayers(pos, increment, num)); } return false; } private static IEnumerator DeferredPositionAllPlayers(Vector3 pos, bool increment, int expectedTotal) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) float waited = 0f; while (PlayerFarming.playersCount < expectedTotal && waited < 15f) { yield return (object)new WaitForSeconds(0.25f); waited += 0.25f; } Plugin.Log.LogInfo((object)$"DeferredPositionAllPlayers: proceeding with {PlayerFarming.playersCount} players after {waited:F1}s"); _positioningDeferred = false; PlayerFarming.PositionAllPlayers(pos, increment); } private static void LogDungeonRoomTypeIfChanged() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown try { if (!GameManager.IsDungeon(PlayerFarming.Location) || (Object)BiomeGenerator.Instance == (Object)null || BiomeGenerator.Instance.CurrentRoom == null) { return; } string text = BiomeGenerator.Instance.CurrentRoom.GameObjectPath ?? "null"; if (!string.Equals(text, _lastLoggedDungeonRoomPath, StringComparison.Ordinal)) { _lastLoggedDungeonRoomPath = text; string text2 = "other"; if (text.IndexOf("Reward Room Tarot.prefab", StringComparison.OrdinalIgnoreCase) >= 0) { text2 = "clauneck_tarot_room"; } else if (text.IndexOf("Special Free Tarot Cards.prefab", StringComparison.OrdinalIgnoreCase) >= 0) { text2 = "cards_only_tarot_room"; } else if (text.IndexOf("Entrance Room Dungeon", StringComparison.OrdinalIgnoreCase) >= 0) { text2 = "dungeon_entrance_room"; } Plugin.Log.LogInfo((object)("[MP] Dungeon room loaded: tag=" + text2 + " path='" + text + "'")); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MP] Failed room-type log: " + ex.Message)); } } private static string GetCurrentDungeonRoomPathSafe() { //IL_0000: 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_0020: Expected O, but got Unknown try { if (!GameManager.IsDungeon(PlayerFarming.Location)) { return null; } if ((Object)BiomeGenerator.Instance == (Object)null || BiomeGenerator.Instance.CurrentRoom == null) { return null; } return BiomeGenerator.Instance.CurrentRoom.GameObjectPath; } catch { return null; } } private static bool IsCurrentDungeonEntranceRoom() { string currentDungeonRoomPathSafe = GetCurrentDungeonRoomPathSafe(); if (!string.IsNullOrEmpty(currentDungeonRoomPathSafe)) { return currentDungeonRoomPathSafe.IndexOf("Entrance Room Dungeon", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } private static int GetCurrentDungeonRoomInstanceIdSafe() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown try { if (!GameManager.IsDungeon(PlayerFarming.Location)) { return int.MinValue; } if ((Object)BiomeGenerator.Instance == (Object)null || BiomeGenerator.Instance.CurrentRoom == null) { return int.MinValue; } return ((object)BiomeGenerator.Instance.CurrentRoom).GetHashCode(); } catch { return int.MinValue; } } private static void StabilizeGoatRoomEntryState(string reason) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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_01d1: Expected O, but got Unknown //IL_0194: 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) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Invalid comparison between Unknown and I4 //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Invalid comparison between Unknown and I4 //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Invalid comparison between Unknown and I4 //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Invalid comparison between Unknown and I4 if (PlayerFarming.players == null) { return; } PlayerFarming instance = PlayerFarming.Instance; if ((Object)instance == (Object)null || (Object)((Component)instance).gameObject == (Object)null || !((Component)instance).gameObject.activeInHierarchy) { return; } foreach (PlayerFarming player in PlayerFarming.players) { if ((Object)player == (Object)null || player.isLamb || (Object)((Component)player).gameObject == (Object)null || !((Component)player).gameObject.activeInHierarchy) { continue; } Vector3 val = ((Component)player).transform.position - ((Component)instance).transform.position; float magnitude = ((Vector3)(ref val)).magnitude; bool flag = IsCurrentDungeonEntranceRoom(); bool flag2 = IsReviveOrCutsceneFlowActive(); if (flag) { if (IsFalseKnockedOutState(player)) { EnsurePlayerAwakeAfterRespawn(player, "RoomEntry:" + reason + ".EntranceFalseDowned"); EnsureExtraSpawnStateUnlocked(player, "RoomEntry:" + reason + ".EntranceFalseDowned"); } continue; } bool num = Time.unscaledTime >= _roomEntryDistanceRepositionGraceUntil; bool flag3 = magnitude > 6f || Mathf.Abs(val.x) > 7.5f || val.y < -2.25f; flag3 = num && (flag ? (magnitude > 10.5f || Mathf.Abs(val.x) > 12f || val.y < -4.5f) : (magnitude > 7.5f || Mathf.Abs(val.x) > 8.75f || (val.y < -4.75f && magnitude > 5.5f))); bool flag4 = false; if (!flag && !flag2) { try { if ((Object)player.state != (Object)null) { State cURRENT_STATE = player.state.CURRENT_STATE; flag4 = player.state.LockStateChanges || (int)cURRENT_STATE == 13 || (int)cURRENT_STATE == 49 || (int)cURRENT_STATE == 24 || (int)cURRENT_STATE == 16; } } catch { } } bool flag5 = IsFalseKnockedOutState(player); bool flag6 = magnitude > 10.5f || Mathf.Abs(val.x) > 12f || (val.y < -6f && magnitude > 6.5f); if ((!flag3 || flag4 || flag5 || flag6) && (flag3 || flag4 || flag5)) { int num2 = player.playerID; if (num2 < 1 || num2 >= SpawnOffsets.Length) { num2 = Mathf.Clamp(num2, 1, SpawnOffsets.Length - 1); } Vector3 position = ((Component)instance).transform.position + SpawnOffsets[num2]; ((Component)player).transform.position = position; EnsurePlayerAwakeAfterRespawn(player, "RoomEntry:" + reason); EnsureExtraSpawnStateUnlocked(player, "RoomEntry:" + reason); Plugin.Log.LogWarning((object)$"[MP] Room stabilize repositioned playerID={player.playerID} (dist={magnitude:0.00}, stuck={flag4}, falseDowned={flag5})"); } } } private static void TryQueueDungeonRoomStabilize(string reason) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!CoopManager.CoopActive || (Object)CoopManager.Instance == (Object)null || !GameManager.IsDungeon(PlayerFarming.Location) || Time.unscaledTime < _nextDungeonRoomStabilizeCheckAt) { return; } _nextDungeonRoomStabilizeCheckAt = Time.unscaledTime + 0.25f; int currentDungeonRoomInstanceIdSafe = GetCurrentDungeonRoomInstanceIdSafe(); if (currentDungeonRoomInstanceIdSafe == int.MinValue || currentDungeonRoomInstanceIdSafe == _lastStabilizedDungeonRoomId || _dungeonRoomStabilizeRunning) { return; } if (IsCurrentDungeonEntranceRoom()) { if (!_p2EntranceGuardRunning) { ((MonoBehaviour)CoopManager.Instance).StartCoroutine(EnsureP2DungeonEntranceNotStuckRoutine()); } _lastStabilizedDungeonRoomId = currentDungeonRoomInstanceIdSafe; _roomEntryDistanceRepositionGraceUntil = Time.unscaledTime + 2.5f; } else { _roomEntryDistanceRepositionGraceUntil = Time.unscaledTime + 0.65f; _lastStabilizedDungeonRoomId = currentDungeonRoomInstanceIdSafe; ((MonoBehaviour)CoopManager.Instance).StartCoroutine(DungeonRoomTransitionStabilizeRoutine(currentDungeonRoomInstanceIdSafe, reason)); } } private static IEnumerator DungeonRoomTransitionStabilizeRoutine(int roomId, string reason) { if (_dungeonRoomStabilizeRunning) { yield break; } _dungeonRoomStabilizeRunning = true; try { yield return (object)new WaitForSeconds(0.2f); for (int i = 0; i < 18; i++) { if ((Object)CoopManager.Instance == (Object)null) { break; } if (!CoopManager.CoopActive) { break; } if (!GameManager.IsDungeon(PlayerFarming.Location)) { break; } int currentDungeonRoomInstanceIdSafe = GetCurrentDungeonRoomInstanceIdSafe(); if (currentDungeonRoomInstanceIdSafe == int.MinValue || currentDungeonRoomInstanceIdSafe == roomId) { ClearFalseKnockedOutStatesForAll("RoomStabilize:" + reason); EnsureAllExtraPlayersUnlocked("RoomStabilize:" + reason); if (i <= 4) { StabilizeGoatRoomEntryState($"{reason}.tick{i}"); } if (i == 0 || i == 2 || i == 6 || i == 12) { AggressiveControllerOwnershipHeartbeat("RoomStabilize:" + reason); _nextAutoRespawnAttemptAt = 0f; TryAutoRespawnMissingExtraSlots($"RoomStabilize:{reason}.tick{i}"); } yield return (object)new WaitForSeconds(0.2f); continue; } break; } } finally { _dungeonRoomStabilizeRunning = false; } } private static void ForceRefreshFaithAmmoUI(FaithAmmo faithAmmo, string reason) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)faithAmmo == (Object)null) { return; } try { if (_faithAmmoUpdateBar != null) { _faithAmmoUpdateBar.Invoke(faithAmmo, null); } else { faithAmmo.Ammo = faithAmmo.Ammo; } } catch { try { faithAmmo.Ammo = faithAmmo.Ammo; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[MP] faithAmmo UI refresh failed (" + reason + "): " + ex.Message)); } } } private static void SyncFaithAmmoForOwner(PlayerFarming owner, HUD_Hearts hearts, string reason, bool forceReinit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_004f: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0070: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_0091: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00ca: Expected O, but got Unknown if ((Object)owner == (Object)null || (Object)hearts == (Object)null || (Object)hearts.faithAmmo == (Object)null) { return; } FaithAmmo faithAmmo = hearts.faithAmmo; bool flag = false; if ((Object)hearts.playerFarming != (Object)owner) { hearts.playerFarming = owner; flag = true; } if ((Object)owner.hudHearts != (Object)hearts) { owner.hudHearts = hearts; flag = true; } if ((Object)faithAmmo.playerFarming != (Object)owner) { faithAmmo.playerFarming = owner; flag = true; } if ((Object)owner.playerSpells != (Object)null && (Object)owner.playerSpells.faithAmmo != (Object)faithAmmo) { owner.playerSpells.faithAmmo = faithAmmo; flag = true; Plugin.Log.LogInfo((object)$"[MP] Synced playerSpells.faithAmmo -> HUD faithAmmo for playerID={owner.playerID} ({reason})"); } if (!forceReinit && !flag) { return; } try { faithAmmo.Init(owner); faithAmmo.Ammo = faithAmmo.Ammo; ForceRefreshFaithAmmoUI(faithAmmo, reason); Plugin.Log.LogInfo((object)$"[MP] Rebound faithAmmo for playerID={owner.playerID} ({reason})"); } catch (Exception ex) { Plugin.Log.LogWarning((object)$"[MP] faithAmmo sync failed playerID={owner.playerID} ({reason}): {ex.Message}"); } } private static IEnumerator ReassignHudHeartsNextFrame(PlayerFarming p, HUD_Hearts hearts) { yield return null; if ((Object)p != (Object)null && (Object)hearts != (Object)null) { if ((Object)hearts.playerFarming != (Object)p) { hearts.playerFarming = p; } if ((Object)p.hudHearts != (Object)hearts) { p.hudHearts = hearts; Plugin.Log.LogInfo((object)$"[MP] Re-assigned hudHearts for playerID={p.playerID} after frame delay"); } } yield return null; SyncFaithAmmoForOwner(p, hearts, "ReassignHudHeartsNextFrame", forceReinit: true); } public static bool HUDHearts_SetWeapon_Prefix(HUD_Hearts __instance, EquipmentType weapon, int level, PlayerFarming playerfarming) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0039: 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_0049: Expected O, but got Unknown //IL_0049: Expected O, but got Unknown if ((Object)playerfarming == (Object)null) { return false; } if ((Object)__instance == (Object)null) { return false; } if ((Object)__instance.playerFarming != (Object)null && (Object)__instance.playerFarming != (Object)playerfarming) { return true; } FieldInfo field = typeof(HUD_Hearts).GetField("currentWeapon", BindingFlags.Instance | BindingFlags.Public); if (field == null) { return true; } if (field.GetValue(__instance) == null) { return false; } return true; } public static bool HUDHearts_SetCurse_Prefix(HUD_Hearts __instance, EquipmentType curse, int level, PlayerFarming playerfarming) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0039: 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_0049: Expected O, but got Unknown //IL_0049: Expected O, but got Unknown if ((Object)playerfarming == (Object)null) { return false; } if ((Object)__instance == (Object)null) { return false; } if ((Object)__instance.playerFarming != (Object)null && (Object)__instance.playerFarming != (Object)playerfarming) { return true; } FieldInfo field = typeof(HUD_Hearts).GetField("currentCurse", BindingFlags.Instance | BindingFlags.Public); if (field == null) { return true; } if (field.GetValue(__instance) == null) { return false; } return true; } private static bool IsCanonicalHudHearts(HUD_Hearts hearts) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0065: Expected O, but got Unknown if ((Object)hearts == (Object)null) { return false; } PlayerFarming playerFarming = hearts.playerFarming; if ((Object)playerFarming == (Object)null || (Object)((Component)playerFarming).gameObject == (Object)null) { return false; } if ((Object)playerFarming.hudHearts == (Object)null) { return true; } return (Object)playerFarming.hudHearts == (Object)hearts; } private static bool ShouldSuppressHudHeartEffects(HUD_Heart heart) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown if ((Object)heart == (Object)null) { return false; } HUD_Hearts val = null; try { val = ((Component)heart).GetComponentInParent(true); } catch { val = null; } if ((Object)val == (Object)null) { return false; } if (IsCanonicalHudHearts(val)) { return false; } int instanceID = ((Object)heart).GetInstanceID(); if (_suppressedHeartEffectLogs.Add(instanceID)) { int num = (((Object)val.playerFarming != (Object)null) ? val.playerFarming.playerID : (-1)); Plugin.Log.LogWarning((object)$"[MP] Suppressing stale heart effect for ownerID={num}, heartInstance={instanceID}"); } return true; } public static void HUDHeart_SetSprite_Prefix(HUD_Heart __instance, ref bool DoEffects) { if (DoEffects && ShouldSuppressHudHeartEffects(__instance)) { DoEffects = false; } } public static void HUDHeart_Activate_Prefix(HUD_Heart __instance, ref bool DoEffects) { if (DoEffects && ShouldSuppressHudHeartEffects(__instance)) { DoEffects = false; } } private static bool IsCanonicalFaithAmmo(FaithAmmo faithAmmo) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0064: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00a9: Expected O, but got Unknown if ((Object)faithAmmo == (Object)null) { return false; } HUD_Hearts val = null; try { val = ((Component)faithAmmo).GetComponentInParent(true); } catch { val = null; } if ((Object)val == (Object)null) { return true; } if (!IsCanonicalHudHearts(val)) { return false; } if ((Object)val.faithAmmo != (Object)null && (Object)val.faithAmmo != (Object)faithAmmo) { return false; } if ((Object)faithAmmo.playerFarming != (Object)null && (Object)val.playerFarming != (Object)null && (Object)faithAmmo.playerFarming != (Object)val.playerFarming) { return false; } return true; } private static bool IsLiveFaithAmmoForOwner(FaithAmmo faithAmmo) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0048: 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_0058: Expected O, but got Unknown //IL_0058: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_008a: Expected O, but got Unknown if ((Object)faithAmmo == (Object)null || (Object)faithAmmo.playerFarming == (Object)null) { return false; } PlayerFarming playerFarming = faithAmmo.playerFarming; if ((Object)playerFarming.hudHearts != (Object)null && (Object)playerFarming.hudHearts.faithAmmo == (Object)faithAmmo) { return true; } if ((Object)playerFarming.playerSpells != (Object)null && (Object)playerFarming.playerSpells.faithAmmo == (Object)faithAmmo) { return true; } return false; } private static void LogFaithAmmoSuppressed(FaithAmmo faithAmmo, string reason) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (!((Object)faithAmmo == (Object)null)) { int instanceID = ((Object)faithAmmo).GetInstanceID(); if (_suppressedFaithAmmoLogs.Add(instanceID)) { int num = (((Object)faithAmmo.playerFarming != (Object)null) ? faithAmmo.playerFarming.playerID : (-1)); Plugin.Log.LogWarning((object)$"[MP] Suppressing stale faithAmmo ({reason}) for ownerID={num}, instance={instanceID}"); } } } private static void LogTrinketHudSuppressed(HUD_ActiveTrinketsCoOp hud, string reason) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (!((Object)hud == (Object)null)) { int instanceID = ((Object)hud).GetInstanceID(); if (_suppressedTrinketHudLogs.Add(instanceID)) { int num = (((Object)hud.playerFarming != (Object)null) ? hud.playerFarming.playerID : (-1)); Plugin.Log.LogWarning((object)$"[MP] Suppressing stale trinket HUD update ({reason}) for ownerID={num}, instance={instanceID}"); } } } public static bool HUDActiveTrinketsCoOp_OnTrinketsChanged_Prefix(HUD_ActiveTrinketsCoOp __instance, ref PlayerFarming playerFarming) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_0092: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown if ((Object)__instance == (Object)null) { return false; } PlayerFarming playerFarming2 = __instance.playerFarming; if ((Object)playerFarming2 == (Object)null) { LogTrinketHudSuppressed(__instance, "OnTrinketsChanged.ownerNull"); if ((Object)__instance.CardPrefab != (Object)null && (Object)((Component)__instance.CardPrefab).gameObject != (Object)null) { ((Component)__instance.CardPrefab).gameObject.SetActive(false); } return false; } if ((Object)playerFarming == (Object)null) { playerFarming = playerFarming2; } if ((Object)playerFarming2 != (Object)playerFarming) { return false; } if (playerFarming.RunTrinkets == null) { LogTrinketHudSuppressed(__instance, "OnTrinketsChanged.runTrinketsNull"); if ((Object)__instance.CardPrefab != (Object)null && (Object)((Component)__instance.CardPrefab).gameObject != (Object)null) { ((Component)__instance.CardPrefab).gameObject.SetActive(false); } return false; } return true; } public static bool HUDActiveTrinketsCoOp_OnRomanNumeralSettingChanged_Prefix(HUD_ActiveTrinketsCoOp __instance, bool state) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown if ((Object)__instance == (Object)null) { return false; } if ((Object)__instance.playerFarming == (Object)null || __instance.playerFarming.RunTrinkets == null) { LogTrinketHudSuppressed(__instance, "OnRomanNumeralSettingChanged.ownerNull"); return false; } if ((Object)__instance.CardPrefab == (Object)null || (Object)__instance.CardPrefab.CardQuantity == (Object)null) { LogTrinketHudSuppressed(__instance, "OnRomanNumeralSettingChanged.cardNull"); return false; } return true; } public static bool FaithAmmo_OnEnable_Prefix(FaithAmmo __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown if ((Object)__instance == (Object)null) { return false; } if (!IsCanonicalFaithAmmo(__instance) && !IsLiveFaithAmmoForOwner(__instance)) { LogFaithAmmoSuppressed(__instance, "OnEnable"); return false; } if ((Object)__instance.playerFarming != (Object)null && (Object)__instance.playerFarming.hudHearts != (Object)null) { SyncFaithAmmoForOwner(__instance.playerFarming, __instance.playerFarming.hudHearts, "FaithAmmo.OnEnable", forceReinit: false); } return true; } public static bool FaithAmmo_OnGetSoul_Prefix(FaithAmmo __instance, int DeltaValue, PlayerFarming playerFarming) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0066: Expected O, but got Unknown if ((Object)__instance == (Object)null) { return false; } if (!IsCanonicalFaithAmmo(__instance) && !IsLiveFaithAmmoForOwner(__instance)) { LogFaithAmmoSuppressed(__instance, "OnGetSoul"); return false; } if ((Object)__instance.playerFarming == (Object)null || (Object)playerFarming == (Object)null) { return false; } return (Object)__instance.playerFarming == (Object)playerFarming; } public static bool FaithAmmo_UseAmmo_Prefix(FaithAmmo __instance, float Amount, bool curseAttack, ref bool __result) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_0123: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Expected O, but got Unknown if ((Object)__instance == (Object)null) { __result = false; return false; } if ((Object)((Component)__instance).gameObject == (Object)null || !((Component)__instance).gameObject.activeInHierarchy || !((Behaviour)__instance).isActiveAndEnabled) { LogFaithAmmoSuppressed(__instance, "UseAmmo.inactive"); __result = false; return false; } if (_reroutingFaithAmmoUse) { return true; } PlayerFarming playerFarming = __instance.playerFarming; if ((Object)playerFarming == (Object)null) { return true; } FaithAmmo val = null; if ((Object)playerFarming.hudHearts != (Object)null && (Object)playerFarming.hudHearts.faithAmmo != (Object)null) { val = playerFarming.hudHearts.faithAmmo; } else if ((Object)playerFarming.playerSpells != (Object)null && (Object)playerFarming.playerSpells.faithAmmo != (Object)null) { val = playerFarming.playerSpells.faithAmmo; } if ((Object)val == (Object)null) { if ((Object)playerFarming.hudHearts != (Object)null) { SyncFaithAmmoForOwner(playerFarming, playerFarming.hudHearts, "FaithAmmo.UseAmmo.ResolveCanonical", forceReinit: true); } return true; } if ((Object)__instance == (Object)val) { return true; } LogFaithAmmoSuppressed(__instance, "UseAmmo"); try { if ((Object)((Component)val).gameObject == (Object)null || !((Component)val).gameObject.activeInHierarchy || !((Behaviour)val).isActiveAndEnabled) { LogFaithAmmoSuppressed(val, "UseAmmo.canonicalInactive"); __result = false; return false; } _reroutingFaithAmmoUse = true; __result = val.UseAmmo(Amount, curseAttack); } catch (Exception ex) { Plugin.Log.LogWarning((object)$"[MP] Failed rerouting UseAmmo to canonical faithAmmo for playerID={playerFarming.playerID}: {ex.Message}"); __result = false; } finally { _reroutingFaithAmmoUse = false; } ForceRefreshFaithAmmoUI(val, "FaithAmmo.UseAmmo.Reroute"); return false; } public static void FaithAmmo_UseAmmo_Postfix(FaithAmmo __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if (!((Object)__instance == (Object)null) && !_reroutingFaithAmmoUse) { ForceRefreshFaithAmmoUI(__instance, "FaithAmmo.UseAmmo.Postfix"); } } public static bool HUDHearts_OnHPUpdated_Prefix(HUD_Hearts __instance, HealthPlayer Target) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0038: Expected O, but got Unknown if (!IsCanonicalHudHearts(__instance)) { return false; } if ((Object)__instance.playerFarming != (Object)null) { return (Object)__instance.playerFarming.health == (Object)Target; } return false; } public static bool HUDHearts_OnTotalHPUpdated_Prefix(HUD_Hearts __instance, HealthPlayer Target) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0038: Expected O, but got Unknown if (!IsCanonicalHudHearts(__instance)) { return false; } if ((Object)__instance.playerFarming != (Object)null) { return (Object)__instance.playerFarming.health == (Object)Target; } return false; } public static bool HUDHearts_OnEnable_Prefix(HUD_Hearts __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0040: 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_0050: Expected O, but got Unknown //IL_0050: Expected O, but got Unknown if ((Object)__instance == (Object)null) { return false; } PlayerFarming playerFarming = __instance.playerFarming; if ((Object)playerFarming == (Object)null) { return true; } if ((Object)playerFarming.hudHearts != (Object)null && (Object)playerFarming.hudHearts != (Object)__instance) { TryClearHudHeartEvents(__instance); return false; } return true; } private static void TryClearHudHeartEvents(HUD_Hearts hearts) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown if ((Object)hearts == (Object)null || _hudHeartsClearHealthEvents == null) { return; } try { _hudHeartsClearHealthEvents.Invoke(hearts, null); } catch (Exception ex) { Plugin.Log.LogWarning((object)("HealthManager: failed ClearHealthEvents invoke: " + ex.Message)); } } public static bool HealthManager_Init(Health_Manager __instance, PlayerFarming p) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) if (p.isLamb) { return true; } if (p.playerID < 2) { return true; } if (!GameManager.IsDungeon(PlayerFarming.Location)) { return true; } FieldInfo field = typeof(Health_Manager).GetField("health_secondPlayer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field2 = typeof(Health_Manager).GetField("healthDungeonTwoPlayer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { Plugin.Log.LogWarning((object)"HealthManager: health_secondPlayer field not found"); return true; } object value = field.GetValue(__instance); HUD_Hearts val = (HUD_Hearts)((value is HUD_Hearts) ? value : null); if ((Object)val == (Object)null) { Plugin.Log.LogWarning((object)"HealthManager: p2Bar is null"); return true; } object obj = field2?.GetValue(__instance); GameObject val2 = (GameObject)((obj is GameObject) ? obj : null); if ((Object)val2 != (Object)null) { val2.SetActive(true); } if (_extraHeartBars.TryGetValue(p.playerID, out var value2) && (Object)value2 != (Object)null) { Object.Destroy((Object)value2); Plugin.Log.LogInfo((object)$"HealthManager: destroyed stale cached heart bar for playerID={p.playerID}"); } _extraHeartBars.Remove(p.playerID); GameObject val3 = Object.Instantiate(((Component)val).gameObject, ((Component)val).transform.parent); ((Object)val3).name = $"HUD_Hearts_P{p.playerID + 1}"; val3.SetActive(false); int num = p.playerID - 2; RectTransform component = ((Component)val).GetComponent(); RectTransform component2 = val3.GetComponent(); if ((Object)component != (Object)null && (Object)component2 != (Object)null) { Vector2 anchoredPosition = component.anchoredPosition; Rect rect = component.rect; component2.anchoredPosition = anchoredPosition + new Vector2(0f, (0f - (((Rect)(ref rect)).height + 10f)) * (float)(num + 1)); } _extraHeartBars[p.playerID] = val3; HUD_Hearts component3 = val3.GetComponent(); if ((Object)component3 != (Object)null) { TryClearHudHeartEvents(component3); component3.playerFarming = null; component3.InitDungeon(p); p.hudHearts = component3; val3.SetActive(true); SyncFaithAmmoForOwner(p, component3, $"HealthManager_Init(playerID={p.playerID})", forceReinit: true); Plugin.Log.LogInfo((object)$"HealthManager: spawned heart bar for playerID={p.playerID} at stack index {num}"); HUD_Hearts hearts = component3; CoopManager instance = CoopManager.Instance; if ((Object)(object)instance != (Object)null) { ((MonoBehaviour)instance).StartCoroutine(ReassignHudHeartsNextFrame(p, hearts)); } } else { val3.SetActive(true); Plugin.Log.LogWarning((object)$"HealthManager: HUD_Hearts component not found on clone for playerID={p.playerID}"); } return false; } public static IEnumerable BiomeConstants_BiomeGenerator_OnBiomeChangeRoom_Transpiler(IEnumerable instructions) { MethodInfo clearNoArgs = AccessTools.Method(typeof(ParticleSystem), "Clear", Type.EmptyTypes, (Type[])null); MethodInfo clearWithChildren = AccessTools.Method(typeof(ParticleSystem), "Clear", new Type[1] { typeof(bool) }, (Type[])null); MethodInfo safeNoArgs = AccessTools.Method(typeof(Patches), "SafeParticleClear_NoArgs", (Type[])null, (Type[])null); MethodInfo safeWithChildren = AccessTools.Method(typeof(Patches), "SafeParticleClear_WithChildren", (Type[])null, (Type[])null); int replacedNoArgs = 0; int replacedWithChildren = 0; foreach (CodeInstruction instruction in instructions) { if (clearNoArgs != null && CodeInstructionExtensions.Calls(instruction, clearNoArgs)) { replacedNoArgs++; instruction.opcode = OpCodes.Call; instruction.operand = safeNoArgs; } else if (clearWithChildren != null && CodeInstructionExtensions.Calls(instruction, clearWithChildren)) { replacedWithChildren++; instruction.opcode = OpCodes.Call; instruction.operand = safeWithChildren; } yield return instruction; } int num = replacedNoArgs + replacedWithChildren; if (_safeBiomeClearPatchCountLog != num) { _safeBiomeClearPatchCountLog = num; Plugin.Log.LogInfo((object)($"[MP] Safe biome particle-clear transpiler replaced {num} ParticleSystem.Clear call(s) " + $"(noArgs={replacedNoArgs}, withChildren={replacedWithChildren})")); } } private static void SafeParticleClear_NoArgs(ParticleSystem _) { } private static void SafeParticleClear_WithChildren(ParticleSystem _, bool __) { } public static Exception SilentFinalizer(Exception __exception) { return null; } private static Texture2D BuildNumberTexture(string label, int w = 32, int h = 32) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown //IL_001e: 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_015d: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(w, h, (TextureFormat)4, false); Color[] array = (Color[])(object)new Color[w * h]; for (int i = 0; i < array.Length; i++) { array[i] = Color.clear; } if (_digitBitmaps.TryGetValue((label.Length > 0) ? label[0] : '?', out var value)) { float num = ((float)w - 4f) / 5f; float num2 = ((float)h - 4f) / 7f; int num3 = 2; int num4 = 2; for (int j = 0; j < 7; j++) { for (int k = 0; k < 5; k++) { if (value[j * 5 + k] == 0) { continue; } for (int l = -2; l <= 2; l++) { for (int m = -2; m <= 2; m++) { int num5 = num3 + (int)((float)k * num) + m; int num6 = num4 + (int)((float)j * num2) + l; if (num5 >= 0 && num5 < w && num6 >= 0 && num6 < h) { array[num6 * w + num5] = Color.black; } } } } } for (int n = 0; n < 7; n++) { for (int num7 = 0; num7 < 5; num7++) { if (value[n * 5 + num7] != 0) { int num8 = num3 + (int)((float)num7 * num); int num9 = num4 + (int)((float)n * num2); if (num8 >= 0 && num8 < w && num9 >= 0 && num9 < h) { array[num9 * w + num8] = Color.white; } } } } } val.SetPixels(array); val.Apply(); return val; } private static Texture2D LoadPNG(string path) { //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Expected O, but got Unknown //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) byte[] array = File.ReadAllBytes(path); int num = (array[16] << 24) | (array[17] << 16) | (array[18] << 8) | array[19]; int num2 = (array[20] << 24) | (array[21] << 16) | (array[22] << 8) | array[23]; int num3 = array[24]; int num4 = array[25]; if (num3 != 8 || (num4 != 6 && num4 != 2)) { Plugin.Log.LogWarning((object)$"[MP] PNG {path} unsupported format colorType={num4} bitDepth={num3}"); return null; } bool flag = num4 == 6; int num5 = (flag ? 4 : 3); List list = new List(); int num6; for (int i = 8; i < array.Length - 4; i += 12 + num6) { num6 = (array[i] << 24) | (array[i + 1] << 16) | (array[i + 2] << 8) | array[i + 3]; if (Encoding.ASCII.GetString(array, i + 4, 4) == "IDAT") { for (int j = 0; j < num6; j++) { list.Add(array[i + 8 + j]); } } } byte[] array2 = list.ToArray(); byte[] array3; using (MemoryStream stream = new MemoryStream(array2, 2, array2.Length - 2)) { using DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress); using MemoryStream memoryStream = new MemoryStream(); deflateStream.CopyTo(memoryStream); array3 = memoryStream.ToArray(); } Color[] array4 = (Color[])(object)new Color[num * num2]; int num7 = num * num5 + 1; byte[] array5 = new byte[num * num5]; for (int k = 0; k < num2; k++) { int num8 = k * num7; byte b = array3[num8]; byte[] array6 = new byte[num * num5]; for (int l = 0; l < num * num5; l++) { byte b2 = array3[num8 + 1 + l]; byte b3 = (byte)((l >= num5) ? array6[l - num5] : 0); byte b4 = array5[l]; byte c = (byte)((l >= num5) ? array5[l - num5] : 0); byte[] array7 = array6; int num9 = l; array7[num9] = b switch { 1 => (byte)(b2 + b3), 2 => (byte)(b2 + b4), 3 => (byte)(b2 + (b3 + b4 >> 1)), 4 => (byte)(b2 + PaethPredictor(b3, b4, c)), _ => b2, }; } int num10 = num2 - 1 - k; for (int m = 0; m < num; m++) { int num11 = m * num5; float num12 = (float)(int)array6[num11] / 255f; float num13 = (float)(int)array6[num11 + 1] / 255f; float num14 = (float)(int)array6[num11 + 2] / 255f; float num15 = (flag ? ((float)(int)array6[num11 + 3] / 255f) : 1f); array4[num10 * num + m] = new Color(num12, num13, num14, num15); } array5 = array6; } Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false) { filterMode = (FilterMode)1 }; val.SetPixels(array4); val.Apply(); return val; } private static byte PaethPredictor(byte a, byte b, byte c) { int num = a + b - c; int num2 = Math.Abs(num - a); int num3 = Math.Abs(num - b); int num4 = Math.Abs(num - c); if (num2 > num3 || num2 > num4) { if (num3 > num4) { return c; } return b; } return a; } } }