using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Microsoft.CodeAnalysis; using MoreMountains.Tools; using MoreMountains.TopDownEngine; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.Utilities; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using UnityEngine.SceneManagement; using UnityEngine.UI; using World; using World.AI; using World.AI.PreventBeingAttackedOnSight; using World.Burrows; using World.Characters; using World.Characters.Bosses; using World.Characters.Enemies.Navigation; using World.CustomTDEAbilities; using World.Evolutions; using World.Evolutions.Abilities.Attacks; using World.Evolutions.Abilities.Dashes; using World.Evolutions.Specializations; using World.Evolutions.UI; using World.HeatAndCold; using World.Items; using World.Mushrooms; using World.Mushrooms.Effects; using World.Stats; using World.Stats.StatValueTypes; using World.TimeManagement; using World.UI; using World.UI.HUD; using World.UI.MainMenuScreen; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("Everything_is_Multiplayer")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+24fd158a5b1ed61a4eaa20c2f65c0bde0a4af2de")] [assembly: AssemblyProduct("Everything_is_Multiplayer")] [assembly: AssemblyTitle("Everything_is_Multiplayer")] [assembly: AssemblyVersion("1.0.0.0")] [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 Everything_is_Multiplayer { public sealed class LocalMultiplayerDriver : MonoBehaviour { private sealed class NightVisionMaterialState { public Material Material; public Vector4 BaseCenter; public float BaseViewportRadius; public float BaseGradientRadius; public Vector4 LastAppliedCenter = new Vector4(float.NaN, float.NaN, float.NaN, float.NaN); public float LastAppliedViewportRadius = float.NaN; public float LastAppliedGradientRadius = float.NaN; } private const string PlayerTwoName = "LocalMultiplayer_Player2"; private const string PlayerOnePendingDestroyName = "LocalMultiplayer_Player1_PendingDestroy"; private const string PlayerOneLabelName = "LocalMultiplayer_Player1_Label"; private const string PlayerTwoLabelName = "LocalMultiplayer_Player2_Label"; private static readonly Color PlayerOneLabelColor = new Color(0.56f, 0.95f, 0.65f, 1f); private static readonly Color PlayerTwoTint = new Color(0.55f, 0.9f, 1f, 1f); private int _sceneHandle; private int _playerOneId; private int _playerTwoId; private int _cameraId; private int _lastGamepadCount = -1; private float _baseOrthographicSize; private float _smoothedOrthographicSize; private Vector2 _smoothedCameraCenter; private bool _hasSharedCameraState; private int _cameraEnforcerId; private readonly Dictionary _nightVisionMaterialStates = new Dictionary(); private bool _previousDashHeld; private bool _previousInteractHeld; private bool _loggedPlayerTwoInput; private bool _loggedFilteredStockInput; private bool _loggedGameplaySpawnFallback; private bool _loggedPlayerTwoDamageAttempt; private bool _loggedPlayerTwoDamageOutputOverride; private bool _loggedPlayerTwoMasterHealthCleared; private bool _loggedPlayerTwoColliderState; private bool _loggedPlayerTwoPhysicalColliderEnabled; private bool _loggedPlayerTwoRigidbodyEnabled; private bool _loggedPlayerTwoDamageOnTouchCollision; private bool _loggedPlayerTwoDamageOnTouchMaskPatched; private bool _loggedPlayerTwoDamageOnTouchIgnoreCleared; private bool _loggedPlayerTwoDamageOnTouchFallback; private bool _loggedPlayerTwoAiIgnoreCleared; private bool _loggedPlayerTwoDirectAiRegistration; private bool _loggedPlayerTwoDirectAiRegistrationFailure; private bool _loggedPlayerTwoAttackScoreForced; private bool _loggedPlayerTwoTargetConsidered; private bool _loggedPlayerTwoPreventSightBypass; private bool _loggedFriendlyFireSuppressed; private int _playerTwoDamageResultLogs; private bool _playerOneDead; private bool _playerOneAwaitingRevive; private bool _playerTwoDead; private bool _playerTwoAwaitingRevive; private string _playerOneObjectName = "PlayerCharacter"; private readonly List _playerOneSpriteColors = new List(); private bool _evolutionPickerOpen; private int _suppressedPlayerDeathDropCount; private bool _previousDumpStateHeld; private bool _previousRespawnHeld; private bool _previousForceSpawnHeld; private bool _previousDamagePlayerTwoHeld; private bool _previousDamagePlayerOneHeld; private readonly bool[] _previousAttackHeld = new bool[5]; private float _nextSpawnAttemptAt; private float _nextStatusLogAt; private float _nextSpawnWaitLogAt; private float _nextAiRefreshAt; private int _damageOnTouchStateKey; private Health _damageOnTouchStateHealth; private GameObject _damageOnTouchStateInstigator; private float _damageOnTouchStateBeforeHealth; private float _damageOnTouchStateFallbackDamage; private float _damageOnTouchStateInvincibilityDuration; private int _damageOnTouchStateContextualDeathTip; private string _damageOnTouchStateSourceName = string.Empty; private string _lastSpawnWaitReason = string.Empty; private string _playerTwoDamageHudStatus = "P2 DMG: WAIT"; private string _playerTwoAiHudStatus = "P2 AI: WAIT"; private string _cameraHudStatus = "CAM: WAIT"; private bool _debugPlayerOneInputOverride; private bool _applyingDiagnosticDamage; private Action _beginCameraRenderingHandler; private bool _debugPlayerTwoInputOverride; private int _debugPlayerOneGamepadIndex = -1; private int _debugPlayerTwoGamepadIndex = -1; private Vector2 _debugPlayerOneMove; private Vector2 _debugPlayerOneAim = Vector2.right; private Vector2 _debugPlayerTwoMove; private Vector2 _debugPlayerTwoAim = Vector2.right; private bool _debugPlayerTwoDashHeld; private bool _debugPlayerTwoInteractHeld; private readonly bool[] _debugPlayerTwoAttackHeld = new bool[5]; private Vector2 _playerOneMove; private Vector2 _playerOneAim = Vector2.right; private bool _playerOneAimControlled; private float _lastPlayerTwoSizePercentage = float.NaN; private int _mushroomManagerId; private List _playerOneMushroomEffects; private List _playerTwoMushroomEffects; private List _mushroomEffectsBeforeConsumption; private int _mushroomConsumptionRoutingDepth; private PlayerCharacter _mushroomConsumerPreviousSingleton; private int _mushroomConsumerSingletonDepth; private bool _updatingOwnedMushroomEffects; private int _lastMushroomEffectUpdatePlayerNumber; public static LocalMultiplayerDriver Instance { get; private set; } public PlayerCharacter PlayerOne { get; private set; } public PlayerCharacter PlayerTwo { get; private set; } public PlayerTwoInputState InputState { get; private set; } public Vector2 PlayerOneMoveInput => _playerOneMove; public int PlayerOneMushroomEffectCount => _playerOneMushroomEffects?.Count ?? 0; public int PlayerTwoMushroomEffectCount => _playerTwoMushroomEffects?.Count ?? 0; public int LastMushroomEffectUpdatePlayerNumber => _lastMushroomEffectUpdatePlayerNumber; public bool IsPlayerOneDead { get { if (!_playerOneAwaitingRevive && !_playerOneDead) { return IsDead(PlayerOne); } return true; } } public bool IsPlayerOneRemoved { get { if (_playerOneDead) { return (Object)(object)PlayerOne == (Object)null; } return false; } } public bool IsPlayerOneAwaitingRevive => _playerOneAwaitingRevive; public bool IsPlayerTwoDead { get { if (!_playerTwoAwaitingRevive && !_playerTwoDead) { return IsDead(PlayerTwo); } return true; } } public bool IsPlayerTwoAwaitingRevive => _playerTwoAwaitingRevive; public bool IsEvolutionPickerOpen => _evolutionPickerOpen; public int PlayerOneReviveCost => Mathf.Max(0, Plugin.PlayerOneReviveMutagenCost.Value); public float PlayerOneReviveHealthFraction => Mathf.Clamp(Plugin.PlayerOneReviveHealthFraction.Value, 0.01f, 1f); public int PlayerTwoReviveCost => Mathf.Max(0, Plugin.PlayerTwoReviveMutagenCost.Value); public float PlayerTwoReviveHealthFraction => Mathf.Clamp(Plugin.PlayerTwoReviveHealthFraction.Value, 0.01f, 1f); public int CurrentMutagenPoints { get { if (!((Object)(object)WorldStats.Instance != (Object)null)) { return 0; } return WorldStats.Instance.CurrentNumMutagenPoints; } } public bool CanRevivePlayerOne { get { if (_playerOneAwaitingRevive && _evolutionPickerOpen && IsAlive(PlayerTwo)) { return CurrentMutagenPoints >= PlayerOneReviveCost; } return false; } } public bool CanRevivePlayerTwo { get { if (_playerTwoAwaitingRevive && _evolutionPickerOpen && IsAlive(PlayerOne)) { return CurrentMutagenPoints >= PlayerTwoReviveCost; } return false; } } public int PendingRevivePlayerNumber { get { if (!_playerOneAwaitingRevive) { if (!_playerTwoAwaitingRevive) { return 0; } return 2; } return 1; } } public int PendingReviveCost { get { if (PendingRevivePlayerNumber != 1) { return PlayerTwoReviveCost; } return PlayerOneReviveCost; } } public bool CanRevivePendingPlayer { get { if (PendingRevivePlayerNumber != 1) { return CanRevivePlayerTwo; } return CanRevivePlayerOne; } } public int PlayerOneCharmCount => GetCharmCount(PlayerOne); public int PlayerTwoCharmCount => GetCharmCount(PlayerTwo); public int SuppressedPlayerDeathDropCount => _suppressedPlayerDeathDropCount; public string PlayerTwoDamageHudStatus => _playerTwoDamageHudStatus; public string PlayerTwoAiHudStatus => _playerTwoAiHudStatus; public string CameraHudStatus => _cameraHudStatus; public float SharedCameraMidpointError { get; private set; } = float.PositiveInfinity; public float RenderCameraMidpointError { get; private set; } = float.PositiveInfinity; public bool IsFriendlyFireEnabled => Plugin.FriendlyFireEnabled.Value; public bool IsSharedNightVisionActive { get; private set; } public float SharedNightVisionCenterError { get; private set; } = float.PositiveInfinity; public float SharedNightVisionRadius { get; private set; } = -1f; public float SharedNightVisionRequiredRadius { get; private set; } = -1f; public float RenderSharedNightVisionCenterError { get; private set; } = float.PositiveInfinity; public float RenderSharedNightVisionRadius { get; private set; } = -1f; public float RenderSharedNightVisionMaxPlayerDistance { get; private set; } = -1f; public Vector2 RenderSharedNightVisionCenter { get; private set; } = new Vector2(float.NaN, float.NaN); public Vector2 RenderNightCameraPlayerOneViewport { get; private set; } = new Vector2(float.NaN, float.NaN); public Vector2 RenderNightCameraPlayerTwoViewport { get; private set; } = new Vector2(float.NaN, float.NaN); public string SharedNightVisionMaterialState { get; private set; } = "none"; public LocalMultiplayerDriver(IntPtr ptr) : base(ptr) { }//IL_007a: 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: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_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_0114: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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_0143: Unknown result type (might be due to invalid IL or missing references) public LocalMultiplayerDriver() : base(ClassInjector.DerivedConstructorPointer()) { //IL_007a: 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: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_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_0114: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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_0143: Unknown result type (might be due to invalid IL or missing references) ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public void SetDebugInputOverride(int playerNumber, Vector2 move, Vector2 aim, bool dashHeld, bool primaryAttackHeld, int attackInputIndex = 0, bool interactHeld = false) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) switch (playerNumber) { case 1: _debugPlayerOneInputOverride = true; _debugPlayerOneMove = Vector2.ClampMagnitude(move, 1f); _debugPlayerOneAim = ((((Vector2)(ref aim)).sqrMagnitude > 0.001f) ? ((Vector2)(ref aim)).normalized : _playerOneAim); break; default: throw new ArgumentOutOfRangeException("playerNumber", playerNumber, "Debug input only supports player 1 or player 2."); case 2: _debugPlayerTwoInputOverride = true; _debugPlayerTwoMove = Vector2.ClampMagnitude(move, 1f); _debugPlayerTwoAim = ((((Vector2)(ref aim)).sqrMagnitude > 0.001f) ? ((Vector2)(ref aim)).normalized : Vector2.right); _debugPlayerTwoDashHeld = dashHeld; _debugPlayerTwoInteractHeld = interactHeld; Array.Clear(_debugPlayerTwoAttackHeld, 0, _debugPlayerTwoAttackHeld.Length); if (attackInputIndex < 0 || attackInputIndex >= _debugPlayerTwoAttackHeld.Length) { throw new ArgumentOutOfRangeException("attackInputIndex", attackInputIndex, "Debug attack input index must be between 0 and 4."); } _debugPlayerTwoAttackHeld[attackInputIndex] = primaryAttackHeld; break; } } public void SetDebugPlayerTwoGamepadIndexOverride(int gamepadIndex) { _debugPlayerTwoGamepadIndex = Math.Max(0, gamepadIndex); } public void SetDebugPlayerOneGamepadIndexOverride(int gamepadIndex) { _debugPlayerOneGamepadIndex = Math.Max(0, gamepadIndex); } public void ClearDebugPlayerOneGamepadIndexOverride() { _debugPlayerOneGamepadIndex = -1; } public void ClearDebugPlayerTwoGamepadIndexOverride() { _debugPlayerTwoGamepadIndex = -1; } public void ClearDebugInputOverride(int playerNumber = 0) { //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) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (playerNumber == 0 || playerNumber == 1) { _debugPlayerOneInputOverride = false; _debugPlayerOneMove = Vector2.zero; _debugPlayerOneAim = Vector2.right; } if (playerNumber == 0 || playerNumber == 2) { _debugPlayerTwoInputOverride = false; _debugPlayerTwoMove = Vector2.zero; _debugPlayerTwoAim = Vector2.right; _debugPlayerTwoDashHeld = false; _debugPlayerTwoInteractHeld = false; Array.Clear(_debugPlayerTwoAttackHeld, 0, _debugPlayerTwoAttackHeld.Length); } } public bool TryApplyDebugMovement(CharacterMovement movement) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)movement == (Object)null) { return false; } PlayerCharacter componentInParent = ((Component)movement).GetComponentInParent(); if (_debugPlayerOneInputOverride && IsSamePlayer(componentInParent, PlayerOne)) { movement.SetMovement(IsPlayerOneDead ? Vector2.zero : _debugPlayerOneMove); return true; } if (_debugPlayerTwoInputOverride && IsSamePlayer(componentInParent, PlayerTwo)) { movement.SetMovement(IsPlayerTwoDead ? Vector2.zero : _debugPlayerTwoMove); return true; } return false; } public void ApplyDebugDamage(int playerNumber, bool lethal, string source) { switch (playerNumber) { case 1: ApplyManualDamage(PlayerOne, PlayerTwo, source, "P1", lethal); break; case 2: ApplyManualDamage(PlayerTwo, PlayerOne, source, "P2", lethal); break; default: throw new ArgumentOutOfRangeException("playerNumber", playerNumber, "Debug damage only supports player 1 or player 2."); } } public void DebugRespawnPlayerTwo(string source) { ForceRespawnPlayerTwo(source); } public bool DebugRevivePlayerTwo(string source, out string result) { return TryRevivePlayerTwo(source, requireEvolutionPicker: false, out result); } public bool DebugRevivePlayerOne(string source, out string result) { return TryRevivePlayerOne(source, requireEvolutionPicker: false, out result); } public void SetEvolutionPickerOpen(bool isOpen) { _evolutionPickerOpen = isOpen; } public bool TrySpendMutagenToRevivePlayerTwo(out string result) { return TryRevivePlayerTwo("level-up UI", requireEvolutionPicker: true, out result); } public bool TrySpendMutagenToRevivePlayerOne(out string result) { return TryRevivePlayerOne("level-up UI", requireEvolutionPicker: true, out result); } public bool TrySpendMutagenToRevivePendingPlayer(out string result) { return PendingRevivePlayerNumber switch { 1 => TrySpendMutagenToRevivePlayerOne(out result), 2 => TrySpendMutagenToRevivePlayerTwo(out result), _ => FailNoPendingRevive(out result), }; } private static bool FailNoPendingRevive(out string result) { result = "Neither player is awaiting revival."; return false; } public void DebugDumpState(string source) { DumpState(source); } public void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); Scene activeScene = SceneManager.GetActiveScene(); _sceneHandle = ((Scene)(ref activeScene)).handle; _beginCameraRenderingHandler = DelegateSupport.ConvertDelegate>((Delegate)new Action(OnBeginCameraRendering)); RenderPipelineManager.beginCameraRendering += _beginCameraRenderingHandler; } public void OnDestroy() { if ((Delegate)(object)_beginCameraRenderingHandler != (Delegate)null) { RenderPipelineManager.beginCameraRendering -= _beginCameraRenderingHandler; _beginCameraRenderingHandler = null; } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private static void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) { Instance?.UpdateSharedCameraFromCamera(camera, renderStage: true); Instance?.UpdateSharedNightVision(renderStage: true); } public void Update() { if (!Plugin.ModEnabled.Value) { CleanupPlayerTwoIfPresent(); return; } ResetForSceneChanges(); ValidateTrackedPlayers(); LogConnectedGamepadsIfChanged(); RefreshInput(); HandleManualControls(); TrySpawnPlayerTwo(); RefreshDeathStateFromHealth(); EnsurePlayerTwoDamageable(); RefreshPlayerTwoAiTargetingIfDue(); RefreshPlayerTwoSizeVisuals(force: false); MaintainPlayerSingleton(); } public void LateUpdate() { if (Plugin.ModEnabled.Value) { MaintainPlayerSingleton(); UpdateLocalPlayerAims(); EnsureSharedCameraEnforcer(Camera.main); UpdateSharedNightVision(renderStage: false); } } public bool IsPlayerTwoComponent(Component component) { if (!Plugin.ModEnabled.Value || (Object)(object)component == (Object)null) { return false; } return IsPlayerTwo(ResolveLocalPlayerOwner(component)); } public bool IsPlayerOneComponent(Component component) { if (!Plugin.ModEnabled.Value || (Object)(object)component == (Object)null) { return false; } return IsPlayerOne(ResolveLocalPlayerOwner(component)); } public bool IsPlayerOneEvolutionHandler(EvolutionHandler handler) { if (!Plugin.ModEnabled.Value || (Object)(object)handler == (Object)null || _playerOneId == 0) { return false; } PlayerCharacter componentInParent = ((Component)handler).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return ((Object)componentInParent).GetInstanceID() == _playerOneId; } return false; } public bool IsPlayerTwoEvolutionHandler(EvolutionHandler handler) { if (!Plugin.ModEnabled.Value || (Object)(object)handler == (Object)null || _playerTwoId == 0) { return false; } PlayerCharacter componentInParent = ((Component)handler).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return ((Object)componentInParent).GetInstanceID() == _playerTwoId; } return false; } public EvolutionHandler GetPlayerOneEvolutionHandler() { if (!((Object)(object)PlayerOne != (Object)null)) { return null; } return PlayerOne.PlayerEvolutionHandler; } public EvolutionHandler GetPlayerTwoEvolutionHandler() { if (!((Object)(object)PlayerTwo != (Object)null)) { return null; } return PlayerTwo.PlayerEvolutionHandler; } public void RefreshPlayerTwoAttackLoadout() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown if ((Object)(object)PlayerTwo == (Object)null) { return; } try { RepairPlayerTwoAttackState(PlayerTwo, resetCooldowns: false); RepairPlayerTwoDashState(PlayerTwo); RefreshPlayerTwoSizeVisuals(force: true); } catch (Exception ex) { ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(75, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to refresh the player-two attack loadout after an evolution change: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } logger.LogWarning(val); } } public void ApplyPlayerTwoMovement(CharacterMovement movement) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (IsPlayerTwoDead) { movement.SetMovement(Vector2.zero); } else { movement.SetMovement(InputState.Move); } } public void ApplyPlayerOneMovement(CharacterMovement movement) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) movement.SetMovement(IsPlayerOneDead ? Vector2.zero : _playerOneMove); } public void HandlePlayerTwoDash(PlayerDashManager dashManager) { if (!IsPlayerTwoDead) { if (InputState.DashPressed) { ((CharacterDashManager)dashManager).StartDash(); } if (InputState.DashReleased) { ((CharacterDashManager)dashManager).DashInputReleased(); } } } public void HandlePlayerTwoAttack(AAttackHandler attackHandler) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (IsPlayerTwoDead) { return; } int num = AttackSlotToInputIndex(attackHandler.AttackSlot); if (num >= 0) { if (InputState.AttackPressed[num]) { ApplyPlayerTwoAttackAim(attackHandler); ((CharacterHandleWeapon)attackHandler).ShootStart(); } if (InputState.AttackReleased[num]) { ApplyPlayerTwoAttackAim(attackHandler); ((CharacterHandleWeapon)attackHandler).ShootStop(); } } } public void HandlePlayerTwoInteraction(PlayerInteraction interaction) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown if (IsPlayerTwoDead || (Object)(object)PlayerTwo == (Object)null || !InputState.InteractPressed) { return; } IPlayerInteractable val = ((interaction != null) ? interaction.CurrentInteractable : null); Burrow currentBurrow = PlayerTwo.CurrentBurrow; if (val == null && (Object)(object)currentBurrow != (Object)null) { val = ((Il2CppObjectBase)currentBurrow).Cast(); } if (val == null) { return; } Burrow val2 = ((Il2CppObjectBase)val).TryCast(); if (!val.CanInteract && (!((Object)(object)val2 != (Object)null) || !PlayerTwo.IsInBurrow)) { return; } PlayerCharacter instance = PlayerCharacter.Instance; try { PlayerCharacter.Instance = PlayerTwo; val.InteractWithPlayer(); } catch (Exception ex) { ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(51, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Player two could not use the focused interactable: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex.Message); } logger.LogWarning(val3); } finally { PlayerCharacter.Instance = instance; } } public bool BeginMushroomConsumerUpdate(EdibleItemConsumer consumer) { PlayerCharacter val = ((consumer != null) ? ((Component)consumer).GetComponentInParent() : null); if (!IsPlayerOne(val) && !IsPlayerTwo(val)) { return false; } if (_mushroomConsumerSingletonDepth == 0) { _mushroomConsumerPreviousSingleton = PlayerCharacter.Instance; } _mushroomConsumerSingletonDepth++; PlayerCharacter.Instance = val; return true; } public void EndMushroomConsumerUpdate() { if (_mushroomConsumerSingletonDepth > 0) { _mushroomConsumerSingletonDepth--; if (_mushroomConsumerSingletonDepth == 0) { PlayerCharacter.Instance = _mushroomConsumerPreviousSingleton; _mushroomConsumerPreviousSingleton = null; } } } public bool BeginMushroomEffectCapture(MushroomManager manager) { PlayerCharacter instance = PlayerCharacter.Instance; if ((Object)(object)manager == (Object)null || (!IsPlayerOne(instance) && !IsPlayerTwo(instance))) { return false; } EnsureMushroomEffectLists(manager); if (_mushroomConsumptionRoutingDepth == 0) { _mushroomEffectsBeforeConsumption = manager._activeEffects; } _mushroomConsumptionRoutingDepth++; manager._activeEffects = (IsPlayerTwo(instance) ? _playerTwoMushroomEffects : _playerOneMushroomEffects); return true; } public void EndMushroomEffectCapture(MushroomManager manager) { if (!((Object)(object)manager == (Object)null) && _mushroomConsumptionRoutingDepth > 0) { _mushroomConsumptionRoutingDepth--; if (_mushroomConsumptionRoutingDepth == 0) { manager._activeEffects = _mushroomEffectsBeforeConsumption ?? _playerOneMushroomEffects; _mushroomEffectsBeforeConsumption = null; } } } public bool TryUpdateOwnedMushroomEffects(MushroomManager manager) { if (_updatingOwnedMushroomEffects || (Object)(object)manager == (Object)null || !Plugin.ModEnabled.Value) { return false; } if (_playerOneMushroomEffects == null && ((Object)(object)PlayerOne == (Object)null || (Object)(object)PlayerTwo == (Object)null)) { return false; } EnsureMushroomEffectLists(manager); List activeEffects = manager._activeEffects; PlayerCharacter instance = PlayerCharacter.Instance; _updatingOwnedMushroomEffects = true; try { UpdateOwnedMushroomEffects(manager, PlayerOne, _playerOneMushroomEffects, 1); UpdateOwnedMushroomEffects(manager, PlayerTwo, _playerTwoMushroomEffects, 2); } finally { manager._activeEffects = activeEffects ?? _playerOneMushroomEffects; PlayerCharacter.Instance = instance; _updatingOwnedMushroomEffects = false; } return true; } public bool DebugQueueMushroomEffectForPlayer(int playerNumber, EMushroomEffect effect, out string result) { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) MushroomManager instance = AMonoBehaviourSingleton.Instance; PlayerCharacter val = (PlayerCharacter)(playerNumber switch { 2 => PlayerTwo, 1 => PlayerOne, _ => null, }); if ((Object)(object)instance == (Object)null || !IsAlive(val)) { result = $"manager={(Object)(object)instance != (Object)null}, P{playerNumber}Alive={IsAlive(val)}."; return false; } EnsureMushroomEffectLists(instance); int playerOneMushroomEffectCount = PlayerOneMushroomEffectCount; int playerTwoMushroomEffectCount = PlayerTwoMushroomEffectCount; PlayerCharacter instance2 = PlayerCharacter.Instance; bool flag = false; _lastMushroomEffectUpdatePlayerNumber = 0; try { PlayerCharacter.Instance = val; flag = BeginMushroomEffectCapture(instance); instance.TriggerMushroomEffect(effect, 0f); } finally { if (flag) { EndMushroomEffectCapture(instance); } PlayerCharacter.Instance = instance2; } bool flag2 = ((playerNumber != 1) ? (PlayerTwoMushroomEffectCount > playerTwoMushroomEffectCount && PlayerOneMushroomEffectCount == playerOneMushroomEffectCount) : (PlayerOneMushroomEffectCount > playerOneMushroomEffectCount && PlayerTwoMushroomEffectCount == playerTwoMushroomEffectCount)); result = $"effect={effect}, routed={flag}, P1 effects {playerOneMushroomEffectCount}->{PlayerOneMushroomEffectCount}, P2 effects {playerTwoMushroomEffectCount}->{PlayerTwoMushroomEffectCount}."; return flag && flag2; } public void DebugClearMushroomEffects() { _playerOneMushroomEffects?.Clear(); _playerTwoMushroomEffects?.Clear(); _lastMushroomEffectUpdatePlayerNumber = 0; } private void EnsureMushroomEffectLists(MushroomManager manager) { int instanceID = ((Object)manager).GetInstanceID(); if (_mushroomManagerId != instanceID || _playerOneMushroomEffects == null || _playerTwoMushroomEffects == null) { _mushroomManagerId = instanceID; _playerOneMushroomEffects = manager._activeEffects ?? new List(); _playerTwoMushroomEffects = new List(); _mushroomEffectsBeforeConsumption = null; _mushroomConsumptionRoutingDepth = 0; _lastMushroomEffectUpdatePlayerNumber = 0; } else { List activeEffects = manager._activeEffects; if (!_updatingOwnedMushroomEffects && _mushroomConsumptionRoutingDepth == 0 && activeEffects != null && ((Il2CppObjectBase)activeEffects).Pointer != ((Il2CppObjectBase)_playerOneMushroomEffects).Pointer && ((Il2CppObjectBase)activeEffects).Pointer != ((Il2CppObjectBase)_playerTwoMushroomEffects).Pointer) { _playerOneMushroomEffects = activeEffects; _playerTwoMushroomEffects = new List(); } } } private void UpdateOwnedMushroomEffects(MushroomManager manager, PlayerCharacter owner, List effects, int playerNumber) { if (effects != null && effects.Count != 0) { if (!IsAlive(owner)) { effects.Clear(); return; } manager._activeEffects = effects; PlayerCharacter.Instance = owner; _lastMushroomEffectUpdatePlayerNumber = playerNumber; manager.UpdateMushroomEffectLogics(); } } public void DebugRefreshPlayerTwoSize() { RefreshPlayerTwoSizeVisuals(force: true); } public bool IsPlayerTwoGamepadContext(CallbackContext context) { if (!Plugin.ModEnabled.Value) { return false; } ReadOnlyArray all = Gamepad.all; int playerTwoGamepadIndex = GetPlayerTwoGamepadIndex(); if (all.Count <= playerTwoGamepadIndex) { return false; } InputControl control = context.control; InputDevice val = ((control != null) ? control.device : null); if (val == null) { return false; } return val.deviceId == ((InputDevice)all[playerTwoGamepadIndex]).deviceId; } public void RecordFilteredStockInput(CallbackContext context) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown if (Plugin.DiagnosticsEnabled.Value && !_loggedFilteredStockInput) { InputControl control = context.control; InputDevice val = ((control != null) ? control.device : null); ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(83, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Filtered stock player-one input from player-two device: action="); InputAction action = context.action; ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(((action != null) ? action.name : null) ?? "unknown"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", control="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(((control != null) ? control.path : null) ?? "unknown"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", device="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(((val != null) ? ((InputControl)val).displayName : null) ?? ((val != null) ? ((InputControl)val).name : null) ?? "unknown"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } logger.LogInfo(val2); _loggedFilteredStockInput = true; } } public bool ShouldSuppressStockAimInjector(PlayerAttackAimInjector injector) { if (!TryGetLocalPlayerAim((Component)(object)injector, out var _, out var _)) { return false; } return true; } public bool TryApplyLocalPlayerAim(WeaponAim2D weaponAim) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!TryGetLocalPlayerAim((Component)(object)weaponAim, out var player, out var aim)) { return false; } if (IsLocalPlayerDead(player)) { return true; } ConfigureWeaponAim((WeaponAim)(object)weaponAim, aim, applyRotation: false); return true; } public bool TryApplyLocalPlayerAttackDirection(EICCharacterAttack attack) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!TryGetLocalPlayerAim((Component)(object)attack, out var player, out var aim)) { return false; } if (IsLocalPlayerDead(player)) { return true; } ConfigureWeaponAim(attack.WeaponAim, aim, applyRotation: true); attack._AimDirectionAtStartOfAttack_k__BackingField = aim; return true; } public bool TryUpdateLocalPlayerAimIndicator(GamepadAimDirection indicator) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (!TryGetLocalPlayerAim((Component)(object)indicator, out var player, out var aim)) { return false; } if (IsLocalPlayerDead(player) || (Object)(object)((Component)indicator).gameObject == (Object)null) { return true; } if (!((Component)indicator).gameObject.activeSelf) { ((Component)indicator).gameObject.SetActive(true); } if (!((Behaviour)indicator).enabled) { ((Behaviour)indicator).enabled = true; } indicator.SetCurrentAim(new Vector2(aim.x, aim.y)); return true; } public void UpdateSharedCamera(CombatCamera combatCamera) { Camera camera = (((Object)(object)combatCamera != (Object)null && (Object)(object)combatCamera.Camera != (Object)null) ? combatCamera.Camera : Camera.main); EnsureSharedCameraEnforcer(camera); UpdateSharedCameraFromCamera(camera, renderStage: false); } public void UpdateSharedCameraFromCamera(Camera camera, bool renderStage) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0173: 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_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: 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_01c5: 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_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)camera == (Object)null) { return; } bool flag = IsAliveForCamera(PlayerOne); bool flag2 = IsAliveForCamera(PlayerTwo); if (!flag && !flag2) { _cameraHudStatus = "CAM: NONE"; return; } _cameraHudStatus = ((flag && flag2) ? "CAM: BOTH" : (flag2 ? "CAM: P2" : "CAM: P1")); Transform transform = ((Component)camera).transform; Vector3 val = ((flag && flag2) ? ((((Component)PlayerOne).transform.position + ((Component)PlayerTwo).transform.position) * 0.5f) : (flag2 ? ((Component)PlayerTwo).transform.position : ((Component)PlayerOne).transform.position)); Vector3 position = transform.position; int instanceID = ((Object)camera).GetInstanceID(); if (!_hasSharedCameraState || _cameraId != instanceID) { _cameraId = instanceID; _baseOrthographicSize = (camera.orthographic ? camera.orthographicSize : 0f); _smoothedOrthographicSize = camera.orthographicSize; _smoothedCameraCenter = new Vector2(position.x, position.y); _hasSharedCameraState = true; } Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(val.x, val.y); if (renderStage) { _smoothedCameraCenter = val2; } else { float num = 1f - Mathf.Exp((0f - Time.unscaledDeltaTime) * Mathf.Max(0.1f, Plugin.CameraFollowLerpSpeed.Value)); _smoothedCameraCenter = Vector2.Lerp(_smoothedCameraCenter, val2, num); } transform.position = new Vector3(_smoothedCameraCenter.x, _smoothedCameraCenter.y, position.z); SharedCameraMidpointError = Vector2.Distance(new Vector2(transform.position.x, transform.position.y), val2); if (renderStage) { RenderCameraMidpointError = SharedCameraMidpointError; } if (camera.orthographic) { float num2 = ((flag && flag2) ? Vector2.Distance(Vector2.op_Implicit(((Component)PlayerOne).transform.position), Vector2.op_Implicit(((Component)PlayerTwo).transform.position)) : 0f); float num3 = Mathf.Clamp(Mathf.Max(_baseOrthographicSize, num2 * Mathf.Max(0f, Plugin.CameraDistanceZoomMultiplier.Value) + Mathf.Max(0f, Plugin.CameraZoomPadding.Value)), _baseOrthographicSize, _baseOrthographicSize * Mathf.Max(1f, Plugin.CameraMaxZoomMultiplier.Value)); float num4 = 1f - Mathf.Exp((0f - Time.unscaledDeltaTime) * Mathf.Max(0.1f, Plugin.CameraZoomLerpSpeed.Value)); _smoothedOrthographicSize = Mathf.Lerp(_smoothedOrthographicSize, num3, num4); camera.orthographicSize = _smoothedOrthographicSize; } } private void EnsureSharedCameraEnforcer(Camera camera) { if ((Object)(object)camera == (Object)null || (Object)(object)((Component)camera).gameObject == (Object)null) { return; } int instanceID = ((Object)camera).GetInstanceID(); if (_cameraEnforcerId != instanceID || !((Object)(object)((Component)camera).GetComponent() != (Object)null)) { if ((Object)(object)((Component)camera).GetComponent() == (Object)null) { ((Component)camera).gameObject.AddComponent(); } _cameraEnforcerId = instanceID; } } private void UpdateSharedNightVision(bool renderStage) { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: 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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0133: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) DayAndNightCycleManager instance = AMonoBehaviourSingleton.Instance; if (!Plugin.SharedNightVisionEnabled.Value || (Object)(object)instance == (Object)null) { RestoreSharedNightVisionRadius(); return; } Camera val = (((Object)(object)Camera.main != (Object)null) ? Camera.main : instance._nightEyesCamera); Material nightShaderMaterialToEdit = instance._nightShaderMaterialToEdit; if ((Object)(object)nightShaderMaterialToEdit == (Object)null || (Object)(object)val == (Object)null) { ClearSharedNightVisionTracking(); return; } NightVisionMaterialState orRefreshNightVisionMaterialState = GetOrRefreshNightVisionMaterialState(nightShaderMaterialToEdit); bool flag = IsAliveForCamera(PlayerOne); bool flag2 = IsAliveForCamera(PlayerTwo); if (!flag && !flag2) { RestoreSharedNightVisionRadius(); return; } Vector3 val2 = (flag ? val.WorldToViewportPoint(((Component)PlayerOne).transform.position) : val.WorldToViewportPoint(((Component)PlayerTwo).transform.position)); Vector3 val3 = (flag2 ? val.WorldToViewportPoint(((Component)PlayerTwo).transform.position) : val2); Vector3 val4 = ((flag && flag2) ? ((val2 + val3) * 0.5f) : (flag2 ? val3 : val2)); float num = (val3.x - val2.x) * Mathf.Max(1f, val.aspect); float num2 = val3.y - val2.y; float num3 = ((flag && flag2) ? (Mathf.Sqrt(num * num + num2 * num2) * 0.5f) : 0f); float num4 = ((flag && flag2) ? Mathf.Max(0f, Plugin.SharedNightVisionPadding.Value) : 0f); float num5 = Mathf.Max(0f, orRefreshNightVisionMaterialState.BaseViewportRadius + num3 + num4); float gradientRadius = Mathf.Max(0f, orRefreshNightVisionMaterialState.BaseGradientRadius + num3 + num4); ApplySharedNightVisionToMaterial(nightShaderMaterialToEdit, val4, num5, gradientRadius); ApplySharedNightVisionToRendererMaterials(instance, val4, num5, gradientRadius); SharedNightVisionRadius = num5; SharedNightVisionRequiredRadius = num5; Vector4 vector = nightShaderMaterialToEdit.GetVector(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH); SharedNightVisionCenterError = Vector2.Distance(new Vector2(vector.x, vector.y), new Vector2(val4.x, val4.y)); IsSharedNightVisionActive = flag && flag2; if (renderStage) { RenderSharedNightVisionCenterError = SharedNightVisionCenterError; RenderSharedNightVisionRadius = num5; RenderSharedNightVisionMaxPlayerDistance = num3; RenderSharedNightVisionCenter = new Vector2(val4.x, val4.y); RenderNightCameraPlayerOneViewport = new Vector2(val2.x, val2.y); RenderNightCameraPlayerTwoViewport = new Vector2(val3.x, val3.y); SharedNightVisionMaterialState = DescribeNightVisionMaterials(instance); } } private NightVisionMaterialState GetOrRefreshNightVisionMaterialState(Material material) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00be: 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_00ab: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)material).GetInstanceID(); if (!_nightVisionMaterialStates.TryGetValue(instanceID, out var value) || (Object)(object)value.Material == (Object)null) { value = new NightVisionMaterialState { Material = material, BaseCenter = material.GetVector(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH), BaseViewportRadius = material.GetFloat(DayAndNightCycleManager.VIEWPORT_RADIUS_SHADER_PARAM_HASH), BaseGradientRadius = material.GetFloat(DayAndNightCycleManager.GRADIENT_RADIUS_SHADER_PARAM_HASH) }; _nightVisionMaterialStates[instanceID] = value; } Vector4 vector = material.GetVector(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH); float num = material.GetFloat(DayAndNightCycleManager.VIEWPORT_RADIUS_SHADER_PARAM_HASH); float num2 = material.GetFloat(DayAndNightCycleManager.GRADIENT_RADIUS_SHADER_PARAM_HASH); if (float.IsNaN(value.LastAppliedCenter.x) || Vector4.Distance(vector, value.LastAppliedCenter) > 0.0001f) { value.BaseCenter = vector; } if (float.IsNaN(value.LastAppliedViewportRadius) || !Mathf.Approximately(num, value.LastAppliedViewportRadius)) { value.BaseViewportRadius = num; } if (float.IsNaN(value.LastAppliedGradientRadius) || !Mathf.Approximately(num2, value.LastAppliedGradientRadius)) { value.BaseGradientRadius = num2; } return value; } private void ApplySharedNightVisionToMaterial(Material material, Vector3 center, float viewportRadius, float gradientRadius) { //IL_003e: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_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) if (!((Object)(object)material == (Object)null) && material.HasProperty(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH) && material.HasProperty(DayAndNightCycleManager.VIEWPORT_RADIUS_SHADER_PARAM_HASH) && material.HasProperty(DayAndNightCycleManager.GRADIENT_RADIUS_SHADER_PARAM_HASH)) { NightVisionMaterialState orRefreshNightVisionMaterialState = GetOrRefreshNightVisionMaterialState(material); material.SetVector(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH, new Vector4(center.x, center.y, 0f, 0f)); material.SetFloat(DayAndNightCycleManager.VIEWPORT_RADIUS_SHADER_PARAM_HASH, viewportRadius); material.SetFloat(DayAndNightCycleManager.GRADIENT_RADIUS_SHADER_PARAM_HASH, gradientRadius); orRefreshNightVisionMaterialState.LastAppliedCenter = new Vector4(center.x, center.y, 0f, 0f); orRefreshNightVisionMaterialState.LastAppliedViewportRadius = viewportRadius; orRefreshNightVisionMaterialState.LastAppliedGradientRadius = gradientRadius; } } private void ApplySharedNightVisionToRendererMaterials(DayAndNightCycleManager manager, Vector3 center, float viewportRadius, float gradientRadius) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) try { object obj; if (manager == null) { obj = null; } else { UniversalRendererData universalRendererData = manager._universalRendererData; obj = ((universalRendererData != null) ? ((ScriptableRendererData)universalRendererData).rendererFeatures : null); } List val = (List)obj; if (val != null) { for (int i = 0; i < val.Count; i++) { ScriptableRendererFeature obj2 = val[i]; FullScreenPassRendererFeature val2 = ((obj2 != null) ? ((Il2CppObjectBase)obj2).TryCast() : null); ApplySharedNightVisionToMaterial((val2 != null) ? val2.passMaterial : null, center, viewportRadius, gradientRadius); } } } catch (Exception ex) { if (Plugin.DiagnosticsEnabled.Value) { ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(47, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Unable to update all night renderer materials: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex.Message); } logger.LogWarning(val3); } } } private string DescribeNightVisionMaterials(DayAndNightCycleManager manager) { List list = new List(); AddNightVisionMaterialDescription(list, "manager", (manager != null) ? manager._nightShaderMaterialToEdit : null); try { object obj; if (manager == null) { obj = null; } else { UniversalRendererData universalRendererData = manager._universalRendererData; obj = ((universalRendererData != null) ? ((ScriptableRendererData)universalRendererData).rendererFeatures : null); } List val = (List)obj; if (val != null) { for (int i = 0; i < val.Count; i++) { ScriptableRendererFeature obj2 = val[i]; FullScreenPassRendererFeature val2 = ((obj2 != null) ? ((Il2CppObjectBase)obj2).TryCast() : null); if ((Object)(object)((val2 != null) ? val2.passMaterial : null) != (Object)null && val2.passMaterial.HasProperty(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH)) { AddNightVisionMaterialDescription(list, $"feature[{i}]", val2.passMaterial); } } } } catch (Exception ex) { list.Add("renderer-error=" + ex.Message); } if (list.Count <= 0) { return "none"; } return string.Join("; ", list); } private static void AddNightVisionMaterialDescription(List descriptions, string source, Material material) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)material == (Object)null) { descriptions.Add(source + "=null"); return; } Vector4 vector = material.GetVector(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH); float value = material.GetFloat(DayAndNightCycleManager.VIEWPORT_RADIUS_SHADER_PARAM_HASH); float value2 = material.GetFloat(DayAndNightCycleManager.GRADIENT_RADIUS_SHADER_PARAM_HASH); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 8); defaultInterpolatedStringHandler.AppendFormatted(source); defaultInterpolatedStringHandler.AppendLiteral("="); defaultInterpolatedStringHandler.AppendFormatted(((Object)material).name); defaultInterpolatedStringHandler.AppendLiteral("#"); defaultInterpolatedStringHandler.AppendFormatted(((Object)material).GetInstanceID()); defaultInterpolatedStringHandler.AppendLiteral(" shader="); Shader shader = material.shader; defaultInterpolatedStringHandler.AppendFormatted(((shader != null) ? ((Object)shader).name : null) ?? "null"); defaultInterpolatedStringHandler.AppendLiteral(" center=("); defaultInterpolatedStringHandler.AppendFormatted(vector.x, "0.000"); defaultInterpolatedStringHandler.AppendLiteral(","); defaultInterpolatedStringHandler.AppendFormatted(vector.y, "0.000"); defaultInterpolatedStringHandler.AppendLiteral(") radius="); defaultInterpolatedStringHandler.AppendFormatted(value, "0.000"); defaultInterpolatedStringHandler.AppendLiteral("/"); defaultInterpolatedStringHandler.AppendFormatted(value2, "0.000"); descriptions.Add(defaultInterpolatedStringHandler.ToStringAndClear()); } private void RestoreSharedNightVisionRadius() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) float num = RestoreNightVisionMaterials(); IsSharedNightVisionActive = false; SharedNightVisionCenterError = float.PositiveInfinity; SharedNightVisionRadius = num; SharedNightVisionRequiredRadius = num; RenderSharedNightVisionCenterError = float.PositiveInfinity; RenderSharedNightVisionRadius = num; RenderSharedNightVisionMaxPlayerDistance = -1f; RenderSharedNightVisionCenter = new Vector2(float.NaN, float.NaN); RenderNightCameraPlayerOneViewport = new Vector2(float.NaN, float.NaN); RenderNightCameraPlayerTwoViewport = new Vector2(float.NaN, float.NaN); SharedNightVisionMaterialState = "none"; } private void ClearSharedNightVisionTracking() { //IL_0066: 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_0090: Unknown result type (might be due to invalid IL or missing references) RestoreNightVisionMaterials(); _nightVisionMaterialStates.Clear(); IsSharedNightVisionActive = false; SharedNightVisionCenterError = float.PositiveInfinity; SharedNightVisionRadius = -1f; SharedNightVisionRequiredRadius = -1f; RenderSharedNightVisionCenterError = float.PositiveInfinity; RenderSharedNightVisionRadius = -1f; RenderSharedNightVisionMaxPlayerDistance = -1f; RenderSharedNightVisionCenter = new Vector2(float.NaN, float.NaN); RenderNightCameraPlayerOneViewport = new Vector2(float.NaN, float.NaN); RenderNightCameraPlayerTwoViewport = new Vector2(float.NaN, float.NaN); SharedNightVisionMaterialState = "none"; } private float RestoreNightVisionMaterials() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) float num = -1f; foreach (NightVisionMaterialState value in _nightVisionMaterialStates.Values) { if (!((Object)(object)value.Material == (Object)null)) { value.Material.SetVector(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH, value.BaseCenter); value.Material.SetFloat(DayAndNightCycleManager.VIEWPORT_RADIUS_SHADER_PARAM_HASH, value.BaseViewportRadius); value.Material.SetFloat(DayAndNightCycleManager.GRADIENT_RADIUS_SHADER_PARAM_HASH, value.BaseGradientRadius); value.LastAppliedCenter = new Vector4(float.NaN, float.NaN, float.NaN, float.NaN); value.LastAppliedViewportRadius = float.NaN; value.LastAppliedGradientRadius = float.NaN; if (num < 0f) { num = value.BaseViewportRadius; } } } return num; } public void RestorePlayerOneSingletonIfNeeded(PlayerCharacter candidate) { if (!((Object)(object)candidate == (Object)null) && _playerTwoId != 0 && _playerOneId != 0 && ((Object)candidate).GetInstanceID() == _playerTwoId && (Object)(object)PlayerOne != (Object)null && !IsPlayerOneDead) { PlayerCharacter.Instance = PlayerOne; } } public bool TryHandlePlayerDeath(PlayerCharacter player, Health health) { if (!Plugin.ModEnabled.Value || (Object)(object)player == (Object)null) { return false; } if (IsPlayerTwoComponent((Component)(object)player)) { if (!Plugin.PreventPlayerTwoDeathRunEnd.Value || !Plugin.ContinueRunWhileAnyPlayerAlive.Value || !IsAlive(PlayerOne)) { return false; } MarkPlayerDead(player, health, isPlayerTwo: true); if (Plugin.RemovePlayerTwoOnDeath.Value) { RemovePlayerTwoAfterDeath(player); } PlayerCharacter.Instance = PlayerOne; MaintainPlayerSingleton(); _playerTwoDamageHudStatus = "P2 DMG: DEAD"; _cameraHudStatus = "CAM: P1"; Plugin.Logger.LogInfo((object)(Plugin.RemovePlayerTwoOnDeath.Value ? "Player two died; removed P2's world entity and opened the revive slot while P1 remains alive." : "Player two died; leaving P2 dead and suppressing the single-player run-end flow while P1 is alive.")); return true; } if (!IsPlayerOne(player) || !Plugin.ContinueRunWhileAnyPlayerAlive.Value || !IsAlive(PlayerTwo)) { return false; } CapturePlayerOneVisualState(player); _playerOneAwaitingRevive = true; MarkPlayerDead(player, health, isPlayerTwo: false); TransferEvolutionProgressToPlayerTwo(); PlayerCharacter.Instance = PlayerTwo; if (Plugin.RemovePlayerOneOnDeath.Value) { RemovePlayerOneAfterDeath(player); } NotifyNearbyAiAboutPlayer(PlayerTwo, "player one death fallback", logSummary: true); MaintainPlayerSingleton(); _cameraHudStatus = "CAM: P2"; Plugin.Logger.LogInfo((object)(Plugin.RemovePlayerOneOnDeath.Value ? "Player one died while P2 is alive; removed P1's world entity and handed camera, XP, and level-up ownership to P2." : "Player one died while P2 is alive; suppressing the single-player run-end flow and shifting control/camera singleton to P2.")); return true; } public bool ShouldSuppressLocalPlayerFoodDrop(DropItemsOnDeath dropItemsOnDeath) { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown if (!Plugin.ModEnabled.Value || !Plugin.SuppressPlayerFoodDrops.Value || (Object)(object)dropItemsOnDeath == (Object)null) { return false; } PlayerCharacter componentInParent = ((Component)dropItemsOnDeath).GetComponentInParent(); bool flag = (Object)(object)componentInParent != (Object)null && (Object)(object)((Component)componentInParent).gameObject != (Object)null && ((Object)((Component)componentInParent).gameObject).name.StartsWith("LocalMultiplayer_Player2", StringComparison.Ordinal); bool flag2 = (Object)(object)componentInParent != (Object)null && (Object)(object)((Component)componentInParent).gameObject != (Object)null && ((Object)((Component)componentInParent).gameObject).name.StartsWith("LocalMultiplayer_Player1_PendingDestroy", StringComparison.Ordinal); if (!IsPlayerOne(componentInParent) && !IsPlayerTwoComponent((Component)(object)componentInParent) && !flag && !flag2) { return false; } _suppressedPlayerDeathDropCount++; if (Plugin.DiagnosticsEnabled.Value) { ManualLogSource logger = Plugin.Logger; bool flag3 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(68, 2, ref flag3); if (flag3) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Suppressed player death food drop for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)componentInParent).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; total suppressed callbacks="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(_suppressedPlayerDeathDropCount); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logger.LogInfo(val); } return true; } public bool ShouldForcePlayerTwoDamageable(Health health) { if (!Plugin.ModEnabled.Value || !Plugin.ForcePlayerTwoDamageEnabled.Value || (Object)(object)health == (Object)null || IsPlayerTwoDead) { return false; } if (!IsPlayerTwoComponent((Component)(object)health)) { return false; } ClearDamageLocks(health); return true; } public bool TryForcePlayerTwoDamageOutput(Health health, float requestedDamage, float computedDamage, out float forcedDamage) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown forcedDamage = computedDamage; if (!Plugin.ModEnabled.Value || !Plugin.ForcePlayerTwoDamageEnabled.Value || (Object)(object)health == (Object)null || IsPlayerTwoDead || requestedDamage <= 0f || computedDamage > 0f || !IsPlayerTwoComponent((Component)(object)health)) { return false; } ClearDamageLocks(health); forcedDamage = requestedDamage; if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoDamageOutputOverride) { _loggedPlayerTwoDamageOutputOverride = true; ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(113, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Forced player-two damage output from "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(computedDamage); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" to "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(forcedDamage); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; a cloned resistance/avoidance rule had zeroed a positive incoming hit."); } logger.LogInfo(val); } return true; } internal void BeforePlayerTwoDamageOnTouchCollision(DamageOnTouch damageOnTouch, Collider2D otherCollider) { //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown ClearDamageOnTouchState(); if (!Plugin.ModEnabled.Value || (Object)(object)damageOnTouch == (Object)null || (Object)(object)otherCollider == (Object)null || (Object)(object)PlayerTwo == (Object)null || IsPlayerTwoDead || !IsPlayerTwoComponent((Component)(object)otherCollider)) { return; } try { if (IsSamePlayer(ResolveLocalPlayerDamageSource(damageOnTouch), PlayerTwo)) { return; } EnsurePlayerTwoHitCollider(PlayerTwo); Health health = ((AStatCharacter)(object)PlayerTwo).Health; if ((Object)(object)health != (Object)null) { ClearDamageLocks(health); } RemovePlayerTwoFromDamageIgnoreList(damageOnTouch, otherCollider, health); IncludePlayerTwoLayerInDamageMask(damageOnTouch, otherCollider); LogPlayerTwoDamageOnTouchCollision(damageOnTouch, otherCollider, health); if (!((Object)(object)health == (Object)null) && !(health.CurrentHealth <= 0f)) { float damageOnTouchFallbackDamage = GetDamageOnTouchFallbackDamage(damageOnTouch); if (!(damageOnTouchFallbackDamage <= 0f) && CanDamageOnTouchReachPlayerTwo(damageOnTouch, otherCollider)) { _damageOnTouchStateKey = BuildDamageOnTouchStateKey(damageOnTouch, otherCollider); _damageOnTouchStateHealth = health; _damageOnTouchStateBeforeHealth = health.CurrentHealth; _damageOnTouchStateFallbackDamage = damageOnTouchFallbackDamage; _damageOnTouchStateInvincibilityDuration = Mathf.Max(0f, damageOnTouch.InvincibilityDuration); _damageOnTouchStateContextualDeathTip = damageOnTouch.ContextualDeathTip; _damageOnTouchStateInstigator = GetDamageOnTouchInstigator(damageOnTouch); _damageOnTouchStateSourceName = ((Object)damageOnTouch).name; } } } catch (Exception ex) { if (Plugin.DiagnosticsEnabled.Value) { ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(63, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed while preparing player two for DamageOnTouch collision: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } logger.LogWarning(val); } } } internal void AfterPlayerTwoDamageOnTouchCollision(DamageOnTouch damageOnTouch, Collider2D otherCollider) { //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Expected O, but got Unknown //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown if (_damageOnTouchStateKey == 0 || (Object)(object)damageOnTouch == (Object)null || (Object)(object)otherCollider == (Object)null || _damageOnTouchStateKey != BuildDamageOnTouchStateKey(damageOnTouch, otherCollider) || (Object)(object)_damageOnTouchStateHealth == (Object)null || (Object)(object)PlayerTwo == (Object)null) { return; } Health damageOnTouchStateHealth = _damageOnTouchStateHealth; float damageOnTouchStateBeforeHealth = _damageOnTouchStateBeforeHealth; float damageOnTouchStateFallbackDamage = _damageOnTouchStateFallbackDamage; float damageOnTouchStateInvincibilityDuration = _damageOnTouchStateInvincibilityDuration; int damageOnTouchStateContextualDeathTip = _damageOnTouchStateContextualDeathTip; GameObject damageOnTouchStateInstigator = _damageOnTouchStateInstigator; string damageOnTouchStateSourceName = _damageOnTouchStateSourceName; ClearDamageOnTouchState(); float currentHealth = damageOnTouchStateHealth.CurrentHealth; if (currentHealth < damageOnTouchStateBeforeHealth - 0.001f) { RecordPlayerTwoDamageResult(damageOnTouchStateHealth, "DamageOnTouch(" + damageOnTouchStateSourceName + ")", damageOnTouchStateBeforeHealth - currentHealth, damageOnTouchStateBeforeHealth); } else { if (IsPlayerTwoDead) { return; } bool flag = default(bool); try { ClearDamageLocks(damageOnTouchStateHealth); float currentHealth2 = damageOnTouchStateHealth.CurrentHealth; damageOnTouchStateHealth.Damage(damageOnTouchStateFallbackDamage, damageOnTouchStateInstigator, damageOnTouchStateInvincibilityDuration, damageOnTouchStateContextualDeathTip); damageOnTouchStateHealth.UpdateHealthBar(true); if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoDamageOnTouchFallback) { _loggedPlayerTwoDamageOnTouchFallback = true; ManualLogSource logger = Plugin.Logger; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(111, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Applied player-two DamageOnTouch fallback from "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(damageOnTouchStateSourceName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; the normal touch-damage path saw P2 but left health unchanged."); } logger.LogInfo(val); } RecordPlayerTwoDamageResult(damageOnTouchStateHealth, "DamageOnTouch fallback(" + damageOnTouchStateSourceName + ")", damageOnTouchStateFallbackDamage, currentHealth2); } catch (Exception ex) { if (Plugin.DiagnosticsEnabled.Value) { ManualLogSource logger2 = Plugin.Logger; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(57, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed while applying player-two DamageOnTouch fallback: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } logger2.LogWarning(val2); } } } } public bool IsPlayerTwoAttackableEntity(IAttackableEntity entity) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown if (!Plugin.ModEnabled.Value || entity == null || (Object)(object)PlayerTwo == (Object)null || IsPlayerTwoDead) { return false; } try { Health health = entity.Health; Health health2 = ((AStatCharacter)(object)PlayerTwo).Health; return (Object)(object)health != (Object)null && (Object)(object)health2 != (Object)null && ((Object)health).GetInstanceID() == ((Object)health2).GetInstanceID(); } catch (Exception ex) { if (Plugin.DiagnosticsEnabled.Value) { ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(51, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to compare attackable entity to player two: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } logger.LogWarning(val); } return false; } } public bool IsPlayerOneAttackableEntity(IAttackableEntity entity) { return IsPlayerAttackableEntity(entity, PlayerOne, IsPlayerOneDead); } public bool TryOverrideLocalPlayerAllyStatus(AIDetectionController controller, IAttackableEntity target, out bool isAlly) { isAlly = false; if ((Object)(object)controller == (Object)null || target == null) { return false; } bool num = IsPlayerOneAttackableEntity(target); bool flag = IsPlayerTwoAttackableEntity(target); if (!num && !flag) { return false; } if (IsAiCharmedByLocalPlayer(controller)) { isAlly = true; return true; } if (flag) { isAlly = false; return true; } return false; } public bool ShouldAiTreatPlayerTwoAsAttackable(AIDetectionController controller, IAttackableEntity target) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!IsPlayerTwoAttackableEntity(target) || (Object)(object)controller == (Object)null || IsAiCharmedByLocalPlayer(controller) || !IsWithinAiRefreshDistance(controller, ((Component)PlayerTwo).transform.position)) { return false; } LogPlayerTwoTargetConsidered(controller); RemovePlayerTwoFromAiIgnoreSet(controller, target); _playerTwoAiHudStatus = "P2 AI: SEEN " + ((Object)controller).name; return true; } public bool IsDestroyedOrDisabledAttackTarget(IAttackableEntity target) { if (target == null) { return true; } try { Health health = target.Health; return (Object)(object)health == (Object)null || (Object)(object)((Component)health).gameObject == (Object)null || !((Behaviour)health).isActiveAndEnabled; } catch { return true; } } public bool TryNormalizeLocalPlayerAttackScore(AIDetectionController controller, IAttackableEntity target, float distanceToTarget, float computedScore, out float normalizedScore) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown normalizedScore = computedScore; if ((Object)(object)controller == (Object)null || target == null) { return false; } bool num = IsPlayerOneAttackableEntity(target); bool flag = IsPlayerTwoAttackableEntity(target); if (!num && !flag) { return false; } if (IsAiCharmedByLocalPlayer(controller)) { normalizedScore = 0f; return true; } normalizedScore = 1f / (1f + Mathf.Max(0f, distanceToTarget)); if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoAttackScoreForced) { _loggedPlayerTwoAttackScoreForced = true; ManualLogSource logger = Plugin.Logger; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(104, 4, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Normalized local-player AI target scores by distance; sample target="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(flag ? "P2" : "P1"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", distance="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(distanceToTarget, "0.##"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", original="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(computedScore, "0.###"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", normalized="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(normalizedScore, "0.###"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logger.LogInfo(val); } return true; } public void RefreshCharmedAiFriendliness(AIDetectionController controller) { if (Plugin.ModEnabled.Value && !((Object)(object)controller == (Object)null) && IsAiCharmedByLocalPlayer(controller)) { ForgetLocalPlayerTarget(controller, PlayerOne); ForgetLocalPlayerTarget(controller, PlayerTwo); controller.ForceRefreshAttackTarget(); } } public bool ShouldBypassPlayerTwoPreventBeingAttackedOnSight(Component preventComponent) { if (!IsPlayerTwoComponent(preventComponent) || IsPlayerTwoDead) { return false; } if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoPreventSightBypass) { Plugin.Logger.LogInfo((object)"Bypassing cloned PreventBeingAttackedOnSight component for player two."); _loggedPlayerTwoPreventSightBypass = true; } return true; } public void RecordPlayerTwoDamageAttempt(Health health, string source, float damage) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoDamageAttempt && IsPlayerTwoComponent((Component)(object)health)) { _loggedPlayerTwoDamageAttempt = true; ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(113, 6, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Observed damage attempt on player two via "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": requestedDamage="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(damage); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", currentHealth="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(health.CurrentHealth); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", maxHealth="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(health.MaximumHealth); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", invulnerable="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(health.Invulnerable); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", immune="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(health.ImmuneToDamage); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logger.LogInfo(val); } } public void RecordPlayerTwoDamageResult(Health health, string source, float damage, float before) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown if (Plugin.DiagnosticsEnabled.Value && !((Object)(object)health == (Object)null) && IsPlayerTwoComponent((Component)(object)health) && _playerTwoDamageResultLogs < 6) { float currentHealth = health.CurrentHealth; bool flag = currentHealth < before - 0.001f; _playerTwoDamageHudStatus = (flag ? $"P2 DMG: OK {Mathf.CeilToInt(before)}->{Mathf.CeilToInt(currentHealth)}" : $"P2 DMG: CHECK {Mathf.CeilToInt(before)}->{Mathf.CeilToInt(currentHealth)}"); _playerTwoDamageResultLogs++; ManualLogSource logger = Plugin.Logger; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(82, 6, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Player-two damage result via "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": requestedDamage="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(damage, "0.##"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", health "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(before, "0.##"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" -> "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(currentHealth, "0.##"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", decreased="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(flag); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", p2Dead="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(IsPlayerTwoDead); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logger.LogInfo(val); } } public bool ShouldSuppressFriendlyFireDamage(Health targetHealth, GameObject instigator) { if (!Plugin.ModEnabled.Value || _applyingDiagnosticDamage || (Object)(object)targetHealth == (Object)null || (Object)(object)instigator == (Object)null) { return false; } PlayerCharacter componentInParent = ((Component)targetHealth).GetComponentInParent(); PlayerCharacter sourcePlayer = ResolveLocalPlayerDamageSource(instigator); return ShouldSuppressLocalPlayerDamage(sourcePlayer, componentInParent, "Health.Damage"); } public bool ShouldSuppressFriendlyFireCollision(DamageOnTouch damageOnTouch, Collider2D targetCollider) { if (!Plugin.ModEnabled.Value || (Object)(object)damageOnTouch == (Object)null || (Object)(object)targetCollider == (Object)null) { return false; } PlayerCharacter sourcePlayer = ResolveLocalPlayerDamageSource(damageOnTouch); PlayerCharacter componentInParent = ((Component)targetCollider).GetComponentInParent(); return ShouldSuppressLocalPlayerDamage(sourcePlayer, componentInParent, "DamageOnTouch(" + ((Object)damageOnTouch).name + ")"); } private bool ShouldSuppressLocalPlayerDamage(PlayerCharacter sourcePlayer, PlayerCharacter targetPlayer, string source) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown if (!IsTrackedLocalPlayer(sourcePlayer) || !IsTrackedLocalPlayer(targetPlayer)) { return false; } bool flag = IsSamePlayer(sourcePlayer, targetPlayer); if (!flag && Plugin.FriendlyFireEnabled.Value) { return false; } if (Plugin.DiagnosticsEnabled.Value && !_loggedFriendlyFireSuppressed) { _loggedFriendlyFireSuppressed = true; string text = (flag ? "self damage" : "friendly fire"); ManualLogSource logger = Plugin.Logger; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(36, 4, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Suppressed local-player "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" via "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)sourcePlayer).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" -> "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)targetPlayer).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logger.LogInfo(val); } return true; } private PlayerCharacter ResolveLocalPlayerDamageSource(DamageOnTouch damageOnTouch) { if ((Object)(object)damageOnTouch == (Object)null) { return null; } PlayerCharacter val = ResolveLocalPlayerDamageSource(damageOnTouch.DamageOwner); if (IsTrackedLocalPlayer(val)) { return val; } val = ResolveLocalPlayerDamageSource(damageOnTouch.Owner); if (IsTrackedLocalPlayer(val)) { return val; } return ResolveLocalPlayerDamageSource(((Component)damageOnTouch).gameObject); } private PlayerCharacter ResolveLocalPlayerDamageSource(GameObject sourceObject) { if ((Object)(object)sourceObject == (Object)null) { return null; } PlayerCharacter componentInParent = sourceObject.GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } componentInParent = ResolveAttackOwner(sourceObject.GetComponentInParent()); return componentInParent ?? ResolveCurrentAttackOwner(sourceObject); } private PlayerCharacter ResolveAttackOwner(EICCharacterAttack attack) { if ((Object)(object)attack == (Object)null) { return null; } try { Character owner = ((Weapon)attack).Owner; PlayerCharacter val = ((owner != null) ? ((Component)owner).GetComponentInParent() : null); if ((Object)(object)val != (Object)null) { return val; } IStatCharacter statCharacterOwner = attack.StatCharacterOwner; object obj; if (statCharacterOwner == null) { obj = null; } else { Health health = statCharacterOwner.Health; obj = ((health != null) ? ((Component)health).GetComponentInParent() : null); } val = (PlayerCharacter)obj; if ((Object)(object)val != (Object)null) { return val; } AAttackHandler attackHandler = attack.AttackHandler; return (attackHandler != null) ? ((Component)attackHandler).GetComponentInParent() : null; } catch { return null; } } private PlayerCharacter ResolveLocalPlayerOwner(Component component) { if ((Object)(object)component == (Object)null) { return null; } PlayerCharacter componentInParent = component.GetComponentInParent(); if (IsPlayerOne(componentInParent) || IsPlayerTwo(componentInParent)) { return componentInParent; } componentInParent = ResolveAttackOwner(component.GetComponentInParent()); if (IsPlayerOne(componentInParent) || IsPlayerTwo(componentInParent)) { return componentInParent; } componentInParent = (((Object)(object)component.gameObject != (Object)null) ? ResolveCurrentAttackOwner(component.gameObject) : null); if (!IsPlayerOne(componentInParent) && !IsPlayerTwo(componentInParent)) { return null; } return componentInParent; } private bool TryGetLocalPlayerAim(Component component, out PlayerCharacter player, out Vector3 aim) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ModEnabled.Value) { player = null; aim = Vector3.zero; return false; } player = ResolveLocalPlayerOwner(component); if (IsPlayerTwo(player)) { aim = GetPlayerTwoAimVector(); return true; } if (_playerOneAimControlled && IsPlayerOne(player)) { aim = new Vector3(_playerOneAim.x, _playerOneAim.y, 0f); return true; } player = null; aim = Vector3.zero; return false; } private bool IsLocalPlayerDead(PlayerCharacter player) { if (!IsPlayerTwo(player)) { return IsPlayerOneDead; } return IsPlayerTwoDead; } private PlayerCharacter ResolveCurrentAttackOwner(GameObject sourceObject) { if ((Object)(object)sourceObject == (Object)null) { return null; } Transform transform = sourceObject.transform; PlayerCharacter[] array = (PlayerCharacter[])(object)new PlayerCharacter[2] { PlayerTwo, PlayerOne }; foreach (PlayerCharacter val in array) { if ((Object)(object)val == (Object)null) { continue; } foreach (AAttackHandler componentsInChild in ((Component)val).GetComponentsInChildren(true)) { object obj; if (componentsInChild == null) { obj = null; } else { Weapon currentWeapon = ((CharacterHandleWeapon)componentsInChild).CurrentWeapon; obj = ((currentWeapon != null) ? ((Il2CppObjectBase)currentWeapon).TryCast() : null); } EICCharacterAttack val2 = (EICCharacterAttack)obj; if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null)) { Transform transform2 = ((Component)val2).transform; if (((Object)((Component)val2).gameObject).GetInstanceID() == ((Object)sourceObject).GetInstanceID() || ((Object)(object)transform != (Object)null && (Object)(object)transform2 != (Object)null && transform.IsChildOf(transform2))) { return val; } WeaponAim weaponAim = val2.WeaponAim; if ((Object)(object)weaponAim != (Object)null && (Object)(object)((Component)weaponAim).gameObject != (Object)null && ((Object)((Component)weaponAim).gameObject).GetInstanceID() == ((Object)sourceObject).GetInstanceID()) { return val; } } } } return null; } private bool IsPlayerTwo(PlayerCharacter player) { if ((Object)(object)player != (Object)null) { if (_playerTwoId == 0 || ((Object)player).GetInstanceID() != _playerTwoId) { if ((Object)(object)((Component)player).gameObject != (Object)null) { return ((Object)((Component)player).gameObject).name.StartsWith("LocalMultiplayer_Player2", StringComparison.Ordinal); } return false; } return true; } return false; } private bool IsTrackedLocalPlayer(PlayerCharacter player) { if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).gameObject == (Object)null) { return false; } if (!IsSamePlayer(player, PlayerOne) && !IsSamePlayer(player, PlayerTwo) && !((Object)((Component)player).gameObject).name.StartsWith("LocalMultiplayer_Player2", StringComparison.Ordinal)) { return ((Object)((Component)player).gameObject).name.StartsWith("LocalMultiplayer_Player1_PendingDestroy", StringComparison.Ordinal); } return true; } private static GameObject GetDamageOnTouchInstigator(DamageOnTouch damageOnTouch) { if ((Object)(object)damageOnTouch == (Object)null) { return null; } if (!((Object)(object)damageOnTouch.DamageOwner != (Object)null)) { return damageOnTouch.Owner; } return damageOnTouch.DamageOwner; } private static float GetDamageOnTouchFallbackDamage(DamageOnTouch damageOnTouch) { if ((Object)(object)damageOnTouch == (Object)null) { return 0f; } float num = Mathf.Max(0f, damageOnTouch.MinDamageCaused); float num2 = Mathf.Max(num, damageOnTouch.MaxDamageCaused); if (num2 <= 0f) { return 0f; } if (!Mathf.Approximately(num, num2)) { return Random.Range(num, num2); } return num2; } private bool CanDamageOnTouchReachPlayerTwo(DamageOnTouch damageOnTouch, Collider2D otherCollider) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown if ((Object)(object)damageOnTouch == (Object)null || (Object)(object)otherCollider == (Object)null || (Object)(object)((Component)otherCollider).gameObject == (Object)null) { return false; } try { return damageOnTouch.EvaluateAvailability(((Component)otherCollider).gameObject); } catch (Exception ex) { if (Plugin.DiagnosticsEnabled.Value) { ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(105, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not evaluate DamageOnTouch availability for player two; fallback will remain enabled for this hit. "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } logger.LogWarning(val); } return true; } } private void ClearDamageOnTouchState() { _damageOnTouchStateKey = 0; _damageOnTouchStateHealth = null; _damageOnTouchStateInstigator = null; _damageOnTouchStateBeforeHealth = 0f; _damageOnTouchStateFallbackDamage = 0f; _damageOnTouchStateInvincibilityDuration = 0f; _damageOnTouchStateContextualDeathTip = 0; _damageOnTouchStateSourceName = string.Empty; } private void ResetHudStatuses() { _playerTwoDamageHudStatus = "P2 DMG: WAIT"; _playerTwoAiHudStatus = "P2 AI: WAIT"; _cameraHudStatus = "CAM: WAIT"; } private static int BuildDamageOnTouchStateKey(DamageOnTouch damageOnTouch, Collider2D otherCollider) { if ((Object)(object)damageOnTouch == (Object)null || (Object)(object)otherCollider == (Object)null) { return 0; } return (((Object)damageOnTouch).GetInstanceID() * 397) ^ ((Object)otherCollider).GetInstanceID(); } private void ResetForSceneChanges() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Expected O, but got Unknown Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).handle != _sceneHandle) { _sceneHandle = ((Scene)(ref activeScene)).handle; PlayerOne = null; PlayerTwo = null; _playerOneId = 0; _playerTwoId = 0; _cameraId = 0; _cameraEnforcerId = 0; _baseOrthographicSize = 0f; _smoothedOrthographicSize = 0f; _smoothedCameraCenter = Vector2.zero; _hasSharedCameraState = false; SharedCameraMidpointError = float.PositiveInfinity; RenderCameraMidpointError = float.PositiveInfinity; ClearSharedNightVisionTracking(); _nextSpawnAttemptAt = Time.unscaledTime + 1f; _nextSpawnWaitLogAt = 0f; _nextAiRefreshAt = 0f; _lastSpawnWaitReason = string.Empty; ResetHudStatuses(); ClearDamageOnTouchState(); _loggedPlayerTwoInput = false; _loggedFilteredStockInput = false; _loggedPlayerTwoDamageAttempt = false; _loggedPlayerTwoDamageOutputOverride = false; _loggedPlayerTwoMasterHealthCleared = false; _loggedPlayerTwoColliderState = false; _loggedPlayerTwoPhysicalColliderEnabled = false; _loggedPlayerTwoRigidbodyEnabled = false; _loggedPlayerTwoDamageOnTouchCollision = false; _loggedPlayerTwoDamageOnTouchMaskPatched = false; _loggedPlayerTwoDamageOnTouchIgnoreCleared = false; _loggedPlayerTwoDamageOnTouchFallback = false; _loggedPlayerTwoAiIgnoreCleared = false; _loggedPlayerTwoDirectAiRegistration = false; _loggedPlayerTwoDirectAiRegistrationFailure = false; _loggedPlayerTwoAttackScoreForced = false; _loggedPlayerTwoTargetConsidered = false; _loggedPlayerTwoPreventSightBypass = false; _loggedFriendlyFireSuppressed = false; _playerTwoDamageResultLogs = 0; _playerOneDead = false; _playerOneAwaitingRevive = false; _playerTwoDead = false; _playerTwoAwaitingRevive = false; _playerOneObjectName = "PlayerCharacter"; _playerOneSpriteColors.Clear(); _playerOneMove = Vector2.zero; ResetMushroomEffectOwnership(); _evolutionPickerOpen = false; _suppressedPlayerDeathDropCount = 0; _previousDamagePlayerTwoHeld = false; _previousDamagePlayerOneHeld = false; ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(44, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Scene changed to "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Scene)(ref activeScene)).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; waiting for player spawn."); } logger.LogInfo(val); } } private void TrySpawnPlayerTwo() { if (!((Object)(object)PlayerTwo != (Object)null) && !_playerTwoAwaitingRevive && !(Time.unscaledTime < _nextSpawnAttemptAt)) { _nextSpawnAttemptAt = Time.unscaledTime + 1f; PlayerCharacter val = FindPrimaryPlayerCandidate(); if ((Object)(object)val == (Object)null) { LogSpawnWaitReason("No active primary PlayerCharacter is available yet."); return; } if (!((Behaviour)val).isActiveAndEnabled) { LogSpawnWaitReason("PlayerCharacter.Instance exists but is inactive: " + ((Object)val).name + "."); return; } if (!PlayerCharacter.IsSpawned && !CanUseGameplaySpawnFallback(val)) { LogSpawnWaitReason("PlayerCharacter.IsSpawned is false."); return; } PlayerOne = val; _playerOneId = ((Object)val).GetInstanceID(); CapturePlayerOneVisualState(val); SpawnPlayerTwoFromPrimary(val, "automatic"); } } private void SpawnPlayerTwoFromPrimary(PlayerCharacter primary, string reason) { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown //IL_01e3: Unknown result type (might be due to invalid IL or missing references) bool flag = default(bool); if ((Object)(object)primary == (Object)null) { ManualLogSource logger = Plugin.Logger; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(56, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Cannot spawn player two ("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(reason); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("): no primary player candidate."); } logger.LogWarning(val); return; } PlayerOne = primary; _playerOneId = ((Object)primary).GetInstanceID(); _playerOneAwaitingRevive = false; CapturePlayerOneVisualState(primary); if (TryAttachExistingPlayerTwo()) { PlayerCharacter.Instance = primary; return; } Vector3 val2 = ((Component)primary).transform.position + new Vector3(Plugin.SpawnOffsetX.Value, Plugin.SpawnOffsetY.Value, 0f); GameObject val3; try { PlayerCharacter.Instance = null; val3 = Object.Instantiate(((Component)primary).gameObject, val2, ((Component)primary).transform.rotation); } catch (Exception ex) { ManualLogSource logger2 = Plugin.Logger; BepInExErrorLogInterpolatedStringHandler val4 = new BepInExErrorLogInterpolatedStringHandler(37, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Failed to instantiate player two ("); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(reason); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("): "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(ex); } logger2.LogError(val4); return; } finally { PlayerCharacter.Instance = primary; } ((Object)val3).name = "LocalMultiplayer_Player2"; PlayerCharacter component = val3.GetComponent(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val3); Plugin.Logger.LogWarning((object)"Cloned player object did not contain PlayerCharacter; player two spawn aborted."); return; } PlayerTwo = component; _playerTwoId = ((Object)component).GetInstanceID(); _playerTwoDead = false; _playerTwoAwaitingRevive = false; ResetHudStatuses(); PreparePlayerTwoForCoop(component); ApplyPlayerOneVisuals(((Component)primary).gameObject); ApplyPlayerTwoVisuals(val3); NotifyExistingAiAboutPlayerTwo(reason); PlayerCharacter.Instance = primary; ManualLogSource logger3 = Plugin.Logger; BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(84, 5, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Spawned player two ("); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(reason); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(") from "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(((Object)primary).name); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" at "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(val2); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(". Gamepads detected: "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(Gamepad.all.Count); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("; configured player-two index: "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(GetPlayerTwoGamepadIndex()); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("."); } logger3.LogInfo(val5); } private void MaintainPlayerSingleton() { if ((Object)(object)PlayerTwo == (Object)null) { if (_playerTwoAwaitingRevive && IsAlive(PlayerOne) && !IsSamePlayer(PlayerCharacter.Instance, PlayerOne)) { PlayerCharacter.Instance = PlayerOne; } } else if (IsPlayerOneDead && IsAlive(PlayerTwo)) { PlayerCharacter.Instance = PlayerTwo; } else if (!((Object)(object)PlayerOne == (Object)null)) { PlayerCharacter instance = PlayerCharacter.Instance; if ((Object)(object)instance != (Object)null && ((Object)instance).GetInstanceID() == _playerTwoId) { PlayerCharacter.Instance = PlayerOne; } } } private void PreparePlayerTwoForCoop(PlayerCharacter playerTwo) { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown if ((Object)(object)playerTwo == (Object)null) { return; } try { playerTwo._timeToMakeInvisibleToEnemiesAtStartOfRun = 0f; playerTwo._timeToMakeInvisibleToEnemiesAtStartOfExtinction = 0f; RepairPlayerTwoInteractionState(playerTwo); EnsurePlayerTwoHitCollider(playerTwo); ResetPlayerTwoCharmState(playerTwo); EvolutionHandler playerEvolutionHandler = playerTwo.PlayerEvolutionHandler; if ((Object)(object)playerEvolutionHandler != (Object)null) { playerEvolutionHandler._PlayerCharacter_k__BackingField = playerTwo; playerEvolutionHandler.CanAddEvoPoints = true; } foreach (EdibleItemConsumer componentsInChild in ((Component)playerTwo).GetComponentsInChildren(true)) { if ((Object)(object)componentsInChild != (Object)null) { componentsInChild._StatCharacter_k__BackingField = ((Il2CppObjectBase)playerTwo).Cast(); } } Health health = ((AStatCharacter)(object)playerTwo).Health; if ((Object)(object)health != (Object)null) { if (health.CurrentHealth <= 0f) { health.ResetHealthToMaxHealth(); } ClearDamageLocks(health); health.UpdateHealthBar(true); } RepairPlayerTwoAttackState(playerTwo, resetCooldowns: true); RepairPlayerTwoDashState(playerTwo); _lastPlayerTwoSizePercentage = float.NaN; RefreshPlayerTwoSizeVisuals(force: true); } catch (Exception ex) { ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(63, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to fully prepare player two for co-op damage/targeting: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } logger.LogWarning(val); } } private void RepairPlayerTwoAttackState(PlayerCharacter playerTwo, bool resetCooldowns) { //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Expected O, but got Unknown //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) Il2CppArrayBase componentsInChildren = ((Component)playerTwo).GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { return; } PlayerAttackManager val = null; foreach (AAttackHandler item in componentsInChildren) { if ((Object)(object)item != (Object)null && (Object)(object)item.AttackManager != (Object)null) { val = ((Il2CppObjectBase)item.AttackManager).TryCast(); if ((Object)(object)val != (Object)null) { break; } } } PlayerCharacter instance = PlayerCharacter.Instance; try { PlayerCharacter.Instance = playerTwo; IStatCharacter val2 = ((Il2CppObjectBase)playerTwo).Cast(); PlayerCharacter playerOne = PlayerOne; PlayerAttackManager val3 = ((playerOne != null) ? ((Component)playerOne).GetComponentInChildren(true) : null); List val4 = new List(); foreach (AAttackHandler item2 in componentsInChildren) { if ((Object)(object)item2 != (Object)null) { val4.Add((CharacterHandleWeapon)(object)item2); } } if ((Object)(object)val != (Object)null) { BindAttackAbilityToPlayer((CharacterAbility)(object)val, playerTwo, val4); ((CharacterAttackManager)val)._StatCharacter_k__BackingField = val2; if (resetCooldowns || ((CharacterAttackManager)val)._attackSlotTypeCooldown == null) { ((CharacterAttackManager)val)._attackSlotTypeCooldown = new Dictionary(); } PlayerAttackManager val5 = ((Il2CppObjectBase)val).TryCast(); if ((Object)(object)val5 != (Object)null) { if (resetCooldowns || val5._timeAttackWasLastUsed == null) { val5._timeAttackWasLastUsed = new Dictionary(); } if ((Object)(object)val3 != (Object)null) { CopyEquippedAttackAbilities(val3, val5); } } } bool flag = default(bool); foreach (AAttackHandler item3 in componentsInChildren) { if ((Object)(object)item3 == (Object)null) { continue; } BindAttackAbilityToPlayer((CharacterAbility)(object)item3, playerTwo, val4); ((CharacterHandleWeapon)item3).ForceWeaponAimControl = true; ((CharacterHandleWeapon)item3).ForcedWeaponAimControl = (AimControls)4; if ((Object)(object)val != (Object)null) { item3._attackManager = (CharacterAttackManager)(object)val; BindAttackHandlerToManager(val, item3); } Weapon currentWeapon = ((CharacterHandleWeapon)item3).CurrentWeapon; EICCharacterAttack val6 = ((currentWeapon != null) ? ((Il2CppObjectBase)currentWeapon).TryCast() : null); if ((Object)(object)val6 == (Object)null) { continue; } try { item3._CurrentAttack_k__BackingField = val6; val6._StatCharacterOwner_k__BackingField = val2; val6._AttackHandler_k__BackingField = item3; ((Weapon)val6).SetOwner((Character)(object)playerTwo, (CharacterHandleWeapon)(object)item3); val6._StatCharacterOwner_k__BackingField = val2; val6._AttackHandler_k__BackingField = item3; if (resetCooldowns || ((Weapon)val6).WeaponState == null) { ((Weapon)val6).Initialization(); } ConfigureWeaponAim(val6.WeaponAim, GetPlayerTwoAimVector(), ((Behaviour)val6).isActiveAndEnabled); if ((Object)(object)val != (Object)null && (resetCooldowns || !((CharacterAttackManager)val)._attackSlotTypeCooldown.ContainsKey(item3.AttackSlot))) { float num = Mathf.Max(0.001f, val6.AttackCooldown); float time = Time.time; ((CharacterAttackManager)val)._attackSlotTypeCooldown[item3.AttackSlot] = new AttackCooldownData(time - num, time, false, false); } } catch (Exception ex) { ManualLogSource logger = Plugin.Logger; BepInExWarningLogInterpolatedStringHandler val7 = new BepInExWarningLogInterpolatedStringHandler(43, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("Failed to prepare player-two attack slot "); ((BepInExLogInterpolatedStringHandler)val7).AppendFormatted(item3.AttackSlot); ((BepInExLogInterpolatedStringHandler)val7).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val7).AppendFormatted(ex.Message); } logger.LogWarning(val7); } } } finally { PlayerCharacter.Instance = instance; } } private static List BuildHandleWeaponList(PlayerCharacter player) { List val = new List(); foreach (AAttackHandler componentsInChild in ((Component)player).GetComponentsInChildren(true)) { if ((Object)(object)componentsInChild != (Object)null) { val.Add((CharacterHandleWeapon)(object)componentsInChild); } } return val; } private static void RepairPlayerTwoInteractionState(PlayerCharacter playerTwo) { List handleWeapons = BuildHandleWeaponList(playerTwo); foreach (PlayerInteraction componentsInChild in ((Component)playerTwo).GetComponentsInChildren(true)) { if (!((Object)(object)componentsInChild == (Object)null)) { BindAttackAbilityToPlayer((CharacterAbility)(object)componentsInChild, playerTwo, handleWeapons); componentsInChild._playerCharacter = playerTwo; componentsInChild._currentInteractable = null; componentsInChild._possibleInteractables = new List(); ((Behaviour)componentsInChild).enabled = true; } } } private void RepairPlayerTwoDashState(PlayerCharacter playerTwo) { RepairDashState(playerTwo, PlayerOne); } private void RepairDashState(PlayerCharacter player, PlayerCharacter referencePlayer) { PlayerDashManager componentInChildren = ((Component)player).GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { return; } PlayerCharacter instance = PlayerCharacter.Instance; try { PlayerCharacter.Instance = player; List handleWeapons = BuildHandleWeaponList(player); IStatCharacter statCharacter_k__BackingField = ((Il2CppObjectBase)player).Cast(); PlayerDashManager val = ((referencePlayer != null) ? ((Component)referencePlayer).GetComponentInChildren(true) : null); ADashCharacterAbility val2 = ((val != null) ? ((CharacterDashManager)val).CurrentDashAbility : null); BindAttackAbilityToPlayer((CharacterAbility)(object)componentInChildren, player, handleWeapons); ((CharacterDashManager)componentInChildren)._StatCharacter_k__BackingField = statCharacter_k__BackingField; ADashCharacterAbility val3 = ((CharacterDashManager)componentInChildren).CurrentDashAbility; if ((Object)(object)val3 == (Object)null) { foreach (ADashCharacterAbility componentsInChild in ((Component)player).GetComponentsInChildren(true)) { if (!((Object)(object)componentsInChild == (Object)null)) { if ((Object)(object)val3 == (Object)null || ((Object)(object)val2 != (Object)null && string.Equals(((Object)componentsInChild).name, ((Object)val2).name, StringComparison.Ordinal))) { val3 = componentsInChild; } if ((Object)(object)val2 != (Object)null && string.Equals(((Object)componentsInChild).name, ((Object)val2).name, StringComparison.Ordinal)) { break; } } } if ((Object)(object)val3 != (Object)null) { ((CharacterDashManager)componentInChildren)._CurrentDashAbility_k__BackingField = val3; ((CharacterDashManager)componentInChildren)._CurrentDashEvolutionAbility_k__BackingField = ((val != null) ? ((CharacterDashManager)val).CurrentDashEvolutionAbility : null); } else if (((val != null) ? ((CharacterDashManager)val).CurrentDashEvolutionAbility : null) != null) { ((CharacterDashManager)componentInChildren).EquipDash(((CharacterDashManager)val).CurrentDashEvolutionAbility); val3 = ((CharacterDashManager)componentInChildren).CurrentDashAbility; } } if (!((Object)(object)val3 == (Object)null)) { BindAttackAbilityToPlayer((CharacterAbility)(object)val3, player, handleWeapons); val3._StatCharacter_k__BackingField = statCharacter_k__BackingField; if (val3._cooldown == null && ((val2 != null) ? val2._cooldown : null) != null) { val3._cooldown = CloneCooldown(val2._cooldown); } else if (val3._cooldown != null && ((val2 != null) ? val2._cooldown : null) != null && ((Il2CppObjectBase)val3._cooldown).Pointer == ((Il2CppObjectBase)val2._cooldown).Pointer) { val3._cooldown = CloneCooldown(val3._cooldown); } } } finally { PlayerCharacter.Instance = instance; } } private static MMCooldown CloneCooldown(MMCooldown source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown MMCooldown val = new MMCooldown { Unlimited = source.Unlimited, ConsumptionDuration = source.ConsumptionDuration, PauseOnEmptyDuration = source.PauseOnEmptyDuration, RefillDuration = source.RefillDuration, CanInterruptRefill = source.CanInterruptRefill }; val.Initialization(); val.CooldownState = source.CooldownState; val.CurrentDurationLeft = source.CurrentDurationLeft; val._emptyReachedTimestamp = source._emptyReachedTimestamp; return val; } private void RefreshPlayerTwoSizeVisuals(bool force) { //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown PlayerCharacter playerTwo = PlayerTwo; object obj; if (playerTwo == null) { obj = null; } else { PlayerStats entityStats = ((AStatCharacter)(object)playerTwo).EntityStats; obj = ((entityStats != null) ? ((AEntityStats)entityStats).Size : null); } SummedPercentageStatValue val = (SummedPercentageStatValue)obj; if ((Object)(object)playerTwo == (Object)null || val == null) { return; } float percentageValue = val.PercentageValue; if (!force && !float.IsNaN(_lastPlayerTwoSizePercentage) && Mathf.Abs(percentageValue - _lastPlayerTwoSizePercentage) <= 0.0001f) { return; } _lastPlayerTwoSizePercentage = percentageValue; PlayerCharacter instance = PlayerCharacter.Instance; try { PlayerCharacter.Instance = playerTwo; ((AStatCharacter)(object)playerTwo).OnSizeChanged(); IStatCharacter statCharacter = ((Il2CppObjectBase)playerTwo).Cast(); foreach (ResizeToCharacterSize componentsInChild in ((Component)playerTwo).GetComponentsInChildren(true)) { if (!((Object)(object)componentsInChild == (Object)null)) { componentsInChild._statCharacter = statCharacter; if ((componentsInChild._adjustYOffset || componentsInChild._adjustHeight) && (Object)(object)componentsInChild._rectTransform == (Object)null) { componentsInChild._rectTransform = ((Component)componentsInChild).GetComponent(); } bool num = componentsInChild._adjustScale && componentsInChild._characterSizeToStatusSizeModifier != null; bool flag = componentsInChild._adjustYOffset && (Object)(object)componentsInChild._rectTransform != (Object)null && componentsInChild._characterSizeToDefaultYOffsetModifier != null; bool flag2 = componentsInChild._adjustHeight && (Object)(object)componentsInChild._rectTransform != (Object)null && componentsInChild._characterSizeToDefaultHeightModifier != null; if (num || flag || flag2) { componentsInChild.ResetSize(); } } } } catch (Exception ex) { ManualLogSource logger = Plugin.Logger; bool flag3 = default(bool); BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(43, 1, ref flag3); if (flag3) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to refresh player-two size visuals: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } logger.LogWarning(val2); } finally { PlayerCharacter.Instance = instance; } } private static void CopyEquippedAttackAbilities(PlayerAttackManager source, PlayerAttackManager destination) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) destination._startingAttackAbilityId = source._startingAttackAbilityId; ((CharacterAttackManager)destination)._primaryAttackAbility = ((CharacterAttackManager)source)._primaryAttackAbility; ((CharacterAttackManager)destination)._secondaryAttackAbility = ((CharacterAttackManager)source)._secondaryAttackAbility; ((CharacterAttackManager)destination)._tertiaryAttackAbility = ((CharacterAttackManager)source)._tertiaryAttackAbility; ((CharacterAttackManager)destination)._quaternaryAttackAbility = ((CharacterAttackManager)source)._quaternaryAttackAbility; ((CharacterAttackManager)destination)._quinaryAttackAbility = ((CharacterAttackManager)source)._quinaryAttackAbility; } private static void BindAttackHandlerToManager(PlayerAttackManager attackManager, AAttackHandler handler) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected I4, but got Unknown EAttackSlot attackSlot = handler.AttackSlot; switch (attackSlot - 1) { case 0: ((CharacterAttackManager)attackManager)._primaryAttackHandler = ((Il2CppObjectBase)handler).TryCast(); break; case 1: ((CharacterAttackManager)attackManager)._secondaryAttackHandler = ((Il2CppObjectBase)handler).TryCast(); break; case 2: ((CharacterAttackManager)attackManager)._tertiaryAttackHandler = ((Il2CppObjectBase)handler).TryCast(); break; case 3: ((CharacterAttackManager)attackManager)._quaternaryAttackHandler = ((Il2CppObjectBase)handler).TryCast(); break; case 4: ((CharacterAttackManager)attackManager)._quinaryAttackHandler = ((Il2CppObjectBase)handler).TryCast(); break; } } private static void BindAttackAbilityToPlayer(CharacterAbility ability, PlayerCharacter player, List handleWeapons) { ability._character = (Character)(object)player; ability._controller = ((Character)player)._controller; TopDownController controller = ((Character)player)._controller; ability._controller2D = ((controller != null) ? ((Il2CppObjectBase)controller).TryCast() : null); TopDownController controller2 = ((Character)player)._controller; ability._controller3D = ((controller2 != null) ? ((Il2CppObjectBase)controller2).TryCast() : null); ability._model = ((Character)player).CharacterModel; ability._health = ((AStatCharacter)(object)player).Health; ability._characterMovement = ((Component)player).GetComponentInChildren(true); ability._inputManager = ((Character)player).LinkedInputManager; ability._animator = ((Character)player).Animator; ability._state = ((Character)player).CharacterState; ability._movement = ((Character)player).MovementState; ability._condition = ((Character)player).ConditionState; ability._handleWeaponList = handleWeapons; ability._abilityInitialized = true; } private static void ResetPlayerTwoCharmState(PlayerCharacter playerTwo) { PlayerCharmController val = (((Object)(object)playerTwo != (Object)null) ? playerTwo.PlayerCharmController : null); if (!((Object)(object)val == (Object)null)) { val._playerCharacter = playerTwo; ((ACharmController)val)._currentCharmedAllies = new List(); ((ACharmController)val)._charmedAllyGameObjects = new HashSet(); val._enemyStatChanges = new Dictionary>(); } } private static int GetCharmCount(PlayerCharacter player) { PlayerCharmController val = (((Object)(object)player != (Object)null) ? player.PlayerCharmController : null); if (!((Object)(object)val != (Object)null)) { return 0; } return ((ACharmController)val).CurrentNumCharmedEnemies; } private static void ReleasePlayerCharms(PlayerCharacter player) { PlayerCharmController val = (((Object)(object)player != (Object)null) ? player.PlayerCharmController : null); IReadOnlyList val2 = (((Object)(object)val != (Object)null) ? ((ACharmController)val).CurrentCharmedAllies : null); int num = (((Object)(object)val != (Object)null) ? ((ACharmController)val).CurrentNumCharmedEnemies : 0); if ((Object)(object)val == (Object)null || val2 == null || num == 0) { return; } List val3 = new List(); for (int i = 0; i < num; i++) { val3.Add(val2[i]); } for (int j = 0; j < val3.Count; j++) { AIDetectionController val4 = val3[j]; if ((Object)(object)val4 != (Object)null) { ((ACharmController)val).StopCharming(val4); } } } private void EnsurePlayerTwoDamageable() { if (Plugin.ForcePlayerTwoDamageEnabled.Value && !((Object)(object)PlayerTwo == (Object)null) && !IsPlayerTwoDead) { EnsurePlayerTwoHitCollider(PlayerTwo); Health health = ((AStatCharacter)(object)PlayerTwo).Health; if (!((Object)(object)health == (Object)null) && !(health.CurrentHealth <= 0f)) { ClearDamageLocks(health); } } } private void ClearDamageLocks(Health health) { health.Invulnerable = false; health.ImmuneToDamage = false; health.CanIgnoreDamageFromTargetCallback = null; ClearClonedMasterHealth(health); health.DamageEnabled(); } private void ClearClonedMasterHealth(Health health) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown Health masterHealth = health.MasterHealth; if ((Object)(object)masterHealth == (Object)null || ((Object)masterHealth).GetInstanceID() == ((Object)health).GetInstanceID()) { return; } health.MasterHealth = null; if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoMasterHealthCleared) { _loggedPlayerTwoMasterHealthCleared = true; ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(104, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Cleared cloned player-two MasterHealth reference to "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)masterHealth).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; P2 damage will apply to P2's own Health component."); } logger.LogInfo(val); } } private void EnsurePlayerTwoHitCollider(PlayerCharacter playerTwo) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown if ((Object)(object)playerTwo == (Object)null) { return; } CircleCollider2D physicalCollider = ((AStatCharacter)(object)playerTwo).PhysicalCollider; if ((Object)(object)physicalCollider == (Object)null) { if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoColliderState) { _loggedPlayerTwoColliderState = true; Plugin.Logger.LogWarning((object)"Player two has no PhysicalCollider; enemy hitboxes may not be able to collide with P2."); } return; } bool flag = default(bool); if (!((Behaviour)physicalCollider).enabled) { ((Behaviour)physicalCollider).enabled = true; if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoPhysicalColliderEnabled) { _loggedPlayerTwoPhysicalColliderEnabled = true; ManualLogSource logger = Plugin.Logger; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(71, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Re-enabled player-two PhysicalCollider "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)physicalCollider).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" so enemy hitboxes can reach P2."); } logger.LogInfo(val); } } Rigidbody2D attachedRigidbody = ((Collider2D)physicalCollider).attachedRigidbody; if ((Object)(object)attachedRigidbody != (Object)null && !attachedRigidbody.simulated) { attachedRigidbody.simulated = true; if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoRigidbodyEnabled) { _loggedPlayerTwoRigidbodyEnabled = true; ManualLogSource logger2 = Plugin.Logger; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(82, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Re-enabled player-two Rigidbody2D simulation on "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)attachedRigidbody).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" so trigger hitboxes can reach P2."); } logger2.LogInfo(val); } } if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoColliderState) { _loggedPlayerTwoColliderState = true; string text = (((Object)(object)attachedRigidbody != (Object)null) ? $"rigidbody={attachedRigidbody.bodyType}, simulated={attachedRigidbody.simulated}" : "rigidbody=none"); ManualLogSource logger3 = Plugin.Logger; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(69, 6, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Player-two hit collider ready: name="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)physicalCollider).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", layer="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(LayerMask.LayerToName(((Component)physicalCollider).gameObject.layer)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Component)physicalCollider).gameObject.layer); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("), enabled="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Behaviour)physicalCollider).enabled); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", trigger="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Collider2D)physicalCollider).isTrigger); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logger3.LogInfo(val); } } private void RemovePlayerTwoFromDamageIgnoreList(DamageOnTouch damageOnTouch, Collider2D otherCollider, Health health) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown List ignoredGameObjects = damageOnTouch._ignoredGameObjects; if (ignoredGameObjects == null || ignoredGameObjects.Count <= 0) { return; } bool flag = false; flag |= RemoveIgnoredGameObject(ignoredGameObjects, ((Component)PlayerTwo).gameObject); flag |= RemoveIgnoredGameObject(ignoredGameObjects, ((Component)otherCollider).gameObject); if ((Object)(object)health != (Object)null) { flag |= RemoveIgnoredGameObject(ignoredGameObjects, ((Component)health).gameObject); } CircleCollider2D physicalCollider = ((AStatCharacter)(object)PlayerTwo).PhysicalCollider; if ((Object)(object)physicalCollider != (Object)null) { flag |= RemoveIgnoredGameObject(ignoredGameObjects, ((Component)physicalCollider).gameObject); } if (flag && Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoDamageOnTouchIgnoreCleared) { _loggedPlayerTwoDamageOnTouchIgnoreCleared = true; ManualLogSource logger = Plugin.Logger; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(100, 1, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Removed player-two objects from DamageOnTouch ignore list for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)damageOnTouch).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; P2 can be processed as a hit target."); } logger.LogInfo(val); } } private static bool RemoveIgnoredGameObject(List ignoredObjects, GameObject candidate) { if ((Object)(object)candidate != (Object)null) { return ignoredObjects.Remove(candidate); } return false; } private void IncludePlayerTwoLayerInDamageMask(DamageOnTouch damageOnTouch, Collider2D otherCollider) { //IL_0014: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown int layer = ((Component)otherCollider).gameObject.layer; int num = 1 << layer; LayerMask targetLayerMask = damageOnTouch.TargetLayerMask; if ((((LayerMask)(ref targetLayerMask)).value & num) != 0) { return; } ((LayerMask)(ref targetLayerMask)).value = ((LayerMask)(ref targetLayerMask)).value | num; damageOnTouch.TargetLayerMask = targetLayerMask; if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoDamageOnTouchMaskPatched) { _loggedPlayerTwoDamageOnTouchMaskPatched = true; ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(69, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Added player-two collider layer "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(LayerMask.LayerToName(layer)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(layer); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") to DamageOnTouch target mask for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)damageOnTouch).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logger.LogInfo(val); } } private void LogPlayerTwoDamageOnTouchCollision(DamageOnTouch damageOnTouch, Collider2D otherCollider, Health health) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoDamageOnTouchCollision) { _loggedPlayerTwoDamageOnTouchCollision = true; string text = (((Object)(object)damageOnTouch.Owner != (Object)null) ? ((Object)damageOnTouch.Owner).name : (((Object)(object)damageOnTouch.DamageOwner != (Object)null) ? ((Object)damageOnTouch.DamageOwner).name : "none")); string text2 = (((Object)(object)health != (Object)null) ? health.CurrentHealth.ToString("0.##") : "none"); string text3 = (((Object)(object)health != (Object)null) ? health.MaximumHealth.ToString("0.##") : "none"); ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(97, 8, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("DamageOnTouch saw player two: damageOnTouch="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)damageOnTouch).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", owner="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", collider="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)otherCollider).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", layer="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(LayerMask.LayerToName(((Component)otherCollider).gameObject.layer)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Component)otherCollider).gameObject.layer); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("), health="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text2); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("/"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text3); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", targetMask="); LayerMask targetLayerMask = damageOnTouch.TargetLayerMask; ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((LayerMask)(ref targetLayerMask)).value); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logger.LogInfo(val); } } private void RemovePlayerTwoFromAiIgnoreSet(AIDetectionController controller, IAttackableEntity target) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown if ((Object)(object)controller == (Object)null || target == null) { return; } HashSet entitiesToIgnore = controller.EntitiesToIgnore; if (entitiesToIgnore != null && entitiesToIgnore.Remove(target) && Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoAiIgnoreCleared) { _loggedPlayerTwoAiIgnoreCleared = true; ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(83, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Removed player two from AI ignore set for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)controller).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; P2 can be selected as an attack target."); } logger.LogInfo(val); } } private void DirectlyRegisterPlayerTwoAttackTarget(AIDetectionController controller, IAttackableEntity target) { //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown if (!Plugin.AiDirectTargetRegistrationEnabled.Value || (Object)(object)controller == (Object)null || target == null) { return; } bool flag2 = default(bool); try { bool flag = false; float unscaledTime = Time.unscaledTime; List potentialAttackInfos = controller._potentialAttackInfos; if (potentialAttackInfos != null && !potentialAttackInfos.Contains(target)) { potentialAttackInfos.Add(target); flag = true; } Dictionary enemiesBeingConsideredForAttackingMappings = controller._enemiesBeingConsideredForAttackingMappings; if (enemiesBeingConsideredForAttackingMappings != null) { if (enemiesBeingConsideredForAttackingMappings.ContainsKey(target)) { enemiesBeingConsideredForAttackingMappings[target] = true; } else { enemiesBeingConsideredForAttackingMappings.Add(target, true); } flag = true; } Dictionary potentialAttackInfoLatestScores = controller._potentialAttackInfoLatestScores; if (potentialAttackInfoLatestScores != null) { if (potentialAttackInfoLatestScores.ContainsKey(target)) { potentialAttackInfoLatestScores[target] = 0f; } else { potentialAttackInfoLatestScores.Add(target, 0f); } flag = true; } Dictionary timeLastNoticedEnemyInAttackRange = controller._timeLastNoticedEnemyInAttackRange; if (timeLastNoticedEnemyInAttackRange != null) { if (timeLastNoticedEnemyInAttackRange.ContainsKey(target)) { timeLastNoticedEnemyInAttackRange[target] = unscaledTime; } else { timeLastNoticedEnemyInAttackRange.Add(target, unscaledTime); } flag = true; } if (flag && Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoDirectAiRegistration) { _loggedPlayerTwoDirectAiRegistration = true; ManualLogSource logger = Plugin.Logger; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(140, 2, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Directly registered player two as a neutral potential attack target for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)controller).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; potentialTargets="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(potentialAttackInfos?.Count ?? (-1)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Distance scoring decides between local players."); } logger.LogInfo(val); } if (flag) { _playerTwoAiHudStatus = "P2 AI: REG " + ((Object)controller).name; } } catch (Exception ex) { _playerTwoAiHudStatus = "P2 AI: CHECK"; if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoDirectAiRegistrationFailure) { _loggedPlayerTwoDirectAiRegistrationFailure = true; ManualLogSource logger2 = Plugin.Logger; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(72, 2, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to directly register player two with AI target collections for "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(((Object)controller).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } logger2.LogWarning(val2); } } } private void MarkPlayerDead(PlayerCharacter player, Health health, bool isPlayerTwo) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown if (isPlayerTwo) { _playerTwoDead = true; } else { _playerOneDead = true; } try { AMovementController movementController = ((AStatCharacter)(object)player).MovementController; if (movementController != null) { movementController.StopCurrentMovement(); } ((Character)player).Freeze(); NotifyAiAboutDeadPlayer(player); Health val = (((Object)(object)health != (Object)null) ? health : ((AStatCharacter)(object)player).Health); if ((Object)(object)val != (Object)null) { val.UpdateHealthBar(true); } } catch (Exception ex) { ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(53, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed while marking "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(isPlayerTwo ? "P2" : "P1"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" dead for co-op death handling: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } logger.LogWarning(val2); } } private void RemovePlayerTwoAfterDeath(PlayerCharacter player) { if (!((Object)(object)player == (Object)null)) { ReleasePlayerCharms(player); NotifyAiAboutDeadPlayer(player); _playerTwoAwaitingRevive = true; _playerTwoDead = true; GameObject gameObject = ((Component)player).gameObject; PlayerTwo = null; _playerTwoId = 0; ClearDebugInputOverride(2); if ((Object)(object)gameObject != (Object)null) { ((Object)gameObject).name = "LocalMultiplayer_Player2_PendingDestroy"; Object.Destroy((Object)(object)gameObject); } } } private void RemovePlayerOneAfterDeath(PlayerCharacter player) { if (!((Object)(object)player == (Object)null)) { ReleasePlayerCharms(player); NotifyAiAboutDeadPlayer(player); _playerOneDead = true; _playerOneAwaitingRevive = true; GameObject gameObject = ((Component)player).gameObject; PlayerOne = null; _playerOneId = 0; ClearDebugInputOverride(1); if ((Object)(object)gameObject != (Object)null) { ((Object)gameObject).name = "LocalMultiplayer_Player1_PendingDestroy"; Object.Destroy((Object)(object)gameObject); } } } private void TransferEvolutionProgressToPlayerTwo() { EvolutionHandler playerOneEvolutionHandler = GetPlayerOneEvolutionHandler(); EvolutionHandler playerTwoEvolutionHandler = GetPlayerTwoEvolutionHandler(); if (!((Object)(object)playerOneEvolutionHandler == (Object)null) && !((Object)(object)playerTwoEvolutionHandler == (Object)null)) { playerTwoEvolutionHandler._PlayerCharacter_k__BackingField = PlayerTwo; playerTwoEvolutionHandler.NumEvolutionPointsInLevel = playerOneEvolutionHandler.NumEvolutionPointsInLevel; playerTwoEvolutionHandler.EvolutionLevel = playerOneEvolutionHandler.EvolutionLevel; playerTwoEvolutionHandler._EvolutionApexLevel_k__BackingField = playerOneEvolutionHandler.EvolutionApexLevel; playerTwoEvolutionHandler._excessPointsToAddAfterLevelUp = playerOneEvolutionHandler._excessPointsToAddAfterLevelUp; playerTwoEvolutionHandler._excessPointsToAddAfterGameUnpauses = playerOneEvolutionHandler._excessPointsToAddAfterGameUnpauses; playerTwoEvolutionHandler._roundingPointsRollover = playerOneEvolutionHandler._roundingPointsRollover; playerTwoEvolutionHandler.CanAddEvoPoints = true; } } private bool TryRevivePlayerOne(string source, bool requireEvolutionPicker, out string result) { //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Expected O, but got Unknown result = string.Empty; if (!_playerOneAwaitingRevive) { result = "P1 is not awaiting revival."; return false; } if (requireEvolutionPicker && !_evolutionPickerOpen) { result = "P1 can only be revived from an open level-up screen."; return false; } if (!IsAlive(PlayerTwo)) { result = "P2 must be alive to revive P1."; return false; } WorldStats instance = WorldStats.Instance; if ((Object)(object)instance == (Object)null) { result = "World DNA state is unavailable."; return false; } int playerOneReviveCost = PlayerOneReviveCost; if (instance.CurrentNumMutagenPoints < playerOneReviveCost) { result = $"Need {playerOneReviveCost} DNA; only {instance.CurrentNumMutagenPoints} available."; return false; } instance.CurrentNumMutagenPoints = Mathf.Max(0, instance.CurrentNumMutagenPoints - playerOneReviveCost); if (!SpawnPlayerOneFromPlayerTwo(source + " revive", out var failure)) { instance.CurrentNumMutagenPoints += playerOneReviveCost; _playerOneAwaitingRevive = true; _playerOneDead = true; result = "P1 clone creation failed; DNA was refunded. " + failure; return false; } Health health = ((AStatCharacter)(object)PlayerOne).Health; if ((Object)(object)health != (Object)null) { float playerOneReviveHealthFraction = PlayerOneReviveHealthFraction; health.SetHealth(Mathf.Max(1f, health.MaximumHealth * playerOneReviveHealthFraction)); ClearDamageLocks(health); health.UpdateHealthBar(true); } result = $"P1 revived for {playerOneReviveCost} DNA at {Mathf.RoundToInt(PlayerOneReviveHealthFraction * 100f)}% health."; ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(2, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(result); } logger.LogInfo(val); return true; } private bool SpawnPlayerOneFromPlayerTwo(string reason, out string failure) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown //IL_01ef: Unknown result type (might be due to invalid IL or missing references) failure = string.Empty; PlayerCharacter playerTwo = PlayerTwo; if (!IsAlive(playerTwo)) { failure = "No living P2 source was available."; return false; } PlayerCharacter playerOne = PlayerOne; int playerOneId = _playerOneId; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Plugin.SpawnOffsetX.Value, Plugin.SpawnOffsetY.Value, 0f); Vector3 val2 = ((Component)playerTwo).transform.position - val; GameObject val3 = null; try { PlayerCharacter.Instance = null; val3 = Object.Instantiate(((Component)playerTwo).gameObject, val2, ((Component)playerTwo).transform.rotation); } catch (Exception ex) { failure = ex.Message; return false; } finally { PlayerCharacter.Instance = playerTwo; } PlayerCharacter val4 = (((Object)(object)val3 != (Object)null) ? val3.GetComponent() : null); if ((Object)(object)val4 == (Object)null) { if ((Object)(object)val3 != (Object)null) { Object.Destroy((Object)(object)val3); } failure = "The cloned object did not contain PlayerCharacter."; return false; } try { ((Object)val3).name = (string.IsNullOrWhiteSpace(_playerOneObjectName) ? "PlayerCharacter" : _playerOneObjectName); PlayerOne = val4; _playerOneId = ((Object)val4).GetInstanceID(); _playerOneDead = false; _playerOneAwaitingRevive = false; PreparePlayerOneFromPlayerTwoClone(val4); RestorePlayerOneSpriteColors(val4); ApplyPlayerOneVisuals(val3); RepairPlayerTwoAttackState(PlayerTwo, resetCooldowns: true); RepairDashState(PlayerTwo, PlayerOne); _lastPlayerTwoSizePercentage = float.NaN; RefreshPlayerTwoSizeVisuals(force: true); if ((Object)(object)playerOne != (Object)null && (Object)(object)((Component)playerOne).gameObject != (Object)null && ((Object)playerOne).GetInstanceID() != ((Object)val4).GetInstanceID()) { ((Object)((Component)playerOne).gameObject).name = "LocalMultiplayer_Player1_PendingDestroy"; Object.Destroy((Object)(object)((Component)playerOne).gameObject); } PlayerCharacter.Instance = val4; NotifyNearbyAiAboutPlayer(val4, reason, logSummary: true); ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(44, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Spawned player one ("); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(reason); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(") from surviving P2 at "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(val2); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("."); } logger.LogInfo(val5); return true; } catch (Exception ex2) { Object.Destroy((Object)(object)val3); PlayerOne = playerOne; _playerOneId = playerOneId; _playerOneDead = true; _playerOneAwaitingRevive = true; PlayerCharacter.Instance = playerTwo; failure = ex2.Message; return false; } } private void PreparePlayerOneFromPlayerTwoClone(PlayerCharacter playerOne) { RepairPlayerTwoInteractionState(playerOne); EnsurePlayerTwoHitCollider(playerOne); ResetPlayerTwoCharmState(playerOne); EvolutionHandler playerEvolutionHandler = playerOne.PlayerEvolutionHandler; if ((Object)(object)playerEvolutionHandler != (Object)null) { playerEvolutionHandler._PlayerCharacter_k__BackingField = playerOne; PlayerCharacter playerTwo = PlayerTwo; EvolutionHandler val = ((playerTwo != null) ? playerTwo.PlayerEvolutionHandler : null); if ((Object)(object)val != (Object)null) { playerEvolutionHandler.NumEvolutionPointsInLevel = val.NumEvolutionPointsInLevel; playerEvolutionHandler.EvolutionLevel = val.EvolutionLevel; playerEvolutionHandler._EvolutionApexLevel_k__BackingField = val.EvolutionApexLevel; playerEvolutionHandler._excessPointsToAddAfterLevelUp = val._excessPointsToAddAfterLevelUp; playerEvolutionHandler._excessPointsToAddAfterGameUnpauses = val._excessPointsToAddAfterGameUnpauses; playerEvolutionHandler._roundingPointsRollover = val._roundingPointsRollover; } playerEvolutionHandler.CanAddEvoPoints = true; } IStatCharacter statCharacter_k__BackingField = ((Il2CppObjectBase)playerOne).Cast(); foreach (EdibleItemConsumer componentsInChild in ((Component)playerOne).GetComponentsInChildren(true)) { if ((Object)(object)componentsInChild != (Object)null) { componentsInChild._StatCharacter_k__BackingField = statCharacter_k__BackingField; } } Health health = ((AStatCharacter)(object)playerOne).Health; if ((Object)(object)health != (Object)null) { ClearDamageLocks(health); } RepairPlayerTwoAttackState(playerOne, resetCooldowns: false); RepairDashState(playerOne, PlayerTwo); ((AStatCharacter)(object)playerOne).OnSizeChanged(); } private bool TryRevivePlayerTwo(string source, bool requireEvolutionPicker, out string result) { //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Expected O, but got Unknown result = string.Empty; if (!_playerTwoAwaitingRevive) { result = "P2 is not awaiting revival."; return false; } if (requireEvolutionPicker && !_evolutionPickerOpen) { result = "P2 can only be revived from an open level-up screen."; return false; } if (!IsAlive(PlayerOne)) { result = "P1 must be alive to revive P2."; return false; } WorldStats instance = WorldStats.Instance; if ((Object)(object)instance == (Object)null) { result = "World DNA state is unavailable."; return false; } int playerTwoReviveCost = PlayerTwoReviveCost; if (instance.CurrentNumMutagenPoints < playerTwoReviveCost) { result = $"Need {playerTwoReviveCost} DNA; only {instance.CurrentNumMutagenPoints} available."; return false; } instance.CurrentNumMutagenPoints = Mathf.Max(0, instance.CurrentNumMutagenPoints - playerTwoReviveCost); _playerTwoAwaitingRevive = false; _playerTwoDead = false; SpawnPlayerTwoFromPrimary(PlayerOne, source + " revive"); if ((Object)(object)PlayerTwo == (Object)null) { instance.CurrentNumMutagenPoints += playerTwoReviveCost; _playerTwoAwaitingRevive = true; _playerTwoDead = true; result = "P2 clone creation failed; DNA was refunded."; return false; } Health health = ((AStatCharacter)(object)PlayerTwo).Health; if ((Object)(object)health != (Object)null) { float playerTwoReviveHealthFraction = PlayerTwoReviveHealthFraction; health.SetHealth(Mathf.Max(1f, health.MaximumHealth * playerTwoReviveHealthFraction)); ClearDamageLocks(health); health.UpdateHealthBar(true); } result = $"P2 revived for {playerTwoReviveCost} DNA at {Mathf.RoundToInt(PlayerTwoReviveHealthFraction * 100f)}% health."; ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(2, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(result); } logger.LogInfo(val); return true; } private void RefreshDeathStateFromHealth() { if ((Object)(object)PlayerOne != (Object)null) { _playerOneDead = _playerOneDead || IsDead(PlayerOne); } if ((Object)(object)PlayerTwo != (Object)null) { _playerTwoDead = _playerTwoDead || IsDead(PlayerTwo); } } private bool IsPlayerOne(PlayerCharacter player) { if ((Object)(object)player != (Object)null && _playerOneId != 0) { return ((Object)player).GetInstanceID() == _playerOneId; } return false; } private static bool IsPlayerAttackableEntity(IAttackableEntity entity, PlayerCharacter player, bool playerIsDead) { if (entity == null || (Object)(object)player == (Object)null || playerIsDead) { return false; } try { Health health = entity.Health; Health health2 = ((AStatCharacter)(object)player).Health; return (Object)(object)health != (Object)null && (Object)(object)health2 != (Object)null && ((Object)health).GetInstanceID() == ((Object)health2).GetInstanceID(); } catch { return false; } } private bool IsAiCharmedByLocalPlayer(AIDetectionController controller) { if ((Object)(object)controller == (Object)null || !controller.IsCharmed) { return false; } if (!IsLocalStatCharacter(controller.RootCharmedBy)) { return IsLocalStatCharacter(controller.CharmedBy); } return true; } private bool IsLocalStatCharacter(IStatCharacter character) { if (character == null) { return false; } Health health = character.Health; if ((Object)(object)health != (Object)null) { if (!((Object)(object)PlayerOne != (Object)null) || !((Object)(object)((AStatCharacter)(object)PlayerOne).Health != (Object)null) || ((Object)health).GetInstanceID() != ((Object)((AStatCharacter)(object)PlayerOne).Health).GetInstanceID()) { if ((Object)(object)PlayerTwo != (Object)null && (Object)(object)((AStatCharacter)(object)PlayerTwo).Health != (Object)null) { return ((Object)health).GetInstanceID() == ((Object)((AStatCharacter)(object)PlayerTwo).Health).GetInstanceID(); } return false; } return true; } return false; } private static void ForgetLocalPlayerTarget(AIDetectionController controller, PlayerCharacter player) { if (!((Object)(object)controller == (Object)null) && !((Object)(object)player == (Object)null) && ((AStatCharacter)(object)player).AttackableEntity != null) { controller.ForgetAboutCharacter(((AStatCharacter)(object)player).AttackableEntity); } } private static bool IsSamePlayer(PlayerCharacter left, PlayerCharacter right) { if ((Object)(object)left != (Object)null && (Object)(object)right != (Object)null) { return ((Object)left).GetInstanceID() == ((Object)right).GetInstanceID(); } return false; } private static bool IsAliveForCamera(PlayerCharacter player) { if ((Object)(object)player != (Object)null && (Object)(object)((Component)player).gameObject != (Object)null && ((Behaviour)player).isActiveAndEnabled) { return !IsDead(player); } return false; } private static bool IsAlive(PlayerCharacter player) { if ((Object)(object)player != (Object)null && (Object)(object)((Component)player).gameObject != (Object)null && ((Behaviour)player).isActiveAndEnabled) { return !IsDead(player); } return false; } private static bool IsDead(PlayerCharacter player) { if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).gameObject == (Object)null) { return false; } Health health = ((AStatCharacter)(object)player).Health; if ((Object)(object)health != (Object)null) { return health.CurrentHealth <= 0f; } return false; } private void RefreshInput() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03a5: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: 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_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_045c: Unknown result type (might be due to invalid IL or missing references) //IL_0463: Expected O, but got Unknown bool[] array = new bool[5]; Vector2 val = Vector2.zero; Vector2 val2 = Vector2.zero; bool flag = false; bool flag2 = false; bool flag3 = false; RefreshPlayerOneInput(); ReadOnlyArray all = Gamepad.all; int playerTwoGamepadIndex = GetPlayerTwoGamepadIndex(); if (all.Count > playerTwoGamepadIndex) { flag3 = true; Gamepad val3 = all[playerTwoGamepadIndex]; val = ApplyDeadZone(((InputControl)(object)val3.leftStick).ReadValue(), Plugin.StickDeadZone.Value); val2 = ApplyDeadZone(((InputControl)(object)val3.rightStick).ReadValue(), Plugin.StickDeadZone.Value); array[0] = ((InputControl)(object)val3.rightTrigger).ReadValue() > Plugin.TriggerThreshold.Value || val3.rightShoulder.isPressed; array[1] = ((InputControl)(object)val3.leftTrigger).ReadValue() > Plugin.TriggerThreshold.Value || val3.buttonSouth.isPressed; array[2] = val3.buttonNorth.isPressed; array[3] = val3.dpad.left.isPressed; array[4] = val3.dpad.right.isPressed; flag = val3.leftShoulder.isPressed || val3.buttonEast.isPressed; flag2 = val3.buttonWest.isPressed; } else if (Plugin.KeyboardFallbackEnabled.Value && Keyboard.current != null) { Keyboard current = Keyboard.current; val = ReadKeyboardVector(((ButtonControl)current.upArrowKey).isPressed || ((ButtonControl)current.iKey).isPressed, ((ButtonControl)current.downArrowKey).isPressed || ((ButtonControl)current.kKey).isPressed, ((ButtonControl)current.leftArrowKey).isPressed || ((ButtonControl)current.jKey).isPressed, ((ButtonControl)current.rightArrowKey).isPressed || ((ButtonControl)current.lKey).isPressed); val2 = val; array[0] = ((ButtonControl)current.rightCtrlKey).isPressed || ((ButtonControl)current.enterKey).isPressed; array[1] = ((ButtonControl)current.rightShiftKey).isPressed; array[2] = ((ButtonControl)current.uKey).isPressed; array[3] = ((ButtonControl)current.oKey).isPressed; array[4] = ((ButtonControl)current.pKey).isPressed; flag = ((ButtonControl)current.rightAltKey).isPressed || ((ButtonControl)current.spaceKey).isPressed; flag2 = ((ButtonControl)current.nKey).isPressed; } if (_debugPlayerTwoInputOverride) { flag3 = true; val = _debugPlayerTwoMove; val2 = _debugPlayerTwoAim; for (int i = 0; i < array.Length; i++) { array[i] = _debugPlayerTwoAttackHeld[i]; } flag = _debugPlayerTwoDashHeld; flag2 = _debugPlayerTwoInteractHeld; } bool flag4 = false; bool[] array2 = array; foreach (bool flag5 in array2) { flag4 = flag4 || flag5; } Vector2 aim = val2; bool observedInput = ((Vector2)(ref val)).sqrMagnitude > 0.001f || ((Vector2)(ref aim)).sqrMagnitude > 0.001f || flag4 || flag || flag2; if (((Vector2)(ref val2)).sqrMagnitude <= 0.001f) { val2 = ((((Vector2)(ref val)).sqrMagnitude > 0.001f) ? val : InputState.Aim); } if (((Vector2)(ref val2)).sqrMagnitude <= 0.001f) { val2 = Vector2.right; } bool[] array3 = new bool[5]; bool[] array4 = new bool[5]; for (int k = 0; k < array.Length; k++) { array3[k] = array[k] && !_previousAttackHeld[k]; array4[k] = !array[k] && _previousAttackHeld[k]; _previousAttackHeld[k] = array[k]; } InputState = new PlayerTwoInputState(val, ((Vector2)(ref val2)).normalized, array, array3, array4, flag, flag && !_previousDashHeld, !flag && _previousDashHeld, flag2, flag2 && !_previousInteractHeld, !flag2 && _previousInteractHeld); _previousDashHeld = flag; _previousInteractHeld = flag2; LogPlayerTwoInputIfObserved(observedInput, flag3, val, aim, flag4, flag); if (!flag3 && Time.unscaledTime >= _nextStatusLogAt) { _nextStatusLogAt = Time.unscaledTime + 15f; string text = (Plugin.KeyboardFallbackEnabled.Value ? "keyboard fallback is active" : "keyboard fallback is disabled"); ManualLogSource logger = Plugin.Logger; bool flag6 = default(bool); BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(54, 2, ref flag6); if (flag6) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("No configured player-two gamepad detected at index "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(playerTwoGamepadIndex); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("; "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(text); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("."); } logger.LogInfo(val4); } } private void RefreshPlayerOneInput() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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) ReadOnlyArray all = Gamepad.all; int playerOneGamepadIndex = GetPlayerOneGamepadIndex(); Vector2 val = Vector2.zero; Vector2 val2 = Vector2.zero; _playerOneAimControlled = playerOneGamepadIndex >= 0 && all.Count > playerOneGamepadIndex; if (_playerOneAimControlled) { Gamepad obj = all[playerOneGamepadIndex]; val = ApplyDeadZone(((InputControl)(object)obj.leftStick).ReadValue(), Plugin.StickDeadZone.Value); val2 = ApplyDeadZone(((InputControl)(object)obj.rightStick).ReadValue(), Plugin.StickDeadZone.Value); } if (_debugPlayerOneInputOverride) { _playerOneAimControlled = true; val = _debugPlayerOneMove; val2 = _debugPlayerOneAim; } _playerOneMove = (IsPlayerOneDead ? Vector2.zero : Vector2.ClampMagnitude(val, 1f)); if (((Vector2)(ref val2)).sqrMagnitude > 0.001f) { _playerOneAim = ((Vector2)(ref val2)).normalized; } } private void HandleManualControls() { if (Plugin.ManualControlsEnabled.Value && Keyboard.current != null) { bool isPressed = ((ButtonControl)Keyboard.current.f8Key).isPressed; bool isPressed2 = ((ButtonControl)Keyboard.current.f9Key).isPressed; bool isPressed3 = ((ButtonControl)Keyboard.current.f10Key).isPressed; bool isPressed4 = ((ButtonControl)Keyboard.current.f6Key).isPressed; bool isPressed5 = ((ButtonControl)Keyboard.current.f7Key).isPressed; bool flag = ((ButtonControl)Keyboard.current.leftShiftKey).isPressed || ((ButtonControl)Keyboard.current.rightShiftKey).isPressed; if (isPressed4 && !_previousDamagePlayerTwoHeld) { ApplyManualDamage(PlayerTwo, PlayerOne, flag ? "Shift+F6" : "F6", "P2", flag); } if (isPressed5 && !_previousDamagePlayerOneHeld) { ApplyManualDamage(PlayerOne, PlayerTwo, flag ? "Shift+F7" : "F7", "P1", flag); } if (isPressed && !_previousDumpStateHeld) { DumpState("F8"); } if (isPressed2 && !_previousRespawnHeld) { ForceRespawnPlayerTwo("F9"); } if (isPressed3 && !_previousForceSpawnHeld) { ForceSpawnPlayerTwo("F10"); } _previousDumpStateHeld = isPressed; _previousRespawnHeld = isPressed2; _previousForceSpawnHeld = isPressed3; _previousDamagePlayerTwoHeld = isPressed4; _previousDamagePlayerOneHeld = isPressed5; } } private void ApplyManualDamage(PlayerCharacter target, PlayerCharacter instigator, string source, string targetLabel, bool lethal) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Expected O, but got Unknown bool flag = default(bool); if ((Object)(object)target == (Object)null || (Object)(object)((Component)target).gameObject == (Object)null) { ManualLogSource logger = Plugin.Logger; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(49, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": cannot damage "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(targetLabel); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; target player is not available."); } logger.LogWarning(val); return; } BepInExInfoLogInterpolatedStringHandler val2; if (targetLabel == "P2" && IsPlayerTwoDead) { ManualLogSource logger2 = Plugin.Logger; val2 = new BepInExInfoLogInterpolatedStringHandler(51, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": P2 is already marked dead; manual damage skipped."); } logger2.LogInfo(val2); return; } if (targetLabel == "P1" && IsPlayerOneDead) { ManualLogSource logger3 = Plugin.Logger; val2 = new BepInExInfoLogInterpolatedStringHandler(51, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": P1 is already marked dead; manual damage skipped."); } logger3.LogInfo(val2); return; } Health health = ((AStatCharacter)(object)target).Health; if ((Object)(object)health == (Object)null) { ManualLogSource logger4 = Plugin.Logger; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(49, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": cannot damage "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(targetLabel); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; target has no Health component."); } logger4.LogWarning(val); return; } if (IsPlayerTwoComponent((Component)(object)health)) { ClearDamageLocks(health); } float num = (lethal ? Mathf.Max(health.CurrentHealth + Mathf.Max(1f, health.MaximumHealth * 0.1f), health.MaximumHealth + 1f) : Mathf.Max(0.1f, Plugin.ManualDamageAmount.Value)); float currentHealth = health.CurrentHealth; GameObject val3 = (((Object)(object)instigator != (Object)null && (Object)(object)((Component)instigator).gameObject != (Object)null) ? ((Component)instigator).gameObject : null); _applyingDiagnosticDamage = true; try { health.Damage(num, val3, 0f, 0); } finally { _applyingDiagnosticDamage = false; } health.UpdateHealthBar(true); ManualLogSource logger5 = Plugin.Logger; val2 = new BepInExInfoLogInterpolatedStringHandler(47, 7, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": applied "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(num, "0.##"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(lethal ? "lethal " : string.Empty); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("diagnostic damage to "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(targetLabel); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; health "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(currentHealth, "0.##"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" -> "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(health.CurrentHealth, "0.##"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(". "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(BuildManualDamageOutcome(targetLabel, health)); } logger5.LogInfo(val2); } private string BuildManualDamageOutcome(string targetLabel, Health health) { bool flag = (((Object)(object)health != (Object)null) ? health.CurrentHealth : 0f) <= 0f; PlayerCharacter instance = PlayerCharacter.Instance; bool flag2 = IsSamePlayer(instance, PlayerOne); bool flag3 = IsSamePlayer(instance, PlayerTwo); string value; if (targetLabel == "P2") { if (flag && IsAlive(PlayerOne)) { string obj = (_playerTwoDead ? "death-handler=ok" : "death-handler=check-not-marked"); string text = (flag2 ? "singleton=ok-P1" : "singleton=check-not-P1"); value = obj + ", " + text + ", expected=P2 stays dead while P1 continues"; } else { value = (flag ? "expected=normal run-end flow may continue because P1 is not alive" : "expected=P2 damaged only"); } } else if (targetLabel == "P1") { if (flag && IsAlive(PlayerTwo)) { string obj2 = (_playerOneDead ? "death-handler=ok" : "death-handler=check-not-marked"); string text2 = (flag3 ? "singleton=ok-P2" : "singleton=check-not-P2"); value = obj2 + ", " + text2 + ", expected=camera/control singleton follows P2"; } else { value = (flag ? "expected=normal run-end flow may continue because P2 is not alive" : "expected=P1 damaged only"); } } else { value = "expected=unknown target label"; } return $"post-state p1Dead={IsPlayerOneDead}, p2Dead={IsPlayerTwoDead}, p1Marked={_playerOneDead}, p2Marked={_playerTwoDead}, singletonP1={flag2}, singletonP2={flag3}, singleton={DescribePlayer(instance)}; {value}."; } private void ForceSpawnPlayerTwo(string source) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val; if ((Object)(object)PlayerTwo != (Object)null) { ManualLogSource logger = Plugin.Logger; val = new BepInExInfoLogInterpolatedStringHandler(36, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": player two already exists ("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)PlayerTwo).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", id="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(_playerTwoId); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")."); } logger.LogInfo(val); return; } PlayerCharacter val2 = FindPrimaryPlayerCandidate(); if ((Object)(object)val2 == (Object)null) { ManualLogSource logger2 = Plugin.Logger; BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(85, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": cannot force-spawn player two because no active primary PlayerCharacter was found. "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(BuildPlayerCandidateDump()); } logger2.LogWarning(val3); return; } ManualLogSource logger3 = Plugin.Logger; val = new BepInExInfoLogInterpolatedStringHandler(34, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": force-spawning player two from "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)val2).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logger3.LogInfo(val); SpawnPlayerTwoFromPrimary(val2, "manual " + source); } private void ForceRespawnPlayerTwo(string source) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown bool flag = default(bool); if ((Object)(object)PlayerTwo != (Object)null && (Object)(object)((Component)PlayerTwo).gameObject != (Object)null) { GameObject gameObject = ((Component)PlayerTwo).gameObject; ((Object)gameObject).name = "LocalMultiplayer_Player2_PendingDestroy"; Object.Destroy((Object)(object)gameObject); ManualLogSource logger = Plugin.Logger; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(61, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": destroyed current player two clone; attempting fresh spawn."); } logger.LogInfo(val); PlayerTwo = null; _playerTwoId = 0; _playerTwoDead = false; } else { ManualLogSource logger2 = Plugin.Logger; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(55, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": no existing player two clone; attempting fresh spawn."); } logger2.LogInfo(val); } _playerTwoAwaitingRevive = false; ForceSpawnPlayerTwo(source); } private void DumpState(string source) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown PlayerCharacter instance = PlayerCharacter.Instance; Scene activeScene = SceneManager.GetActiveScene(); ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(154, 10, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": Local multiplayer state: scene="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Scene)(ref activeScene)).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", modEnabled="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(Plugin.ModEnabled.Value); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("PlayerCharacter.IsSpawned="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(PlayerCharacter.IsSpawned); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", singleton="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(DescribePlayer(instance)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("playerOne="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(DescribePlayer(PlayerOne)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", playerTwo="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(DescribePlayer(PlayerTwo)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("gamepads="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(Gamepad.all.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", configuredP2Index="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(GetPlayerTwoGamepadIndex()); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", candidates="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(BuildPlayerCandidateDump()); } logger.LogInfo(val); } private void UpdateLocalPlayerAims() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (_playerOneAimControlled) { UpdateLocalPlayerAim(PlayerOne, new Vector3(_playerOneAim.x, _playerOneAim.y, 0f)); } UpdateLocalPlayerAim(PlayerTwo, GetPlayerTwoAimVector()); } private void UpdateLocalPlayerAim(PlayerCharacter player, Vector3 aim) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } foreach (WeaponAim2D componentsInChild in ((Component)player).GetComponentsInChildren(true)) { if ((Object)(object)componentsInChild != (Object)null) { ConfigureWeaponAim((WeaponAim)(object)componentsInChild, aim, applyRotation: false); } } foreach (AAttackHandler componentsInChild2 in ((Component)player).GetComponentsInChildren(true)) { object obj; if (componentsInChild2 == null) { obj = null; } else { Weapon currentWeapon = ((CharacterHandleWeapon)componentsInChild2).CurrentWeapon; if (currentWeapon == null) { obj = null; } else { EICCharacterAttack obj2 = ((Il2CppObjectBase)currentWeapon).TryCast(); obj = ((obj2 != null) ? obj2.WeaponAim : null); } } WeaponAim val = (WeaponAim)obj; if ((Object)(object)val != (Object)null) { ConfigureWeaponAim(val, aim, applyRotation: true); } } foreach (GamepadAimDirection componentsInChild3 in ((Component)player).GetComponentsInChildren(true)) { TryUpdateLocalPlayerAimIndicator(componentsInChild3); } } private void ApplyPlayerTwoAttackAim(AAttackHandler attackHandler) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)attackHandler == (Object)null)) { Weapon currentWeapon = ((CharacterHandleWeapon)attackHandler).CurrentWeapon; EICCharacterAttack val = ((currentWeapon != null) ? ((Il2CppObjectBase)currentWeapon).TryCast() : null); if ((Object)(object)val != (Object)null) { TryApplyLocalPlayerAttackDirection(val); } else { ConfigureWeaponAim(((CharacterHandleWeapon)attackHandler)._weaponAim, GetPlayerTwoAimVector(), applyRotation: true); } } } private static void ConfigureWeaponAim(WeaponAim weaponAim, Vector3 aim, bool applyRotation) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)weaponAim == (Object)null) { return; } weaponAim.AimControl = (AimControls)4; weaponAim.AimControlActive = true; weaponAim.SetCurrentAim(aim, true); weaponAim._lastNonNullMovement = new Vector2(aim.x, aim.y); if (applyRotation) { WeaponAim2D val = ((Il2CppObjectBase)weaponAim).TryCast(); if ((Object)(object)val != (Object)null) { val.GetScriptAim(); } else { weaponAim.GetCurrentAim(); } weaponAim.ApplyAim(); } } private Vector3 GetPlayerTwoAimVector() { //IL_0009: 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_002b: Unknown result type (might be due to invalid IL or missing references) return new Vector3(InputState.Aim.x, InputState.Aim.y, 0f); } private void ValidateTrackedPlayers() { if ((Object)(object)PlayerOne != (Object)null && (Object)(object)((Component)PlayerOne).gameObject == (Object)null) { Plugin.Logger.LogInfo((object)"Tracked player one was destroyed; clearing local multiplayer state."); ResetTrackedPlayers(); } else if ((Object)(object)PlayerTwo != (Object)null && (Object)(object)((Component)PlayerTwo).gameObject == (Object)null) { Plugin.Logger.LogInfo((object)(_playerTwoAwaitingRevive ? "Tracked player two was destroyed after death; preserving the pending revive slot." : "Tracked player two was destroyed; waiting to respawn if gameplay is still active.")); PlayerTwo = null; _playerTwoId = 0; if (!_playerTwoAwaitingRevive) { _playerTwoDead = false; } } } private void CleanupPlayerTwoIfPresent() { if ((Object)(object)PlayerTwo != (Object)null && (Object)(object)((Component)PlayerTwo).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)PlayerTwo).gameObject); Plugin.Logger.LogInfo((object)"Local multiplayer disabled; destroyed player two clone."); } ResetTrackedPlayers(); } private void ResetTrackedPlayers() { //IL_0041: 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_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) PlayerOne = null; PlayerTwo = null; _playerOneId = 0; _playerTwoId = 0; _cameraId = 0; _cameraEnforcerId = 0; _baseOrthographicSize = 0f; _smoothedOrthographicSize = 0f; _smoothedCameraCenter = Vector2.zero; _hasSharedCameraState = false; SharedCameraMidpointError = float.PositiveInfinity; RenderCameraMidpointError = float.PositiveInfinity; ClearSharedNightVisionTracking(); ResetHudStatuses(); ClearDamageOnTouchState(); _loggedPlayerTwoInput = false; _loggedFilteredStockInput = false; _loggedPlayerTwoDamageAttempt = false; _loggedPlayerTwoDamageOutputOverride = false; _loggedPlayerTwoMasterHealthCleared = false; _loggedPlayerTwoColliderState = false; _loggedPlayerTwoPhysicalColliderEnabled = false; _loggedPlayerTwoRigidbodyEnabled = false; _loggedPlayerTwoDamageOnTouchCollision = false; _loggedPlayerTwoDamageOnTouchMaskPatched = false; _loggedPlayerTwoDamageOnTouchIgnoreCleared = false; _loggedPlayerTwoDamageOnTouchFallback = false; _loggedPlayerTwoAiIgnoreCleared = false; _loggedPlayerTwoDirectAiRegistration = false; _loggedPlayerTwoDirectAiRegistrationFailure = false; _loggedPlayerTwoAttackScoreForced = false; _loggedPlayerTwoTargetConsidered = false; _loggedPlayerTwoPreventSightBypass = false; _loggedFriendlyFireSuppressed = false; _playerTwoDamageResultLogs = 0; _playerOneDead = false; _playerOneAwaitingRevive = false; _playerTwoDead = false; _playerTwoAwaitingRevive = false; _playerOneObjectName = "PlayerCharacter"; _playerOneSpriteColors.Clear(); _playerOneMove = Vector2.zero; ResetMushroomEffectOwnership(); _evolutionPickerOpen = false; _suppressedPlayerDeathDropCount = 0; _previousDamagePlayerTwoHeld = false; _previousDamagePlayerOneHeld = false; } private void ResetMushroomEffectOwnership() { _mushroomManagerId = 0; _playerOneMushroomEffects = null; _playerTwoMushroomEffects = null; _mushroomEffectsBeforeConsumption = null; _mushroomConsumptionRoutingDepth = 0; _mushroomConsumerPreviousSingleton = null; _mushroomConsumerSingletonDepth = 0; _updatingOwnedMushroomEffects = false; _lastMushroomEffectUpdatePlayerNumber = 0; } private bool TryAttachExistingPlayerTwo() { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown GameObject val = GameObject.Find("LocalMultiplayer_Player2"); if ((Object)(object)val == (Object)null) { return false; } PlayerCharacter component = val.GetComponent(); if ((Object)(object)component == (Object)null) { return false; } PlayerTwo = component; _playerTwoId = ((Object)component).GetInstanceID(); _playerTwoDead = IsDead(component); _playerTwoAwaitingRevive = false; PreparePlayerTwoForCoop(component); PlayerCharacter playerOne = PlayerOne; ApplyPlayerOneVisuals((playerOne != null) ? ((Component)playerOne).gameObject : null); ApplyPlayerTwoVisuals(val); NotifyExistingAiAboutPlayerTwo("reattach"); ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(39, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Reattached existing player two clone: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(((Object)val).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } logger.LogInfo(val2); return true; } private void NotifyExistingAiAboutPlayerTwo(string reason) { NotifyNearbyAiAboutPlayer(PlayerTwo, reason, logSummary: true); } private void RefreshPlayerTwoAiTargetingIfDue() { if (Plugin.NotifyExistingAiOnPlayerTwoSpawn.Value && !((Object)(object)PlayerTwo == (Object)null) && IsAlive(PlayerTwo)) { float num = Mathf.Max(0f, Plugin.AiPlayerTwoRefreshInterval.Value); if (!(num <= 0f) && !(Time.unscaledTime < _nextAiRefreshAt)) { _nextAiRefreshAt = Time.unscaledTime + num; NotifyNearbyAiAboutPlayer(PlayerTwo, "periodic", logSummary: false); } } } private void NotifyNearbyAiAboutPlayer(PlayerCharacter player, string reason, bool logSummary) { //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.NotifyExistingAiOnPlayerTwoSpawn.Value || (Object)(object)player == (Object)null || !IsAlive(player)) { return; } CircleCollider2D physicalCollider = ((AStatCharacter)(object)player).PhysicalCollider; bool flag = default(bool); if ((Object)(object)physicalCollider == (Object)null) { ManualLogSource logger = Plugin.Logger; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(71, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not notify existing AI about "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)player).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(reason); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("): player has no PhysicalCollider."); } logger.LogWarning(val); return; } IAttackableEntity attackableEntity = ((AStatCharacter)(object)player).AttackableEntity; if (attackableEntity == null) { ManualLogSource logger2 = Plugin.Logger; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(71, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not notify existing AI about "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)player).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(reason); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("): player has no AttackableEntity."); } logger2.LogWarning(val); return; } Il2CppArrayBase obj = Object.FindObjectsOfType(); int num = 0; foreach (AIDetectionController item in obj) { if ((Object)(object)item == (Object)null || !((Behaviour)item).isActiveAndEnabled) { continue; } try { if (IsWithinAiRefreshDistance(item, ((Component)player).transform.position)) { item.OnTargetEnteredAttackDetectionRadius((Collider2D)(object)physicalCollider); RemovePlayerTwoFromAiIgnoreSet(item, attackableEntity); DirectlyRegisterPlayerTwoAttackTarget(item, attackableEntity); item.ForceRefreshAttackTarget(); num++; } } catch (Exception ex) { ManualLogSource logger3 = Plugin.Logger; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(40, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to notify AI controller "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)item).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" about "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)player).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } logger3.LogWarning(val); } } if (Plugin.DiagnosticsEnabled.Value && logSummary) { ManualLogSource logger4 = Plugin.Logger; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(54, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Notified "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(num); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" nearby AI detection controller(s) about "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(((Object)player).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ("); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(reason); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(")."); } logger4.LogInfo(val2); } } private void NotifyAiAboutDeadPlayer(PlayerCharacter player) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown if ((Object)(object)player == (Object)null) { return; } IAttackableEntity attackableEntity = ((AStatCharacter)(object)player).AttackableEntity; if (attackableEntity == null) { return; } bool flag = default(bool); foreach (AIDetectionController item in Object.FindObjectsOfType()) { if ((Object)(object)item == (Object)null || !((Behaviour)item).isActiveAndEnabled) { continue; } try { item.ForgetAboutCharacter(attackableEntity); NavMeshController componentInParent = ((Component)item).GetComponentInParent(); Transform val = (((Object)(object)componentInParent != (Object)null) ? componentInParent.CurrentTransformTargetDestination : null); if ((Object)(object)val != (Object)null && (Object)(object)((Component)player).transform != (Object)null && (((Object)val).GetInstanceID() == ((Object)((Component)player).transform).GetInstanceID() || val.IsChildOf(((Component)player).transform))) { componentInParent.StopTrackingTargetAndKillCurrentPathfinding(); } item.ForceRefreshAttackTarget(); } catch (Exception ex) { ManualLogSource logger = Plugin.Logger; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(56, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to clear dead player target from AI controller "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(((Object)item).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } logger.LogWarning(val2); } } } private bool IsWithinAiRefreshDistance(AIDetectionController controller, Vector3 targetPosition) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(0f, Plugin.AiPlayerTwoRefreshDistance.Value); if (num <= 0f) { return true; } return Vector3.Distance(((Component)controller).transform.position, targetPosition) <= num; } private void LogPlayerTwoTargetConsidered(AIDetectionController controller) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoTargetConsidered) { _loggedPlayerTwoTargetConsidered = true; ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(70, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("AI targetability override allowed player two as an attack target for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)controller).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logger.LogInfo(val); } } private string BuildPlayerCandidateDump() { Il2CppArrayBase val = Object.FindObjectsOfType(); if (val == null || val.Length == 0) { return "none"; } string[] array = new string[val.Length]; for (int i = 0; i < val.Length; i++) { array[i] = DescribePlayer(val[i]); } return string.Join("; ", array); } private PlayerCharacter FindPrimaryPlayerCandidate() { PlayerCharacter instance = PlayerCharacter.Instance; if (IsValidPrimaryPlayerCandidate(instance)) { return instance; } foreach (PlayerCharacter item in Object.FindObjectsOfType()) { if (IsValidPrimaryPlayerCandidate(item)) { return item; } } return null; } private bool IsValidPrimaryPlayerCandidate(PlayerCharacter candidate) { if ((Object)(object)candidate == (Object)null || !((Behaviour)candidate).isActiveAndEnabled || (Object)(object)((Component)candidate).gameObject == (Object)null) { return false; } if (((Object)((Component)candidate).gameObject).name == "LocalMultiplayer_Player2" || ((Object)candidate).GetInstanceID() == _playerTwoId) { return false; } return true; } private bool CanUseGameplaySpawnFallback(PlayerCharacter primary) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown if (!((Object)(object)primary == (Object)null)) { Scene activeScene = SceneManager.GetActiveScene(); if (!(((Scene)(ref activeScene)).name != "Gameplay")) { if (Plugin.DiagnosticsEnabled.Value && !_loggedGameplaySpawnFallback) { ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(125, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("PlayerCharacter.IsSpawned is false, but an active gameplay PlayerCharacter was found ("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((Object)primary).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("); using gameplay-scene spawn fallback."); } logger.LogInfo(val); _loggedGameplaySpawnFallback = true; } return true; } } return false; } private void LogSpawnWaitReason(string reason) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown if (Plugin.DiagnosticsEnabled.Value && (!(reason == _lastSpawnWaitReason) || !(Time.unscaledTime < _nextSpawnWaitLogAt))) { _lastSpawnWaitReason = reason; _nextSpawnWaitLogAt = Time.unscaledTime + 5f; ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(29, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Waiting to spawn player two: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(reason); } logger.LogInfo(val); } } private void LogConnectedGamepadsIfChanged() { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown if (!Plugin.DiagnosticsEnabled.Value) { return; } ReadOnlyArray all = Gamepad.all; if (all.Count != _lastGamepadCount) { _lastGamepadCount = all.Count; string[] array = new string[all.Count]; for (int i = 0; i < all.Count; i++) { Gamepad val = all[i]; array[i] = $"{i}:{((InputControl)val).displayName ?? ((InputControl)val).name ?? "unknown"}#{((InputDevice)val).deviceId}"; } ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(55, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Detected "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(all.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" gamepad(s). Player two uses index "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(GetPlayerTwoGamepadIndex()); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(". Devices: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(string.Join(", ", array)); } logger.LogInfo(val2); } } private void LogPlayerTwoInputIfObserved(bool observedInput, bool hasGamepad, Vector2 move, Vector2 aim, bool hasAttack, bool dashHeld) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoInput && observedInput) { string text = (hasGamepad ? $"gamepad index {GetPlayerTwoGamepadIndex()}" : "keyboard fallback"); ManualLogSource logger = Plugin.Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(64, 5, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Observed player-two input from "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": move="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(move); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", aim="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(aim); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", dash="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(dashHeld); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", anyAttack="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(hasAttack); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } logger.LogInfo(val); _loggedPlayerTwoInput = true; } } private int GetPlayerTwoGamepadIndex() { if (_debugPlayerTwoGamepadIndex < 0) { return Math.Max(0, Plugin.PlayerTwoGamepadIndex.Value); } return _debugPlayerTwoGamepadIndex; } private int GetPlayerOneGamepadIndex() { if (_debugPlayerOneGamepadIndex >= 0) { return _debugPlayerOneGamepadIndex; } int playerTwoGamepadIndex = GetPlayerTwoGamepadIndex(); for (int i = 0; i < Gamepad.all.Count; i++) { if (i != playerTwoGamepadIndex) { return i; } } return -1; } private static string DescribePlayer(PlayerCharacter player) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return "null"; } GameObject gameObject = ((Component)player).gameObject; if (!((Object)(object)gameObject == (Object)null)) { return $"{((Object)gameObject).name}#{((Object)player).GetInstanceID()} active={((Behaviour)player).isActiveAndEnabled} pos={((Component)player).transform.position}"; } return $"destroyed#{((Object)player).GetInstanceID()}"; } private static Vector2 ApplyDeadZone(Vector2 value, float deadZone) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp01(deadZone); if (!(((Vector2)(ref value)).sqrMagnitude >= num * num)) { return Vector2.zero; } return value; } private static Vector2 ReadKeyboardVector(bool up, bool down, bool left, bool right) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) float num = (right ? 1f : 0f) - (left ? 1f : 0f); float num2 = (up ? 1f : 0f) - (down ? 1f : 0f); Vector2 result = default(Vector2); ((Vector2)(ref result))..ctor(num, num2); if (!(((Vector2)(ref result)).sqrMagnitude > 1f)) { return result; } return ((Vector2)(ref result)).normalized; } private static int AttackSlotToInputIndex(EAttackSlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected I4, but got Unknown return (slot - 1) switch { 0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, _ => -1, }; } private void CapturePlayerOneVisualState(PlayerCharacter player) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).gameObject == (Object)null) { return; } _playerOneObjectName = ((Object)((Component)player).gameObject).name; _playerOneSpriteColors.Clear(); foreach (SpriteRenderer componentsInChild in ((Component)player).GetComponentsInChildren(true)) { _playerOneSpriteColors.Add(((Object)(object)componentsInChild != (Object)null) ? componentsInChild.color : Color.white); } } private void RestorePlayerOneSpriteColors(PlayerCharacter player) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } Il2CppArrayBase componentsInChildren = ((Component)player).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { componentsInChildren[i].color = ((i < _playerOneSpriteColors.Count) ? _playerOneSpriteColors[i] : Color.white); } } } private static void ApplyPlayerOneVisuals(GameObject player) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) RemovePlayerLabel(player, "LocalMultiplayer_Player2_Label"); ApplyPlayerLabel(player, "LocalMultiplayer_Player1_Label", "P1", PlayerOneLabelColor, Plugin.LabelPlayerOne.Value); } private static void ApplyPlayerTwoVisuals(GameObject clone) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) RemovePlayerLabel(clone, "LocalMultiplayer_Player1_Label"); if (Plugin.TintPlayerTwo.Value) { foreach (SpriteRenderer componentsInChild in clone.GetComponentsInChildren(true)) { if ((Object)(object)componentsInChild != (Object)null) { componentsInChild.color = PlayerTwoTint; } } } ApplyPlayerLabel(clone, "LocalMultiplayer_Player2_Label", "P2", PlayerTwoTint, Plugin.LabelPlayerTwo.Value); } private static void ApplyPlayerLabel(GameObject player, string objectName, string labelText, Color color, bool enabled) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } Transform val = player.transform.Find(objectName); if (!enabled) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } return; } GameObject val2 = (GameObject)(((Object)(object)val != (Object)null) ? ((object)((Component)val).gameObject) : ((object)new GameObject(objectName))); val2.transform.SetParent(player.transform, false); val2.transform.localPosition = new Vector3(0f, 1.35f, -0.05f); TextMesh obj = val2.GetComponent() ?? val2.AddComponent(); obj.text = labelText; obj.anchor = (TextAnchor)4; obj.alignment = (TextAlignment)1; obj.characterSize = 0.22f; obj.color = color; MeshRenderer component = val2.GetComponent(); if ((Object)(object)component != (Object)null) { ((Renderer)component).sortingOrder = 1000; } } private static void RemovePlayerLabel(GameObject player, string objectName) { Transform val = ((player != null) ? player.transform.Find(objectName) : null); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)val).gameObject); } } } public readonly record struct PlayerTwoInputState(Vector2 Move, Vector2 Aim, bool[] AttackHeld, bool[] AttackPressed, bool[] AttackReleased, bool DashHeld, bool DashPressed, bool DashReleased, bool InteractHeld, bool InteractPressed, bool InteractReleased); public sealed class LocalMultiplayerHud : MonoBehaviour { private sealed class AbilityHudSlot { private readonly RectTransform _fill; private readonly Text _label; private readonly float _width; public GameObject Root { get; } public AbilityHudSlot(GameObject root, RectTransform fill, Text label, float width) { Root = root; _fill = fill; _label = label; _width = width; } public void SetReadiness(float readiness, bool available) { //IL_0018: 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_003f: Unknown result type (might be due to invalid IL or missing references) _fill.sizeDelta = new Vector2(_width * Mathf.Clamp01(readiness), 0f); ((Graphic)_label).color = (Color)(available ? Color.white : new Color(0.48f, 0.51f, 0.54f, 1f)); } } private const string HudRootName = "Everything_is_Multiplayer_HUD"; private const float PanelWidth = 360f; private const float PanelHeight = 96f; private const float BarWidth = 244f; private const float StatusWidth = 940f; private const float StatusHeight = 30f; private GameObject _root; private Font _font; private GameObject _playerOneRoot; private RectTransform _playerOneFill; private Image _playerOneFillImage; private Text _playerOneLabel; private Text _playerOneValue; private Text _playerOneStatus; private readonly AbilityHudSlot[] _playerOneAbilities = new AbilityHudSlot[6]; private GameObject _playerTwoRoot; private RectTransform _playerTwoFill; private Image _playerTwoFillImage; private Text _playerTwoLabel; private Text _playerTwoValue; private Text _playerTwoStatus; private readonly AbilityHudSlot[] _playerTwoAbilities = new AbilityHudSlot[6]; private GameObject _statusRoot; private Text _statusText; private GameObject _reviveRoot; private Button _reviveButton; private Image _reviveButtonImage; private Text _reviveButtonText; private GameObject _runRoot; private RectTransform _runProgressFill; private Text _runTimerText; private Text _cataclysmText; private readonly GameObject[] _bossIndicatorRoots = (GameObject[])(object)new GameObject[12]; private readonly GameObject[] _bossRoots = (GameObject[])(object)new GameObject[3]; private readonly RectTransform[] _bossHealthFills = (RectTransform[])(object)new RectTransform[3]; private readonly RectTransform[] _bossPlatingFills = (RectTransform[])(object)new RectTransform[3]; private readonly RectTransform[] _bossEnrageFills = (RectTransform[])(object)new RectTransform[3]; private readonly Text[] _bossLabels = (Text[])(object)new Text[3]; private readonly StockHudBridge _stockHudBridge = new StockHudBridge(); private GameObject _homepageRoot; private GameObject _homepageSettingsPanel; private Toggle _friendlyFireToggle; public static LocalMultiplayerHud Instance { get; private set; } public bool IsStockHudReplaced => _stockHudBridge.IsStockCanvasDisabled; public bool IsRunHudVisible { get { if ((Object)(object)_runRoot != (Object)null) { return _runRoot.activeSelf; } return false; } } public bool ArePlayerPanelsVisible { get { if ((Object)(object)_playerOneRoot != (Object)null && _playerOneRoot.activeSelf && (Object)(object)_playerTwoRoot != (Object)null) { return _playerTwoRoot.activeSelf; } return false; } } public bool IsReviveButtonVisible { get { if ((Object)(object)_reviveRoot != (Object)null && _reviveRoot.activeSelf && (Object)(object)_reviveButton != (Object)null) { return ((Selectable)_reviveButton).interactable; } return false; } } public bool IsHomepageSettingsButtonVisible { get { if ((Object)(object)_homepageRoot != (Object)null) { return _homepageRoot.activeSelf; } return false; } } public bool IsFriendlyFireEnabled => Plugin.FriendlyFireEnabled.Value; public LocalMultiplayerHud(IntPtr ptr) : base(ptr) { } public LocalMultiplayerHud() : base(ClassInjector.DerivedConstructorPointer()) { ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this); } public void SetFriendlyFireForDebug(bool enabled) { Plugin.FriendlyFireEnabled.Value = enabled; Toggle friendlyFireToggle = _friendlyFireToggle; if (friendlyFireToggle != null) { friendlyFireToggle.SetIsOnWithoutNotify(enabled); } } public bool SetFriendlyFireThroughHomepageForDebug(bool enabled) { if (!IsHomepageSettingsButtonVisible || (Object)(object)_friendlyFireToggle == (Object)null) { return false; } _homepageSettingsPanel.SetActive(true); _friendlyFireToggle.isOn = enabled; return Plugin.FriendlyFireEnabled.Value == enabled; } public bool InvokeReviveButtonForDebug() { if (!IsReviveButtonVisible) { return false; } ((UnityEvent)_reviveButton.onClick).Invoke(); return true; } public void Awake() { Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } public void Update() { UpdateHomepageSettingsUi(); LocalMultiplayerDriver instance = LocalMultiplayerDriver.Instance; if (!Plugin.ModEnabled.Value || !Plugin.CoopHudEnabled.Value || !((Object)(object)instance != (Object)null) || (!((Object)(object)instance.PlayerOne != (Object)null) && !((Object)(object)instance.PlayerTwo != (Object)null))) { _stockHudBridge.RestoreStockHud(); SetVisible(visible: false); return; } EnsureHud(); SetVisible(visible: true); UpdatePlayerOnePanel(instance); UpdatePlayerTwoPanel(instance); UpdateStatusRow(instance); UpdateReviveButton(instance); _stockHudBridge.Refresh(Plugin.ReplaceStockHud.Value); UpdateRunHud(); UpdateBossHud(); } public void OnDestroy() { _stockHudBridge.RestoreStockHud(); if ((Object)(object)_homepageRoot != (Object)null) { Object.Destroy((Object)(object)_homepageRoot); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void EnsureHud() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_root != (Object)null)) { _font = Resources.GetBuiltinResource("Arial.ttf"); _root = new GameObject("Everything_is_Multiplayer_HUD"); Object.DontDestroyOnLoad((Object)(object)_root); Canvas obj = _root.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 32000; CanvasScaler obj2 = _root.AddComponent(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 0.5f; _root.AddComponent(); CreatePanel("P1", new Vector2(24f, -24f), (TextAnchor)0, new Color(0.56f, 0.95f, 0.65f, 1f), playerTwo: false); CreatePanel("P2", new Vector2(-24f, -24f), (TextAnchor)2, new Color(0.55f, 0.9f, 1f, 1f), playerTwo: true); CreateStatusRow(); CreateReviveButton(); CreateRunHud(); CreateBossHud(); } } private void UpdateHomepageSettingsUi() { bool flag = ShouldShowHomepageSettingsUi(); if (flag) { EnsureHomepageSettingsUi(); } if ((Object)(object)_homepageRoot != (Object)null) { _homepageRoot.SetActive(flag); } if ((Object)(object)_friendlyFireToggle != (Object)null && _friendlyFireToggle.isOn != Plugin.FriendlyFireEnabled.Value) { _friendlyFireToggle.SetIsOnWithoutNotify(Plugin.FriendlyFireEnabled.Value); } } private static bool ShouldShowHomepageSettingsUi() { //IL_000c: 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) if (Plugin.ModEnabled.Value) { Scene activeScene = SceneManager.GetActiveScene(); if (string.Equals(((Scene)(ref activeScene)).name, "MainMenu", StringComparison.OrdinalIgnoreCase)) { MainMenuScreenUI val = Object.FindObjectOfType(true); if ((Object)(object)val != (Object)null && ((Behaviour)val).isActiveAndEnabled) { return !val._isWaitingOnInitialInteraction; } return false; } } return false; } private void EnsureHomepageSettingsUi() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Expected O, but got Unknown //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Expected O, but got Unknown //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_0448: Unknown result type (might be due to invalid IL or missing references) //IL_0457: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_homepageRoot != (Object)null)) { if (_font == null) { _font = Resources.GetBuiltinResource("Arial.ttf"); } _homepageRoot = new GameObject("Everything_is_Multiplayer_HomepageSettings"); Object.DontDestroyOnLoad((Object)(object)_homepageRoot); Canvas obj = _homepageRoot.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 32500; CanvasScaler obj2 = _homepageRoot.AddComponent(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 0.5f; _homepageRoot.AddComponent(); GameObject val = new GameObject("LocalCoopButton"); val.transform.SetParent(_homepageRoot.transform, false); SetRect(val.AddComponent(), new Vector2(0f, 28f), new Vector2(154f, 40f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f)); Image val2 = val.AddComponent(); ((Graphic)val2).color = new Color(0.035f, 0.04f, 0.045f, 0.96f); Button obj3 = val.AddComponent