using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Peak.Afflictions; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Thanks.ImZombie")] [assembly: AssemblyDescription("Client-side controllable zombie form for PEAK.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Thanks")] [assembly: AssemblyProduct("I'm Zombie")] [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("4fe3df28-2f61-446e-839f-56e4d41c6f0a")] [assembly: AssemblyFileVersion("0.0.4.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.0.4.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ImZombie { [BepInPlugin("com.github.Thanks.ImZombie", "I'm Zombie", "0.0.4")] public sealed class Plugin : BaseUnityPlugin { private enum ConfigKey { ToggleKey, MoveForwardKey, MoveBackwardKey, MoveLeftKey, MoveRightKey, JumpKey, SprintKey, ClimbKey, PounceKey, ChaseToggleKey, ViewToggleKey, PounceDuration, PounceCooldown, PounceForwardVelocity, PounceUpVelocity, PounceSfxEnabled, ZombieMushroomAppearance, SprintStaminaRefill, ControlledJitterChance, ControlledJitterIntensity, ControlledJitterDuration, FirstPersonHeightOffset, ThirdPersonHeightOffset, ThirdPersonDistance, StartInThirdPerson, SourceStashDistance, RestoreAtZombiePosition, RestoreGroundOffset, VerboseLogs } private readonly struct RendererVisualState { public readonly bool Enabled; public readonly bool ForceRenderingOff; public RendererVisualState(bool enabled, bool forceRenderingOff) { Enabled = enabled; ForceRenderingOff = forceRenderingOff; } } private sealed class ImZombiePrefabPool : IPunPrefabPool { private readonly IPunPrefabPool _inner; private GameObject _playerZombiePrefab; public IPunPrefabPool Inner => _inner; public ImZombiePrefabPool(IPunPrefabPool inner) { _inner = inner; } public bool TryGetCachedPrefab(string prefabId, out GameObject prefab) { prefab = null; if (string.Equals(prefabId, "MushroomZombie_Player", StringComparison.Ordinal)) { if ((Object)(object)_playerZombiePrefab != (Object)null) { prefab = _playerZombiePrefab; return true; } _playerZombiePrefab = null; } return false; } public GameObject Instantiate(string prefabId, Vector3 position, Quaternion rotation) { //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0154: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) bool flag = string.Equals(prefabId, "MushroomZombie_Player", StringComparison.Ordinal); bool flag2 = string.Equals(prefabId, "Character", StringComparison.Ordinal); if (!flag && !flag2) { if (_inner == null) { return null; } return _inner.Instantiate(prefabId, position, rotation); } GameObject instance; if (flag) { if (TryGetRuntimeOrKnownPrefab(prefabId, out var prefab)) { GameObject val = InstantiateCachedPlayerZombiePrefab(prefab, position, rotation); if ((Object)(object)val != (Object)null) { LogVerbose("Instantiated " + prefabId + " through ImZombie stable prefab backup."); return val; } ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Stable prefab backup for " + prefabId + " was present but could not be cloned; falling back to inner prefab pool.")); } } if (TryCapturePrefabFromPool(_inner, prefabId, new HashSet(), out var prefab2) && (Object)(object)prefab2 != (Object)null) { RegisterRuntimeNetworkPrefabBackupFromPrefab(prefabId, prefab2, !HasAliveRuntimeNetworkPrefabBackup(prefabId)); GameObject val2 = InstantiateCachedPlayerZombiePrefab(prefab2, position, rotation); if ((Object)(object)val2 != (Object)null) { _playerZombiePrefab = prefab2; LogVerbose("Instantiated " + prefabId + " through ImZombie prefab pool wrapper."); return val2; } } if (TryGetCachedPrefab(prefabId, out var prefab3) || TryGetRuntimeOrKnownPrefab(prefabId, out prefab3)) { GameObject val3 = InstantiateCachedPlayerZombiePrefab(prefab3, position, rotation); if ((Object)(object)val3 != (Object)null) { LogVerbose("Instantiated " + prefabId + " through ImZombie prefab pool wrapper."); return val3; } } } else if (flag2 && ShouldRecoverOriginalCharacterSpawnFromBackup() && !TryCaptureOriginalCharacterPrefabFromInnerPool(_inner) && TryInstantiateOriginalPlayerCharacterBackup(position, rotation, out instance)) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)"[I'm Zombie] Inner prefab pool has no usable Character prefab during level spawn; instantiated cached original Character backup before exception fallback."); } return instance; } GameObject val4 = null; try { val4 = ((_inner != null) ? _inner.Instantiate(prefabId, position, rotation) : null); } catch (Exception ex) { if (flag && (TryGetCachedPrefab(prefabId, out var prefab4) || TryGetRuntimeOrKnownPrefab(prefabId, out prefab4))) { GameObject val5 = InstantiateCachedNetworkPrefab(prefabId, prefab4, position, rotation); if ((Object)(object)val5 != (Object)null) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)("[I'm Zombie] Inner prefab pool failed for " + prefabId + "; instantiated cached prefab through ImZombie wrapper instead: " + ex.Message)); } return val5; } } if (_inner != null) { try { ClearInvalidPrefabPoolResourceCache(_inner, prefabId, new HashSet()); val4 = _inner.Instantiate(prefabId, position, rotation); if ((Object)(object)val4 != (Object)null) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogWarning((object)("[I'm Zombie] Inner prefab pool failed for " + prefabId + "; cleared invalid cache and retried successfully: " + ex.Message)); } return val4; } } catch (Exception ex2) { ManualLogSource log5 = Log; if (log5 != null) { log5.LogWarning((object)("[I'm Zombie] Inner prefab pool failed for " + prefabId + " and cache retry did not recover:\n" + ex2)); } } } ManualLogSource log6 = Log; if (log6 != null) { log6.LogWarning((object)("[I'm Zombie] Inner prefab pool failed for " + prefabId + ":\n" + ex)); } if (flag2 && TryInstantiateOriginalPlayerCharacterBackup(position, rotation, out var instance2)) { ManualLogSource log7 = Log; if (log7 != null) { log7.LogWarning((object)"[I'm Zombie] Inner prefab pool failed for Character; instantiated cached original Character backup as a last-resort fallback."); } return instance2; } throw; } if (flag) { CapturePlayerZombiePrefabFromInnerPool(prefabId); } else if (flag2) { CaptureOriginalPlayerCharacterPrefabBackup(prefabId); } return val4; } public void Destroy(GameObject gameObject) { if ((Object)(object)gameObject == (Object)null) { return; } try { if (_inner != null) { _inner.Destroy(gameObject); return; } } catch (Exception ex) { LogVerbose("Inner prefab pool destroy failed for " + ((Object)gameObject).name + ": " + ex.Message); } Object.Destroy((Object)(object)gameObject); } private static GameObject InstantiateCachedPlayerZombiePrefab(GameObject prefab, Vector3 position, Quaternion rotation) { //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) return InstantiateCachedNetworkPrefab("MushroomZombie_Player", prefab, position, rotation); } private static GameObject InstantiateCachedNetworkPrefab(string prefabId, GameObject prefab, Vector3 position, Quaternion rotation) { //IL_000d: 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_0036: 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) if ((Object)(object)prefab == (Object)null) { return null; } try { GameObject val = InstantiateInactivePrefabCopy(prefab, position, rotation); if ((Object)(object)val == (Object)null) { return null; } ((Object)val).name = prefabId; ResetRuntimeNetworkPrefabObject(val, keepInactive: true); val.transform.SetPositionAndRotation(position, rotation); return val; } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to instantiate cached " + prefabId + " prefab: " + ex.Message)); } return null; } } private void CapturePlayerZombiePrefabFromInnerPool(string prefabId) { if ((Object)(object)_playerZombiePrefab != (Object)null) { return; } try { if (TryCapturePrefabFromPool(_inner, prefabId, new HashSet(), out var prefab) && (Object)(object)prefab != (Object)null) { _playerZombiePrefab = prefab; _knownPhotonPrefabCache[prefabId] = prefab; RegisterRuntimeNetworkPrefabBackupFromPrefab(prefabId, prefab, !HasAliveRuntimeNetworkPrefabBackup(prefabId)); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Captured " + prefabId + " prefab in ImZombie prefab pool wrapper.")); } } } catch (Exception ex) { LogVerbose("Failed to capture " + prefabId + " prefab from inner Photon pool: " + ex.Message); } } } [StructLayout(LayoutKind.Sequential, Size = 1)] internal readonly struct ControlledZombieOriginalBehaviorScope : IDisposable { public void Dispose() { EndControlledZombieOriginalBehavior(); } } private sealed class ActiveZombieSession { private enum SessionState { Created, Entering, Active, Exiting, Exited } private readonly struct BodypartPhysicsState { public readonly Rigidbody Rig; public readonly bool IsKinematic; public readonly bool DetectCollisions; public readonly bool UseGravity; public BodypartPhysicsState(Rigidbody rig) { Rig = rig; IsKinematic = (Object)(object)rig != (Object)null && rig.isKinematic; DetectCollisions = (Object)(object)rig != (Object)null && rig.detectCollisions; UseGravity = (Object)(object)rig != (Object)null && rig.useGravity; } } [CompilerGenerated] private sealed class d__33 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ActiveZombieSession <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__33(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; ActiveZombieSession activeZombieSession = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; if (activeZombieSession._state != 0) { return false; } activeZombieSession._state = SessionState.Entering; activeZombieSession.PreconfigureZombieForLocalControl(); activeZombieSession._controller = activeZombieSession._zombieObject.GetComponent() ?? activeZombieSession._zombieObject.AddComponent(); activeZombieSession._controller.Initialize(activeZombieSession._sourceCharacter, activeZombieSession._zombie, activeZombieSession._zombieCharacter); RegisterControlledZombie(activeZombieSession._zombie); Character.localCharacter = activeZombieSession._zombieCharacter; ForcePlayerCharacterLookup(activeZombieSession._zombieCharacter); activeZombieSession._localCharacterSwapped = true; BeginNativeAriseSuppressionByViewId(activeZombieSession._sourceViewId); ExtendNativeAriseSuppressionByViewId(activeZombieSession._sourceViewId); SetGameObjectActive(activeZombieSession._zombieObject, active: true); activeZombieSession.AlignZombieBodyToSource(); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; activeZombieSession.AlignZombieBodyToSource(); activeZombieSession.PrepareZombie(); ApplyControlledZombieNativePresentation(activeZombieSession._zombie, activeZombieSession._zombieCharacter, activeZombieSession._sourceCharacter); SetCameraOverride(activeZombieSession._zombieCharacter); _viewZombieObject = activeZombieSession._zombieObject; HideHudForZombie(); SetZombieRenderersVisible(activeZombieSession._zombieObject, visible: true); activeZombieSession._controller.ActivateDynamicRagdollControl(); activeZombieSession._controller.ForceGroundSnap(); Character.localCharacter = activeZombieSession._zombieCharacter; ForcePlayerCharacterLookup(activeZombieSession._zombieCharacter); activeZombieSession._localCharacterSwapped = true; activeZombieSession._state = SessionState.Active; activeZombieSession.HideSourceCharacter(); LogVerbose("Entered zombie form."); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private readonly Character _sourceCharacter; private readonly int _sourceViewId; private readonly GameObject _zombieObject; private readonly MushroomZombie _zombie; private readonly Character _zombieCharacter; private readonly Vector3 _sourceStartPosition; private readonly Vector3 _sourceStashPosition; private readonly Quaternion _sourceStartRotation; private readonly bool _sourceWasActive; private readonly List _sourceBodypartPhysicsStates = new List(); private PlayerZombieController _controller; private bool _sourcePhysicsSuspended; private bool _sourceStatusRestoredThisExit; private Vector3 _lastStableRestorePosition; private bool _hasLastStableRestorePosition; private SessionState _state; private bool _sourceLossLogged; private bool _localCharacterSwapped; private bool _sourceHidden; public bool IsActive { get { if (_state == SessionState.Active) { return HasControlledZombieObjects; } return false; } } private bool HasRequiredObjects { get { if ((Object)(object)_sourceCharacter != (Object)null) { return HasControlledZombieObjects; } return false; } } private bool HasControlledZombieObjects { get { if ((Object)(object)_zombieObject != (Object)null && (Object)(object)_zombie != (Object)null) { return (Object)(object)_zombieCharacter != (Object)null; } return false; } } public ActiveZombieSession(Character sourceCharacter, GameObject zombieObject, MushroomZombie zombie, Character zombieCharacter, bool sourceWasActive) { //IL_003c: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_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) _sourceCharacter = sourceCharacter; _sourceViewId = GetCharacterViewId(sourceCharacter); _zombieObject = zombieObject; _zombie = zombie; _zombieCharacter = zombieCharacter; _sourceStartPosition = sourceCharacter.Center; _sourceStashPosition = BuildSourceStashPosition(_sourceStartPosition); _sourceStartRotation = GetSpawnRotation(sourceCharacter); _sourceWasActive = sourceWasActive; } internal bool IsSourceCharacter(Character character) { if ((Object)(object)character != (Object)null) { return (Object)(object)character == (Object)(object)_sourceCharacter; } return false; } internal bool IsSourceViewId(int viewId) { if (viewId > 0) { return viewId == _sourceViewId; } return false; } internal bool TryGetControlledCharacter(out Character character) { character = null; if ((_state != SessionState.Entering && _state != SessionState.Active) || !HasControlledZombieObjects) { return false; } character = _zombieCharacter; return true; } internal bool TryTriggerFaint() { if (!IsActive || (Object)(object)_controller == (Object)null) { return false; } return _controller.TryTriggerFaint(); } private static Vector3 BuildSourceStashPosition(Vector3 sourcePosition) { //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_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_0017: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) float effectiveSourceStashDistance = GetEffectiveSourceStashDistance(); Vector3 val = sourcePosition + Vector3.down * effectiveSourceStashDistance; if (!IsFiniteVector(val)) { return sourcePosition; } return val; } [IteratorStateMachine(typeof(d__33))] public IEnumerator Enter() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__33(0) { <>4__this = this }; } private void SendNativeArise() { if ((Object)(object)_sourceCharacter == (Object)null || (Object)(object)((MonoBehaviourPun)_sourceCharacter).photonView == (Object)null || (Object)(object)_zombie == (Object)null) { return; } int viewID = ((MonoBehaviourPun)_sourceCharacter).photonView.ViewID; if (viewID <= 0) { return; } try { BeginControlledZombieOriginalBehavior(); try { PhotonView photonView = ((MonoBehaviourPun)_zombie).photonView; if (HasNetworkView(photonView)) { photonView.RPC("RPC_Arise", (RpcTarget)0, new object[1] { viewID }); } else if (PhotonNetwork.InRoom) { LogVerbose("Skipped native arise RPC for local-only zombie in a network room."); } else if (!PhotonNetwork.OfflineMode) { InvokeNativeAriseReflectively(viewID); } } finally { EndControlledZombieOriginalBehavior(); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Native RPC_Arise failed: " + ex.Message)); } } } private void InvokeNativeAriseReflectively(int sourceViewId) { MethodBase methodBase = FindMushroomZombieAriseMethod(); if (!(methodBase == null)) { ParameterInfo[] parameters = methodBase.GetParameters(); object[] array = new object[parameters.Length]; if (array.Length != 0) { array[0] = sourceViewId; } for (int i = 1; i < array.Length; i++) { Type parameterType = parameters[i].ParameterType; array[i] = (parameterType.IsValueType ? Activator.CreateInstance(parameterType) : null); } methodBase.Invoke(_zombie, array); } } public void AbortEnter() { //IL_0067: 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) if (_state == SessionState.Exited) { return; } _state = SessionState.Exiting; try { if ((Object)(object)_controller != (Object)null) { ((Behaviour)_controller).enabled = false; } } catch { } try { ClearCameraOverride(); _viewZombieObject = null; RestoreHudAfterZombie(); ForceClearSpectatorState(); } catch { } try { if ((Object)(object)_sourceCharacter != (Object)null) { if (_sourceHidden) { RestoreSourceCharacter(_sourceStartPosition, _sourceStartRotation); } else if (_sourceWasActive && !((Component)_sourceCharacter).gameObject.activeSelf) { ((Component)_sourceCharacter).gameObject.SetActive(true); } if (_localCharacterSwapped || (Object)(object)Character.localCharacter == (Object)(object)_zombieCharacter || (Object)(object)Character.localCharacter == (Object)null) { Character.localCharacter = _sourceCharacter; } ForcePlayerCharacterLookup(_sourceCharacter); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to restore source after aborted zombie transform: " + ex.Message)); } } try { EndNativeAriseSuppressionByViewId(_sourceViewId); UnregisterStashedSourceCharacter(_sourceCharacter); ClearLocalSourceProxyCharacter(_sourceCharacter); RegisterStatusUiSuppressedCharacter(_zombieCharacter, 1.5f); UnregisterControlledZombie(_zombie); BeginPeakStatsCleanupGraceWindow(); RequestThirdPartyStatusUiCleanup(aggressive: true); CompleteSessionCleanup(restorePlayer: true); DestroyZombieObject(_zombieObject); } catch (Exception ex2) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[I'm Zombie] Failed to clean up aborted zombie transform: " + ex2.Message)); } } _state = SessionState.Exited; } private void PreconfigureZombieForLocalControl() { EnsureMushroomZombieNativeFields(_zombie); PrepareControlledZombieCharacterRefs(_zombieCharacter); _zombie.isNPCZombie = false; _zombie.targetForcedUntil = 0f; _zombie.initialWakeUpTime = 0f; _zombie.lifetime = float.PositiveInfinity; _zombie.currentTarget = null; SetMushroomZombieStateSilently(_zombie, (State)2); _zombieCharacter.isZombie = true; ConfigureControlledZombieCustomization(_zombieCharacter, _sourceCharacter); EnableZombiePhysics(); } private void AlignZombieBodyToSource() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_sourceCharacter == (Object)null || (Object)(object)_zombieCharacter == (Object)null || (Object)(object)_zombieObject == (Object)null) { return; } try { Quaternion spawnRotation = GetSpawnRotation(_sourceCharacter); SetCharacterPositionImmediate(_zombieCharacter, _sourceCharacter.Center, spawnRotation); CopyLookStateForZombieEnter(_sourceCharacter, _zombieCharacter, spawnRotation); _zombieCharacter.data.currentRagdollControll = 1f; _zombieCharacter.data.fallSeconds = 0f; _zombieCharacter.data.isGrounded = (Object)(object)_sourceCharacter.data != (Object)null && _sourceCharacter.data.isGrounded; _zombieCharacter.data.groundPos = (((Object)(object)_sourceCharacter.data != (Object)null) ? _sourceCharacter.data.groundPos : _sourceCharacter.Center); EnableZombiePhysics(); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to align controlled zombie body: " + ex.Message)); } } } private void EnableZombiePhysics() { if ((Object)(object)_zombieCharacter == (Object)null || _zombieCharacter.refs?.ragdoll?.partList == null) { return; } try { foreach (Bodypart part in _zombieCharacter.refs.ragdoll.partList) { Rigidbody val = (((Object)(object)part != (Object)null) ? part.Rig : null); if (!((Object)(object)val == (Object)null)) { val.isKinematic = false; val.detectCollisions = true; val.useGravity = true; val.WakeUp(); } } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to enable controlled zombie physics: " + ex.Message)); } } } private static void CopyBodypartPose(Bodypart sourcePart, Bodypart targetPart) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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) //IL_0065: 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_0073: 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) if (!((Object)(object)sourcePart == (Object)null) && !((Object)(object)targetPart == (Object)null)) { Rigidbody rig = sourcePart.Rig; Rigidbody rig2 = targetPart.Rig; Vector3 val = (((Object)(object)rig != (Object)null) ? rig.position : ((Component)sourcePart).transform.position); Quaternion val2 = (((Object)(object)rig != (Object)null) ? rig.rotation : ((Component)sourcePart).transform.rotation); if ((Object)(object)rig2 != (Object)null) { rig2.position = val; rig2.rotation = val2; rig2.linearVelocity = Vector3.zero; rig2.angularVelocity = Vector3.zero; } else { ((Component)targetPart).transform.SetPositionAndRotation(val, val2); } } } public void Tick() { if (_state != SessionState.Active) { return; } if ((Object)(object)_sourceCharacter == (Object)null && !_sourceLossLogged) { _sourceLossLogged = true; ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[I'm Zombie] Source character was destroyed while transformed; keeping controlled zombie active and blocking source restore until a valid source exists."); } } if (!HasControlledZombieObjects) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[I'm Zombie] Zombie session became inactive: " + GetInactiveReason())); } Instance?.ExitZombieForm(restorePlayer: true); return; } Character.localCharacter = _zombieCharacter; ForcePlayerCharacterLookup(_zombieCharacter); KeepZombieAwake(); if ((Object)(object)_sourceCharacter != (Object)null) { KeepSourceOutOfPlay(); UpdateRestoreAnchorCache(); } } private string GetInactiveReason() { if ((Object)(object)_zombieObject == (Object)null) { return "zombie object missing"; } if ((Object)(object)_zombie == (Object)null) { return "MushroomZombie missing"; } if ((Object)(object)_zombieCharacter == (Object)null) { return "zombie character missing"; } if ((Object)(object)_sourceCharacter == (Object)null) { return "source character missing"; } return "unknown"; } public void Exit(bool restorePlayer) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if (_state == SessionState.Exiting || _state == SessionState.Exited) { return; } if (restorePlayer && (Object)(object)_sourceCharacter == (Object)null && HasControlledZombieObjects) { _state = SessionState.Active; Character.localCharacter = _zombieCharacter; SetCameraOverride(_zombieCharacter); _viewZombieObject = _zombieObject; if ((Object)(object)_controller != (Object)null) { ((Behaviour)_controller).enabled = true; } ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[I'm Zombie] Cannot restore the original player model because the source character no longer exists; keeping zombie form active."); } return; } _state = SessionState.Exiting; _sourceStatusRestoredThisExit = false; Vector3 position = ResolveRestorePosition(); Quaternion rotation = (((Object)(object)_zombieCharacter != (Object)null) ? GetCharacterYaw(_zombieCharacter) : _sourceStartRotation); if ((Object)(object)_controller != (Object)null) { try { ((Behaviour)_controller).enabled = false; } catch { } } SetZombieRenderersVisible(_zombieObject, visible: true); ClearCameraOverride(); _viewZombieObject = null; RestoreHudAfterZombie(); ForceClearSpectatorState(); if (restorePlayer && (Object)(object)_sourceCharacter != (Object)null) { UnregisterStashedSourceCharacter(_sourceCharacter); Character.localCharacter = _sourceCharacter; ForcePlayerCharacterLookup(_sourceCharacter); CopyLookStateForRestore(_zombieCharacter, _sourceCharacter); RestoreSourceCharacter(position, rotation); ApplyLookStateFromRotation(_sourceCharacter, rotation); BeginCameraRestoreAssist(_sourceCharacter); } EndNativeAriseSuppressionByViewId(_sourceViewId); UnregisterStashedSourceCharacter(_sourceCharacter); ClearLocalSourceProxyCharacter(_sourceCharacter); RegisterStatusUiSuppressedCharacter(_zombieCharacter, 1.5f); UnregisterControlledZombie(_zombie); BeginPeakStatsCleanupGraceWindow(); RequestThirdPartyStatusUiCleanup(aggressive: true); if (restorePlayer && (Object)(object)_sourceCharacter != (Object)null && !_sourceStatusRestoredThisExit) { RestoreOriginalPlayerStatusProcessing(_sourceCharacter); _sourceStatusRestoredThisExit = true; } CompleteSessionCleanup(restorePlayer); DestroyZombieObject(_zombieObject); _state = SessionState.Exited; LogVerbose("Exited zombie form."); } private void CompleteSessionCleanup(bool restorePlayer) { try { EndNativeAriseSuppressionByViewId(_sourceViewId); UnregisterControlledZombie(_zombie); UnregisterControlledZombieIds(_zombie, _zombieCharacter); RegisterStatusUiSuppressedCharacter(_zombieCharacter, 1.5f); RequestThirdPartyStatusUiCleanup(aggressive: true); _controlledClimbStartCooldownUntil.Remove(((Object)(object)_zombieCharacter != (Object)null) ? ((Object)_zombieCharacter).GetInstanceID() : 0); if ((Object)(object)_zombie != (Object)null) { _localMushroomGrowthInitializedZombieIds.Remove(((Object)_zombie).GetInstanceID()); } if ((Object)(object)_cameraOverrideCharacter == (Object)(object)_zombieCharacter) { ClearCameraOverride(); } if ((Object)(object)_cameraRestoreCharacter == (Object)(object)_zombieCharacter) { _cameraRestoreCharacter = null; _cameraRestoreUntil = 0f; } if ((Object)(object)_viewZombieObject == (Object)(object)_zombieObject) { _viewZombieObject = null; } _controlledZombieOriginalBehaviorDepth = 0; if ((Object)(object)_sourceCharacter != (Object)null) { UnregisterStashedSourceCharacter(_sourceCharacter); ClearLocalSourceProxyCharacter(_sourceCharacter); if (restorePlayer && !_sourceStatusRestoredThisExit) { RestoreOriginalPlayerStatusProcessing(_sourceCharacter); _sourceStatusRestoredThisExit = true; } } RestoreHudAfterZombie(); ForceClearSpectatorState(); Instance?.BeginLocalZombieSessionResidualCleanupWindow(); LogZombieSessionCleanupResult(restorePlayer); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to complete zombie session cleanup: " + ex.Message)); } } } private void LogZombieSessionCleanupResult(bool restorePlayer) { try { bool flag = IsStashedSourceCharacter(_sourceCharacter); bool flag2 = (Object)(object)_sourceCharacter != (Object)null && (Object)(object)_sourceCharacter == (Object)(object)Character.localCharacter; bool flag3 = (Object)(object)_sourceCharacter != (Object)null && _sourceCharacter.isZombie; bool flag4 = (Object)(object)_sourceCharacter?.data != (Object)null && _sourceCharacter.data.zombified; bool flag5 = (Object)(object)_zombie != (Object)null && _controlledZombieInstanceIds.Contains(((Object)_zombie).GetInstanceID()); bool flag6 = (Object)(object)_zombieCharacter != (Object)null && _controlledZombieCharacterInstanceIds.Contains(((Object)_zombieCharacter).GetInstanceID()); bool flag7 = (Object)(object)_zombieCharacter != (Object)null && _statusUiSuppressedCharacterUntilById.ContainsKey(((Object)_zombieCharacter).GetInstanceID()); bool flag8 = (Object)(object)_cameraOverrideCharacter != (Object)(object)_zombieCharacter; bool flag9 = !_hudHiddenForZombie; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Zombie session cleanup complete: restorePlayer=" + restorePlayer + ", sourceLocal=" + flag2 + ", sourceZombie=" + flag3 + ", sourceZombified=" + flag4 + ", sourceStashed=" + flag + ", zombieTracked=" + flag5 + ", zombieCharacterTracked=" + flag6 + ", zombieStatusSuppressed=" + flag7 + ", cameraCleared=" + flag8 + ", hudRestored=" + flag9)); } } catch { } } private Vector3 ResolveRestorePosition() { //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_0008: 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_0022: 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) Vector3 preferredRestoreAnchor = GetPreferredRestoreAnchor(); return ResolveSafeRestorePosition(GetInsuredRestoreAnchor(preferredRestoreAnchor), extraLift: GetRestoreExtraLift(), zombieCharacter: _zombieCharacter, sourceCharacter: _sourceCharacter, fallbackPosition: _sourceStartPosition, logResult: true); } private Vector3 GetPreferredRestoreAnchor() { //IL_000f: 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_0024: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_zombieCharacter == (Object)null) { return _sourceStartPosition; } if (TryGetStableRestoreAnchor(_zombieCharacter, out var anchor)) { return anchor; } return GetRestoreAnchor(_zombieCharacter); } private Vector3 GetInsuredRestoreAnchor(Vector3 requestedPosition) { //IL_0015: 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_0017: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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 (!_hasLastStableRestorePosition || !IsFiniteVector(_lastStableRestorePosition)) { return requestedPosition; } if (!IsFiniteVector(requestedPosition)) { return _lastStableRestorePosition; } if (ShouldPreferCachedRestorePosition(requestedPosition)) { LogVerbose("Using cached stable restore anchor instead of current zombie anchor."); return _lastStableRestorePosition; } return requestedPosition; } private bool ShouldPreferCachedRestorePosition(Vector3 requestedPosition) { //IL_0009: 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_0023: 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_004c: Unknown result type (might be due to invalid IL or missing references) if (!_hasLastStableRestorePosition || !IsFiniteVector(_lastStableRestorePosition)) { return false; } if (!IsFiniteVector(requestedPosition)) { return true; } Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(requestedPosition.x - _lastStableRestorePosition.x, requestedPosition.z - _lastStableRestorePosition.z); float num = Mathf.Abs(requestedPosition.y - _lastStableRestorePosition.y); if (!(((Vector2)(ref val)).sqrMagnitude > 64f)) { return num > 4f; } return true; } private bool IsAggressiveRestoreState() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 if ((Object)(object)_zombie == (Object)null) { return false; } if ((int)_zombie.currentState != 4) { return (int)_zombie.currentState == 3; } return true; } private float GetRestoreExtraLift() { float num = 0.55f; if (IsAggressiveRestoreState()) { num += 0.45f; } return num; } private static Vector3 GetRestoreAnchor(Character character) { //IL_0009: 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_0026: 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_0019: 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_0037: 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_002f: 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) //IL_0048: 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_0040: 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_0051: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null) { return Vector3.zero; } if (TryGetStableRestoreAnchor(character, out var anchor)) { return anchor; } Vector3 position = ((Component)character).transform.position; if (IsFiniteVector(position)) { return position; } Vector3 center = character.Center; if (IsFiniteVector(center)) { return center; } Vector3 head = character.Head; if (IsFiniteVector(head)) { return head; } return ((Component)character).transform.position; } private void UpdateRestoreAnchorCache() { //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_0016: 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_002d: 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_003d: 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_0048: 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) if ((Object)(object)_zombieCharacter == (Object)null) { return; } Vector3 preferredRestoreAnchor = GetPreferredRestoreAnchor(); if (IsFiniteVector(preferredRestoreAnchor)) { Vector3 val = ResolveSafeRestorePosition(preferredRestoreAnchor, _zombieCharacter, _sourceCharacter, _sourceStartPosition, 0.55f, logResult: false); if (IsFiniteVector(val)) { _lastStableRestorePosition = val; _hasLastStableRestorePosition = true; } } } private static Vector3 ResolveSafeRestorePosition(Vector3 requestedPosition, Character zombieCharacter, Character sourceCharacter, Vector3 fallbackPosition, float extraLift, bool logResult) { //IL_0006: 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_000e: 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_0037: 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_0042: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_005c: 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: 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_00a5: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_012a: 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_012d: 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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) float num = 1.35f; Vector3 val = (IsFiniteVector(requestedPosition) ? requestedPosition : fallbackPosition); if (!IsFiniteVector(val)) { val = (((Object)(object)sourceCharacter != (Object)null) ? ((Component)sourceCharacter).transform.position : Vector3.zero); } Vector3 origin = val + Vector3.up * 3f; Vector3 origin2 = val + Vector3.up * 8f; Vector3 val3; if (TryFindRestoreGround(origin, 24f, val, zombieCharacter, sourceCharacter, out var groundHit) || TryFindRestoreGround(origin2, 72f, val, zombieCharacter, sourceCharacter, out groundHit)) { float num2 = ((RaycastHit)(ref groundHit)).point.y + num + Mathf.Max(0f, extraLift); Vector3 val2 = val; if (val2.y < num2) { val2.y = num2; } if (logResult) { string[] obj = new string[7] { "Resolved safe restore position at ", null, null, null, null, null, null }; val3 = val2; obj[1] = ((object)(Vector3)(ref val3)).ToString(); obj[2] = " from requested zombie anchor "; val3 = val; obj[3] = ((object)(Vector3)(ref val3)).ToString(); obj[4] = " using ground hit "; obj[5] = ((Object)((RaycastHit)(ref groundHit)).collider).name; obj[6] = "."; LogVerbose(string.Concat(obj)); } return val2; } Vector3 val4 = val; if (IsUnsafeRestoreAnchorWithoutGround(val, fallbackPosition)) { val4 = fallbackPosition; if (IsFiniteVector(val4)) { val4.y += num + Mathf.Max(0f, extraLift); } } if (logResult) { val3 = val4; LogVerbose("No ground hit found for restore; using requested zombie anchor " + ((object)(Vector3)(ref val3)).ToString() + "."); } return val4; } private static bool IsUnsafeRestoreAnchorWithoutGround(Vector3 anchor, Vector3 fallbackPosition) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_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 (!IsFiniteVector(anchor) || !IsFiniteVector(fallbackPosition)) { return false; } if (anchor.y < fallbackPosition.y - 10f) { return true; } Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(anchor.x - fallbackPosition.x, anchor.z - fallbackPosition.z); if (((Vector2)(ref val)).sqrMagnitude > 16f) { return Mathf.Abs(anchor.y - fallbackPosition.y) > 8f; } return false; } private static bool TryFindRestoreGround(Vector3 origin, float distance, Vector3 anchor, Character zombieCharacter, Character sourceCharacter, out RaycastHit groundHit) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_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) groundHit = default(RaycastHit); if (!IsFiniteVector(origin)) { return false; } RaycastHit[] array; try { array = Physics.RaycastAll(origin, Vector3.down, distance, -1, (QueryTriggerInteraction)1); } catch { return false; } Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance)); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val = array2[i]; if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !((RaycastHit)(ref val)).collider.isTrigger && !(Vector3.Dot(((RaycastHit)(ref val)).normal, Vector3.up) < 0.2f) && !IsRestoreIgnoredCollider(((RaycastHit)(ref val)).collider, zombieCharacter, sourceCharacter) && IsRestoreGroundCandidateNearAnchor(((RaycastHit)(ref val)).point, anchor)) { groundHit = val; return true; } } return false; } private static bool IsRestoreIgnoredCollider(Collider collider, Character zombieCharacter, Character sourceCharacter) { if ((Object)(object)collider == (Object)null) { return true; } Transform transform = ((Component)collider).transform; if (!IsColliderOwnedBy(transform, zombieCharacter)) { return IsColliderOwnedBy(transform, sourceCharacter); } return true; } private static bool IsColliderOwnedBy(Transform colliderTransform, Character character) { if ((Object)(object)colliderTransform == (Object)null || (Object)(object)character == (Object)null) { return false; } Transform transform = ((Component)character).transform; if (!((Object)(object)colliderTransform == (Object)(object)transform)) { return colliderTransform.IsChildOf(transform); } return true; } private static bool IsRestoreGroundCandidateNearAnchor(Vector3 hitPoint, Vector3 anchor) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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) if (!IsFiniteVector(hitPoint) || !IsFiniteVector(anchor)) { return false; } if (hitPoint.y - anchor.y < -8f) { return false; } Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(hitPoint.x - anchor.x, hitPoint.z - anchor.z); return ((Vector2)(ref val)).sqrMagnitude <= 36f; } private static bool TryGetStableRestoreAnchor(Character character, out Vector3 anchor) { //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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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) //IL_0034: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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) anchor = Vector3.zero; if ((Object)(object)character == (Object)null) { return false; } if (!TryGetCharacterBodyHorizontalAnchor(character, out var anchor2)) { return false; } if (TryGetRestoreFootAnchorY(character, out var footY)) { anchor = new Vector3(anchor2.x, footY, anchor2.z); return true; } Vector3 center = character.Center; if (IsFiniteVector(center)) { anchor = new Vector3(anchor2.x, center.y, anchor2.z); return true; } anchor = anchor2; return true; } private static bool TryGetCharacterBodyHorizontalAnchor(Character character, out Vector3 anchor) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_00de: 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_00fa: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010f: 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_011b: 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) //IL_0082: 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_0097: 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_00a1: 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) anchor = Vector3.zero; if ((Object)(object)character == (Object)null) { return false; } Vector3 val = Vector3.zero; int num = 0; try { if (character.refs?.ragdoll?.partList != null) { foreach (Bodypart part in character.refs.ragdoll.partList) { if (!((Object)(object)part == (Object)null)) { Vector3 val2 = (((Object)(object)part.Rig != (Object)null) ? part.Rig.position : ((Component)part).transform.position); if (IsFiniteVector(val2)) { val += val2; num++; } } } } } catch { } if (num > 0) { anchor = val / (float)num; return IsFiniteVector(anchor); } Vector3 center = character.Center; if (IsFiniteVector(center)) { anchor = center; return true; } try { Vector3 position = ((Component)character).transform.position; if (IsFiniteVector(position)) { anchor = position; return true; } } catch { } return false; } private static bool TryGetRestoreFootAnchorY(Character character, out float footY) { footY = float.PositiveInfinity; if (character?.refs?.ragdoll?.partList == null) { return false; } if (false | TryUpdateRestoreAnchorY(character, (BodypartType)13, ref footY) | TryUpdateRestoreAnchorY(character, (BodypartType)16, ref footY) | TryUpdateRestoreAnchorY(character, (BodypartType)27, ref footY) | TryUpdateRestoreAnchorY(character, (BodypartType)28, ref footY)) { return IsFiniteFloat(footY); } return false; } private static bool TryUpdateRestoreAnchorY(Character character, BodypartType bodypartType, ref float anchorY) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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) bool result = false; foreach (Bodypart part in character.refs.ragdoll.partList) { if (!((Object)(object)part == (Object)null) && part.partType == bodypartType) { Vector3 val = (((Object)(object)part.Rig != (Object)null) ? part.Rig.position : ((Component)part).transform.position); if (IsFiniteFloat(val.y)) { anchorY = Mathf.Min(anchorY, val.y); result = true; } } } return result; } private static bool IsFiniteVector(Vector3 value) { //IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references) if (IsFiniteFloat(value.x) && IsFiniteFloat(value.y)) { return IsFiniteFloat(value.z); } return false; } private static bool IsFiniteFloat(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } private void PrepareZombie() { EnsureMushroomZombieNativeFields(_zombie); PrepareControlledZombieCharacterRefs(_zombieCharacter); _zombie.isNPCZombie = false; _zombie.initialWakeUpTime = 0f; _zombie.distanceBeforeChase = 0f; _zombie.chaseTimeBeforeSprint = 0f; _zombie.zombieSprintDistance = 9999f; _zombie.lifetime = float.PositiveInfinity; _zombie.currentTarget = null; SetMushroomZombieStateSilently(_zombie, (State)2); _zombieCharacter.isZombie = true; _zombieCharacter.data.dead = false; _zombieCharacter.data.passedOut = false; _zombieCharacter.data.fullyPassedOut = false; _zombieCharacter.data.fallSeconds = 0f; _zombieCharacter.data.currentRagdollControll = 1f; float effectiveSprintStaminaRefill = GetEffectiveSprintStaminaRefill(); _zombieCharacter.data.currentStamina = effectiveSprintStaminaRefill; _zombieCharacter.data.extraStamina = effectiveSprintStaminaRefill; ClearAssistJumpState(_zombieCharacter); ResetDisabledInventoryState(_zombieCharacter.refs?.items, _zombieCharacter); SetGameObjectActive(_zombie.biteColliderObject, active: false); ApplyMushroomAppearance(_zombie); ApplyControlledZombieNativePresentation(_zombie, _zombieCharacter, _sourceCharacter); } private void HideSourceCharacter() { //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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_00f2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_sourceCharacter == (Object)null) { return; } try { RegisterStashedSourceCharacter(_sourceCharacter); _sourceHidden = true; _sourceCharacter.data.fallSeconds = 0f; _sourceCharacter.data.passedOut = false; _sourceCharacter.data.fullyPassedOut = false; ClearAssistJumpState(_sourceCharacter); if (_sourceWasActive && !((Component)_sourceCharacter).gameObject.activeSelf) { ((Component)_sourceCharacter).gameObject.SetActive(true); } Quaternion rotation = ((Component)_sourceCharacter).transform.rotation; HideSourceRenderers(((Component)_sourceCharacter).gameObject); ResetCharacterFallState(_sourceCharacter, _sourceStashPosition, grounded: true); SetCharacterPositionImmediate(_sourceCharacter, _sourceStashPosition, rotation); SuspendSourcePhysics(); ZeroCharacterBodyVelocity(_sourceCharacter, wake: false); SyncPhysicsTransforms(); SendSourceCharacterOutOfPlay(_sourceStashPosition, rotation); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to stash source character: " + ex.Message)); } } } private void RestoreSourceCharacter(Vector3 position, Quaternion rotation) { //IL_005d: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00b8: 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_00c5: 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_00e8: 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_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0101: 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_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) UnregisterStashedSourceCharacter(_sourceCharacter); Character.localCharacter = _sourceCharacter; ForcePlayerCharacterLookup(_sourceCharacter); try { if (_sourceWasActive && !((Component)_sourceCharacter).gameObject.activeSelf) { ((Component)_sourceCharacter).gameObject.SetActive(true); } TryRunLocalRevive(_sourceCharacter); ResetCharacterFallState(_sourceCharacter, GetRestoreGroundPosition(position), grounded: true); ClearAssistJumpState(_sourceCharacter); RefreshCharacterAfflictionSceneState(_sourceCharacter, clearTransientCampfireAfflictions: true); SetCharacterPositionImmediate(_sourceCharacter, position, rotation); LiftCharacterBodyAbovePosition(_sourceCharacter, position); RestoreSourcePhysics(); ZeroCharacterBodyVelocity(_sourceCharacter, wake: true); SyncPhysicsTransforms(); Vector3 centerPosition = FinalizeRestoredSourcePosition(_sourceCharacter, position, rotation); ResetCharacterFallState(_sourceCharacter, GetRestoreGroundPosition(centerPosition), grounded: true); ZeroCharacterBodyVelocity(_sourceCharacter, wake: true); SyncPhysicsTransforms(); Vector3 center = _sourceCharacter.Center; Quaternion rotation2 = ((Component)_sourceCharacter).transform.rotation; SendSourceCharacterRestore(center, rotation2); RestoreSourceRenderers(((Component)_sourceCharacter).gameObject); RestoreCharacterHumanPresentation(_sourceCharacter, resetCamera: false); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Restored source character position: requested=" + FormatVector(position) + ", final=" + FormatVector(center) + ", ground=" + FormatVector(GetRestoreGroundPosition(center)) + ".")); } } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[I'm Zombie] Failed to restore source character: " + ex.Message)); } } finally { RestoreOriginalPlayerStatusProcessing(_sourceCharacter); _sourceStatusRestoredThisExit = true; } } private void SendSourceCharacterOutOfPlay(Vector3 stashPosition, Quaternion rotation) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) SendSourceCharacterStateRpc(stashPosition, "[I'm Zombie] Failed to move source character out of play: "); } private Vector3 FinalizeRestoredSourcePosition(Character character, Vector3 requestedPosition, Quaternion rotation) { //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) //IL_0012: 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_001d: 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_0025: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null) { return requestedPosition; } Vector3 center = character.Center; Vector3 val = ResolveSafeRestorePosition(IsFiniteVector(center) ? center : requestedPosition, _zombieCharacter, character, IsFiniteVector(requestedPosition) ? requestedPosition : _sourceStartPosition, 0.55f, logResult: false); if (IsFiniteVector(val)) { SetCharacterPositionImmediate(character, val, rotation); LiftCharacterBodyAbovePosition(character, val); return val; } if (!IsFiniteVector(center)) { return requestedPosition; } return center; } private static Vector3 GetRestoreGroundPosition(Vector3 centerPosition) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0008: Unknown result type (might be due to invalid IL or missing references) if (!IsFiniteVector(centerPosition)) { return centerPosition; } Vector3 result = centerPosition; result.y -= 1.35f; return result; } private static string FormatVector(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (!IsFiniteVector(value)) { return "(invalid)"; } return "(" + value.x.ToString("0.00", CultureInfo.InvariantCulture) + ", " + value.y.ToString("0.00", CultureInfo.InvariantCulture) + ", " + value.z.ToString("0.00", CultureInfo.InvariantCulture) + ")"; } private void SendSourceCharacterRestore(Vector3 restorePosition, Quaternion rotation) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) SendSourceCharacterStateRpc(restorePosition, "[I'm Zombie] Failed to restore source character over network: "); } private void SendSourceCharacterStateRpc(Vector3 position, string warningPrefix) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_sourceCharacter == (Object)null || (Object)(object)((MonoBehaviourPun)_sourceCharacter).photonView == (Object)null || (!PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode)) { return; } try { PhotonView photonView = ((MonoBehaviourPun)_sourceCharacter).photonView; photonView.RPC("RPCA_UnFall", (RpcTarget)1, Array.Empty()); photonView.RPC("RPCA_Revive", (RpcTarget)1, new object[1] { false }); photonView.RPC("WarpPlayerRPC", (RpcTarget)1, new object[2] { position, false }); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)(warningPrefix + ex.Message)); } } } private void SuspendSourcePhysics() { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_sourceCharacter == (Object)null || _sourceCharacter.refs?.ragdoll?.partList == null) { return; } try { if (!_sourcePhysicsSuspended) { _sourceBodypartPhysicsStates.Clear(); } foreach (Bodypart part in _sourceCharacter.refs.ragdoll.partList) { Rigidbody val = (((Object)(object)part != (Object)null) ? part.Rig : null); if (!((Object)(object)val == (Object)null)) { if (!_sourcePhysicsSuspended) { _sourceBodypartPhysicsStates.Add(new BodypartPhysicsState(val)); } if (!val.isKinematic) { val.linearVelocity = Vector3.zero; val.angularVelocity = Vector3.zero; } val.detectCollisions = false; val.useGravity = false; val.isKinematic = true; } } _sourcePhysicsSuspended = true; } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to suspend source physics: " + ex.Message)); } } } private void RestoreSourcePhysics() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (!_sourcePhysicsSuspended) { return; } try { foreach (BodypartPhysicsState sourceBodypartPhysicsState in _sourceBodypartPhysicsStates) { Rigidbody rig = sourceBodypartPhysicsState.Rig; if (!((Object)(object)rig == (Object)null)) { rig.isKinematic = sourceBodypartPhysicsState.IsKinematic; if (!rig.isKinematic) { rig.linearVelocity = Vector3.zero; rig.angularVelocity = Vector3.zero; } rig.detectCollisions = sourceBodypartPhysicsState.DetectCollisions; rig.useGravity = sourceBodypartPhysicsState.UseGravity; } } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to restore source physics: " + ex.Message)); } } finally { _sourceBodypartPhysicsStates.Clear(); _sourcePhysicsSuspended = false; } } private static void TryRunLocalRevive(Character character) { if ((Object)(object)character == (Object)null) { return; } try { InvokeCharacterUnFall(character); CharacterReviveRpcMethod?.Invoke(character, new object[1] { false }); } catch { } } private static void InvokeCharacterUnFall(Character character) { if (!((Object)(object)character == (Object)null) && !(CharacterUnFallRpcMethod == null)) { ParameterInfo[] parameters = CharacterUnFallRpcMethod.GetParameters(); object[] array = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { Type parameterType = parameters[i].ParameterType; array[i] = (parameterType.IsValueType ? Activator.CreateInstance(parameterType) : null); } CharacterUnFallRpcMethod.Invoke(character, array); } } private static void ResetCharacterFallState(Character character, Vector3 groundPosition, bool grounded) { //IL_00d7: 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_00e4: 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_011e: 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) if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null)) { character.data.dead = false; character.data.zombified = false; character.isZombie = false; character.data.passedOut = false; character.data.fullyPassedOut = false; character.data.fallSeconds = 0f; character.data.deathTimer = 0f; character.data.currentRagdollControll = 1f; character.data.isGrounded = grounded; character.data.isJumping = false; character.data.sinceGrounded = 0f; character.data.groundedFor = (grounded ? Mathf.Max(character.data.groundedFor, Time.fixedDeltaTime) : 0f); character.data.groundPos = groundPosition; character.data.lastGroundedHeight = character.Center.y; character.data.sinceJump = 0f; character.data.sinceFallSlide = 0f; character.data.avarageVelocity = Vector3.zero; character.data.avarageLastFrameVelocity = Vector3.zero; } } private static void ZeroCharacterBodyVelocity(Character character, bool wake) { //IL_006d: 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) if (character?.refs?.ragdoll?.partList == null) { return; } try { foreach (Bodypart part in character.refs.ragdoll.partList) { Rigidbody val = (((Object)(object)part != (Object)null) ? part.Rig : null); if (!((Object)(object)val == (Object)null)) { if (!val.isKinematic) { val.linearVelocity = Vector3.zero; val.angularVelocity = Vector3.zero; } if (wake) { val.WakeUp(); } } } } catch { } } private static void SyncPhysicsTransforms() { try { Physics.SyncTransforms(); } catch { } } private static void SetCharacterPositionImmediate(Character character, Vector3 position, Quaternion rotation) { //IL_0199: 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_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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0020: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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) //IL_002e: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013d: 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_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null) { return; } try { Transform transform = ((Component)character).transform; Vector3 center = character.Center; Quaternion rotation2 = transform.rotation; Quaternion val = rotation * Quaternion.Inverse(rotation2); Vector3 val2 = position - center; transform.SetPositionAndRotation(transform.position + val2, rotation); if (character.refs?.ragdoll?.partList == null) { return; } foreach (Bodypart part in character.refs.ragdoll.partList) { if ((Object)(object)part == (Object)null) { continue; } if ((Object)(object)part.Rig != (Object)null) { Vector3 position2 = part.Rig.position; part.Rig.position = position + val * (position2 - center); part.Rig.rotation = val * part.Rig.rotation; if (!part.Rig.isKinematic) { part.Rig.linearVelocity = Vector3.zero; part.Rig.angularVelocity = Vector3.zero; } } else { Vector3 position3 = ((Component)part).transform.position; ((Component)part).transform.position = position + val * (position3 - center); ((Component)part).transform.rotation = val * ((Component)part).transform.rotation; } } } catch { ((Component)character).transform.SetPositionAndRotation(position, rotation); } } private static void LiftCharacterBodyAbovePosition(Character character, Vector3 minimumBodyPosition) { //IL_0009: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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) if ((Object)(object)character == (Object)null || !IsFiniteVector(minimumBodyPosition) || !TryGetCharacterLowestY(character, out var lowestY)) { return; } float num = minimumBodyPosition.y - 1.35f + 0.18f - lowestY; if (!(num <= 0f) && !(num > 5f)) { TranslateCharacterImmediate(character, Vector3.up * num); if ((Object)(object)character.data != (Object)null) { CharacterData data = character.data; data.groundPos += Vector3.up * num; } LogVerbose("Lifted restored source character by " + num.ToString("0.00", CultureInfo.InvariantCulture) + " to keep body above restore position."); } } private static bool TryGetCharacterLowestY(Character character, out float lowestY) { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_0098: Unknown result type (might be due to invalid IL or missing references) lowestY = float.PositiveInfinity; bool flag = false; if ((Object)(object)character == (Object)null) { return false; } try { if (character.refs?.ragdoll?.partList != null) { foreach (Bodypart part in character.refs.ragdoll.partList) { if (!((Object)(object)part == (Object)null)) { Vector3 val = (((Object)(object)part.Rig != (Object)null) ? part.Rig.position : ((Component)part).transform.position); if (IsFiniteFloat(val.y)) { lowestY = Mathf.Min(lowestY, val.y); flag = true; } } } } Collider[] componentsInChildren = ((Component)character).GetComponentsInChildren(true); foreach (Collider val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !val2.isTrigger) { Bounds bounds = val2.bounds; float y = ((Bounds)(ref bounds)).min.y; if (IsFiniteFloat(y)) { lowestY = Mathf.Min(lowestY, y); flag = true; } } } } catch { } if (flag) { return IsFiniteFloat(lowestY); } return false; } private static void TranslateCharacterImmediate(Character character, Vector3 delta) { //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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_0028: 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) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: 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_009e: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null || !IsFiniteVector(delta) || ((Vector3)(ref delta)).sqrMagnitude <= 0f) { return; } try { Transform transform = ((Component)character).transform; transform.position += delta; if (character.refs?.ragdoll?.partList == null) { return; } foreach (Bodypart part in character.refs.ragdoll.partList) { if ((Object)(object)part == (Object)null) { continue; } if ((Object)(object)part.Rig != (Object)null) { Rigidbody rig = part.Rig; rig.position += delta; if (!part.Rig.isKinematic) { part.Rig.linearVelocity = Vector3.zero; part.Rig.angularVelocity = Vector3.zero; } } else { Transform transform2 = ((Component)part).transform; transform2.position += delta; } } } catch { Transform transform3 = ((Component)character).transform; transform3.position += delta; } } private void KeepZombieAwake() { RefreshCharacterAfflictionSceneState(_zombieCharacter); _zombie.lifetime = float.PositiveInfinity; _zombieCharacter.data.dead = false; _zombieCharacter.data.passedOut = false; _zombieCharacter.data.fullyPassedOut = false; _zombieCharacter.data.fallSeconds = 0f; _zombieCharacter.data.currentRagdollControll = 1f; float effectiveSprintStaminaRefill = GetEffectiveSprintStaminaRefill(); _zombieCharacter.data.currentStamina = effectiveSprintStaminaRefill; _zombieCharacter.data.extraStamina = effectiveSprintStaminaRefill; ClearAssistJumpState(_zombieCharacter); ResetDisabledInventoryState(_zombieCharacter.refs?.items, _zombieCharacter); } private void KeepSourceOutOfPlay() { //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0170: 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) if (!((Object)(object)_sourceCharacter == (Object)null)) { if ((Object)(object)_sourceCharacter == (Object)(object)Character.localCharacter && (Object)(object)_zombieCharacter != (Object)null) { Character.localCharacter = _zombieCharacter; } _sourceCharacter.data.dead = false; _sourceCharacter.data.zombified = false; _sourceCharacter.data.passedOut = false; _sourceCharacter.data.fullyPassedOut = false; _sourceCharacter.data.fallSeconds = 0f; _sourceCharacter.data.deathTimer = 0f; _sourceCharacter.data.isGrounded = true; _sourceCharacter.data.sinceGrounded = 0f; _sourceCharacter.data.groundedFor = Mathf.Max(_sourceCharacter.data.groundedFor, Time.fixedDeltaTime); PinSourceAtStashPosition(); Vector3 center = _sourceCharacter.Center; _sourceCharacter.data.groundPos = (IsFiniteVector(center) ? center : _sourceStartPosition); _sourceCharacter.data.lastGroundedHeight = _sourceCharacter.data.groundPos.y; _sourceCharacter.data.avarageVelocity = Vector3.zero; _sourceCharacter.data.avarageLastFrameVelocity = Vector3.zero; ClearAssistJumpState(_sourceCharacter); RefreshCharacterAfflictionSceneState(_sourceCharacter); HideSourceRenderers(((Component)_sourceCharacter).gameObject); SuspendSourcePhysics(); ZeroCharacterBodyVelocity(_sourceCharacter, wake: false); } } private void PinSourceAtStashPosition() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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) if (!((Object)(object)_sourceCharacter == (Object)null) && IsFiniteVector(_sourceStashPosition)) { Vector3 center = _sourceCharacter.Center; if (!IsFiniteVector(center) || Vector3.Distance(center, _sourceStashPosition) > 0.5f) { SetCharacterPositionImmediate(_sourceCharacter, _sourceStashPosition, ((Component)_sourceCharacter).transform.rotation); } } } private void SyncZombieState(State state, bool sprinting) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected I4, but got Unknown if (_state != SessionState.Active) { return; } PhotonView val = ResolveCharacterPhotonView(_zombieCharacter); if ((Object)(object)val == (Object)null && (Object)(object)_zombieObject != (Object)null) { try { val = _zombieObject.GetComponent(); } catch { val = null; } } if (HasNetworkView(val)) { val.RPC("RPC_SyncState", (RpcTarget)1, new object[4] { (int)state, sprinting, 0f, false }); } } } [CompilerGenerated] private sealed class d__366 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Plugin <>4__this; private Character 5__2; private bool 5__3; private GameObject 5__4; private ActiveZombieSession 5__5; private IEnumerator 5__6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__366(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__4 = null; 5__5 = null; 5__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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) //IL_00c5: 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) int num = <>1__state; Plugin plugin = <>4__this; MushroomZombie component; Character component2; switch (num) { default: return false; case 0: { <>1__state = -1; plugin._switching = true; plugin.SuppressExpensiveMaintenance(0.65f); if (plugin._session != null) { plugin.ExitZombieForm(restorePlayer: true); } 5__2 = Character.localCharacter; if (!CanTransform(5__2)) { plugin._enteringZombieForm = false; plugin._switching = false; return false; } plugin.SetConflictingZombieRebornPluginsSuppressed(suppress: true); Vector3 center = 5__2.Center; Quaternion spawnRotation = GetSpawnRotation(5__2); 5__3 = ((Component)5__2).gameObject.activeSelf; SetLocalSourceProxyCharacter(5__2); ForcePlayerCharacterLookup(5__2); 5__4 = CreateZombie(5__2, center, spawnRotation); RestoreLocalSourceProxyCharacterActive(); if ((Object)(object)5__4 == (Object)null) { ((BaseUnityPlugin)plugin).Logger.LogWarning((object)"[I'm Zombie] Could not create a MushroomZombie prefab."); ClearLocalSourceProxyCharacter(5__2); plugin.SetConflictingZombieRebornPluginsSuppressed(suppress: false); plugin._enteringZombieForm = false; plugin._switching = false; return false; } RestoreLocalSourceProxyCharacterActive(); component = 5__4.GetComponent(); component2 = 5__4.GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null) { <>2__current = null; <>1__state = 1; return true; } goto IL_017b; } case 1: <>1__state = -1; component = 5__4.GetComponent(); component2 = 5__4.GetComponent(); goto IL_017b; case 2: { <>1__state = -1; break; } IL_017b: if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null) { ((BaseUnityPlugin)plugin).Logger.LogWarning((object)"[I'm Zombie] Created object is missing MushroomZombie or Character."); DestroyZombieObject(5__4); ClearLocalSourceProxyCharacter(5__2); plugin.SetConflictingZombieRebornPluginsSuppressed(suppress: false); plugin._enteringZombieForm = false; plugin._switching = false; return false; } 5__5 = new ActiveZombieSession(5__2, 5__4, component, component2, 5__3); plugin._session = 5__5; try { 5__6 = 5__5.Enter(); } catch (Exception ex) { ((BaseUnityPlugin)plugin).Logger.LogWarning((object)("[I'm Zombie] Failed to start zombie form:\n" + ex)); 5__5.AbortEnter(); plugin._session = null; plugin.SetConflictingZombieRebornPluginsSuppressed(suppress: false); plugin._enteringZombieForm = false; plugin._switching = false; return false; } break; } object current; try { if (5__6.MoveNext()) { current = 5__6.Current; goto IL_02ce; } } catch (Exception ex2) { ((BaseUnityPlugin)plugin).Logger.LogWarning((object)("[I'm Zombie] Failed while entering zombie form:\n" + ex2)); 5__5.AbortEnter(); plugin._session = null; plugin.SetConflictingZombieRebornPluginsSuppressed(suppress: false); plugin._enteringZombieForm = false; plugin._switching = false; return false; } plugin._enteringZombieForm = false; plugin._switching = false; return false; IL_02ce: <>2__current = current; <>1__state = 2; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__754 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private Transform <>2__current; private int <>l__initialThreadId; private object menuInstance; public object <>3__menuInstance; private Type menuType; public Type <>3__menuType; Transform IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__754(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { object? obj2; Transform val2; switch (<>1__state) { default: return false; case 0: { <>1__state = -1; object obj = menuInstance; Component val = (Component)((obj is Component) ? obj : null); if (val != null) { <>2__current = val.transform; <>1__state = 1; return true; } goto IL_004d; } case 1: <>1__state = -1; goto IL_004d; case 2: { <>1__state = -1; break; } IL_004d: obj2 = menuType?.GetProperty("Content", InstanceBindingFlags)?.GetValue(menuInstance); val2 = (Transform)((obj2 is Transform) ? obj2 : null); if (val2 != null) { <>2__current = val2; <>1__state = 2; return true; } break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__754 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__754(0); } d__.menuInstance = <>3__menuInstance; d__.menuType = <>3__menuType; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__753 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private Transform <>2__current; private int <>l__initialThreadId; private object menuInstance; public object <>3__menuInstance; private Type menuType; public Type <>3__menuType; private HashSet 5__2; private IEnumerator <>7__wrap2; Transform IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__753(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__2 = null; <>7__wrap2 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = new HashSet(); <>7__wrap2 = EnumerateCandidateTransforms(menuInstance, menuType).GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } while (<>7__wrap2.MoveNext()) { Transform current = <>7__wrap2.Current; if ((Object)(object)current != (Object)null && 5__2.Add(((Object)current).GetInstanceID())) { <>2__current = current; <>1__state = 1; return true; } } <>m__Finally1(); <>7__wrap2 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap2 != null) { <>7__wrap2.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__753 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__753(0); } d__.menuInstance = <>3__menuInstance; d__.menuType = <>3__menuType; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__725 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private ConfigDefinition <>2__current; private int <>l__initialThreadId; private ConfigKey configKey; public ConfigKey <>3__configKey; private string 5__2; private string 5__3; private string 5__4; private string 5__5; ConfigDefinition IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__725(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__3 = null; 5__4 = null; 5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = GetConfigKeyName(configKey); 5__3 = GetKeyName(configKey, isChineseLanguage: true); 5__4 = GetConfigSectionName(configKey); 5__5 = GetSectionName(configKey, isChineseLanguage: true); <>2__current = new ConfigDefinition(5__4, 5__2); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = new ConfigDefinition(5__4, 5__3); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = new ConfigDefinition(5__5, 5__2); <>1__state = 3; return true; case 3: <>1__state = -1; <>2__current = new ConfigDefinition(5__5, 5__3); <>1__state = 4; return true; case 4: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__725 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__725(0); } d__.configKey = <>3__configKey; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__721 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private ConfigKey <>2__current; private int <>l__initialThreadId; ConfigKey IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__721(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = ConfigKey.MoveForwardKey; <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = ConfigKey.MoveBackwardKey; <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = ConfigKey.MoveLeftKey; <>1__state = 3; return true; case 3: <>1__state = -1; <>2__current = ConfigKey.MoveRightKey; <>1__state = 4; return true; case 4: <>1__state = -1; <>2__current = ConfigKey.JumpKey; <>1__state = 5; return true; case 5: <>1__state = -1; <>2__current = ConfigKey.SprintKey; <>1__state = 6; return true; case 6: <>1__state = -1; <>2__current = ConfigKey.ClimbKey; <>1__state = 7; return true; case 7: <>1__state = -1; <>2__current = ConfigKey.PounceKey; <>1__state = 8; return true; case 8: <>1__state = -1; <>2__current = ConfigKey.ChaseToggleKey; <>1__state = 9; return true; case 9: <>1__state = -1; <>2__current = ConfigKey.ViewToggleKey; <>1__state = 10; return true; case 10: <>1__state = -1; <>2__current = ConfigKey.PounceDuration; <>1__state = 11; return true; case 11: <>1__state = -1; <>2__current = ConfigKey.PounceCooldown; <>1__state = 12; return true; case 12: <>1__state = -1; <>2__current = ConfigKey.PounceForwardVelocity; <>1__state = 13; return true; case 13: <>1__state = -1; <>2__current = ConfigKey.PounceUpVelocity; <>1__state = 14; return true; case 14: <>1__state = -1; <>2__current = ConfigKey.PounceSfxEnabled; <>1__state = 15; return true; case 15: <>1__state = -1; <>2__current = ConfigKey.FirstPersonHeightOffset; <>1__state = 16; return true; case 16: <>1__state = -1; <>2__current = ConfigKey.StartInThirdPerson; <>1__state = 17; return true; case 17: <>1__state = -1; <>2__current = ConfigKey.RestoreAtZombiePosition; <>1__state = 18; return true; case 18: <>1__state = -1; <>2__current = ConfigKey.RestoreGroundOffset; <>1__state = 19; return true; case 19: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__721(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } public const string Id = "com.github.Thanks.ImZombie"; public const string Name = "I'm Zombie"; public const string Version = "0.0.4"; private const string PlayerZombieResourceName = "MushroomZombie_Player"; private const string OriginalPlayerResourceName = "Character"; private const string FallbackZombieResourceName = "MushroomZombie"; private const string NetworkSpawnMarker = "Thanks.ImZombie"; private const float ToggleDebounceSeconds = 0.35f; private const float ToggleHoldSeconds = 1f; private const float ZombieFaintTapMaxSeconds = 0.3f; private const int SimplifiedChineseLanguageIndex = 9; private const string ControlsConfigSectionName = "Controls"; private const string ZombieControlConfigSectionName = "Zombie Control"; private const string ThirdPersonCameraConfigSectionName = "Third Person Camera"; private const string OriginalPounceConfigSectionName = "Original Pounce"; private const string OriginalSfxConfigSectionName = "Original Zombie SFX"; private const string ZombieAppearanceConfigSectionName = "Zombie Appearance"; private const string PlayerRestoreConfigSectionName = "Player Restore"; private const string DiagnosticsConfigSectionName = "Diagnostics"; private const string ModConfigPluginGuid = "com.github.PEAKModding.PEAKLib.ModConfig"; private const string PeakStatsExPluginGuid = "com.github.LengSword.PeakStatsEx"; private const float ModConfigUiLocalizationIntervalSeconds = 0.25f; private const float CameraRestoreAssistSeconds = 1.5f; private const float PeakerGuardFallbackSeconds = 6f; private const float ThirdPartyCompatibilityRetryIntervalSeconds = 1f; private const float PrefabPoolWrapperRetryIntervalSeconds = 0.5f; private const float ThirdPartyStatusUiCleanupIntervalSeconds = 0.35f; private const float TransientAfflictionSceneRefreshIntervalSeconds = 0.35f; private const float TransientAfflictionSceneRefreshDurationSeconds = 15f; private const float GameplayAfflictionMaintenanceIntervalSeconds = 0.5f; private const float ZombieSessionResidualCleanupDurationSeconds = 4f; private const float ZombieSessionResidualCleanupIntervalSeconds = 0.25f; private const float ZombieTransformMaintenanceSuppressionSeconds = 0.65f; private const float ZombieRestoreMaintenanceSuppressionSeconds = 0.85f; private const float SceneTransitionMaintenanceSuppressionSeconds = 12f; private const float PostSpawnMaintenanceSuppressionSeconds = 1.5f; private const float StatusUiSuppressionDurationSeconds = 3f; private const float NativeAriseCoroutineSuppressionSeconds = 8f; private const float OldDefaultThirdPersonHeightOffset = 1.45f; private const float OldDefaultThirdPersonDistance = 4.2f; private const float DefaultThirdPersonHeightOffset = 0.85f; private const float DefaultThirdPersonDistance = 2.8f; private const float ThirdPersonCameraFollowSharpness = 18f; private const float ThirdPersonClimbCameraFollowSharpness = 7f; private const float ThirdPersonClimbCameraVerticalFollowSharpness = 2.4f; private const float ThirdPersonClimbCameraVerticalCatchupSharpness = 9f; private const float ThirdPersonClimbCameraVerticalCatchupDistance = 0.75f; private const float ThirdPersonClimbCameraVerticalDeadZone = 0.06f; private const float ThirdPersonCameraPositionSharpness = 16f; private const float ThirdPersonClimbCameraPositionSharpness = 8f; private const float ThirdPersonCameraRotationSharpness = 22f; private const float ThirdPersonClimbCameraRotationSharpness = 10f; private const float ThirdPersonCameraSnapDistance = 8f; private const float ThirdPersonClimbHeadTargetWeight = 0.25f; private const float ThirdPersonClimbMaxHeadTargetDistance = 3f; private const float ThirdPersonAttackHeightOffset = 0.45f; private const float ControlledClimbStartCooldownSeconds = 0.12f; private const float DefaultConfigMigrationTolerance = 0.001f; private const float ClearBoostReticleTimer = 10f; private const float ControlledZombieJumpVelocity = 8.5f; private const float RestoreGroundProbeUpDistance = 3f; private const float RestoreGroundProbeDownDistance = 24f; private const float RestoreGroundProbeExtendedUpDistance = 8f; private const float RestoreGroundProbeExtendedDownDistance = 72f; private const float MaxRestoreVerticalError = 8f; private const float MaxRestoreHorizontalError = 6f; private const float RestoreSafetyLift = 0.55f; private const float RestoreEmergencyLift = 1.15f; private const float RestoreAggressiveStateExtraLift = 0.45f; private const float MaxRestoreAnchorHorizontalDrift = 4f; private const float MaxRestoreAnchorVerticalDrift = 5f; private const float RestoreBodyBottomClearance = 0.18f; private const float MaxRestoreBodyLift = 5f; private const float MaxRestoreCachedAnchorHorizontalDrift = 8f; private const float MaxRestoreCachedAnchorVerticalDrift = 4f; private const float MaxUnsafeRestoreFallbackVerticalDrift = 10f; private const float RestoreGroundOffsetValue = 1.35f; internal const float MinSprintStaminaRefillValue = 1f; internal const float MaxSprintStaminaRefillValue = 3f; internal const float MinControlledJitterChanceValue = 0f; internal const float MaxControlledJitterChanceValue = 0.5f; internal const float MinControlledJitterIntensityValue = 0f; internal const float MaxControlledJitterIntensityValue = 2.5f; internal const float MinControlledJitterDurationValue = 0.05f; internal const float MaxControlledJitterDurationValue = 0.6f; internal const float MinThirdPersonHeightOffsetValue = 0.3f; internal const float MaxThirdPersonHeightOffsetValue = 1.8f; internal const float MinThirdPersonDistanceValue = 1.5f; internal const float MaxThirdPersonDistanceValue = 6f; internal const float MinSourceStashDistanceValue = 10f; internal const float MaxSourceStashDistanceValue = 2000f; private static readonly BindingFlags InstanceBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly BindingFlags StaticBindingFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static readonly PropertyInfo ConfigFileEntriesProperty = typeof(ConfigFile).GetProperty("Entries", InstanceBindingFlags); private static readonly PropertyInfo MainCameraSpecCharacterProperty = typeof(MainCameraMovement).GetProperty("specCharacter", StaticBindingFlags); private static readonly FieldInfo MainCameraIsSpectatingField = typeof(MainCameraMovement).GetField("isSpectating", InstanceBindingFlags); private static readonly FieldInfo MainCameraRagdollCamField = typeof(MainCameraMovement).GetField("ragdollCam", InstanceBindingFlags); private static readonly FieldInfo MainCameraCurrentForwardOffsetField = typeof(MainCameraMovement).GetField("currentForwardOffset", InstanceBindingFlags); private static readonly FieldInfo MainCameraTargetPlayerPovPositionField = typeof(MainCameraMovement).GetField("targetPlayerPovPosition", InstanceBindingFlags); private static readonly FieldInfo MainCameraPhysicsRotField = typeof(MainCameraMovement).GetField("physicsRot", InstanceBindingFlags); private static readonly FieldInfo MushroomZombieWearingSkirtField = typeof(MushroomZombie).GetField("wearingSkirt", InstanceBindingFlags); private static readonly FieldInfo MushroomZombieMushroomsGrowingField = typeof(MushroomZombie).GetField("mushroomsGrowing", InstanceBindingFlags); private static readonly FieldInfo MushroomZombieMushroomGrowTimesField = typeof(MushroomZombie).GetField("mushroomGrowTimes", InstanceBindingFlags); private static readonly FieldInfo MushroomZombieSpawnedFromCharacterField = typeof(MushroomZombie).GetField("spawnedFromCharacter", InstanceBindingFlags); private static readonly FieldInfo MushroomZombieCharacterField = typeof(MushroomZombie).GetField("character", InstanceBindingFlags); private static readonly FieldInfo MushroomZombieViewField = typeof(MushroomZombie).GetField("view", InstanceBindingFlags); private static readonly FieldInfo MushroomZombieSettingField = typeof(MushroomZombie).GetField("_setting", InstanceBindingFlags); private static readonly FieldInfo MushroomZombieCurrentStateField = typeof(MushroomZombie).GetField("_currentState", InstanceBindingFlags); private static readonly MethodInfo MushroomZombieSetOutfitMethod = typeof(MushroomZombie).GetMethod("RPC_SetOutfit", InstanceBindingFlags); private static readonly MethodInfo MushroomZombieSetZombieEyesMethod = typeof(MushroomZombie).GetMethod("SetZombieEyes", InstanceBindingFlags); private static readonly MethodInfo MushroomZombieSetMushroomManMethod = typeof(MushroomZombie).GetMethod("SetMushroomMan", InstanceBindingFlags); private static readonly MethodInfo MushroomZombieUpdateMushroomGrowthMethod = typeof(MushroomZombie).GetMethod("UpdateMushroomGrowth", InstanceBindingFlags); private static readonly PropertyInfo MushroomZombieIsMushroomManProperty = typeof(MushroomZombie).GetProperty("isMushroomMan", InstanceBindingFlags); private static readonly MethodInfo FindObjectsOfTypeByTypeMethod = typeof(Object).GetMethod("FindObjectsOfType", new Type[1] { typeof(Type) }); private static readonly PropertyInfo PlayerHandlerInstanceProperty = typeof(PlayerHandler).GetProperty("Instance", StaticBindingFlags); private static readonly FieldInfo PlayerHandlerCharacterLookupField = typeof(PlayerHandler).GetField("m_playerCharacterLookup", InstanceBindingFlags); private static readonly FieldInfo CharacterSpawnerHasSpawnedPlayerField = typeof(CharacterSpawner).GetField("hasSpawnedPlayer", InstanceBindingFlags); private static readonly FieldInfo CharacterItemsCurrentSelectedSlotField = typeof(CharacterItems).GetField("currentSelectedSlot", InstanceBindingFlags); private static readonly FieldInfo CharacterItemsLastSelectedSlotField = typeof(CharacterItems).GetField("lastSelectedSlot", InstanceBindingFlags); private static readonly FieldInfo CharacterViewField = typeof(Character).GetField("view", InstanceBindingFlags); private static readonly FieldInfo CharacterStartedField = typeof(Character).GetField("started", InstanceBindingFlags); private static readonly FieldInfo CharacterSmoothedCamPosField = typeof(Character).GetField("smoothedCamPos", InstanceBindingFlags); private static readonly MethodInfo CharacterUnFallRpcMethod = FindCharacterUnFallRpcMethod(); private static readonly MethodInfo CharacterReviveRpcMethod = typeof(Character).GetMethod("RPCA_Revive", InstanceBindingFlags, null, new Type[1] { typeof(bool) }, null); private static readonly MethodInfo CharacterZombieFailsafeMethod = typeof(Character).GetMethod("ZombieFailsafe", InstanceBindingFlags); private static readonly MethodInfo CharacterGetBodypartMethod = typeof(Character).GetMethod("GetBodypart", InstanceBindingFlags); private static readonly FieldInfo CharacterAfflictionsInAirportField = typeof(CharacterAfflictions).GetField("m_inAirport", InstanceBindingFlags); private static readonly FieldInfo CharacterDataCharacterField = typeof(CharacterData).GetField("character", InstanceBindingFlags); private static readonly FieldInfo CharacterCustomizationCharacterField = typeof(CharacterCustomization).GetField("_character", InstanceBindingFlags); private static readonly FieldInfo CustomizationRefsSkirtField = typeof(CustomizationRefs).GetField("skirt", InstanceBindingFlags); private static readonly FieldInfo CustomizationRefsShortsField = typeof(CustomizationRefs).GetField("shorts", InstanceBindingFlags); private static readonly MethodInfo CharacterClimbingCanClimbMethod = FindCharacterClimbingCanClimbMethod(); private static readonly MethodInfo CharacterClimbingStartClimbRpcMethod = FindCharacterClimbingStartClimbRpcMethod(); private static readonly FieldInfo CharacterClimbingClimbToggledOnField = typeof(CharacterClimbing).GetField("climbToggledOn", InstanceBindingFlags); private static readonly FieldInfo CharacterClimbingSinceLastClimbStartedField = typeof(CharacterClimbing).GetField("sinceLastClimbStarted", InstanceBindingFlags); private static readonly FieldInfo CharacterClimbingPlayerSlideField = typeof(CharacterClimbing).GetField("playerSlide", InstanceBindingFlags); private static readonly object CharacterItemsNoneSlotValue = CreateOptionableNoneValue(CharacterItemsCurrentSelectedSlotField?.FieldType); private static FieldInfo PeakStatsStaminaBarsField; private static FieldInfo PeakStatsObservedCharacterField; private static FieldInfo PeakStatsAfflictionBarField; private static Type PeakStatsStaminaBarType; private static Type PeakStatsAfflictionType; private static float _peakStatsCleanupGraceUntil; private static readonly Dictionary _nativeAriseSuppressedSourceViewIdCounts = new Dictionary(); private static readonly Dictionary _nativeAriseSuppressionUntilByViewId = new Dictionary(); private static readonly HashSet _loggedSuppressedAriseSourceViewIds = new HashSet(); private static readonly HashSet _loggedSuppressedPhotonDestroyViewIds = new HashSet(); private static readonly HashSet _loggedSuppressedUnityDestroyIds = new HashSet(); private static readonly HashSet _loggedSuppressedSetActiveIds = new HashSet(); private static readonly HashSet _loggedSkippedCharacterRegistrationIds = new HashSet(); private static int _controlledZombieDestroyDepth; private static int _runtimePrefabBackupCreationDepth; private static readonly HashSet _thirdPartyStatusPatchedMethods = new HashSet(); private static readonly Dictionary _thirdPartyStatusFieldCache = new Dictionary(); private static readonly Dictionary _thirdPartyStatusPropertyCache = new Dictionary(); private static bool _skipControlledCharacterFixedUpdate = true; private bool _characterFixedUpdateCompatibilityConfigured; private bool _loggedWaitingForPeakerHook; private float _nextPeakerGuardAttemptTime; private bool _peakStatsCompatibilityConfigured; private bool _thirdPartyStatusCompatibilityConfigured; private bool _mikuDanceCompatibilityConfigured; private float _nextThirdPartyCompatibilityAttemptTime; private float _nextThirdPartyStatusUiCleanupTime; private float _nextHumanPresentationMaintenanceTime; private readonly Harmony _harmony = new Harmony("com.github.Thanks.ImZombie"); private ActiveZombieSession _session; private bool _switching; private bool _enteringZombieForm; private float _lastToggleTime; private bool _toggleKeyReleasedSinceEnter = true; private float _toggleKeyHoldStartTime = -1f; private bool _toggleKeyHoldConsumed; private bool _lastDetectedChineseLanguage; private bool _isRefreshingLanguage; private bool _pendingConfigFileLocalizationRefresh; private bool _pendingConfigFileLocalizationSave; private float _nextModConfigUiLocalizationTime; private static Transform _controlledZombieCreationRoot; private static int _controlledZombieNetworkCreationDepth; private static string _controlledZombieNetworkCreationResourceName; private static readonly HashSet _controlledZombieInstanceIds = new HashSet(); private static readonly HashSet _controlledZombieViewIds = new HashSet(); private static readonly HashSet _controlledZombieCharacterInstanceIds = new HashSet(); private static readonly HashSet _localMushroomGrowthInitializedZombieIds = new HashSet(); private static readonly Dictionary _knownPhotonPrefabCache = new Dictionary(); private static readonly Dictionary _runtimeNetworkPrefabBackups = new Dictionary(); private static GameObject _originalPlayerCharacterPrefabBackup; private static readonly Dictionary _controlledZombieSourceViewIdsByViewId = new Dictionary(); private static readonly Dictionary _controlledClimbStartCooldownUntil = new Dictionary(); private static readonly HashSet _stashedSourceCharacterIds = new HashSet(); private static readonly Dictionary _statusUiSuppressedCharacterUntilById = new Dictionary(); private static int _controlledZombieOriginalBehaviorDepth; private static readonly Dictionary _rendererVisualStates = new Dictionary(); private static readonly Dictionary _sourceRendererVisualStates = new Dictionary(); private readonly Dictionary _temporarilyDisabledConflictingPluginStates = new Dictionary(); private static Character _cameraOverrideCharacter; private static Character _localSourceProxyCharacter; private static int _localSourceProxyActorNumber = -1; private static float _nextDuplicateSpawnSuppressionLogTime; private static Character _cameraRestoreCharacter; private static float _cameraRestoreUntil; private static GameObject _viewZombieObject; private static GameObject _hudCanvasObject; private static GameObject _namesCanvasObject; private static bool _hudHiddenForZombie; private static bool _hudPreviousActive; private static bool _namesPreviousActive; private static bool _hudPreviousKnown; private static bool _namesPreviousKnown; private static int _smoothedThirdPersonCharacterId = -1; private static readonly Dictionary _hudChildPreviousActiveStates = new Dictionary(); private static bool _hasSmoothedThirdPersonCameraTarget; private static Vector3 _smoothedThirdPersonCameraTarget; private static bool _hasSmoothedThirdPersonCameraPose; private static Vector3 _smoothedThirdPersonCameraPosition; private static Quaternion _smoothedThirdPersonCameraRotation = Quaternion.identity; private static ImZombiePrefabPool _prefabPoolWrapper; private static float _nextPrefabPoolWrapperEnsureTime; private bool _preferOriginalLocalSpawnAfterSceneLoad; private float _preferOriginalLocalSpawnUntil; private float _expensiveMaintenanceSuppressedUntil; private float _transientAfflictionSceneRefreshUntil; private float _nextTransientAfflictionSceneRefreshTime; private float _nextGameplayAfflictionMaintenanceTime; private float _localZombieSessionResidualCleanupUntil; private float _nextLocalZombieSessionResidualCleanupTime; private static float _nextStatusProcessingRestoreLogTime; private bool _pendingThirdPartyStatusUiCleanup; private bool _pendingThirdPartyStatusUiCleanupAggressive; private float _lastEnterZombieAttemptTime = -100f; private string _lastObservedSceneName; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } internal static ConfigEntry ToggleKey { get; private set; } internal static ConfigEntry MoveForwardKey { get; private set; } internal static ConfigEntry MoveBackwardKey { get; private set; } internal static ConfigEntry MoveLeftKey { get; private set; } internal static ConfigEntry MoveRightKey { get; private set; } internal static ConfigEntry JumpKey { get; private set; } internal static ConfigEntry SprintKey { get; private set; } internal static ConfigEntry ClimbKey { get; private set; } internal static ConfigEntry PounceKey { get; private set; } internal static ConfigEntry ChaseToggleKey { get; private set; } internal static ConfigEntry ZombieMushroomAppearance { get; private set; } internal static ConfigEntry SprintStaminaRefill { get; private set; } internal static ConfigEntry ControlledJitterChance { get; private set; } internal static ConfigEntry ControlledJitterIntensity { get; private set; } internal static ConfigEntry ControlledJitterDuration { get; private set; } internal static ConfigEntry SourceStashDistance { get; private set; } internal static ConfigEntry VerboseLogs { get; private set; } internal static ConfigEntry ViewToggleKey { get; private set; } internal static ConfigEntry FirstPersonHeightOffset { get; private set; } internal static ConfigEntry ThirdPersonHeightOffset { get; private set; } internal static ConfigEntry ThirdPersonDistance { get; private set; } internal static ConfigEntry StartInThirdPerson { get; private set; } private void Awake() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; _lastDetectedChineseLanguage = DetectChineseLanguage(); BindConfig(_lastDetectedChineseLanguage); RegisterConfigChangeHandlers(); MarkConfigFileLocalizationDirty(saveConfigFile: true); _harmony.PatchAll(typeof(ZombieHarmonyPatches).Assembly); EnsureImZombiePrefabPoolWrapper(); ConfigureCharacterFixedUpdateCompatibility(); ConfigureThirdPartyCompatibility(); Scene activeScene = SceneManager.GetActiveScene(); _lastObservedSceneName = ((Scene)(ref activeScene)).name ?? string.Empty; SceneManager.sceneLoaded += OnSceneLoaded; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[I'm Zombie] Config language: " + BuildLanguageDetectionSummary(_lastDetectedChineseLanguage))); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[I'm Zombie] Loaded version 0.0.4."); } private void OnDestroy() { try { ExitZombieForm(restorePlayer: true); RestorePhotonPrefabPoolWrapper(); SceneManager.sceneLoaded -= OnSceneLoaded; UnregisterConfigChangeHandlers(); _harmony.UnpatchSelf(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] Cleanup failed: " + ex.Message)); } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { string sceneName = ((Scene)(ref scene)).name ?? string.Empty; HandleObservedScene(sceneName, "scene loaded"); } private void PollActiveSceneForTransition() { //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) try { Scene activeScene = SceneManager.GetActiveScene(); string text = ((Scene)(ref activeScene)).name ?? string.Empty; if (!string.Equals(text, _lastObservedSceneName, StringComparison.Ordinal)) { HandleObservedScene(text, "active scene changed"); } } catch { } } private void HandleObservedScene(string sceneName, string reason) { _lastObservedSceneName = sceneName ?? string.Empty; EnsureImZombiePrefabPoolWrapper(); bool num = IsGameplaySceneName(_lastObservedSceneName); RefreshKnownCharacterAfflictionSceneState(num); if (num) { SuppressExpensiveMaintenance(12f); BeginTransientAfflictionSceneRefreshWindow(); _preferOriginalLocalSpawnAfterSceneLoad = true; _preferOriginalLocalSpawnUntil = Time.unscaledTime + 12f; EndZombieSessionForSceneTransition(reason + ": " + _lastObservedSceneName); ClearManagedCharacterTrackingForSceneTransition(); } else { SuppressExpensiveMaintenance(1f); _transientAfflictionSceneRefreshUntil = 0f; _nextTransientAfflictionSceneRefreshTime = 0f; } PreparePlayerRegistryForOriginalLocalSpawn(reason + ": " + _lastObservedSceneName); RefreshKnownCharacterAfflictionSceneState(num); } private void BeginTransientAfflictionSceneRefreshWindow() { float num = Time.unscaledTime + 15f; _transientAfflictionSceneRefreshUntil = Mathf.Max(_transientAfflictionSceneRefreshUntil, num); _nextTransientAfflictionSceneRefreshTime = 0f; } private void MaintainTransientAfflictionSceneState() { //IL_000e: 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) if (!(_transientAfflictionSceneRefreshUntil <= 0f)) { Scene activeScene = SceneManager.GetActiveScene(); if (!IsGameplaySceneName(((Scene)(ref activeScene)).name ?? string.Empty)) { _transientAfflictionSceneRefreshUntil = 0f; _nextTransientAfflictionSceneRefreshTime = 0f; } else if (Time.unscaledTime > _transientAfflictionSceneRefreshUntil) { _transientAfflictionSceneRefreshUntil = 0f; _nextTransientAfflictionSceneRefreshTime = 0f; } else if (!(Time.unscaledTime < _nextTransientAfflictionSceneRefreshTime)) { _nextTransientAfflictionSceneRefreshTime = Time.unscaledTime + 0.35f; RefreshKnownCharacterAfflictionSceneState(clearTransientCampfireAfflictions: true); } } } private void MaintainGameplayAfflictionState() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!(Time.unscaledTime < _nextGameplayAfflictionMaintenanceTime)) { _nextGameplayAfflictionMaintenanceTime = Time.unscaledTime + 0.5f; Scene activeScene = SceneManager.GetActiveScene(); if (IsGameplaySceneName(((Scene)(ref activeScene)).name ?? string.Empty)) { MaintainRestoredLocalPlayerStatusProcessing(); RefreshKnownCharacterAfflictionSceneState(clearTransientCampfireAfflictions: true); } } } private void BeginLocalZombieSessionResidualCleanupWindow() { float num = Time.unscaledTime + 4f; _localZombieSessionResidualCleanupUntil = Mathf.Max(_localZombieSessionResidualCleanupUntil, num); _nextLocalZombieSessionResidualCleanupTime = 0f; } private void MaintainLocalZombieSessionResidualCleanup() { if (_session == null && !_switching && !(_localZombieSessionResidualCleanupUntil <= 0f)) { if (Time.unscaledTime > _localZombieSessionResidualCleanupUntil) { _localZombieSessionResidualCleanupUntil = 0f; _nextLocalZombieSessionResidualCleanupTime = 0f; } else if (!(Time.unscaledTime < _nextLocalZombieSessionResidualCleanupTime)) { _nextLocalZombieSessionResidualCleanupTime = Time.unscaledTime + 0.25f; RestoreLocalPlayerAfterZombieResiduals(); } } } private static void RestoreLocalPlayerAfterZombieResiduals() { Character sourceCharacter = Character.localCharacter; if ((Object)(object)sourceCharacter == (Object)null || IsImZombieManagedCharacter(sourceCharacter)) { Player localPlayer = Player.localPlayer; object photonPlayer; if (localPlayer == null) { photonPlayer = null; } else { PhotonView photonView = ((MonoBehaviourPun)localPlayer).photonView; photonPlayer = ((photonView != null) ? photonView.Owner : null); } if (!TryFindOriginalCharacterForPhotonPlayer((Player)photonPlayer, out sourceCharacter) && !TryGetStableLocalCharacter(out sourceCharacter)) { return; } } if (!((Object)(object)sourceCharacter == (Object)null) && !IsImZombieManagedCharacter(sourceCharacter)) { RestoreOriginalPlayerStatusProcessing(sourceCharacter); if ((Object)(object)_cameraOverrideCharacter != (Object)null && !IsImZombieManagedCharacter(_cameraOverrideCharacter)) { ClearCameraOverride(); } RestoreHudAfterZombie(); ForceClearSpectatorState(); } } private static void MaintainRestoredLocalPlayerStatusProcessing() { Plugin instance = Instance; if ((instance != null && (instance._session?.IsActive).GetValueOrDefault()) || (Object)(object)Player.localPlayer == (Object)null) { return; } Character sourceCharacter = Character.localCharacter; if ((Object)(object)sourceCharacter == (Object)null || IsImZombieManagedCharacter(sourceCharacter)) { PhotonView photonView = ((MonoBehaviourPun)Player.localPlayer).photonView; Player photonPlayer = ((photonView != null) ? photonView.Owner : null); if (!TryGetStableSourceCharacterForPhotonPlayer(photonPlayer, out sourceCharacter) && !TryFindOriginalCharacterForPhotonPlayer(photonPlayer, out sourceCharacter)) { return; } } if (!((Object)(object)sourceCharacter == (Object)null) && !IsImZombieManagedCharacter(sourceCharacter)) { if (ShouldMaintainOriginalLocalPlayerStatusProcessing(sourceCharacter) && TryGetCharacterAfflictions(sourceCharacter, out var afflictions)) { EnsureCharacterAfflictionsRuntime(sourceCharacter, afflictions); CharacterAfflictionsInAirportField?.SetValue(afflictions, IsCurrentSceneAirport()); } if (IsStashedSourceCharacter(sourceCharacter) || (Object)(object)sourceCharacter != (Object)(object)Character.localCharacter || sourceCharacter.isZombie || ((Object)(object)sourceCharacter.data != (Object)null && sourceCharacter.data.zombified)) { RestoreOriginalPlayerStatusProcessing(sourceCharacter); } else { RefreshCharacterAfflictionSceneState(sourceCharacter, clearTransientCampfireAfflictions: true); } } } private static bool ShouldMaintainOriginalLocalPlayerStatusProcessing(Character character) { if ((Object)(object)character == (Object)null || IsImZombieManagedCharacter(character)) { return false; } try { return (Object)(object)Player.localPlayer != (Object)null && (Object)(object)((MonoBehaviourPun)Player.localPlayer).photonView != (Object)null && IsSamePhotonOwner(character, ((MonoBehaviourPun)Player.localPlayer).photonView.Owner); } catch { return (Object)(object)character == (Object)(object)Character.localCharacter; } } private static bool TryGetCharacterAfflictions(Character character, out CharacterAfflictions afflictions) { afflictions = null; if ((Object)(object)character == (Object)null) { return false; } try { afflictions = character.refs?.afflictions ?? ((Component)character).GetComponent(); return (Object)(object)afflictions != (Object)null; } catch { afflictions = null; return false; } } private void ConfigureCharacterFixedUpdateCompatibility() { //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown if (_characterFixedUpdateCompatibilityConfigured) { return; } try { Type type = FindLoadedType("PEAKER.Testing"); if (type == null) { if (Time.unscaledTime >= 6f) { _skipControlledCharacterFixedUpdate = false; _characterFixedUpdateCompatibilityConfigured = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)"[I'm Zombie] PEAKER ragdoll hook was not found after startup; enabling controlled zombie Character.FixedUpdate fallback."); return; } _skipControlledCharacterFixedUpdate = true; if (!_loggedWaitingForPeakerHook) { _loggedWaitingForPeakerHook = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[I'm Zombie] Waiting for PEAKER ragdoll hook before enabling controlled zombie Character.FixedUpdate."); } return; } MethodInfo method = type.GetMethod("PostCharacterGetTargetRagdollControll", StaticBindingFlags, null, new Type[2] { typeof(CharacterData), typeof(float).MakeByRefType() }, null); MethodInfo methodInfo = AccessTools.Method(typeof(Plugin), "PeakerRagdollControlPostfixPrefix", (Type[])null, (Type[])null); if (method == null || methodInfo == null) { _skipControlledCharacterFixedUpdate = false; _characterFixedUpdateCompatibilityConfigured = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)"[I'm Zombie] Could not install PEAKER ragdoll guard; enabling controlled zombie Character.FixedUpdate fallback."); } else { _harmony.Patch((MethodBase)method, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _skipControlledCharacterFixedUpdate = false; _characterFixedUpdateCompatibilityConfigured = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[I'm Zombie] Installed PEAKER ragdoll guard; controlled zombie Character.FixedUpdate enabled."); } } catch (Exception ex) { if (Time.unscaledTime >= 6f) { _skipControlledCharacterFixedUpdate = false; _characterFixedUpdateCompatibilityConfigured = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] Failed to install PEAKER ragdoll guard; enabling controlled zombie Character.FixedUpdate fallback: " + ex.Message)); } else { _skipControlledCharacterFixedUpdate = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] Failed to install PEAKER ragdoll guard; will retry briefly while keeping controlled zombie Character.FixedUpdate isolated: " + ex.Message)); } } } private static Type FindLoadedType(string fullName) { if (string.IsNullOrEmpty(fullName)) { return null; } try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(fullName, throwOnError: false); if (type != null) { return type; } } } catch { } return null; } private static MethodInfo FindMethod(Type type, string name, bool preferStatic, params Type[] parameterTypes) { if (type == null || string.IsNullOrEmpty(name)) { return null; } BindingFlags bindingAttr = BindingFlags.Public | BindingFlags.NonPublic | (preferStatic ? BindingFlags.Static : BindingFlags.Instance); try { MethodInfo method = type.GetMethod(name, bindingAttr, null, parameterTypes ?? Type.EmptyTypes, null); if (method != null) { return method; } } catch { } try { MethodInfo[] methods = type.GetMethods(bindingAttr); foreach (MethodInfo methodInfo in methods) { if (methodInfo == null || methodInfo.Name != name) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); int num = ((parameterTypes != null) ? parameterTypes.Length : 0); if (parameters.Length != num) { continue; } bool flag = true; for (int j = 0; j < num; j++) { Type type2 = parameterTypes[j]; Type parameterType = parameters[j].ParameterType; if (!(type2 == null) && !(parameterType == type2) && !string.Equals(parameterType.FullName, type2.FullName, StringComparison.Ordinal)) { flag = false; break; } } if (flag) { return methodInfo; } } } catch { } return null; } private static bool PeakerRagdollControlPostfixPrefix([HarmonyArgument("__instance")] CharacterData data, [HarmonyArgument("__result")] ref float ragdollControl) { try { Character character = (Character)((CharacterDataCharacterField != null) ? /*isinst with value type is only supported in some contexts*/: null); if (IsLocallyControlledZombieCharacter(character) || IsStashedSourceCharacter(character)) { ragdollControl = 1f; return false; } } catch { } return true; } private void Update() { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) PollActiveSceneForTransition(); MaintainLocalZombieSessionResidualCleanup(); MaintainTransientAfflictionSceneState(); MaintainGameplayAfflictionState(); if (Time.unscaledTime >= _nextPrefabPoolWrapperEnsureTime) { _nextPrefabPoolWrapperEnsureTime = Time.unscaledTime + 0.5f; EnsureImZombiePrefabPoolWrapper(); } if (!_characterFixedUpdateCompatibilityConfigured && Time.unscaledTime >= _nextPeakerGuardAttemptTime) { _nextPeakerGuardAttemptTime = Time.unscaledTime + 0.5f; ConfigureCharacterFixedUpdateCompatibility(); } if ((!_peakStatsCompatibilityConfigured || !_thirdPartyStatusCompatibilityConfigured || !_mikuDanceCompatibilityConfigured) && Time.unscaledTime >= _nextThirdPartyCompatibilityAttemptTime) { _nextThirdPartyCompatibilityAttemptTime = Time.unscaledTime + 1f; ConfigureThirdPartyCompatibility(); } HandleLanguageChangeIfNeeded(); HandlePendingConfigFileLocalizationRefresh(); bool num = IsExpensiveMaintenanceSuppressed(); if (!num) { TryLocalizeVisibleModConfigUiThrottled(); } if ((int)ToggleKey.Value == 0 || !Input.GetKey(ToggleKey.Value)) { if (_toggleKeyHoldStartTime >= 0f && !_toggleKeyHoldConsumed && _toggleKeyReleasedSinceEnter) { float num2 = Time.unscaledTime - _toggleKeyHoldStartTime; if (num2 > 0f && num2 < 0.3f) { ActiveZombieSession session = _session; if (session != null && session.IsActive && Time.unscaledTime - _lastToggleTime >= 0.35f) { _lastToggleTime = Time.unscaledTime; TriggerControlledZombieFaint(); } } } _toggleKeyReleasedSinceEnter = true; _toggleKeyHoldStartTime = -1f; _toggleKeyHoldConsumed = false; } else { if (_toggleKeyHoldStartTime < 0f) { _toggleKeyHoldStartTime = Time.unscaledTime; } if (!_toggleKeyHoldConsumed && _toggleKeyReleasedSinceEnter && Time.unscaledTime - _toggleKeyHoldStartTime >= 1f && Time.unscaledTime - _lastToggleTime >= 0.35f) { _toggleKeyReleasedSinceEnter = false; _toggleKeyHoldConsumed = true; _lastToggleTime = Time.unscaledTime; ToggleZombieForm(); } } _session?.Tick(); MaintainThirdPartyStatusUi(); if (!num) { MaintainLocalHumanPresentation(); } } private void TriggerControlledZombieFaint() { if (_session != null) { _session.TryTriggerFaint(); } } private void ConfigureThirdPartyCompatibility() { //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Expected O, but got Unknown //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Expected O, but got Unknown //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Expected O, but got Unknown if (_peakStatsCompatibilityConfigured && _thirdPartyStatusCompatibilityConfigured && _mikuDanceCompatibilityConfigured) { return; } if (!_mikuDanceCompatibilityConfigured) { _mikuDanceCompatibilityConfigured = ConfigureMikuDanceCompatibility(); } if (!_thirdPartyStatusCompatibilityConfigured) { _thirdPartyStatusCompatibilityConfigured = ConfigureGenericThirdPartyStatusCompatibility(); } if (_peakStatsCompatibilityConfigured) { return; } try { if (IsPeakStatsExPluginLoaded()) { _peakStatsCompatibilityConfigured = true; LogVerbose("[I'm Zombie] PeakStatsEx is using the generic status guard; skipping legacy PeakStats type probe."); return; } Type type = FindLoadedType("PeakStats.MonoBehaviours.ProximityStaminaManager"); Type type2 = FindLoadedType("PeakStats.MonoBehaviours.CharacterStaminaBar"); Type type3 = FindLoadedType("PeakStats.MonoBehaviours.CharacterBarAffliction"); if (type == null || type2 == null || type3 == null) { LogVerbose("[I'm Zombie] PeakStats types not found yet, will retry. ProximityManager=" + (type != null) + " StaminaBar=" + (type2 != null) + " BarAffliction=" + (type3 != null)); return; } MethodInfo methodInfo = FindMethod(type, "Update", preferStatic: false, Type.EmptyTypes); MethodInfo methodInfo2 = FindMethod(type2, "Update", preferStatic: false, Type.EmptyTypes); MethodInfo methodInfo3 = FindMethod(type3, "FetchReferences", preferStatic: false, Type.EmptyTypes); FieldInfo field = type.GetField("staminaBars", InstanceBindingFlags); FieldInfo field2 = type2.GetField("_observedCharacter", InstanceBindingFlags); FieldInfo field3 = type3.GetField("characterStaminaBar", InstanceBindingFlags); MethodInfo methodInfo4 = AccessTools.Method(typeof(Plugin), "PeakStatsProximityManagerUpdatePrefix", (Type[])null, (Type[])null); MethodInfo methodInfo5 = AccessTools.Method(typeof(Plugin), "PeakStatsCharacterStaminaBarUpdatePrefix", (Type[])null, (Type[])null); MethodInfo methodInfo6 = AccessTools.Method(typeof(Plugin), "PeakStatsCharacterBarAfflictionFetchReferencesPrefix", (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null || methodInfo3 == null || field == null || field2 == null || field3 == null || methodInfo4 == null || methodInfo5 == null || methodInfo6 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] PeakStats types found but some members missing. Update=" + (methodInfo != null) + " StaminaBarUpdate=" + (methodInfo2 != null) + " FetchReferences=" + (methodInfo3 != null) + " staminaBars=" + (field != null) + " _observedCharacter=" + (field2 != null) + " characterStaminaBar=" + (field3 != null) + " prunePrefix=" + (methodInfo4 != null))); } else { PeakStatsStaminaBarsField = field; PeakStatsObservedCharacterField = field2; PeakStatsAfflictionBarField = field3; PeakStatsStaminaBarType = type2; PeakStatsAfflictionType = type3; _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(methodInfo5), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(methodInfo6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); RequestThirdPartyStatusUiCleanup(); _peakStatsCompatibilityConfigured = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[I'm Zombie] Installed PeakStats compatibility guard for controlled zombies."); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] Failed to install PeakStats compatibility guard: " + ex.Message)); } } private bool ConfigureMikuDanceCompatibility() { //IL_0137: 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_014b: Expected O, but got Unknown //IL_014b: Expected O, but got Unknown try { Type type = FindLoadedType("MikuDanceProject.Runtime.DanceController"); if (type == null) { return false; } Type type2 = typeof(Transform).MakeByRefType(); MethodInfo methodInfo = FindMethod(type, "TryExtractTransform", true, typeof(object), type2) ?? FindMethod(type, "TryExtractTransform", false, typeof(object), type2); MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), "MikuDanceTryExtractTransformPrefix", (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(typeof(Plugin), "MikuDanceTryExtractTransformFinalizer", (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null || methodInfo3 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] MikuDance compatibility target not found. TryExtractTransform=" + (methodInfo != null) + " Prefix=" + (methodInfo2 != null) + " Finalizer=" + (methodInfo3 != null))); return true; } _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo3), (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[I'm Zombie] Installed MikuDance transform safety guard for controlled zombie sessions."); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] Failed to install MikuDance compatibility guard: " + ex.Message)); return false; } } private bool ConfigureGenericThirdPartyStatusCompatibility() { //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_0125: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(typeof(Plugin), "ThirdPartyStatusMethodPrefix", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), "ThirdPartyStatusMethodFinalizer", (Type[])null, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[I'm Zombie] Could not find generic third-party status bar guard prefix."); return true; } if (methodInfo2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[I'm Zombie] Could not find generic third-party status bar guard finalizer."); return true; } int num = 0; int num2 = 0; bool flag = IsPeakStatsExPluginLoaded(); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (!IsThirdPartyStatusAssemblyCandidate(assembly)) { continue; } Type[] loadableTypes = GetLoadableTypes(assembly); foreach (Type type in loadableTypes) { if (!IsLikelyThirdPartyStatusUiType(type)) { continue; } num++; MethodInfo[] methods; try { methods = type.GetMethods(InstanceBindingFlags | StaticBindingFlags | BindingFlags.DeclaredOnly); } catch { continue; } foreach (MethodInfo methodInfo3 in methods) { if (ShouldPatchThirdPartyStatusMethod(methodInfo3) && _thirdPartyStatusPatchedMethods.Add(methodInfo3)) { try { _harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null); num2++; } catch { _thirdPartyStatusPatchedMethods.Remove(methodInfo3); } } } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("[I'm Zombie] Installed generic status bar guard. CandidateTypes=" + num.ToString(CultureInfo.InvariantCulture) + " PatchedMethods=" + num2.ToString(CultureInfo.InvariantCulture) + ".")); if (flag) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[I'm Zombie] PeakStatsEx detected; enabled reinforced status bar protection."); } return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] Failed to install generic status bar guard: " + ex.Message)); return false; } } private static Type[] GetLoadableTypes(Assembly assembly) { if (assembly == null) { return Array.Empty(); } try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { List list = new List(); Type[] types = ex.Types; if (types != null) { for (int i = 0; i < types.Length; i++) { if (types[i] != null) { list.Add(types[i]); } } } return list.ToArray(); } catch { return Array.Empty(); } } private static bool IsThirdPartyStatusAssemblyCandidate(Assembly assembly) { if (assembly == null || assembly == typeof(Plugin).Assembly) { return false; } string name; try { name = assembly.GetName().Name; } catch { return false; } if (string.IsNullOrEmpty(name)) { return false; } switch (name) { default: if (!name.StartsWith("System", StringComparison.Ordinal) && !name.StartsWith("Unity", StringComparison.Ordinal) && !name.StartsWith("BepInEx", StringComparison.Ordinal) && !name.StartsWith("Photon", StringComparison.Ordinal) && !name.StartsWith("Mono.", StringComparison.Ordinal)) { return true; } goto case "Assembly-CSharp"; case "Assembly-CSharp": case "mscorlib": case "netstandard": case "0Harmony": return false; } } private static bool ShouldPatchThirdPartyStatusMethod(MethodInfo method) { if (method == null || method.IsAbstract || method.ContainsGenericParameters) { return false; } if (method.IsSpecialName && !method.Name.StartsWith("set_", StringComparison.Ordinal)) { return false; } ParameterInfo[] parameters; try { parameters = method.GetParameters(); } catch { return false; } if (parameters == null || parameters.Length == 0) { return ShouldPatchZeroArgumentThirdPartyStatusMethod(method); } for (int i = 0; i < parameters.Length; i++) { Type type = parameters[i].ParameterType; if (type != null && type.IsByRef) { type = type.GetElementType(); } if (!(type == null) && (typeof(Character).IsAssignableFrom(type) || IsLikelyThirdPartyStatusUiType(type))) { return true; } } return false; } private static bool ShouldPatchZeroArgumentThirdPartyStatusMethod(MethodInfo method) { if (method == null || method.DeclaringType == null || !IsLikelyThirdPartyStatusUiType(method.DeclaringType)) { return false; } string text = method.Name ?? string.Empty; if (string.Equals(text, "Update", StringComparison.Ordinal) || string.Equals(text, "LateUpdate", StringComparison.Ordinal) || string.Equals(text, "FixedUpdate", StringComparison.Ordinal)) { return true; } if (!ContainsOrdinalIgnoreCase(text, "refresh") && !ContainsOrdinalIgnoreCase(text, "rebuild") && !ContainsOrdinalIgnoreCase(text, "fetch") && !ContainsOrdinalIgnoreCase(text, "sync") && !ContainsOrdinalIgnoreCase(text, "tick")) { return ContainsOrdinalIgnoreCase(text, "update"); } return true; } private void MaintainThirdPartyStatusUi() { PruneExpiredStatusUiSuppressedCharacters(); if (_pendingThirdPartyStatusUiCleanup && !IsExpensiveMaintenanceSuppressed()) { if (!HasThirdPartyStatusCleanupWork()) { _pendingThirdPartyStatusUiCleanup = false; _pendingThirdPartyStatusUiCleanupAggressive = false; } else if (!(Time.unscaledTime < _nextThirdPartyStatusUiCleanupTime)) { _nextThirdPartyStatusUiCleanupTime = Time.unscaledTime + 0.35f; bool aggressive = _pendingThirdPartyStatusUiCleanupAggressive || IsInPeakStatsCleanupGraceWindow() || _statusUiSuppressedCharacterUntilById.Count > 0; _pendingThirdPartyStatusUiCleanup = false; _pendingThirdPartyStatusUiCleanupAggressive = false; CleanupThirdPartyStatusUi(aggressive); } } } private void SuppressExpensiveMaintenance(float seconds) { if (!(seconds <= 0f)) { _expensiveMaintenanceSuppressedUntil = Mathf.Max(_expensiveMaintenanceSuppressedUntil, Time.unscaledTime + seconds); } } private bool IsExpensiveMaintenanceSuppressed() { if (!(Time.unscaledTime < _expensiveMaintenanceSuppressedUntil)) { return IsSceneSwitchingStatusActive(); } return true; } private static bool IsSceneSwitchingStatusActive() { try { SceneSwitchingStatus val = default(SceneSwitchingStatus); return GameHandler.TryGetStatus(ref val); } catch { return false; } } private void LateUpdate() { RefreshControlledZombieVisuals(); ActiveZombieSession session = _session; if (session != null && session.IsActive) { EnforceZombieHudHidden(); } } private void BindConfig(bool isChineseLanguage) { ToggleKey = BindEntry(ConfigKey.ToggleKey, (KeyCode)102, isChineseLanguage); ZombieMushroomAppearance = BindEntry(ConfigKey.ZombieMushroomAppearance, defaultValue: true, isChineseLanguage); SprintStaminaRefill = BindEntry(ConfigKey.SprintStaminaRefill, 1f, isChineseLanguage); ControlledJitterChance = BindEntry(ConfigKey.ControlledJitterChance, 0f, isChineseLanguage); ControlledJitterIntensity = BindEntry(ConfigKey.ControlledJitterIntensity, 1f, isChineseLanguage); ControlledJitterDuration = BindEntry(ConfigKey.ControlledJitterDuration, 0.22f, isChineseLanguage); if (Mathf.Abs(ControlledJitterChance.Value - 0.18f) < 0.001f) { ControlledJitterChance.Value = 0f; } ThirdPersonHeightOffset = BindEntry(ConfigKey.ThirdPersonHeightOffset, 0.85f, isChineseLanguage); ThirdPersonDistance = BindEntry(ConfigKey.ThirdPersonDistance, 2.8f, isChineseLanguage); SourceStashDistance = BindEntry(ConfigKey.SourceStashDistance, 600f, isChineseLanguage); VerboseLogs = BindEntry(ConfigKey.VerboseLogs, defaultValue: false, isChineseLanguage); MigrateLocalizedConfigEntries(); MigrateThirdPersonCameraDefaults(); ClampConfigValues(); } private ConfigEntry BindEntry(ConfigKey configKey, T defaultValue, bool isChineseLanguage) { return ((BaseUnityPlugin)this).Config.Bind(GetSectionName(configKey, isChineseLanguage), GetKeyName(configKey, isChineseLanguage), defaultValue, CreateConfigDescription(configKey, isChineseLanguage)); } private ConfigDescription CreateConfigDescription(ConfigKey configKey, bool isChineseLanguage) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Expected O, but got Unknown //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Expected O, but got Unknown string localizedDescription = GetLocalizedDescription(configKey, isChineseLanguage); return (ConfigDescription)(configKey switch { ConfigKey.PounceDuration => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 5f), Array.Empty()), ConfigKey.PounceCooldown => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(0f, 5f), Array.Empty()), ConfigKey.PounceForwardVelocity => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(0f, 50f), Array.Empty()), ConfigKey.PounceUpVelocity => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty()), ConfigKey.SprintStaminaRefill => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(1f, 3f), Array.Empty()), ConfigKey.ControlledJitterChance => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(0f, 0.5f), Array.Empty()), ConfigKey.ControlledJitterIntensity => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(0f, 2.5f), Array.Empty()), ConfigKey.ControlledJitterDuration => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 0.6f), Array.Empty()), ConfigKey.FirstPersonHeightOffset => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(-1f, 1f), Array.Empty()), ConfigKey.ThirdPersonHeightOffset => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(0.3f, 1.8f), Array.Empty()), ConfigKey.ThirdPersonDistance => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(1.5f, 6f), Array.Empty()), ConfigKey.SourceStashDistance => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(10f, 2000f), Array.Empty()), ConfigKey.RestoreGroundOffset => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange(0.2f, 5f), Array.Empty()), _ => (object)new ConfigDescription(localizedDescription, (AcceptableValueBase)null, Array.Empty()), }); } private void ToggleZombieForm() { if (!_switching && !_enteringZombieForm) { if (_session != null) { ExitZombieForm(restorePlayer: true); } else if (CanTransform(Character.localCharacter) && !(Time.unscaledTime - _lastEnterZombieAttemptTime < 0.75f)) { _lastEnterZombieAttemptTime = Time.unscaledTime; _enteringZombieForm = true; ((MonoBehaviour)this).StartCoroutine(EnterZombieFormRoutine()); } } } [IteratorStateMachine(typeof(d__366))] private IEnumerator EnterZombieFormRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__366(0) { <>4__this = this }; } private static bool CanTransform(Character sourceCharacter) { if ((Object)(object)sourceCharacter == (Object)null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[I'm Zombie] No local character found."); } return false; } if (sourceCharacter.isZombie) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)"[I'm Zombie] Current local character is already a zombie."); } return false; } if ((Object)(object)sourceCharacter.data == (Object)null || sourceCharacter.refs == null || (Object)(object)((MonoBehaviourPun)sourceCharacter).photonView == (Object)null) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)"[I'm Zombie] Local character is not ready yet."); } return false; } if (sourceCharacter.data.dead || sourceCharacter.data.passedOut || sourceCharacter.data.fullyPassedOut || sourceCharacter.data.fallSeconds > 0f || sourceCharacter.data.isClimbing || sourceCharacter.data.isRopeClimbing || sourceCharacter.data.isVineClimbing) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogWarning((object)"[I'm Zombie] Local character is not in a valid state to transform."); } return false; } return true; } private void SetConflictingZombieRebornPluginsSuppressed(bool suppress) { try { if (suppress) { foreach (KeyValuePair pluginInfo in Chainloader.PluginInfos) { PluginInfo value = pluginInfo.Value; BaseUnityPlugin val = ((value != null) ? value.Instance : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)this) && IsConflictingZombieRebornPlugin(value)) { BepInPlugin metadata = value.Metadata; string text = ((metadata != null) ? metadata.GUID : null) ?? pluginInfo.Key; if (!_temporarilyDisabledConflictingPluginStates.ContainsKey(text)) { _temporarilyDisabledConflictingPluginStates[text] = ((Behaviour)val).enabled; } if (((Behaviour)val).enabled) { ((Behaviour)val).enabled = false; ManualLogSource log = Log; if (log != null) { BepInPlugin metadata2 = value.Metadata; log.LogWarning((object)("[I'm Zombie] Temporarily disabled conflicting plugin '" + (((metadata2 != null) ? metadata2.Name : null) ?? text) + "' during this transform.")); } } } } return; } foreach (KeyValuePair temporarilyDisabledConflictingPluginState in _temporarilyDisabledConflictingPluginStates) { if (Chainloader.PluginInfos.TryGetValue(temporarilyDisabledConflictingPluginState.Key, out var value2) && !((Object)(object)((value2 != null) ? value2.Instance : null) == (Object)null)) { ((Behaviour)value2.Instance).enabled = temporarilyDisabledConflictingPluginState.Value; } } _temporarilyDisabledConflictingPluginStates.Clear(); } catch (Exception ex) { LogVerbose("Failed to update conflicting zombie plugin suppression: " + ex.Message); } } private static bool IsConflictingZombieRebornPlugin(PluginInfo pluginInfo) { if (pluginInfo == null) { return false; } BepInPlugin metadata = pluginInfo.Metadata; string value = ((metadata != null) ? metadata.GUID : null) ?? string.Empty; BepInPlugin metadata2 = pluginInfo.Metadata; string value2 = ((metadata2 != null) ? metadata2.Name : null) ?? string.Empty; string value3 = (((Object)(object)pluginInfo.Instance != (Object)null) ? ((object)pluginInfo.Instance).GetType().FullName : string.Empty); if (!ContainsOrdinalIgnoreCase(value, "ImZombieReborn") && !ContainsOrdinalIgnoreCase(value, "ZombieReborn") && !ContainsOrdinalIgnoreCase(value2, "Zombie Reborn") && !ContainsOrdinalIgnoreCase(value2, "ImZombieReborn") && !ContainsOrdinalIgnoreCase(value3, "ImZombieReborn")) { return ContainsOrdinalIgnoreCase(value3, "ZombieReborn"); } return true; } private static Quaternion GetSpawnRotation(Character sourceCharacter) { //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_0026: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) Vector3 val = sourceCharacter.data.lookDirection_Flat; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = ((Component)sourceCharacter).transform.forward; } val = Vector3.ProjectOnPlane(val, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.forward; } return Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up); } private static void EnsureImZombiePrefabPoolWrapper() { try { IPunPrefabPool prefabPool = PhotonNetwork.PrefabPool; if (prefabPool is ImZombiePrefabPool prefabPoolWrapper) { _prefabPoolWrapper = prefabPoolWrapper; return; } _prefabPoolWrapper = new ImZombiePrefabPool(prefabPool); PhotonNetwork.PrefabPool = (IPunPrefabPool)(object)_prefabPoolWrapper; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Installed ImZombie prefab pool wrapper around " + ((prefabPool != null) ? ((object)prefabPool).GetType().FullName : "null") + ".")); } } catch (Exception ex) { LogVerbose("Failed to install ImZombie prefab pool wrapper: " + ex.Message); } } private static void RestorePhotonPrefabPoolWrapper() { try { if (_prefabPoolWrapper != null && PhotonNetwork.PrefabPool == _prefabPoolWrapper) { PhotonNetwork.PrefabPool = _prefabPoolWrapper.Inner; } _prefabPoolWrapper = null; } catch { _prefabPoolWrapper = null; } } private static GameObject CreateZombie(Character sourceCharacter, Vector3 position, Quaternion rotation) { //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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) GameObject val = TryCreateNetworkZombie("MushroomZombie_Player", sourceCharacter, position, rotation); if ((Object)(object)val != (Object)null) { return val; } if (PhotonNetwork.InRoom || PhotonNetwork.OfflineMode) { return null; } return TryCreateLocalZombie("MushroomZombie_Player", position, rotation); } private static GameObject TryCreateNetworkZombie(string resourceName, Character sourceCharacter, Vector3 position, Quaternion rotation) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(resourceName) || (!PhotonNetwork.InRoom && !PhotonNetwork.OfflineMode)) { return null; } try { object[] instantiationData = BuildNetworkZombieInstantiationData(sourceCharacter); int characterViewId = GetCharacterViewId(sourceCharacter); ExtendNativeAriseSuppressionByViewId(characterViewId); GameObject val = InstantiateNetworkZombieWithControlledScope(resourceName, position, rotation, instantiationData); PhotonView val2 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); MushroomZombie val3 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); CaptureRuntimeNetworkPrefab(resourceName, val); DestroyDuplicateControlledZombiesForSource(characterViewId, ((Object)(object)val2 != (Object)null) ? val2.ViewID : (-1)); if ((Object)(object)val3 != (Object)null) { RegisterControlledZombie(val3); ClearMushroomZombieSpawnSource(val3); } RestoreLocalSourceProxyCharacterActive(); LogVerbose("Network zombie instantiated from " + resourceName + " with ViewID " + (((Object)(object)val2 != (Object)null) ? val2.ViewID.ToString(CultureInfo.InvariantCulture) : "none") + "."); return val; } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Photon instantiate failed for " + resourceName + ", clearing invalid Photon prefab cache and retrying once:\n" + ex)); } ClearInvalidPhotonPrefabPoolResourceCache(resourceName); try { object[] instantiationData2 = BuildNetworkZombieInstantiationData(sourceCharacter); int characterViewId2 = GetCharacterViewId(sourceCharacter); GameObject val4 = InstantiateNetworkZombieWithControlledScope(resourceName, position, rotation, instantiationData2); PhotonView val5 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent() : null); MushroomZombie val6 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent() : null); CaptureRuntimeNetworkPrefab(resourceName, val4); DestroyDuplicateControlledZombiesForSource(characterViewId2, ((Object)(object)val5 != (Object)null) ? val5.ViewID : (-1)); if ((Object)(object)val6 != (Object)null) { RegisterControlledZombie(val6); ClearMushroomZombieSpawnSource(val6); } RestoreLocalSourceProxyCharacterActive(); LogVerbose("Network zombie instantiated from " + resourceName + " after cache retry with ViewID " + (((Object)(object)val5 != (Object)null) ? val5.ViewID.ToString(CultureInfo.InvariantCulture) : "none") + "."); return val4; } catch (Exception ex2) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[I'm Zombie] Photon instantiate retry failed for " + resourceName + ":\n" + ex2)); } return null; } } } private static GameObject InstantiateNetworkZombieWithControlledScope(string resourceName, Vector3 position, Quaternion rotation, object[] instantiationData) { //IL_0019: 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) string controlledZombieNetworkCreationResourceName = _controlledZombieNetworkCreationResourceName; _controlledZombieNetworkCreationDepth++; _controlledZombieNetworkCreationResourceName = resourceName; try { return PhotonNetwork.Instantiate(resourceName, position, rotation, (byte)0, instantiationData); } finally { _controlledZombieNetworkCreationDepth = Mathf.Max(0, _controlledZombieNetworkCreationDepth - 1); _controlledZombieNetworkCreationResourceName = ((_controlledZombieNetworkCreationDepth > 0) ? controlledZombieNetworkCreationResourceName : null); } } private static void DestroyDuplicateControlledZombiesForSource(int sourceViewId, int keepViewId) { if (sourceViewId <= 0 || _controlledZombieSourceViewIdsByViewId.Count == 0) { return; } List list = null; foreach (KeyValuePair item in _controlledZombieSourceViewIdsByViewId) { if (item.Key > 0 && item.Key != keepViewId && item.Value == sourceViewId) { if (list == null) { list = new List(); } list.Add(item.Key); } } if (list == null) { return; } for (int i = 0; i < list.Count; i++) { int num = list[i]; PhotonView val = null; try { val = PhotonNetwork.GetPhotonView(num); } catch { } GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null); Character val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent() : null); if (Instance?._session != null && Instance._session.TryGetControlledCharacter(out var character) && (Object)(object)val3 != (Object)null && (Object)(object)val3 == (Object)(object)character) { continue; } UnregisterControlledZombieInstance(val3, val); if ((Object)(object)val2 != (Object)null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Destroying duplicate controlled zombie ViewID " + num.ToString(CultureInfo.InvariantCulture) + " for source ViewID " + sourceViewId.ToString(CultureInfo.InvariantCulture) + ".")); } ForceDestroyControlledZombieObject(val2); } else { _controlledZombieViewIds.Remove(num); _controlledZombieSourceViewIdsByViewId.Remove(num); } } } private static void CaptureRuntimeNetworkPrefab(string resourceName, GameObject instantiatedObject) { if (string.IsNullOrWhiteSpace(resourceName)) { return; } if (string.Equals(resourceName, "MushroomZombie_Player", StringComparison.Ordinal)) { if (!HasAliveRuntimeNetworkPrefabBackup(resourceName) && TryCapturePrefabFromPhotonPool(resourceName, out var prefab) && (Object)(object)prefab != (Object)null) { RegisterRuntimeNetworkPrefabBackupFromPrefab(resourceName, prefab, replaceExisting: true); } if (!HasAliveRuntimeNetworkPrefabBackup(resourceName)) { RegisterRuntimeNetworkPrefabBackup(resourceName, instantiatedObject, replaceExisting: true); } } else { if (_runtimeNetworkPrefabBackups.ContainsKey(resourceName)) { return; } if (TryCapturePrefabFromPhotonPool(resourceName, out var prefab2)) { _runtimeNetworkPrefabBackups[resourceName] = prefab2; _knownPhotonPrefabCache[resourceName] = prefab2; RegisterRuntimePrefabWithPhotonPool(resourceName, prefab2); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Captured pooled network prefab for " + resourceName + ".")); } } else { RegisterRuntimeNetworkPrefabBackup(resourceName, instantiatedObject); } } } private static bool HasAliveRuntimeNetworkPrefabBackup(string resourceName) { if (!string.IsNullOrWhiteSpace(resourceName) && _runtimeNetworkPrefabBackups.TryGetValue(resourceName, out var value)) { return (Object)(object)value != (Object)null; } return false; } private static bool TryCapturePrefabFromPhotonPool(string resourceName, out GameObject prefab) { prefab = null; if (string.IsNullOrWhiteSpace(resourceName)) { return false; } try { return TryCapturePrefabFromPool(PhotonNetwork.PrefabPool, resourceName, new HashSet(), out prefab); } catch { prefab = null; return false; } } private static bool TryCapturePrefabFromPool(object pool, string resourceName, HashSet visited, out GameObject prefab) { prefab = null; if (pool == null || !visited.Add(pool)) { return false; } if (pool is ImZombiePrefabPool imZombiePrefabPool) { if (imZombiePrefabPool.TryGetCachedPrefab(resourceName, out prefab)) { return true; } return TryCapturePrefabFromPool(imZombiePrefabPool.Inner, resourceName, visited, out prefab); } Type type = pool.GetType(); if (type.GetField("idToGameObject", InstanceBindingFlags)?.GetValue(pool) is IDictionary dictionary && dictionary.Contains(resourceName)) { object? obj = dictionary[resourceName]; prefab = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)prefab != (Object)null) { return true; } } if (type.GetField("ResourceCache", InstanceBindingFlags)?.GetValue(pool) is IDictionary dictionary2 && dictionary2.Contains(resourceName)) { object? obj2 = dictionary2[resourceName]; prefab = (GameObject)((obj2 is GameObject) ? obj2 : null); if ((Object)(object)prefab != (Object)null) { return true; } } PropertyInfo property = type.GetProperty("DefaultPool", InstanceBindingFlags); if (property != null && property.GetIndexParameters().Length == 0 && TryCapturePrefabFromPool(property.GetValue(pool, null), resourceName, visited, out prefab)) { return true; } FieldInfo field = type.GetField("_defaultPool", InstanceBindingFlags); if (field != null) { return TryCapturePrefabFromPool(field.GetValue(pool), resourceName, visited, out prefab); } return false; } private static void RegisterRuntimeNetworkPrefabBackup(string resourceName, GameObject instantiatedObject, bool replaceExisting = false) { if (string.IsNullOrWhiteSpace(resourceName) || (Object)(object)instantiatedObject == (Object)null || (!replaceExisting && _runtimeNetworkPrefabBackups.ContainsKey(resourceName))) { return; } try { bool activeSelf = instantiatedObject.activeSelf; _runtimePrefabBackupCreationDepth++; GameObject val; try { if (activeSelf) { instantiatedObject.SetActive(false); } val = Object.Instantiate(instantiatedObject); ((Object)val).name = "ImZombie_RuntimePrefabBackup_" + resourceName; val.SetActive(false); if (activeSelf) { instantiatedObject.SetActive(true); } } finally { if (activeSelf && (Object)(object)instantiatedObject != (Object)null && !instantiatedObject.activeSelf) { instantiatedObject.SetActive(true); } _runtimePrefabBackupCreationDepth = Mathf.Max(0, _runtimePrefabBackupCreationDepth - 1); } val.transform.SetParent((Transform)null, true); Object.DontDestroyOnLoad((Object)(object)val); PhotonView[] componentsInChildren = val.GetComponentsInChildren(true); foreach (PhotonView val2 in componentsInChildren) { try { val2.ViewID = 0; } catch { } } PrepareRuntimeNetworkPrefabBackup(resourceName, val); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Registered runtime network prefab backup for " + resourceName + ".")); } } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[I'm Zombie] Failed to register runtime network prefab backup for " + resourceName + ": " + ex.Message)); } } } private static void RegisterRuntimeNetworkPrefabBackupFromPrefab(string resourceName, GameObject sourcePrefab, bool replaceExisting = false) { //IL_0026: 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) if (string.IsNullOrWhiteSpace(resourceName) || (Object)(object)sourcePrefab == (Object)null || (!replaceExisting && HasAliveRuntimeNetworkPrefabBackup(resourceName))) { return; } try { GameObject val = InstantiateInactivePrefabCopy(sourcePrefab, sourcePrefab.transform.position, sourcePrefab.transform.rotation); if (!((Object)(object)val == (Object)null)) { ((Object)val).name = "ImZombie_RuntimePrefabBackup_" + resourceName; PrepareRuntimeNetworkPrefabBackup(resourceName, val); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Registered runtime network prefab backup for " + resourceName + " from pooled prefab.")); } } } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[I'm Zombie] Failed to register pooled runtime network prefab backup for " + resourceName + ": " + ex.Message)); } } } private static void PrepareRuntimeNetworkPrefabBackup(string resourceName, GameObject backupPrefab) { if (!string.IsNullOrWhiteSpace(resourceName) && !((Object)(object)backupPrefab == (Object)null)) { ResetRuntimeNetworkPrefabObject(backupPrefab, keepInactive: true); backupPrefab.transform.SetParent((Transform)null, true); Object.DontDestroyOnLoad((Object)(object)backupPrefab); _runtimeNetworkPrefabBackups[resourceName] = backupPrefab; _knownPhotonPrefabCache[resourceName] = backupPrefab; RegisterRuntimePrefabWithPhotonPool(resourceName, backupPrefab); } } private static GameObject InstantiateInactivePrefabCopy(GameObject sourcePrefab, Vector3 position, Quaternion rotation) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)sourcePrefab == (Object)null) { return null; } _runtimePrefabBackupCreationDepth++; bool flag = false; bool flag2 = false; try { flag = sourcePrefab.activeSelf; if (flag) { sourcePrefab.SetActive(false); flag2 = true; } GameObject val = Object.Instantiate(sourcePrefab, position, rotation); if ((Object)(object)val != (Object)null && val.activeSelf) { val.SetActive(false); } return val; } catch (Exception ex) { LogVerbose("Failed to instantiate inactive prefab copy for " + ((Object)sourcePrefab).name + ": " + ex.Message); return null; } finally { try { if (flag2 && (Object)(object)sourcePrefab != (Object)null && flag && !sourcePrefab.activeSelf) { sourcePrefab.SetActive(true); } } catch { } _runtimePrefabBackupCreationDepth = Mathf.Max(0, _runtimePrefabBackupCreationDepth - 1); } } private static void ResetRuntimeNetworkPrefabObject(GameObject prefabObject, bool keepInactive) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefabObject == (Object)null) { return; } _runtimePrefabBackupCreationDepth++; try { try { MonoBehaviour[] componentsInChildren = prefabObject.GetComponentsInChildren(true); foreach (MonoBehaviour obj in componentsInChildren) { if (obj != null) { obj.StopAllCoroutines(); } } } catch { } PhotonView[] componentsInChildren2 = prefabObject.GetComponentsInChildren(true); foreach (PhotonView val in componentsInChildren2) { try { val.ViewID = 0; } catch { } } PlayerZombieController[] componentsInChildren3 = prefabObject.GetComponentsInChildren(true); foreach (PlayerZombieController playerZombieController in componentsInChildren3) { try { Object.DestroyImmediate((Object)(object)playerZombieController); } catch { Object.Destroy((Object)(object)playerZombieController); } } Rigidbody[] componentsInChildren4 = prefabObject.GetComponentsInChildren(true); foreach (Rigidbody val2 in componentsInChildren4) { if ((Object)(object)val2 == (Object)null) { continue; } try { if (!val2.isKinematic) { val2.linearVelocity = Vector3.zero; val2.angularVelocity = Vector3.zero; } val2.Sleep(); } catch { } } Character[] componentsInChildren5 = prefabObject.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren5.Length; i++) { ResetRuntimeNetworkPrefabCharacter(componentsInChildren5[i]); } MushroomZombie[] componentsInChildren6 = prefabObject.GetComponentsInChildren(true); foreach (MushroomZombie val3 in componentsInChildren6) { try { val3.currentTarget = null; val3.distanceToTarget = 0f; val3.chaseTimeBeforeSprint = 0f; MushroomZombieCurrentStateField?.SetValue(val3, (object)(State)2); } catch { } } if (keepInactive && prefabObject.activeSelf) { prefabObject.SetActive(false); } } finally { _runtimePrefabBackupCreationDepth = Mathf.Max(0, _runtimePrefabBackupCreationDepth - 1); } } private static void ResetRuntimeNetworkPrefabCharacter(Character character) { if ((Object)(object)character == (Object)null) { return; } try { CharacterStartedField?.SetValue(character, false); } catch { } try { if ((Object)(object)character.data != (Object)null) { character.data.dead = false; character.data.zombified = false; character.data.fullyPassedOut = false; character.data.passedOut = false; character.data.fallSeconds = 0f; character.data.currentRagdollControll = 1f; character.data.isSprinting = false; } } catch { } } private static void RegisterRuntimePrefabWithPhotonPool(string resourceName, GameObject prefab) { if (string.IsNullOrWhiteSpace(resourceName) || (Object)(object)prefab == (Object)null) { return; } try { RegisterRuntimePrefabWithPool(PhotonNetwork.PrefabPool, resourceName, prefab, new HashSet()); ClearInvalidPrefabPoolResourceCache(PhotonNetwork.PrefabPool, resourceName, new HashSet()); } catch (Exception ex) { LogVerbose("Failed to register runtime prefab with Photon pool for " + resourceName + ": " + ex.Message); } } private static void RegisterRuntimePrefabWithPool(object pool, string resourceName, GameObject prefab, HashSet visited) { if (pool == null || (Object)(object)prefab == (Object)null || !visited.Add(pool)) { return; } if (pool is ImZombiePrefabPool imZombiePrefabPool) { RegisterRuntimePrefabWithPool(imZombiePrefabPool.Inner, resourceName, prefab, visited); return; } Type type = pool.GetType(); if (type.GetField("idToGameObject", InstanceBindingFlags)?.GetValue(pool) is IDictionary dictionary) { dictionary[resourceName] = prefab; if (type.GetField("gameObjectToId", InstanceBindingFlags)?.GetValue(pool) is IDictionary dictionary2) { dictionary2[prefab] = resourceName; } } if (type.GetField("ResourceCache", InstanceBindingFlags)?.GetValue(pool) is IDictionary dictionary3) { dictionary3[resourceName] = prefab; } PropertyInfo property = type.GetProperty("DefaultPool", InstanceBindingFlags); if (property != null && property.GetIndexParameters().Length == 0) { RegisterRuntimePrefabWithPool(property.GetValue(pool, null), resourceName, prefab, visited); } FieldInfo field = type.GetField("_defaultPool", InstanceBindingFlags); if (field != null) { RegisterRuntimePrefabWithPool(field.GetValue(pool), resourceName, prefab, visited); } } private static void ClearInvalidPhotonPrefabPoolResourceCache(string resourceName) { if (string.IsNullOrWhiteSpace(resourceName) || !IsImZombieOwnedNetworkResource(resourceName)) { return; } try { if (TryGetRuntimeOrKnownPrefab(resourceName, out var prefab)) { RegisterRuntimePrefabWithPhotonPool(resourceName, prefab); } ClearInvalidPrefabPoolResourceCache(PhotonNetwork.PrefabPool, resourceName, new HashSet()); } catch (Exception ex) { LogVerbose("Failed to inspect Photon prefab cache for " + resourceName + ": " + ex.Message); } } private static bool IsImZombieOwnedNetworkResource(string resourceName) { if (!string.Equals(resourceName, "MushroomZombie_Player", StringComparison.Ordinal)) { return string.Equals(resourceName, "Character", StringComparison.Ordinal); } return true; } private static bool IsCreatingControlledPlayerZombieNetworkResource() { if (_controlledZombieNetworkCreationDepth > 0) { return string.Equals(_controlledZombieNetworkCreationResourceName, "MushroomZombie_Player", StringComparison.Ordinal); } return false; } private static void ClearInvalidPrefabPoolResourceCache(object pool, string resourceName, HashSet visited) { if (pool == null || !visited.Add(pool)) { return; } if (pool is ImZombiePrefabPool imZombiePrefabPool) { ClearInvalidPrefabPoolResourceCache(imZombiePrefabPool.Inner, resourceName, visited); return; } Type type = pool.GetType(); FieldInfo field = type.GetField("idToGameObject", InstanceBindingFlags); GameObject prefab2; if (field?.GetValue(pool) is IDictionary dictionary && dictionary.Contains(resourceName)) { object? obj = dictionary[resourceName]; GameObject val = (GameObject)((obj is GameObject) ? obj : null); GameObject prefab; if ((Object)(object)val != (Object)null) { _knownPhotonPrefabCache[resourceName] = val; } else if (TryGetRuntimeOrKnownPrefab(resourceName, out prefab)) { dictionary[resourceName] = prefab; RestoreCustomPrefabReverseMap(type, pool, resourceName, prefab); LogVerbose("Restored invalid Photon CustomPrefabPool entry for " + resourceName + "."); } else { dictionary.Remove(resourceName); LogVerbose("Cleared invalid Photon CustomPrefabPool entry for " + resourceName + "."); } } else if (field?.GetValue(pool) is IDictionary dictionary2 && TryGetRuntimeOrKnownPrefab(resourceName, out prefab2)) { dictionary2[resourceName] = prefab2; RestoreCustomPrefabReverseMap(type, pool, resourceName, prefab2); LogVerbose("Restored missing Photon CustomPrefabPool entry for " + resourceName + "."); } FieldInfo field2 = type.GetField("ResourceCache", InstanceBindingFlags); GameObject prefab3; if (field2?.GetValue(pool) is IDictionary dictionary3 && dictionary3.Contains(resourceName)) { object? obj2 = dictionary3[resourceName]; GameObject val2 = (GameObject)((obj2 is GameObject) ? obj2 : null); GameObject value; GameObject value2; if ((Object)(object)val2 != (Object)null) { _knownPhotonPrefabCache[resourceName] = val2; } else if (_runtimeNetworkPrefabBackups.TryGetValue(resourceName, out value) && (Object)(object)value != (Object)null) { dictionary3[resourceName] = value; RegisterRuntimePrefabWithPhotonPool(resourceName, value); LogVerbose("Restored invalid Photon DefaultPool ResourceCache entry for " + resourceName + " from runtime backup prefab."); } else if (_knownPhotonPrefabCache.TryGetValue(resourceName, out value2) && (Object)(object)value2 != (Object)null) { dictionary3[resourceName] = value2; LogVerbose("Restored invalid Photon DefaultPool ResourceCache entry for " + resourceName + " from known prefab."); } else { dictionary3.Remove(resourceName); LogVerbose("Cleared invalid Photon DefaultPool ResourceCache entry for " + resourceName + "."); } } else if (field2?.GetValue(pool) is IDictionary dictionary4 && TryGetRuntimeOrKnownPrefab(resourceName, out prefab3)) { dictionary4[resourceName] = prefab3; RegisterRuntimePrefabWithPhotonPool(resourceName, prefab3); LogVerbose("Restored missing Photon DefaultPool ResourceCache entry for " + resourceName + " from known prefab."); } PropertyInfo property = type.GetProperty("DefaultPool", InstanceBindingFlags); if (property != null && property.GetIndexParameters().Length == 0) { ClearInvalidPrefabPoolResourceCache(property.GetValue(pool, null), resourceName, visited); } FieldInfo field3 = type.GetField("_defaultPool", InstanceBindingFlags); if (field3 != null) { ClearInvalidPrefabPoolResourceCache(field3.GetValue(pool), resourceName, visited); } } private static void RestoreCustomPrefabReverseMap(Type poolType, object pool, string resourceName, GameObject prefab) { if (!(poolType == null) && pool != null && !((Object)(object)prefab == (Object)null) && poolType.GetField("gameObjectToId", InstanceBindingFlags)?.GetValue(pool) is IDictionary dictionary) { dictionary[prefab] = resourceName; } } private static bool TryGetRuntimeOrKnownPrefab(string resourceName, out GameObject prefab) { if (_runtimeNetworkPrefabBackups.TryGetValue(resourceName, out prefab) && (Object)(object)prefab != (Object)null) { return true; } if ((Object)(object)prefab == (Object)null) { _runtimeNetworkPrefabBackups.Remove(resourceName); } if (_knownPhotonPrefabCache.TryGetValue(resourceName, out prefab) && (Object)(object)prefab != (Object)null) { return true; } if ((Object)(object)prefab == (Object)null) { _knownPhotonPrefabCache.Remove(resourceName); } prefab = null; return false; } private static bool ShouldRecoverOriginalCharacterSpawnFromBackup() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Instance; if ((Object)(object)instance == (Object)null || !instance._preferOriginalLocalSpawnAfterSceneLoad || (Object)(object)_originalPlayerCharacterPrefabBackup == (Object)null) { return false; } if (Time.unscaledTime > instance._preferOriginalLocalSpawnUntil) { instance._preferOriginalLocalSpawnAfterSceneLoad = false; instance._preferOriginalLocalSpawnUntil = 0f; return false; } try { Scene activeScene = SceneManager.GetActiveScene(); return IsGameplaySceneName(((Scene)(ref activeScene)).name ?? string.Empty); } catch { return false; } } private static bool TryCaptureOriginalCharacterPrefabFromInnerPool(IPunPrefabPool innerPool) { try { if (!TryCapturePrefabFromPool(innerPool, "Character", new HashSet(), out var prefab) || (Object)(object)prefab == (Object)null) { return false; } _knownPhotonPrefabCache["Character"] = prefab; RegisterRuntimePrefabWithPhotonPool("Character", prefab); return true; } catch { return false; } } private static bool TryInstantiateOriginalPlayerCharacterBackup(Vector3 position, Quaternion rotation, out GameObject instance) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) instance = null; if ((Object)(object)_originalPlayerCharacterPrefabBackup == (Object)null) { _originalPlayerCharacterPrefabBackup = null; LogVerbose("Original Character prefab backup is not available for fallback instantiate."); return false; } try { instance = InstantiateInactivePrefabCopy(_originalPlayerCharacterPrefabBackup, position, rotation); if ((Object)(object)instance == (Object)null) { return false; } ((Object)instance).name = "Character"; ResetRuntimeNetworkPrefabObject(instance, keepInactive: true); instance.transform.SetPositionAndRotation(position, rotation); ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[I'm Zombie] Instantiated original Character from protected backup as a last-resort fallback."); } return true; } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[I'm Zombie] Failed to instantiate cached Character prefab backup: " + ex.Message)); } instance = null; return false; } } private static void CaptureOriginalPlayerCharacterPrefabBackup(string prefabId) { //IL_0059: 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) if (!string.Equals(prefabId, "Character", StringComparison.Ordinal) || (Object)(object)_originalPlayerCharacterPrefabBackup != (Object)null) { return; } try { if (!TryCapturePrefabFromPool(PhotonNetwork.PrefabPool, prefabId, new HashSet(), out var prefab) || (Object)(object)prefab == (Object)null) { return; } _knownPhotonPrefabCache[prefabId] = prefab; RegisterRuntimePrefabWithPhotonPool(prefabId, prefab); GameObject val = InstantiateInactivePrefabCopy(prefab, prefab.transform.position, prefab.transform.rotation); if (!((Object)(object)val == (Object)null)) { ((Object)val).name = "ImZombie_OriginalCharacterPrefabBackup"; ResetRuntimeNetworkPrefabObject(val, keepInactive: true); val.transform.SetParent((Transform)null, true); Object.DontDestroyOnLoad((Object)(object)val); _originalPlayerCharacterPrefabBackup = val; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[I'm Zombie] Captured original Character prefab backup for last-resort spawn recovery."); } } } catch (Exception ex) { LogVerbose("Failed to capture original Character prefab backup: " + ex.Message); } } private static GameObject TryCreateLocalZombie(string resourceName, Vector3 position, Quaternion rotation) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = Resources.Load(resourceName); if ((Object)(object)val != (Object)null) { GameObject val2 = new GameObject("ImZombie_LocalZombie_Staging"); val2.SetActive(false); _controlledZombieCreationRoot = val2.transform; try { GameObject obj = Object.Instantiate(val, position, rotation, val2.transform); obj.SetActive(false); obj.transform.SetParent((Transform)null, true); return obj; } finally { _controlledZombieCreationRoot = null; Object.Destroy((Object)(object)val2); } } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Local instantiate failed for " + resourceName + ": " + ex.Message)); } } return null; } private static object[] BuildNetworkZombieInstantiationData(Character sourceCharacter) { int characterViewId = GetCharacterViewId(sourceCharacter); return new object[3] { "Thanks.ImZombie", "0.0.4", characterViewId }; } internal void ExitZombieForm(bool restorePlayer) { _enteringZombieForm = false; if (_session == null) { return; } _switching = true; SuppressExpensiveMaintenance(0.85f); try { _session.Exit(restorePlayer); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] Failed while exiting zombie form: " + ex.Message)); } finally { _session = null; SetConflictingZombieRebornPluginsSuppressed(suppress: false); ClearLocalSourceProxyCharacter(null); ClearCameraOverride(); _viewZombieObject = null; RestoreHudAfterZombie(); BeginPeakStatsCleanupGraceWindow(); RequestThirdPartyStatusUiCleanup(aggressive: true); BeginLocalZombieSessionResidualCleanupWindow(); _toggleKeyReleasedSinceEnter = true; _toggleKeyHoldStartTime = -1f; _toggleKeyHoldConsumed = false; _switching = false; } } private void EndZombieSessionForSceneTransition(string reason) { if (_session == null) { return; } _switching = true; SuppressExpensiveMaintenance(0.85f); try { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Ending active zombie session before original local spawn (" + reason + ").")); } _session.Exit(restorePlayer: false); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] Failed to end zombie session for scene transition: " + ex.Message)); } finally { _session = null; SetConflictingZombieRebornPluginsSuppressed(suppress: false); ClearLocalSourceProxyCharacter(null); ClearCameraOverride(); _viewZombieObject = null; RestoreHudAfterZombie(); BeginPeakStatsCleanupGraceWindow(); RequestThirdPartyStatusUiCleanup(aggressive: true); BeginLocalZombieSessionResidualCleanupWindow(); _toggleKeyReleasedSinceEnter = true; _toggleKeyHoldStartTime = -1f; _toggleKeyHoldConsumed = false; _switching = false; } } internal static void PrepareForOriginalLocalCharacterSpawn() { Instance?.PrepareForOriginalLocalCharacterSpawnInstance(); } private void PrepareForOriginalLocalCharacterSpawnInstance() { if (_preferOriginalLocalSpawnAfterSceneLoad && Time.unscaledTime > _preferOriginalLocalSpawnUntil) { _preferOriginalLocalSpawnAfterSceneLoad = false; _preferOriginalLocalSpawnUntil = 0f; } if (_preferOriginalLocalSpawnAfterSceneLoad) { EndZombieSessionForSceneTransition("CharacterSpawner original local spawn"); } PreparePlayerRegistryForOriginalLocalSpawn("CharacterSpawner original local spawn"); } internal static void CompleteOriginalLocalCharacterSpawn(Character character) { if (!((Object)(object)Instance == (Object)null) && (Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null && !IsImZombieManagedCharacter(character)) { Instance._preferOriginalLocalSpawnAfterSceneLoad = false; Instance._preferOriginalLocalSpawnUntil = 0f; Instance.SuppressExpensiveMaintenance(1.5f); ForcePlayerCharacterLookup(character); Character.localCharacter = character; } } internal static Exception HandleOriginalLocalCharacterSpawnException(CharacterSpawner spawner, Exception exception) { if (exception == null) { return null; } if (!LooksLikeOriginalCharacterSpawnFailure(exception)) { return exception; } ResetCharacterSpawnerSpawnedFlag(spawner); PreparePlayerRegistryForOriginalLocalSpawn("CharacterSpawner exception recovery"); ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Recovered CharacterSpawner state after Character prefab spawn failure; original exception will remain logged:\n" + exception)); } return exception; } private static bool LooksLikeOriginalCharacterSpawnFailure(Exception exception) { if (exception == null) { return false; } string text = exception.ToString(); if (text.IndexOf("PhotonNetwork.Instantiate", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("DefaultPool.Instantiate", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("CustomPrefabPool.Instantiate", StringComparison.OrdinalIgnoreCase) < 0) { return text.IndexOf("Character", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static void ResetCharacterSpawnerSpawnedFlag(CharacterSpawner spawner) { if ((Object)(object)spawner == (Object)null || CharacterSpawnerHasSpawnedPlayerField == null) { return; } try { CharacterSpawnerHasSpawnedPlayerField.SetValue(spawner, false); } catch (Exception ex) { LogVerbose("Failed to reset CharacterSpawner.hasSpawnedPlayer after failed spawn: " + ex.Message); } } private static bool IsGameplaySceneName(string sceneName) { if (!string.IsNullOrWhiteSpace(sceneName)) { return sceneName.StartsWith("Level_", StringComparison.OrdinalIgnoreCase); } return false; } private static void PreparePlayerRegistryForOriginalLocalSpawn(string reason) { bool flag = Instance?._preferOriginalLocalSpawnAfterSceneLoad ?? false; try { object obj = PlayerHandlerInstanceProperty?.GetValue(null, null); IDictionary lookup = PlayerHandlerCharacterLookupField?.GetValue(obj) as IDictionary; PruneNullPlayerCharacterLookupEntries(lookup); if (flag) { PruneImZombiePlayerCharacterLookupEntries(lookup); } } catch (Exception ex) { LogVerbose("Failed to prune player character lookup before original spawn (" + reason + "): " + ex.Message); } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null) { Character.localCharacter = null; } else if (IsImZombieManagedCharacter(localCharacter) || IsStashedSourceCharacter(localCharacter) || flag) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Cleared stale local character before original spawn (" + reason + ").")); } Character.localCharacter = null; } } internal static bool TryApplyCameraOverride(Character character, ref Vector3 cameraPosition) { //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) if ((Object)(object)character == (Object)null || (Object)(object)character != (Object)(object)_cameraOverrideCharacter) { return false; } cameraPosition = GetThirdPersonCameraPosition(character); return true; } internal static void SetCameraOverride(Character character) { _cameraOverrideCharacter = character; ResetThirdPersonCameraSmoothing(); } internal static void ClearCameraOverride() { _cameraOverrideCharacter = null; ResetThirdPersonCameraSmoothing(); _rendererVisualStates.Clear(); } private static void HideHudForZombie() { _hudHiddenForZombie = true; _hudPreviousKnown = false; _namesPreviousKnown = false; _hudCanvasObject = null; _namesCanvasObject = null; EnforceZombieHudHidden(); } private static void EnforceZombieHudHidden() { if (_hudHiddenForZombie) { HideHudCanvas(ref _hudCanvasObject, "Canvas_HUD", ref _hudPreviousKnown, ref _hudPreviousActive, keepRootActive: true); HideHudCanvas(ref _namesCanvasObject, "Canvas_Names", ref _namesPreviousKnown, ref _namesPreviousActive); } } private static void HideHudCanvas(ref GameObject canvasObject, string objectName, ref bool previousKnown, ref bool previousActive, bool keepRootActive = false) { if ((Object)(object)canvasObject == (Object)null) { canvasObject = GameObject.Find(objectName); } if ((Object)(object)canvasObject == (Object)null) { return; } if (!previousKnown) { previousActive = canvasObject.activeSelf; previousKnown = true; } if (keepRootActive) { if (!canvasObject.activeSelf) { canvasObject.SetActive(true); } HideHudChildrenExceptEmoteWheel(canvasObject); } else if (canvasObject.activeSelf) { canvasObject.SetActive(false); } } private static void RestoreHudAfterZombie() { RestoreHudChildren(); RestoreHudCanvas(_hudCanvasObject, _hudPreviousKnown, _hudPreviousActive); RestoreHudCanvas(_namesCanvasObject, _namesPreviousKnown, _namesPreviousActive); _hudCanvasObject = null; _namesCanvasObject = null; _hudPreviousKnown = false; _namesPreviousKnown = false; _hudPreviousActive = false; _namesPreviousActive = false; _hudHiddenForZombie = false; } private static void HideHudChildrenExceptEmoteWheel(GameObject canvasObject) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown if ((Object)(object)canvasObject == (Object)null) { return; } GameObject emoteWheel = null; try { emoteWheel = (((Object)(object)GUIManager.instance != (Object)null) ? GUIManager.instance.emoteWheel : null); } catch { } foreach (Transform item in canvasObject.transform) { Transform val = item; if ((Object)(object)val == (Object)null) { continue; } GameObject gameObject = ((Component)val).gameObject; if (!ShouldKeepHudChildForZombie(gameObject, emoteWheel)) { int instanceID = ((Object)gameObject).GetInstanceID(); if (!_hudChildPreviousActiveStates.ContainsKey(instanceID)) { _hudChildPreviousActiveStates[instanceID] = gameObject.activeSelf; } if (gameObject.activeSelf) { gameObject.SetActive(false); } } } } private static bool ShouldKeepHudChildForZombie(GameObject childObject, GameObject emoteWheel) { if ((Object)(object)childObject == (Object)null) { return false; } if ((Object)(object)emoteWheel == (Object)null) { return false; } Transform transform = childObject.transform; Transform transform2 = emoteWheel.transform; if (!((Object)(object)transform == (Object)(object)transform2)) { return transform2.IsChildOf(transform); } return true; } private static void RestoreHudChildren() { foreach (KeyValuePair hudChildPreviousActiveState in _hudChildPreviousActiveStates) { try { GameObject val = FindGameObjectByInstanceId(hudChildPreviousActiveState.Key); if ((Object)(object)val != (Object)null) { val.SetActive(hudChildPreviousActiveState.Value); } } catch { } } _hudChildPreviousActiveStates.Clear(); } private static GameObject FindGameObjectByInstanceId(int instanceId) { if (instanceId == 0) { return null; } GameObject[] array = Resources.FindObjectsOfTypeAll(); foreach (GameObject val in array) { if ((Object)(object)val != (Object)null && ((Object)val).GetInstanceID() == instanceId) { return val; } } return null; } private static void RestoreHudCanvas(GameObject canvasObject, bool previousKnown, bool previousActive) { if (!((Object)(object)canvasObject == (Object)null) && previousKnown) { canvasObject.SetActive(previousActive); } } internal static void BeginNativeAriseSuppression(Character sourceCharacter) { BeginNativeAriseSuppressionByViewId(GetCharacterViewId(sourceCharacter)); } internal static void EndNativeAriseSuppression(Character sourceCharacter) { EndNativeAriseSuppressionByViewId(GetCharacterViewId(sourceCharacter)); } internal static void BeginNativeAriseSuppressionByViewId(int viewId) { if (viewId >= 0) { _nativeAriseSuppressedSourceViewIdCounts.TryGetValue(viewId, out var value); _nativeAriseSuppressedSourceViewIdCounts[viewId] = value + 1; } } internal static void EndNativeAriseSuppressionByViewId(int viewId) { if (viewId >= 0) { if (!_nativeAriseSuppressedSourceViewIdCounts.TryGetValue(viewId, out var value) || value <= 1) { _nativeAriseSuppressedSourceViewIdCounts.Remove(viewId); } else { _nativeAriseSuppressedSourceViewIdCounts[viewId] = value - 1; } } } internal static void ExtendNativeAriseSuppressionByViewId(int viewId) { if (viewId >= 0) { float num = Time.unscaledTime + 8f; if (!_nativeAriseSuppressionUntilByViewId.TryGetValue(viewId, out var value) || value < num) { _nativeAriseSuppressionUntilByViewId[viewId] = num; } } } internal static bool ShouldSuppressFinishZombifying(Character sourceCharacter) { if (!IsStashedSourceCharacter(sourceCharacter)) { Plugin instance = Instance; if (instance == null || !(instance._session?.IsSourceCharacter(sourceCharacter)).GetValueOrDefault()) { int characterViewId = GetCharacterViewId(sourceCharacter); if (characterViewId < 0) { return false; } CleanupExpiredNativeAriseSuppression(); if (!_nativeAriseSuppressedSourceViewIdCounts.ContainsKey(characterViewId)) { return _nativeAriseSuppressionUntilByViewId.ContainsKey(characterViewId); } return true; } } return true; } private static void CleanupExpiredNativeAriseSuppression() { if (_nativeAriseSuppressionUntilByViewId.Count == 0) { return; } float unscaledTime = Time.unscaledTime; List list = null; foreach (KeyValuePair item in _nativeAriseSuppressionUntilByViewId) { if (!(item.Value > unscaledTime)) { if (list == null) { list = new List(); } list.Add(item.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { _nativeAriseSuppressionUntilByViewId.Remove(list[i]); } } } internal static bool ShouldSuppressNetworkAriseFinishZombifying(MushroomZombie zombie, int sourceViewId) { if (sourceViewId <= 0) { return false; } try { CleanupExpiredNativeAriseSuppression(); if (!_nativeAriseSuppressedSourceViewIdCounts.ContainsKey(sourceViewId) && !_nativeAriseSuppressionUntilByViewId.ContainsKey(sourceViewId)) { Plugin instance = Instance; if (instance == null || !(instance._session?.IsSourceViewId(sourceViewId)).GetValueOrDefault()) { if ((Object)(object)zombie == (Object)null) { return false; } if (IsControlledZombieBeingCreated(zombie) || IsControlledZombie(zombie)) { LogSuppressedNativeArise(sourceViewId, "controlled zombie"); return true; } PhotonView photonView = ((MonoBehaviourPun)zombie).photonView; if ((Object)(object)photonView == (Object)null || photonView.ViewID <= 0 || !IsImZombieNetworkSpawn(photonView)) { return false; } PhotonView photonView2 = PhotonNetwork.GetPhotonView(sourceViewId); if ((Object)(object)photonView2 == (Object)null || photonView2.Owner == null || photonView.Owner == null) { return false; } bool num = photonView2.Owner.ActorNumber == photonView.Owner.ActorNumber; if (num) { LogSuppressedNativeArise(sourceViewId, "network spawn owner match"); } return num; } } LogSuppressedNativeArise(sourceViewId, "active suppression"); return true; } catch { return false; } } private static void LogSuppressedNativeArise(int sourceViewId, string reason) { if (sourceViewId > 0 && _loggedSuppressedAriseSourceViewIds.Add(sourceViewId)) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Suppressing native MushroomZombie RPC_Arise FinishZombifying for source ViewID " + sourceViewId.ToString(CultureInfo.InvariantCulture) + " (" + reason + ").")); } } } private static bool IsImZombieNetworkSpawn(PhotonView view) { int sourceViewId; return TryReadNetworkZombieInstantiationData(view, out sourceViewId); } private static bool TryReadNetworkZombieInstantiationData(PhotonView view, out int sourceViewId) { sourceViewId = -1; if ((Object)(object)view == (Object)null) { return false; } object[] instantiationData; try { instantiationData = view.InstantiationData; } catch { return false; } if (instantiationData == null || instantiationData.Length < 1 || !(instantiationData[0] is string a) || !string.Equals(a, "Thanks.ImZombie", StringComparison.Ordinal)) { return false; } if (instantiationData.Length >= 3) { try { sourceViewId = Convert.ToInt32(instantiationData[2], CultureInfo.InvariantCulture); } catch { sourceViewId = -1; } } return true; } private static bool GetMushroomZombieWearingSkirt(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null || MushroomZombieWearingSkirtField == null) { return false; } try { object value = MushroomZombieWearingSkirtField.GetValue(zombie); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static void SyncPhysicsTransforms() { try { Physics.SyncTransforms(); } catch { } } private static void SetCharacterPositionImmediate(Character character, Vector3 position, Quaternion rotation) { //IL_01c2: 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_0009: 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_001c: 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_0026: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0045: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_0059: 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) //IL_0062: 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_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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: 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_0186: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null || !IsFiniteVector(position)) { return; } try { Transform transform = ((Component)character).transform; rotation = NormalizeFiniteQuaternion(rotation, transform.rotation); Vector3 val = character.Center; if (!IsFiniteVector(val)) { val = transform.position; } Quaternion rotation2 = transform.rotation; Quaternion val2 = rotation * Quaternion.Inverse(rotation2); Vector3 val3 = position - val; transform.SetPositionAndRotation(transform.position + val3, rotation); if (character.refs?.ragdoll?.partList == null) { return; } foreach (Bodypart part in character.refs.ragdoll.partList) { if ((Object)(object)part == (Object)null) { continue; } if ((Object)(object)part.Rig != (Object)null) { Vector3 position2 = part.Rig.position; part.Rig.position = position + val2 * (position2 - val); part.Rig.rotation = val2 * part.Rig.rotation; if (!part.Rig.isKinematic) { part.Rig.linearVelocity = Vector3.zero; part.Rig.angularVelocity = Vector3.zero; } } else { Vector3 position3 = ((Component)part).transform.position; ((Component)part).transform.position = position + val2 * (position3 - val); ((Component)part).transform.rotation = val2 * ((Component)part).transform.rotation; } } } catch { ((Component)character).transform.SetPositionAndRotation(position, rotation); } } private static void LiftCharacterBodyAbovePosition(Character character, Vector3 minimumBodyPosition) { //IL_0009: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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) if ((Object)(object)character == (Object)null || !IsFiniteVector(minimumBodyPosition) || !TryGetCharacterLowestY(character, out var lowestY)) { return; } float num = minimumBodyPosition.y - 1.35f + 0.18f - lowestY; if (!(num <= 0f) && !(num > 5f)) { TranslateCharacterImmediate(character, Vector3.up * num); if ((Object)(object)character.data != (Object)null) { CharacterData data = character.data; data.groundPos += Vector3.up * num; } LogVerbose("Lifted remote restored source character by " + num.ToString("0.00", CultureInfo.InvariantCulture) + " to keep body above restore position."); } } private static bool TryGetCharacterLowestY(Character character, out float lowestY) { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_0098: Unknown result type (might be due to invalid IL or missing references) lowestY = float.PositiveInfinity; bool flag = false; if ((Object)(object)character == (Object)null) { return false; } try { if (character.refs?.ragdoll?.partList != null) { foreach (Bodypart part in character.refs.ragdoll.partList) { if (!((Object)(object)part == (Object)null)) { Vector3 val = (((Object)(object)part.Rig != (Object)null) ? part.Rig.position : ((Component)part).transform.position); if (IsFiniteFloat(val.y)) { lowestY = Mathf.Min(lowestY, val.y); flag = true; } } } } Collider[] componentsInChildren = ((Component)character).GetComponentsInChildren(true); foreach (Collider val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !val2.isTrigger) { Bounds bounds = val2.bounds; float y = ((Bounds)(ref bounds)).min.y; if (IsFiniteFloat(y)) { lowestY = Mathf.Min(lowestY, y); flag = true; } } } } catch { } if (flag) { return IsFiniteFloat(lowestY); } return false; } private static void TranslateCharacterImmediate(Character character, Vector3 delta) { //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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_0028: 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) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: 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_009e: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null || !IsFiniteVector(delta) || ((Vector3)(ref delta)).sqrMagnitude <= 0f) { return; } try { Transform transform = ((Component)character).transform; transform.position += delta; if (character.refs?.ragdoll?.partList == null) { return; } foreach (Bodypart part in character.refs.ragdoll.partList) { if ((Object)(object)part == (Object)null) { continue; } if ((Object)(object)part.Rig != (Object)null) { Rigidbody rig = part.Rig; rig.position += delta; if (!part.Rig.isKinematic) { part.Rig.linearVelocity = Vector3.zero; part.Rig.angularVelocity = Vector3.zero; } } else { Transform transform2 = ((Component)part).transform; transform2.position += delta; } } } catch { Transform transform3 = ((Component)character).transform; transform3.position += delta; } } internal static MethodBase FindMushroomZombieAriseMethod() { try { MethodInfo methodInfo = null; MethodInfo[] methods = typeof(MushroomZombie).GetMethods(InstanceBindingFlags); foreach (MethodInfo methodInfo2 in methods) { if (!(methodInfo2.Name != "RPC_Arise")) { ParameterInfo[] parameters = methodInfo2.GetParameters(); if (parameters.Length != 0 && parameters[0].ParameterType == typeof(int)) { return methodInfo2; } if ((object)methodInfo == null) { methodInfo = methodInfo2; } } } return methodInfo; } catch { return null; } } internal static int GetMushroomZombieAriseSourceViewId(object[] args) { if (args == null || args.Length == 0 || args[0] == null) { return -1; } try { if (args[0] is int result) { return result; } return Convert.ToInt32(args[0], CultureInfo.InvariantCulture); } catch { return -1; } } internal static MethodBase FindMushroomZombieAwakeRoutineMoveNextMethod() { try { Type[] nestedTypes = typeof(MushroomZombie).GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic); foreach (Type type in nestedTypes) { if (!(type == null) && type.Name.IndexOf("AwakeRoutine", StringComparison.OrdinalIgnoreCase) >= 0) { MethodInfo method = type.GetMethod("MoveNext", InstanceBindingFlags); if (method != null) { return method; } } } } catch { } return null; } internal static bool TrySkipControlledZombieAwakeRoutine(object stateMachine, ref bool result) { MushroomZombie zombie = ResolveMushroomZombieAwakeRoutineOwner(stateMachine); if (!ShouldHandleControlledZombieAwakeRoutine(zombie)) { return false; } PrepareControlledZombieAwakeRoutine(zombie); result = false; return true; } internal static Exception FinalizeControlledZombieAwakeRoutine(object stateMachine, Exception exception) { if (exception == null) { return null; } MushroomZombie zombie = ResolveMushroomZombieAwakeRoutineOwner(stateMachine); if (!ShouldHandleControlledZombieAwakeRoutine(zombie)) { return exception; } PrepareControlledZombieAwakeRoutine(zombie); ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Suppressed controlled zombie AwakeRoutine exception: " + exception.Message)); } return null; } private static MushroomZombie ResolveMushroomZombieAwakeRoutineOwner(object stateMachine) { if (stateMachine == null) { return null; } try { Type type = stateMachine.GetType(); FieldInfo field = type.GetField("<>4__this", InstanceBindingFlags); if (field != null) { object? value = field.GetValue(stateMachine); MushroomZombie val = (MushroomZombie)((value is MushroomZombie) ? value : null); if ((Object)(object)val != (Object)null) { return val; } } FieldInfo[] fields = type.GetFields(InstanceBindingFlags); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo != null && typeof(MushroomZombie).IsAssignableFrom(fieldInfo.FieldType)) { object? value2 = fieldInfo.GetValue(stateMachine); MushroomZombie val2 = (MushroomZombie)((value2 is MushroomZombie) ? value2 : null); if ((Object)(object)val2 != (Object)null) { return val2; } } } } catch { } return null; } private static bool ShouldHandleControlledZombieAwakeRoutine(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null) { return false; } try { return IsControlledZombieBeingCreated(zombie) || IsControlledZombie(zombie); } catch { return false; } } private static void PrepareControlledZombieAwakeRoutine(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null) { return; } try { MarkControlledZombieForLocalSession(zombie); PreconfigureControlledZombieAwake(zombie); EnsureMushroomZombieNativeFields(zombie); Character component = ((Component)zombie).GetComponent(); Character sourceCharacter = ResolveControlledZombieSourceCharacter(zombie); PrepareControlledZombieCharacterRefs(component); ConfigureControlledZombieCustomizationForOwner(zombie, component, sourceCharacter); ApplyControlledZombieNativePresentation(zombie, component, sourceCharacter); SetControlledZombieName(zombie, component); LogVerbose("Handled controlled zombie AwakeRoutine manually."); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to handle controlled zombie AwakeRoutine: " + ex.Message)); } } } private static void EnsureMushroomZombieNativeFields(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null) { return; } try { Character component = ((Component)zombie).GetComponent(); PhotonView component2 = ((Component)zombie).GetComponent(); if ((Object)(object)component != (Object)null) { MushroomZombieCharacterField?.SetValue(zombie, component); } if ((Object)(object)component2 != (Object)null) { MushroomZombieViewField?.SetValue(zombie, component2); } } catch { } } private static void SetMushroomZombieStateSilently(MushroomZombie zombie, State state) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)zombie == (Object)null) { return; } try { if (MushroomZombieCurrentStateField != null) { MushroomZombieCurrentStateField.SetValue(zombie, state); } else { zombie.currentState = state; } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to set controlled zombie state: " + ex.Message)); } } } private static void PrepareControlledZombieCharacterRefs(Character character) { if ((Object)(object)character == (Object)null) { return; } try { RegisterControlledZombieAsVanillaPlayerCharacter(character); RefreshCharacterAfflictionSceneState(character); CharacterViewField?.SetValue(character, ((Component)character).GetComponent()); character.InitializeRefs(); if (character.refs != null && (Object)(object)character.refs.customization == (Object)null) { character.refs.customization = ((Component)character).GetComponentInChildren(true); } if ((Object)(object)character.refs?.customization != (Object)null) { CharacterCustomizationCharacterField?.SetValue(character.refs.customization, character); } character.isZombie = true; } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to prepare controlled zombie Character refs: " + ex.Message)); } } } private static void RegisterControlledZombieAsVanillaPlayerCharacter(Character character) { if ((Object)(object)character == (Object)null) { return; } try { character.isBot = false; Character.AllBotCharacters?.Remove(character); List allCharacters = Character.AllCharacters; if (allCharacters != null && !allCharacters.Contains(character)) { allCharacters.Add(character); } } catch (Exception ex) { LogVerbose("Failed to register controlled zombie as vanilla player character: " + ex.Message); } } private static void UnregisterControlledZombieAsVanillaPlayerCharacter(Character character) { if ((Object)(object)character == (Object)null) { return; } try { Character.AllCharacters?.Remove(character); Character.AllBotCharacters?.Remove(character); } catch (Exception ex) { LogVerbose("Failed to unregister controlled zombie from vanilla character lists: " + ex.Message); } } private static Character ResolveControlledZombieSourceCharacter(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null) { return null; } try { PhotonView photonView = ((MonoBehaviourPun)zombie).photonView; int value = -1; if ((Object)(object)photonView != (Object)null && photonView.ViewID > 0) { _controlledZombieSourceViewIdsByViewId.TryGetValue(photonView.ViewID, out value); if (value <= 0 && TryReadNetworkZombieInstantiationData(photonView, out var sourceViewId)) { value = sourceViewId; if (value > 0) { _controlledZombieSourceViewIdsByViewId[photonView.ViewID] = value; } } } PhotonView val = ((value > 0) ? PhotonNetwork.GetPhotonView(value) : null); return ((Object)(object)val != (Object)null) ? ((Component)val).GetComponent() : null; } catch { return null; } } private static void ConfigureControlledZombieCustomizationForOwner(MushroomZombie zombie, Character zombieCharacter, Character sourceCharacter) { CharacterCustomization val = ResolveCharacterCustomization(zombieCharacter); if ((Object)(object)val == (Object)null) { return; } try { Player val2 = ResolveSourcePhotonOwner(sourceCharacter) ?? ResolveZombiePhotonOwner(zombie) ?? ResolveLocalPhotonOwner(); if (val2 != null) { val.overridePhotonPlayer = val2; } } catch { } } private static Player ResolveZombiePhotonOwner(MushroomZombie zombie) { try { return ((Object)(object)zombie != (Object)null && (Object)(object)((MonoBehaviourPun)zombie).photonView != (Object)null) ? ((MonoBehaviourPun)zombie).photonView.Owner : null; } catch { return null; } } private static void SetControlledZombieName(MushroomZombie zombie, Character zombieCharacter) { if ((Object)(object)zombie == (Object)null) { return; } try { CharacterCustomization val = ResolveCharacterCustomization(zombieCharacter); Player val2 = (((Object)(object)val != (Object)null) ? val.overridePhotonPlayer : null); ((Object)((Component)zombie).gameObject).name = ((val2 != null) ? ("Zombie [" + val2.NickName + " : " + val2.ActorNumber.ToString(CultureInfo.InvariantCulture) + "]") : "Zombie (NPC)"); } catch { } } private static int GetCharacterViewId(Character character) { PhotonView val = ResolveCharacterPhotonView(character); if (!((Object)(object)val != (Object)null)) { return -1; } return val.ViewID; } private static PhotonView ResolveCharacterPhotonView(Character character) { if ((Object)(object)character == (Object)null) { return null; } try { PhotonView photonView = ((MonoBehaviourPun)character).photonView; if ((Object)(object)photonView != (Object)null) { return photonView; } } catch { } try { return ((Component)character).GetComponent(); } catch { return null; } } private static bool IsImZombieNetworkSpawn(Character character) { return IsImZombieNetworkSpawn(ResolveCharacterPhotonView(character)); } internal static Transform ResolveHeadTransform(Character character) { if ((Object)(object)character == (Object)null) { return null; } if (!((Object)(object)character.refs?.head != (Object)null)) { return null; } return ((Component)character.refs.head).transform; } internal static bool ShouldForceShowControlledZombie(Character character) { if ((Object)(object)character != (Object)null && HasMushroomZombieComponent(character)) { return IsControlledZombieCharacter(character); } return false; } internal static void PreconfigureControlledZombieAwake(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null || (!IsControlledZombieBeingCreated(zombie) && !IsControlledZombie(zombie))) { return; } try { MarkControlledZombieForLocalSession(zombie); zombie.isNPCZombie = false; zombie.targetForcedUntil = 0f; zombie.initialWakeUpTime = 0f; zombie.lifetime = float.PositiveInfinity; zombie.currentTarget = null; Character component = ((Component)zombie).GetComponent(); if ((Object)(object)component != (Object)null) { component.isZombie = true; } LogVerbose("Preconfigured controlled zombie before vanilla MushroomZombie.Awake."); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to preconfigure controlled network zombie Awake: " + ex.Message)); } } } internal static bool ShouldSkipControlledZombieAwake(MushroomZombie zombie) { if ((Object)(object)zombie != (Object)null) { if (!IsControlledZombieBeingCreated(zombie)) { return IsControlledZombie(zombie); } return true; } return false; } internal static bool ShouldSkipZombieManagerRegistration(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null) { return false; } if (IsCreatingControlledPlayerZombieNetworkResource()) { PreconfigureControlledZombieAwake(zombie); return true; } if (!IsControlledZombie(zombie)) { return IsControlledZombieBeingCreated(zombie); } return true; } internal static bool ShouldUseIsolatedCharacterLifecycle(Character character) { if ((Object)(object)character == (Object)null || !HasMushroomZombieComponent(character)) { return false; } if (IsCharacterInControlledCreationRoot(character) || IsCreatingControlledPlayerZombieNetworkResource()) { return true; } return IsLocallyControlledZombieCharacter(character); } internal static void RunIsolatedCharacterAwake(Character character) { if ((Object)(object)character == (Object)null) { return; } try { RegisterControlledZombieAsVanillaPlayerCharacter(character); RefreshCharacterAfflictionSceneState(character); CharacterViewField?.SetValue(character, ((Component)character).GetComponent()); character.InitializeRefs(); CharacterInput input = character.input; if (input != null) { input.Init(); } LogVerbose("Initialized controlled zombie character without player registration."); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Isolated character Awake failed: " + ex.Message)); } } } internal static void RunIsolatedCharacterStart(Character character) { //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_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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null || IsCharacterStarted(character)) { return; } try { CharacterStartedField?.SetValue(character, true); if (character.refs != null) { character.refs.hip = GetCharacterBodypart(character, (BodypartType)0); character.refs.head = GetCharacterBodypart(character, (BodypartType)4); } Bodypart characterBodypart = GetCharacterBodypart(character, (BodypartType)4); Vector3 val = ((!((Object)(object)characterBodypart != (Object)null)) ? character.Head : ((Component)characterBodypart).transform.TransformPoint(Vector3.up)); CharacterSmoothedCamPosField?.SetValue(character, val); ((Object)((Component)character).gameObject).name = "Local Player Zombie"; } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Isolated character Start failed: " + ex.Message)); } } } internal static void RunIsolatedCharacterDataAwake(CharacterData data, Character character) { if ((Object)(object)data == (Object)null) { return; } try { if ((Object)(object)character == (Object)null) { character = ((Component)data).GetComponent(); } CharacterDataCharacterField?.SetValue(data, character); LogVerbose("Initialized controlled zombie CharacterData without badge RPC."); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Isolated CharacterData Awake failed: " + ex.Message)); } } } internal static bool ShouldSkipControlledZombieBadgeStatus(CharacterData data) { return ShouldUseIsolatedCharacterLifecycle(ResolveCharacterDataCharacter(data)); } internal static bool ShouldSkipControlledZombieCustomizationStart(CharacterCustomization customization) { if ((Object)(object)customization == (Object)null) { return false; } if (!ShouldUseIsolatedCharacterLifecycle(ResolveCustomizationCharacter(customization))) { return false; } if (customization.overridePhotonPlayer != null) { return false; } Player val = ResolveSourcePhotonOwner(null) ?? ResolveLocalPhotonOwner(); if (val != null) { customization.overridePhotonPlayer = val; return false; } LogVerbose("Skipped controlled zombie CharacterCustomization Start because no Photon owner is available."); return true; } internal static bool ShouldSkipControlledZombieCustomizationDestroy(CharacterCustomization customization) { Character val = ResolveCustomizationCharacter(customization); if (!IsImZombieManagedCharacter(val)) { return false; } if (ShouldUseIsolatedCharacterLifecycle(val)) { return true; } try { PhotonView photonView = ((MonoBehaviourPun)val).photonView; return (Object)(object)photonView == (Object)null || photonView.ViewID <= 0 || photonView.Owner == null; } catch { return true; } } private static Character ResolveCharacterDataCharacter(CharacterData data) { if ((Object)(object)data == (Object)null) { return null; } try { object? obj = CharacterDataCharacterField?.GetValue(data); Character val = (Character)((obj is Character) ? obj : null); return ((Object)(object)val != (Object)null) ? val : ((Component)data).GetComponent(); } catch { return null; } } private static Character ResolveCustomizationCharacter(CharacterCustomization customization) { if ((Object)(object)customization == (Object)null) { return null; } try { object? obj = CharacterCustomizationCharacterField?.GetValue(customization); Character val = (Character)((obj is Character) ? obj : null); if ((Object)(object)val != (Object)null) { return val; } val = ((Component)customization).GetComponent(); return ((Object)(object)val != (Object)null) ? val : ((Component)customization).GetComponentInParent(); } catch { return null; } } private static void ConfigureControlledZombieCustomization(Character zombieCharacter, Character sourceCharacter) { CharacterCustomization val = ResolveCharacterCustomization(zombieCharacter); if ((Object)(object)val == (Object)null) { return; } try { Player val2 = ResolveSourcePhotonOwner(sourceCharacter) ?? ResolveLocalPhotonOwner(); if (val2 != null) { val.overridePhotonPlayer = val2; } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to configure controlled zombie customization: " + ex.Message)); } } } private static CharacterCustomization ResolveCharacterCustomization(Character character) { if ((Object)(object)character == (Object)null) { return null; } try { return character.refs?.customization ?? ((Component)character).GetComponent() ?? ((Component)character).GetComponentInChildren(true); } catch { return null; } } private static void RestoreCharacterHumanPresentation(Character character, bool resetCamera) { if ((Object)(object)character == (Object)null) { return; } try { CharacterCustomization val = ResolveCharacterCustomization(character); if ((Object)(object)val != (Object)null) { try { CustomizationRefs refs = val.refs; if (refs != null) { refs.SetMushroomMan(false); } } catch { } try { val.ShowAllRenderers(); } catch { } } try { CharacterZombieFailsafeMethod?.Invoke(character, Array.Empty()); } catch { } if (resetCamera) { EnsureUsableLookState(character); ResetMainCameraState(character, snapCamera: true); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to restore human presentation: " + ex.Message)); } } } private static Player ResolveSourcePhotonOwner(Character sourceCharacter) { try { return ((Object)(object)sourceCharacter != (Object)null && (Object)(object)((MonoBehaviourPun)sourceCharacter).photonView != (Object)null) ? ((MonoBehaviourPun)sourceCharacter).photonView.Owner : null; } catch { return null; } } private static Player ResolveLocalPhotonOwner() { try { return ((Object)(object)Player.localPlayer != (Object)null && (Object)(object)((MonoBehaviourPun)Player.localPlayer).photonView != (Object)null) ? ((MonoBehaviourPun)Player.localPlayer).photonView.Owner : null; } catch { return null; } } private static Bodypart GetCharacterBodypart(Character character, BodypartType bodypartType) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null || CharacterGetBodypartMethod == null) { return null; } try { object? obj = CharacterGetBodypartMethod.Invoke(character, new object[1] { bodypartType }); return (Bodypart)((obj is Bodypart) ? obj : null); } catch { return null; } } private static bool IsCharacterStarted(Character character) { if ((Object)(object)character == (Object)null || CharacterStartedField == null) { return false; } try { return (bool)CharacterStartedField.GetValue(character); } catch { return false; } } internal static bool IsControlledZombieCharacter(Character character) { return IsImZombieManagedCharacter(character); } internal static bool IsLocallyControlledZombieCharacter(Character character) { if ((Object)(object)character == (Object)null) { return false; } if ((Object)(object)character == (Object)(object)_cameraOverrideCharacter) { return true; } try { PlayerZombieController component = ((Component)character).GetComponent(); return (Object)(object)component != (Object)null && ((Behaviour)component).enabled; } catch { return false; } } internal static bool IsLocallyControlledZombie(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null) { return false; } try { if (IsLocallyControlledZombieCharacter(((Component)zombie).GetComponent())) { return true; } PlayerZombieController component = ((Component)zombie).GetComponent(); return (Object)(object)component != (Object)null && ((Behaviour)component).enabled; } catch { return false; } } internal static bool IsControlledZombieOriginalAiActive(Character character) { if ((Object)(object)character == (Object)null) { return false; } try { PlayerZombieController component = ((Component)character).GetComponent(); return (Object)(object)component != (Object)null && ((Behaviour)component).enabled && component.IsOriginalAiEnabled; } catch { return false; } } internal static bool ShouldSkipThirdPartyCharacterTracking(Character character) { if (!IsControlledZombieCharacter(character) && !IsStashedSourceCharacter(character)) { return IsStatusUiSuppressedCharacter(character); } return true; } private static bool MikuDanceTryExtractTransformPrefix(object source, [HarmonyArgument(1)] ref Transform transform, ref bool __result) { if (!IsDestroyedUnityObject(source)) { return true; } transform = null; __result = false; return false; } private static Exception MikuDanceTryExtractTransformFinalizer(Exception __exception, [HarmonyArgument(1)] ref Transform transform, ref bool __result) { if (__exception == null) { return null; } if (__exception is NullReferenceException || __exception is MissingReferenceException) { transform = null; __result = false; return null; } return __exception; } private static bool IsDestroyedUnityObject(object value) { if (value == null) { return true; } try { Object val = (Object)((value is Object) ? value : null); return val != null && val == (Object)null; } catch { return false; } } private static bool ThirdPartyStatusMethodPrefix(MethodBase __originalMethod, object[] __args, ref List __state) { __state = null; if (!HasThirdPartyStatusProtectionWork()) { return true; } if (__args == null) { if (ShouldApplyThirdPartyAllCharactersShield(__originalMethod, argumentCharactersResolved: false)) { return ExtractThirdPartyCharactersForShield(ref __state); } return true; } bool argumentCharactersResolved = false; for (int i = 0; i < __args.Length; i++) { if (TryResolveThirdPartyStatusCharacter(__args[i], out var character)) { argumentCharactersResolved = true; if (ShouldSkipThirdPartyStatusCharacter(character)) { return false; } } } if (ShouldApplyThirdPartyAllCharactersShield(__originalMethod, argumentCharactersResolved)) { ExtractThirdPartyCharactersForShield(ref __state); } return true; } private static Exception ThirdPartyStatusMethodFinalizer(Exception __exception, List __state) { RestoreThirdPartySkippedCharactersToAllCharacters(__state); return __exception; } private static bool ShouldApplyThirdPartyAllCharactersShield(MethodBase method, bool argumentCharactersResolved) { if (method == null) { return false; } Type declaringType = method.DeclaringType; if (declaringType == null || !IsLikelyThirdPartyStatusUiType(declaringType)) { return false; } if (!argumentCharactersResolved) { return true; } return IsPeakStatsExAssembly(declaringType.Assembly); } private static bool ExtractThirdPartyCharactersForShield(ref List removedCharacters) { removedCharacters = ExtractThirdPartySkippedCharactersFromAllCharacters(); return true; } private static bool IsInPeakStatsCleanupGraceWindow() { return Time.unscaledTime <= _peakStatsCleanupGraceUntil; } private static void BeginPeakStatsCleanupGraceWindow() { _peakStatsCleanupGraceUntil = Time.unscaledTime + 1.25f; } private static void RegisterStatusUiSuppressedCharacter(Character character, float durationSeconds = 3f) { if ((Object)(object)character == (Object)null) { return; } int instanceID = ((Object)character).GetInstanceID(); if (instanceID != 0) { float num = Time.unscaledTime + Mathf.Max(0.1f, durationSeconds); if (_statusUiSuppressedCharacterUntilById.TryGetValue(instanceID, out var value)) { _statusUiSuppressedCharacterUntilById[instanceID] = Mathf.Max(value, num); } else { _statusUiSuppressedCharacterUntilById.Add(instanceID, num); } } } private static bool IsStatusUiSuppressedCharacter(Character character) { if ((Object)(object)character == (Object)null) { return false; } int instanceID = ((Object)character).GetInstanceID(); if (instanceID == 0 || !_statusUiSuppressedCharacterUntilById.TryGetValue(instanceID, out var value)) { return false; } if (Time.unscaledTime <= value) { return true; } _statusUiSuppressedCharacterUntilById.Remove(instanceID); return false; } private static void UnregisterStatusUiSuppressedCharacter(Character character) { if (!((Object)(object)character == (Object)null)) { int instanceID = ((Object)character).GetInstanceID(); if (instanceID != 0) { _statusUiSuppressedCharacterUntilById.Remove(instanceID); } } } private static void PruneExpiredStatusUiSuppressedCharacters() { if (_statusUiSuppressedCharacterUntilById.Count == 0) { return; } float unscaledTime = Time.unscaledTime; List list = null; foreach (KeyValuePair item in _statusUiSuppressedCharacterUntilById) { if (!(unscaledTime <= item.Value)) { if (list == null) { list = new List(); } list.Add(item.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { _statusUiSuppressedCharacterUntilById.Remove(list[i]); } } } private static bool IsInvalidPeakStatsCharacter(Character character) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null) { return true; } try { if ((Object)(object)((Component)character).gameObject == (Object)null || !((Component)character).gameObject.activeInHierarchy) { return true; } } catch { return true; } try { if ((Object)(object)character.data == (Object)null || character.refs == null) { return true; } } catch { return true; } try { if (!IsFiniteVector(character.Head)) { return true; } } catch { return true; } return false; } private static bool ShouldSkipPeakStatsCharacter(Character character) { if (!HasThirdPartyStatusProtectionWork()) { return false; } if (IsInPeakStatsCleanupGraceWindow()) { return true; } if (!ShouldSkipThirdPartyCharacterTracking(character)) { return IsInvalidPeakStatsCharacter(character); } return true; } private static bool ShouldSkipThirdPartyStatusCharacter(Character character) { if (!HasThirdPartyStatusProtectionWork()) { return false; } if (!ShouldSkipThirdPartyCharacterTracking(character)) { return IsInvalidPeakStatsCharacter(character); } return true; } private static bool PeakStatsProximityManagerUpdatePrefix(object __instance) { if (!HasThirdPartyStatusProtectionWork()) { return true; } PrunePeakStatsControlledZombieBars(__instance); return !ShouldBlockPeakStatsUpdate(); } private static bool PeakStatsCreateStaminaBarPrefix(Character observedCharacter) { return !ShouldSkipPeakStatsCharacter(observedCharacter); } private static bool ShouldBlockPeakStatsUpdate() { if (!IsInPeakStatsCleanupGraceWindow() && _controlledZombieCharacterInstanceIds.Count <= 0 && _stashedSourceCharacterIds.Count <= 0) { return _statusUiSuppressedCharacterUntilById.Count > 0; } return true; } private static bool HasThirdPartyStatusProtectionWork() { if (!IsInPeakStatsCleanupGraceWindow()) { return HasThirdPartyStatusCleanupWork(); } return true; } private static List ExtractThirdPartySkippedCharactersFromAllCharacters() { List allCharacters = Character.AllCharacters; if (allCharacters == null || allCharacters.Count == 0) { return null; } List list = null; for (int num = allCharacters.Count - 1; num >= 0; num--) { Character val = allCharacters[num]; if (ShouldSkipThirdPartyStatusCharacter(val)) { if (list == null) { list = new List(); } list.Add(val); allCharacters.RemoveAt(num); } } return list; } private static void RestoreThirdPartySkippedCharactersToAllCharacters(List removed) { if (removed == null || removed.Count == 0) { return; } List allCharacters = Character.AllCharacters; if (allCharacters == null) { return; } for (int num = removed.Count - 1; num >= 0; num--) { Character val = removed[num]; if ((Object)(object)val != (Object)null && !allCharacters.Contains(val)) { allCharacters.Add(val); } } } private static bool PeakStatsCharacterStaminaBarUpdatePrefix(object __instance) { if (!ShouldSkipPeakStatsObject(__instance)) { return true; } DisablePeakStatsComponent(__instance); return false; } private static bool PeakStatsCharacterBarAfflictionFetchReferencesPrefix(object __instance) { if (!ShouldSkipPeakStatsAffliction(__instance)) { return true; } DisablePeakStatsComponent(__instance); return false; } private static bool ShouldSkipPeakStatsObject(object instance) { if (instance == null || PeakStatsObservedCharacterField == null) { return false; } try { object? value = PeakStatsObservedCharacterField.GetValue(instance); return ShouldSkipPeakStatsCharacter((Character)((value is Character) ? value : null)); } catch { return false; } } private static bool ShouldSkipPeakStatsAffliction(object instance) { if (instance == null || PeakStatsAfflictionBarField == null) { return false; } try { return ShouldSkipPeakStatsObject(PeakStatsAfflictionBarField.GetValue(instance)); } catch { return false; } } private static void DisablePeakStatsComponent(object instance) { try { Behaviour val = (Behaviour)((instance is Behaviour) ? instance : null); if (val != null) { if (val.enabled) { val.enabled = false; } GameObject gameObject = ((Component)val).gameObject; if ((Object)(object)gameObject != (Object)null && gameObject.activeSelf) { gameObject.SetActive(false); } } } catch { } } private static void CleanupPeakStatsUi(bool aggressive = false) { CleanupPeakStatsObjects(PeakStatsStaminaBarType, aggressive ? new Func(ShouldCleanupPeakStatsObjectAggressive) : new Func(ShouldSkipPeakStatsObject)); CleanupPeakStatsObjects(PeakStatsAfflictionType, aggressive ? new Func(ShouldCleanupPeakStatsAfflictionAggressive) : new Func(ShouldSkipPeakStatsAffliction)); } private static void RequestThirdPartyStatusUiCleanup(bool aggressive = false) { if (!HasThirdPartyStatusCleanupWork()) { Plugin instance = Instance; if ((Object)(object)instance != (Object)null) { instance._pendingThirdPartyStatusUiCleanup = false; instance._pendingThirdPartyStatusUiCleanupAggressive = false; } } else { Plugin instance2 = Instance; if ((Object)(object)instance2 != (Object)null) { instance2._pendingThirdPartyStatusUiCleanup = true; instance2._pendingThirdPartyStatusUiCleanupAggressive |= aggressive; } else { CleanupThirdPartyStatusUi(aggressive); } } } private static void CleanupThirdPartyStatusUi(bool aggressive = false) { if (HasThirdPartyStatusCleanupWork()) { CleanupPeakStatsUi(aggressive); PruneGenericThirdPartyStatusDictionaries(); CleanupGenericThirdPartyStatusObjects(aggressive); } } private static bool HasThirdPartyStatusCleanupWork() { if (_controlledZombieCharacterInstanceIds.Count > 0 || _stashedSourceCharacterIds.Count > 0 || _statusUiSuppressedCharacterUntilById.Count > 0) { return true; } Plugin instance = Instance; if (instance == null) { return false; } return (instance._session?.IsActive).GetValueOrDefault(); } private static void ClearManagedCharacterTrackingForSceneTransition() { _controlledZombieInstanceIds.Clear(); _controlledZombieCharacterInstanceIds.Clear(); _controlledZombieViewIds.Clear(); _controlledZombieSourceViewIdsByViewId.Clear(); _localMushroomGrowthInitializedZombieIds.Clear(); _stashedSourceCharacterIds.Clear(); _statusUiSuppressedCharacterUntilById.Clear(); } private static void CleanupGenericThirdPartyStatusObjects(bool aggressive) { try { Object[] array = Resources.FindObjectsOfTypeAll(typeof(Behaviour)); if (array == null || array.Length == 0) { return; } foreach (Object obj in array) { Behaviour val = (Behaviour)(object)((obj is Behaviour) ? obj : null); if (val == null || (Object)(object)val == (Object)null || !IsLikelyThirdPartyStatusUiType(((object)val).GetType()) || !TryResolveThirdPartyStatusCharacter(val, out var character)) { continue; } bool num; if (!aggressive) { if (ShouldSkipThirdPartyCharacterTracking(character)) { goto IL_0067; } num = IsInvalidPeakStatsCharacter(character); } else { num = ShouldSkipThirdPartyStatusCharacter(character); } if (!num) { continue; } goto IL_0067; IL_0067: DisablePeakStatsComponent(val); try { Object.Destroy((Object)(object)((Component)val).gameObject); } catch { } } } catch { } } private static void PruneGenericThirdPartyStatusDictionaries() { try { Object[] array = Resources.FindObjectsOfTypeAll(typeof(Behaviour)); if (array == null || array.Length == 0) { return; } foreach (Object obj in array) { Behaviour val = (Behaviour)(object)((obj is Behaviour) ? obj : null); if (val == null || (Object)(object)val == (Object)null) { continue; } Type type = ((object)val).GetType(); if (!IsLikelyThirdPartyStatusUiType(type)) { continue; } FieldInfo[] cachedThirdPartyStatusFields = GetCachedThirdPartyStatusFields(type); foreach (FieldInfo fieldInfo in cachedThirdPartyStatusFields) { if (!(fieldInfo == null) && typeof(IDictionary).IsAssignableFrom(fieldInfo.FieldType)) { IDictionary dictionary = null; try { dictionary = fieldInfo.GetValue(val) as IDictionary; } catch { } if (dictionary != null && dictionary.Count != 0) { PruneThirdPartyStatusDictionary(dictionary); } } } } } catch { } } private static void PruneThirdPartyStatusDictionary(IDictionary dictionary) { List list = null; foreach (DictionaryEntry item in dictionary) { Character character = null; bool flag = false; Character character3; if (TryResolveThirdPartyStatusCharacter(item.Key, out var character2)) { character = character2; flag = true; } else if (TryResolveThirdPartyStatusCharacter(item.Value, out character3)) { character = character3; flag = true; } if (flag && ShouldSkipThirdPartyStatusCharacter(character)) { if (list == null) { list = new List(); } list.Add(item.Key); DisablePeakStatsComponent(item.Value); } } if (list == null) { return; } for (int i = 0; i < list.Count; i++) { try { dictionary.Remove(list[i]); } catch { } } } private static bool TryResolveThirdPartyStatusCharacter(object instance, out Character character) { return TryResolveThirdPartyStatusCharacter(instance, out character, 0); } private static bool TryResolveThirdPartyStatusCharacter(object instance, out Character character, int depth) { character = null; if (instance == null || depth > 3) { return false; } Character val = (Character)((instance is Character) ? instance : null); if (val != null) { character = val; return (Object)(object)character != (Object)null; } Component val2 = (Component)((instance is Component) ? instance : null); if (val2 != null && (Object)(object)val2 != (Object)null) { try { Character component = val2.GetComponent(); if ((Object)(object)component != (Object)null) { character = component; return true; } } catch { } } Type type = instance.GetType(); FieldInfo[] cachedThirdPartyStatusFields = GetCachedThirdPartyStatusFields(type); foreach (FieldInfo fieldInfo in cachedThirdPartyStatusFields) { if (!(fieldInfo == null) && !fieldInfo.IsStatic) { object value; try { value = fieldInfo.GetValue(instance); } catch { continue; } Character val3 = (Character)((value is Character) ? value : null); if (val3 != null && (Object)(object)val3 != (Object)null) { character = val3; return true; } if (value != null && depth < 3 && IsLikelyThirdPartyStatusUiType(value.GetType()) && TryResolveThirdPartyStatusCharacter(value, out character, depth + 1)) { return true; } } } PropertyInfo[] cachedThirdPartyStatusProperties = GetCachedThirdPartyStatusProperties(type); foreach (PropertyInfo propertyInfo in cachedThirdPartyStatusProperties) { if (propertyInfo == null || propertyInfo.GetIndexParameters().Length != 0 || !typeof(Character).IsAssignableFrom(propertyInfo.PropertyType)) { continue; } try { object? value2 = propertyInfo.GetValue(instance, null); character = (Character)((value2 is Character) ? value2 : null); if ((Object)(object)character != (Object)null) { return true; } } catch { } } Component val4 = (Component)((instance is Component) ? instance : null); if (val4 != null && (Object)(object)val4 != (Object)null && depth == 0) { try { Transform parent = val4.transform.parent; int num = 0; while ((Object)(object)parent != (Object)null && num < 3) { Component[] components = ((Component)parent).GetComponents(); foreach (Component val5 in components) { if (!((Object)(object)val5 == (Object)null) && IsLikelyThirdPartyStatusUiType(((object)val5).GetType()) && TryResolveThirdPartyStatusCharacter(val5, out character, depth + 1)) { return true; } } parent = parent.parent; num++; } } catch { } } return false; } private static FieldInfo[] GetCachedThirdPartyStatusFields(Type type) { if (type == null) { return Array.Empty(); } if (_thirdPartyStatusFieldCache.TryGetValue(type, out var value)) { return value; } try { value = type.GetFields(InstanceBindingFlags); } catch { value = Array.Empty(); } _thirdPartyStatusFieldCache[type] = value; return value; } private static PropertyInfo[] GetCachedThirdPartyStatusProperties(Type type) { if (type == null) { return Array.Empty(); } if (_thirdPartyStatusPropertyCache.TryGetValue(type, out var value)) { return value; } try { value = type.GetProperties(InstanceBindingFlags); } catch { value = Array.Empty(); } _thirdPartyStatusPropertyCache[type] = value; return value; } private static bool IsLikelyThirdPartyStatusUiType(Type type) { if (type == null) { return false; } Assembly assembly = type.Assembly; if (assembly == typeof(Plugin).Assembly) { return false; } string text = type.FullName ?? type.Name; if (string.IsNullOrEmpty(text) || text.StartsWith("UnityEngine.", StringComparison.Ordinal) || text.StartsWith("TMPro.", StringComparison.Ordinal) || text.StartsWith("BepInEx.", StringComparison.Ordinal) || text.StartsWith("HarmonyLib.", StringComparison.Ordinal) || text.StartsWith("Photon.", StringComparison.Ordinal)) { return false; } if (!ContainsOrdinalIgnoreCase(text, "stamina") && !ContainsOrdinalIgnoreCase(text, "status") && !ContainsOrdinalIgnoreCase(text, "affliction") && !ContainsOrdinalIgnoreCase(text, "health") && !ContainsOrdinalIgnoreCase(text, "characterbar") && !ContainsOrdinalIgnoreCase(text, "baraffliction") && !ContainsOrdinalIgnoreCase(text, "stats")) { return IsPeakStatsExAssembly(assembly); } return true; } private static bool IsPeakStatsExPluginLoaded() { if (Chainloader.PluginInfos.TryGetValue("com.github.LengSword.PeakStatsEx", out var value) && (Object)(object)((value != null) ? value.Instance : null) != (Object)null) { return true; } Assembly[] assemblies; try { assemblies = AppDomain.CurrentDomain.GetAssemblies(); } catch { return false; } for (int i = 0; i < assemblies.Length; i++) { if (IsPeakStatsExAssembly(assemblies[i])) { return true; } } return false; } private static bool IsPeakStatsExAssembly(Assembly assembly) { if (assembly == null) { return false; } string value = string.Empty; string value2 = string.Empty; string value3 = string.Empty; try { value = assembly.GetName().Name ?? string.Empty; } catch { } try { value2 = assembly.FullName ?? string.Empty; } catch { } try { value3 = assembly.Location ?? string.Empty; } catch { } if (!ContainsOrdinalIgnoreCase(value, "PeakStatsEx") && !ContainsOrdinalIgnoreCase(value2, "com.github.LengSword.PeakStatsEx")) { return ContainsOrdinalIgnoreCase(value3, "PeakStatsEx"); } return true; } private static bool ContainsOrdinalIgnoreCase(string value, string fragment) { if (value != null && fragment != null) { return value.IndexOf(fragment, StringComparison.OrdinalIgnoreCase) >= 0; } return false; } private static bool ShouldCleanupPeakStatsObjectAggressive(object instance) { if (instance == null || PeakStatsObservedCharacterField == null) { return true; } try { object? value = PeakStatsObservedCharacterField.GetValue(instance); return ShouldSkipPeakStatsCharacter((Character)((value is Character) ? value : null)); } catch { return true; } } private static bool ShouldCleanupPeakStatsAfflictionAggressive(object instance) { if (instance == null || PeakStatsAfflictionBarField == null) { return true; } try { return ShouldCleanupPeakStatsObjectAggressive(PeakStatsAfflictionBarField.GetValue(instance)); } catch { return true; } } private static void CleanupPeakStatsObjects(Type componentType, Func shouldRemove) { if (componentType == null || shouldRemove == null) { return; } try { Object[] array = Resources.FindObjectsOfTypeAll(componentType); if (array == null || array.Length == 0) { return; } foreach (object obj in array) { if (obj == null || !shouldRemove(obj)) { continue; } DisablePeakStatsComponent(obj); Component val = (Component)((obj is Component) ? obj : null); if (val != null && (Object)(object)val != (Object)null) { try { Object.Destroy((Object)(object)val.gameObject); } catch { } } } } catch { } } private static void PrunePeakStatsControlledZombieBars(object managerInstance) { if (managerInstance == null || PeakStatsStaminaBarsField == null) { return; } try { if (!(PeakStatsStaminaBarsField.GetValue(managerInstance) is IDictionary dictionary) || dictionary.Count == 0) { return; } List list = null; foreach (DictionaryEntry item in dictionary) { object key = item.Key; Character val = (Character)((key is Character) ? key : null); if (val != null && ShouldSkipPeakStatsCharacter(val)) { if (list == null) { list = new List(); } list.Add(item.Key); DisablePeakStatsComponent(item.Value); } } if (list != null) { for (int i = 0; i < list.Count; i++) { dictionary.Remove(list[i]); } } } catch { } } internal static bool IsStashedSourceCharacter(Character character) { if ((Object)(object)character == (Object)null) { return false; } return _stashedSourceCharacterIds.Contains(((Object)character).GetInstanceID()); } internal static bool ShouldDisableInventoryForCharacter(Character character) { if (!IsControlledZombieCharacter(character)) { return IsStashedSourceCharacter(character); } return true; } internal static void ResetDisabledInventoryState(CharacterItems items, Character character) { if ((Object)(object)character == (Object)null && (Object)(object)items != (Object)null) { character = ((Component)items).GetComponent(); } if ((Object)(object)items == (Object)null && (Object)(object)character != (Object)null) { items = character.refs?.items ?? ((Component)character).GetComponent(); } if ((Object)(object)items != (Object)null) { items.throwChargeLevel = 0f; items.isChargingThrow = false; } if (!IsControlledZombieCharacter(character)) { return; } ClearSelectedInventorySlots(items); if ((Object)(object)character?.data == (Object)null) { return; } try { Item currentItem = character.data.currentItem; if ((Object)(object)currentItem != (Object)null) { currentItem.CancelUsePrimary(); currentItem.CancelUseSecondary(); } if ((Object)(object)items != (Object)null) { items.UnAttachEquippedItem(); } else { character.data.currentItem = null; } } catch { character.data.currentItem = null; } } internal static bool ShouldSuppressControlledCharacterFall(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return false; } if (!IsStashedSourceCharacter(character)) { return false; } character.data.fallSeconds = 0f; character.data.passedOut = false; character.data.fullyPassedOut = false; character.data.passOutValue = 0f; character.data.deathTimer = 0f; character.data.currentRagdollControll = 1f; character.data.sinceFallSlide = 0f; return true; } internal static void ClearControlledZombieExternalPassOutState(Character character) { if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null)) { character.data.dead = false; character.data.passedOut = false; character.data.fullyPassedOut = false; character.data.passOutValue = 0f; character.data.deathTimer = 0f; character.data.fallSeconds = 0f; character.data.currentRagdollControll = 1f; character.data.sinceFallSlide = 0f; ClearControlledZombieExternalPassOutAfflictions(character); } } private static void ClearControlledZombieExternalPassOutAfflictions(Character character) { if ((Object)(object)character == (Object)null) { return; } try { CharacterAfflictions val = character.refs?.afflictions; if ((Object)(object)val == (Object)null) { val = ((Component)character).GetComponent(); } if (!((Object)(object)val == (Object)null)) { val.RemoveAffliction((AfflictionType)11); if (val.GetCurrentStatus((STATUSTYPE)6) > 0f) { val.SetStatus((STATUSTYPE)6, 0f, false); } } } catch { } } internal static bool ShouldSuppressControlledZombieStatus(CharacterAfflictions afflictions, STATUSTYPE statusType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)statusType != 6) { return false; } Character val = null; try { val = (((Object)(object)afflictions != (Object)null) ? (afflictions.character ?? ((Component)afflictions).GetComponent()) : null); } catch { val = null; } if ((Object)(object)val == (Object)null || !IsStashedSourceCharacter(val)) { return false; } ClearControlledZombieExternalPassOutState(val); return true; } internal static bool IsControlledZombieIncapacitated(Character character) { if (!IsControlledZombieCharacter(character) || (Object)(object)character?.data == (Object)null) { return false; } try { return character.data.passedOut || character.data.fullyPassedOut || character.data.fallSeconds > 0.05f || character.data.currentRagdollControll < 0.95f; } catch { return false; } } internal static bool ShouldSkipCharacterFixedUpdate(Character character) { if (!IsStashedSourceCharacter(character)) { if (_skipControlledCharacterFixedUpdate && IsLocallyControlledZombieCharacter(character)) { return !IsControlledZombieOriginalAiActive(character); } return false; } return true; } internal static bool ShouldUseControlledZombieKinematicLocomotion(Character character) { if (_skipControlledCharacterFixedUpdate && IsLocallyControlledZombieCharacter(character)) { return !IsControlledZombieOriginalAiActive(character); } return false; } internal static bool ShouldSkipCharacterMovementUpdate(Character character) { return IsStashedSourceCharacter(character); } internal static bool TryHandleControlledZombieJump(Character character) { if (!IsLocallyControlledZombieCharacter(character) || IsControlledZombieOriginalAiActive(character)) { return false; } ApplyControlledZombieLocalJump(character); return true; } internal static bool ShouldSuppressControlledZombieJumpRpc(Character character) { if (IsLocallyControlledZombieCharacter(character)) { return !IsControlledZombieOriginalAiActive(character); } return false; } internal static void PlayControlledZombieSfx(MushroomZombie zombie, int sfxIndex) { //IL_0029: 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_002e: 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_006b: 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) if ((Object)(object)zombie == (Object)null) { return; } try { Character component = ((Component)zombie).GetComponent(); Vector3 val = (((Object)(object)component != (Object)null) ? component.Center : ((Component)zombie).transform.position); switch (sfxIndex) { case 0: if ((Object)(object)zombie.gruntSFX != (Object)null) { zombie.gruntSFX.Play(val); } break; case 1: { SFX_Instance knockoutSFX = zombie.knockoutSFX; if (knockoutSFX != null) { knockoutSFX.Play(val); } break; } case 2: { if (zombie.biteSFX == null) { break; } SFX_Instance[] biteSFX = zombie.biteSFX; foreach (SFX_Instance obj in biteSFX) { if (obj != null) { obj.Play(val); } } break; } } } catch { } } internal static bool TryHandleControlledZombieBitCharacter(MushroomZombie zombie, Character bitCharacter) { if (!IsControlledZombie(zombie)) { return false; } try { if ((Object)(object)bitCharacter == (Object)null || bitCharacter.IsLocal) { PlayControlledZombieSfx(zombie, 2); } } catch { PlayControlledZombieSfx(zombie, 2); } return true; } internal static bool ShouldRunControlledZombieOriginalBitCharacter(MushroomZombie zombie, Character bitCharacter) { if (!IsControlledZombie(zombie) || (Object)(object)bitCharacter == (Object)null || !IsRunGameplayReady()) { return false; } if (IsControlledZombieCharacter(bitCharacter) || IsStashedSourceCharacter(bitCharacter)) { return false; } return true; } internal static bool ShouldSuppressControlledZombieBiteCollider(MushroomZombieBiteCollider biteCollider, Collider other) { MushroomZombie zombie = (((Object)(object)biteCollider != (Object)null) ? biteCollider.parentZombie : null); if (!IsControlledZombie(zombie)) { return false; } Character val = null; try { if ((Object)(object)other != (Object)null) { CharacterRagdoll.TryGetCharacterFromCollider(other, ref val); } } catch { val = null; } if ((Object)(object)val == (Object)null) { return !IsRunGameplayReady(); } if (IsControlledZombieCharacter(val) || IsStashedSourceCharacter(val)) { PlayControlledZombieSfx(zombie, 2); return true; } try { if (val.IsLocal && !IsRunGameplayReady()) { PlayControlledZombieSfx(zombie, 2); return true; } } catch { if (!IsRunGameplayReady()) { PlayControlledZombieSfx(zombie, 2); return true; } } return false; } private static bool IsRunGameplayReady() { try { return GameHandler.Initialized && GameHandler.IsInGameplayScene && GameHandler.IsOnIslandAndInitialized; } catch { return false; } } internal static bool TryHandleControlledZombieStopClimb(CharacterClimbing climbing, Character character, float setFall) { if ((Object)(object)climbing == (Object)null || !IsLocallyControlledZombieCharacter(character) || IsControlledZombieOriginalAiActive(character)) { return false; } StopControlledZombieClimb(climbing, character, setFall); return true; } internal static void StopControlledZombieClimb(CharacterClimbing climbing, Character character, float setFall) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character?.data == (Object)null) { return; } character.data.isClimbing = false; character.data.isRopeClimbing = false; character.data.isVineClimbing = false; character.data.isJumping = false; character.data.sinceGrounded = 0f; character.data.groundedFor = Mathf.Max(character.data.groundedFor, Time.fixedDeltaTime); character.data.sinceClimb = 999f; character.data.sinceCanClimb = 999f; character.data.sincePressClimb = 999f; character.data.climbNormal = Vector3.zero; _controlledClimbStartCooldownUntil[((Object)character).GetInstanceID()] = Time.time + 0.12f; try { CharacterClimbingPlayerSlideField?.SetValue(climbing, Vector2.zero); CharacterClimbingClimbToggledOnField?.SetValue(climbing, false); CharacterClimbingSinceLastClimbStartedField?.SetValue(climbing, 999f); } catch { } } internal static bool TryHandleControlledZombieStartWallClimb(CharacterClimbing climbing, Character character, bool forceAttempt, Vector3 overrideDirection, bool botGrab, float raycastDistance) { //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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_012c: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)climbing == (Object)null || !IsLocallyControlledZombieCharacter(character) || IsControlledZombieOriginalAiActive(character)) { return false; } if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return true; } if (character.data.isClimbing || character.data.isRopeClimbing || character.data.isVineClimbing) { return true; } if (!CanControlledZombieClimb(climbing)) { return true; } Vector3 center = character.Center; Vector3 direction = ((forceAttempt && ((Vector3)(ref overrideDirection)).sqrMagnitude > 0.0001f) ? overrideDirection : Vector3.zero); if (((Vector3)(ref direction)).sqrMagnitude < 0.0001f && (Object)(object)Camera.main != (Object)null) { direction = ((Component)Camera.main).transform.forward; } if (((Vector3)(ref direction)).sqrMagnitude < 0.0001f) { direction = ((Component)character).transform.forward; } if (((Vector3)(ref direction)).sqrMagnitude < 0.0001f) { direction = character.data.lookDirection; } if (((Vector3)(ref direction)).sqrMagnitude < 0.0001f) { direction = character.data.lookDirection_Flat; } ((Vector3)(ref direction)).Normalize(); float distance = Mathf.Clamp((raycastDistance > 0f) ? raycastDistance : 1.65f, 0.75f, 3f); if (!TryFindControlledZombieClimbHit(character, center, direction, distance, out var climbHit)) { return true; } TryStartControlledZombieClimb(climbing, character, ((RaycastHit)(ref climbHit)).point, ((RaycastHit)(ref climbHit)).normal, "Controlled zombie climb"); return true; } internal static bool CanControlledZombieClimb(CharacterClimbing climbing) { if ((Object)(object)climbing == (Object)null) { return false; } try { if (CharacterClimbingCanClimbMethod != null) { object obj = CharacterClimbingCanClimbMethod.Invoke(climbing, null); if (obj is bool) { return (bool)obj; } } } catch { } return true; } internal static bool TryStartControlledZombieClimb(CharacterClimbing climbing, Character character, Vector3 climbPos, Vector3 climbNormal, string context) { //IL_0071: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)climbing == (Object)null) { return false; } int num = (((Object)(object)character != (Object)null) ? ((Object)character).GetInstanceID() : (-1)); if (num > 0 && _controlledClimbStartCooldownUntil.TryGetValue(num, out var value) && Time.time < value) { return true; } if (CharacterClimbingStartClimbRpcMethod == null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] " + context + " start failed: StartClimbRpc method not found.")); } return false; } try { object[] array = BuildStartClimbRpcArguments(CharacterClimbingStartClimbRpcMethod, climbPos, climbNormal); if (array == null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[I'm Zombie] " + context + " start failed: unsupported StartClimbRpc signature.")); } return false; } CharacterClimbingStartClimbRpcMethod.Invoke(climbing, array); CharacterClimbingClimbToggledOnField?.SetValue(climbing, false); CharacterClimbingPlayerSlideField?.SetValue(climbing, Vector2.zero); CharacterClimbingSinceLastClimbStartedField?.SetValue(climbing, 0f); if ((Object)(object)character?.data != (Object)null) { _controlledClimbStartCooldownUntil[((Object)character).GetInstanceID()] = Time.time + 0.12f; character.data.climbPos = climbPos; character.data.climbNormal = ((((Vector3)(ref climbNormal)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref climbNormal)).normalized : Vector3.zero); character.data.sincePressClimb = 0f; character.data.sinceCanClimb = 0f; character.data.sinceGrounded = 0f; character.data.fallSeconds = 0f; character.data.passedOut = false; character.data.fullyPassedOut = false; character.data.avarageVelocity = Vector3.zero; character.data.avarageLastFrameVelocity = Vector3.zero; character.data.worldMovementInput_Grounded = Vector3.zero; } return true; } catch (TargetInvocationException ex) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)("[I'm Zombie] " + context + " start failed: " + (ex.InnerException?.Message ?? ex.Message))); } return false; } catch (Exception ex2) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogWarning((object)("[I'm Zombie] " + context + " start failed: " + ex2.Message)); } return false; } } private static MethodInfo FindCharacterClimbingCanClimbMethod() { return typeof(CharacterClimbing).GetMethod("CanClimb", InstanceBindingFlags, null, Type.EmptyTypes, null); } private static MethodInfo FindCharacterUnFallRpcMethod() { MethodInfo methodInfo = null; MethodInfo[] methods = typeof(Character).GetMethods(InstanceBindingFlags); foreach (MethodInfo methodInfo2 in methods) { if (!(methodInfo2 == null) && string.Equals(methodInfo2.Name, "RPCA_UnFall", StringComparison.Ordinal)) { if (methodInfo2.GetParameters().Length == 0) { return methodInfo2; } if ((object)methodInfo == null) { methodInfo = methodInfo2; } } } return methodInfo; } private static MethodInfo FindCharacterClimbingStartClimbRpcMethod() { MethodInfo methodInfo = null; MethodInfo[] methods = typeof(CharacterClimbing).GetMethods(InstanceBindingFlags); foreach (MethodInfo methodInfo2 in methods) { if (methodInfo2 == null || methodInfo2.Name != "StartClimbRpc") { continue; } ParameterInfo[] parameters = methodInfo2.GetParameters(); if (parameters.Length >= 2 && !(parameters[0].ParameterType != typeof(Vector3)) && !(parameters[1].ParameterType != typeof(Vector3))) { if (parameters.Length == 2) { return methodInfo2; } if ((object)methodInfo == null) { methodInfo = methodInfo2; } } } return methodInfo; } private static object[] BuildStartClimbRpcArguments(MethodInfo method, Vector3 climbPos, Vector3 climbNormal) { //IL_004e: 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) ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length < 2) { return null; } if (parameters[0].ParameterType != typeof(Vector3) || parameters[1].ParameterType != typeof(Vector3)) { return null; } object[] array = new object[parameters.Length]; array[0] = climbPos; array[1] = climbNormal; for (int i = 2; i < parameters.Length; i++) { Type parameterType = parameters[i].ParameterType; array[i] = (parameterType.IsValueType ? Activator.CreateInstance(parameterType) : null); } return array; } private static bool TryFindControlledZombieClimbHit(Character character, Vector3 origin, Vector3 direction, float distance, out RaycastHit climbHit) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) climbHit = default(RaycastHit); RaycastHit[] array; try { array = Physics.RaycastAll(origin, direction, distance, -1, (QueryTriggerInteraction)1); } catch { return false; } if (array == null || array.Length == 0) { return false; } Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance)); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val = array2[i]; if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !((RaycastHit)(ref val)).collider.isTrigger && !((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent() == (Object)(object)character) && !(Vector3.Dot(((RaycastHit)(ref val)).normal, Vector3.up) > 0.75f)) { climbHit = val; return true; } } return false; } private static void ApplyControlledZombieLocalJump(Character character) { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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_00eb: 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) if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return; } try { if (!character.data.isGrounded && character.data.sinceGrounded > 0.25f && !character.data.isClimbing && !character.data.isRopeClimbing && !character.data.isVineClimbing) { return; } if (character.refs?.ragdoll?.partList != null) { foreach (Bodypart part in character.refs.ragdoll.partList) { Rigidbody val = (((Object)(object)part != (Object)null) ? part.Rig : null); if (!((Object)(object)val == (Object)null) && !val.isKinematic) { Vector3 linearVelocity = val.linearVelocity; if (linearVelocity.y < 8.5f) { val.linearVelocity = new Vector3(linearVelocity.x, 8.5f, linearVelocity.z); } val.WakeUp(); } } } character.data.sinceJump = 0f; character.data.isJumping = true; character.data.isGrounded = false; character.data.sinceGrounded = 0.25f; character.data.groundedFor = 0f; if ((Object)(object)character.input != (Object)null) { character.input.jumpWasPressed = false; } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Controlled zombie local jump failed: " + ex.Message)); } } } internal static bool ShouldSkipCharacterNetworkInterpolation(Character character) { return IsStashedSourceCharacter(character); } internal static void PrepareControlledZombieReticle() { Character controlledZombieCharacter = GetControlledZombieCharacter(); if (!((Object)(object)controlledZombieCharacter == (Object)null)) { ClearAssistJumpState(controlledZombieCharacter); } } private static object CreateOptionableNoneValue(Type optionableType) { if (optionableType == null) { return null; } try { PropertyInfo property = optionableType.GetProperty("None", StaticBindingFlags); if (property != null) { return property.GetValue(null, null); } } catch { } try { return Activator.CreateInstance(optionableType); } catch { return null; } } private static void ClearSelectedInventorySlots(CharacterItems items) { if ((Object)(object)items == (Object)null || CharacterItemsNoneSlotValue == null) { return; } try { CharacterItemsCurrentSelectedSlotField?.SetValue(items, CharacterItemsNoneSlotValue); CharacterItemsLastSelectedSlotField?.SetValue(items, CharacterItemsNoneSlotValue); } catch { } } private static void RegisterStashedSourceCharacter(Character character) { if ((Object)(object)character != (Object)null) { _stashedSourceCharacterIds.Add(((Object)character).GetInstanceID()); } } private static void ClearAssistJumpState(Character character) { if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null)) { character.data.sincePalJump = 10f; character.data.sinceStandOnPlayer = 10f; character.data.lastStoodOnPlayer = null; character.data.launchedByCannon = false; } } private static void UnregisterStashedSourceCharacter(Character character) { if ((Object)(object)character != (Object)null) { _stashedSourceCharacterIds.Remove(((Object)character).GetInstanceID()); } } internal static void RefreshCharacterAfflictionSceneState(Character character, bool clearTransientCampfireAfflictions = false) { if ((Object)(object)character == (Object)null) { return; } try { CharacterAfflictions val = character.refs?.afflictions; if ((Object)(object)val == (Object)null) { val = ((Component)character).GetComponent(); } if ((Object)(object)val == (Object)null) { return; } EnsureCharacterAfflictionsRuntime(character, val); bool flag = IsCurrentSceneAirport(); CharacterAfflictionsInAirportField?.SetValue(val, flag); if (!clearTransientCampfireAfflictions || flag || !ShouldClearTransientCampfireAfflictions(character)) { return; } if (!IsCharacterWithinLitCampfireProtection(character)) { ForceRemoveAffliction(val, (AfflictionType)21); } if (!HasMushroomZombieComponent(character)) { character.isZombie = false; if ((Object)(object)character.data != (Object)null) { character.data.zombified = false; } } } catch (Exception ex) { LogVerbose("Failed to refresh CharacterAfflictions scene state: " + ex.Message); } } private static void EnsureCharacterAfflictionsRuntime(Character character, CharacterAfflictions afflictions) { if ((Object)(object)character == (Object)null || (Object)(object)afflictions == (Object)null) { return; } try { if ((Object)(object)afflictions.character == (Object)null) { afflictions.character = character; } if (!((Behaviour)afflictions).enabled && ShouldMaintainOriginalLocalPlayerStatusProcessing(character)) { ((Behaviour)afflictions).enabled = true; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Re-enabled CharacterAfflictions for original player status processing: " + ((Object)character).name)); } } } catch (Exception ex) { LogVerbose("Failed to ensure CharacterAfflictions runtime: " + ex.Message); } } private static void RestoreOriginalPlayerStatusProcessing(Character character) { if ((Object)(object)character == (Object)null) { return; } try { UnregisterStashedSourceCharacter(character); if ((Object)(object)((Component)character).gameObject != (Object)null && !((Component)character).gameObject.activeSelf) { ((Component)character).gameObject.SetActive(true); } Character.localCharacter = character; ForcePlayerCharacterLookup(character); character.isZombie = false; if ((Object)(object)((MonoBehaviourPun)character).photonView != (Object)null && !((MonoBehaviourPun)character).photonView.IsMine) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Original player status processing restore found local character PhotonView.IsMine=false: " + ((Object)character).name)); } } if ((Object)(object)character.data != (Object)null) { character.data.zombified = false; character.data.dead = false; character.data.passedOut = false; character.data.fullyPassedOut = false; character.data.fallSeconds = 0f; character.data.deathTimer = 0f; } RefreshCharacterAfflictionSceneState(character, clearTransientCampfireAfflictions: true); CharacterAfflictions val = character.refs?.afflictions; if ((Object)(object)val == (Object)null) { val = ((Component)character).GetComponent(); } if ((Object)(object)val != (Object)null) { EnsureCharacterAfflictionsRuntime(character, val); CharacterAfflictionsInAirportField?.SetValue(val, IsCurrentSceneAirport()); if (!IsCurrentSceneAirport() && !IsCharacterWithinLitCampfireProtection(character)) { ForceRemoveAffliction(val, (AfflictionType)21); } } try { CharacterData data = character.data; if (data != null) { data.RecalculateInvincibility(); } CharacterData data2 = character.data; if (data2 != null) { data2.RecalculateLowGrav(); } GUIManager instance = GUIManager.instance; if (instance != null) { StaminaBar bar = instance.bar; if (bar != null) { bar.ChangeBar(); } } } catch { } LogStatusProcessingRestore(character, val); } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[I'm Zombie] Failed to restore original player status processing: " + ex.Message)); } } } private static void LogStatusProcessingRestore(Character character, CharacterAfflictions afflictions) { //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime < _nextStatusProcessingRestoreLogTime) { return; } _nextStatusProcessingRestoreLogTime = Time.unscaledTime + 5f; try { bool flag = (Object)(object)character != (Object)null && character.IsLocal; bool flag2 = (Object)(object)character != (Object)null && character.isZombie; bool flag3 = (Object)(object)character?.data != (Object)null && character.data.zombified; bool flag4 = (Object)(object)character?.data != (Object)null && character.data.dead; bool flag5 = (Object)(object)((character != null) ? ((MonoBehaviourPun)character).photonView : null) != (Object)null && ((MonoBehaviourPun)character).photonView.IsMine; bool flag6 = (Object)(object)afflictions != (Object)null && ((Behaviour)afflictions).enabled; int num = ((afflictions?.afflictionList != null) ? afflictions.afflictionList.Count : (-1)); bool flag7 = (Object)(object)afflictions != (Object)null && (bool)(CharacterAfflictionsInAirportField?.GetValue(afflictions) ?? ((object)false)); bool flag8 = (Object)(object)afflictions == (Object)null || afflictions.canGetHungry; Affliction val = default(Affliction); bool flag9 = (Object)(object)afflictions != (Object)null && afflictions.HasAfflictionType((AfflictionType)21, ref val); ManualLogSource log = Log; if (log != null) { string[] obj = new string[24] { "[I'm Zombie] Restored original player status processing: name=", ((Object)(object)character != (Object)null) ? ((Object)character).name : "null", ", isLocal=", flag.ToString(), ", isZombie=", flag2.ToString(), ", zombified=", flag3.ToString(), ", dead=", flag4.ToString(), ", viewIsMine=", flag5.ToString(), ", afflictionsEnabled=", flag6.ToString(), ", afflictionCount=", num.ToString(), ", inAirport=", flag7.ToString(), ", canGetHungry=", flag8.ToString(), ", hasNoHunger=", flag9.ToString(), ", scene=", null }; Scene activeScene = SceneManager.GetActiveScene(); obj[23] = ((Scene)(ref activeScene)).name ?? string.Empty; log.LogInfo((object)string.Concat(obj)); } } catch { } } private static bool ForceRemoveAffliction(CharacterAfflictions afflictions, AfflictionType type) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)afflictions == (Object)null) { return false; } try { Affliction val = default(Affliction); if (!afflictions.HasAfflictionType(type, ref val) || val == null) { return false; } afflictions.RemoveAffliction(val, true, false); Character val2 = afflictions.character ?? ((Component)afflictions).GetComponent(); if ((Object)(object)val2 != (Object)null && val2.IsLocal) { afflictions.PushAfflictions((Player)null); } try { GUIManager instance = GUIManager.instance; if (instance != null) { StaminaBar bar = instance.bar; if (bar != null) { bar.ChangeBar(); } } } catch { } return true; } catch (Exception ex) { LogVerbose("Failed to force remove affliction " + ((object)(AfflictionType)(ref type)).ToString() + ": " + ex.Message); return false; } } private static bool IsCharacterWithinLitCampfireProtection(Character character) { //IL_0022: 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_0061: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null) { return false; } try { Campfire[] array = Object.FindObjectsByType((FindObjectsSortMode)0); if (array == null || array.Length == 0) { return false; } Vector3 center = character.Center; foreach (Campfire val in array) { if (!((Object)(object)val == (Object)null) && val.Lit && !(val.moraleBoostRadius <= 0f)) { float num = val.moraleBoostRadius + 0.35f; Vector3 val2 = center - ((Component)val).transform.position; if (((Vector3)(ref val2)).sqrMagnitude <= num * num) { return true; } } } } catch (Exception ex) { LogVerbose("Failed to check campfire protection range: " + ex.Message); } return false; } internal static bool ShouldSuppressManagedNoHungerAffliction(CharacterAfflictions afflictions, Affliction affliction) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_003c: 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) if ((Object)(object)afflictions == (Object)null || affliction == null || (int)affliction.GetAfflictionType() != 21) { return false; } Character val = null; try { val = afflictions.character ?? ((Component)afflictions).GetComponent(); } catch { val = null; } if (!ShouldClearTransientCampfireAfflictions(val)) { return false; } Scene activeScene = SceneManager.GetActiveScene(); if (!IsGameplaySceneName(((Scene)(ref activeScene)).name ?? string.Empty) || IsCurrentSceneAirport()) { return false; } if (IsCharacterWithinLitCampfireProtection(val)) { return false; } ForceRemoveAffliction(afflictions, (AfflictionType)21); return true; } private static bool ShouldClearTransientCampfireAfflictions(Character character) { if ((Object)(object)character == (Object)null) { return false; } if ((Object)(object)character == (Object)(object)Character.localCharacter || (Object)(object)character == (Object)(object)_localSourceProxyCharacter || (Object)(object)character == (Object)(object)_cameraOverrideCharacter || IsStashedSourceCharacter(character) || IsLocallyControlledZombieCharacter(character)) { return true; } try { return (Object)(object)Player.localPlayer != (Object)null && (Object)(object)((MonoBehaviourPun)Player.localPlayer).photonView != (Object)null && IsSamePhotonOwner(character, ((MonoBehaviourPun)Player.localPlayer).photonView.Owner); } catch { return false; } } private static void RefreshKnownCharacterAfflictionSceneState(bool clearTransientCampfireAfflictions) { try { RefreshCharacterAfflictionSceneState(Character.localCharacter, clearTransientCampfireAfflictions); RefreshCharacterAfflictionSceneState(_localSourceProxyCharacter, clearTransientCampfireAfflictions); RefreshCharacterAfflictionSceneState(_cameraOverrideCharacter, clearTransientCampfireAfflictions); if (Character.AllCharacters != null) { for (int i = 0; i < Character.AllCharacters.Count; i++) { RefreshCharacterAfflictionSceneState(Character.AllCharacters[i], clearTransientCampfireAfflictions); } } if (Character.AllBotCharacters != null) { for (int j = 0; j < Character.AllBotCharacters.Count; j++) { RefreshCharacterAfflictionSceneState(Character.AllBotCharacters[j], clearTransientCampfireAfflictions); } } } catch (Exception ex) { LogVerbose("Failed to refresh known CharacterAfflictions scene state: " + ex.Message); } } private static bool IsCurrentSceneAirport() { //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) try { Scene activeScene = SceneManager.GetActiveScene(); return string.Equals(((Scene)(ref activeScene)).name, "Airport", StringComparison.Ordinal); } catch { return false; } } internal static bool ShouldSkipCharacterRegistration(Character character) { if ((Object)(object)character == (Object)null || !HasMushroomZombieComponent(character)) { return false; } bool flag = IsCharacterInControlledCreationRoot(character); bool flag2 = IsCreatingControlledPlayerZombieNetworkResource(); bool flag3 = IsLocallyControlledZombieCharacter(character); bool flag4 = IsImZombieManagedCharacter(character); bool flag5 = IsLocalTransformingZombieCharacter(character); bool flag6 = IsLocalTransformingReplacementCharacter(character); if (!flag && !flag2 && !flag3 && !flag4 && !flag5 && !flag6) { return false; } if (flag6) { RestoreLocalSourceProxyCharacterActive(); } LogSkippedCharacterRegistration(character, flag, flag2, flag3, flag4, flag5, flag6); return true; } private static bool IsLocalTransformingReplacementCharacter(Character character) { if (!((Object)(object)character == (Object)null)) { Plugin instance = Instance; if (instance != null && instance._switching && !((Object)(object)_localSourceProxyCharacter == (Object)null) && !((Object)(object)character == (Object)(object)_localSourceProxyCharacter)) { try { PhotonView val = ResolveCharacterPhotonView(character); if ((Object)(object)val == (Object)null || val.Owner == null || _localSourceProxyActorNumber <= 0) { return false; } return val.Owner.ActorNumber == _localSourceProxyActorNumber; } catch { return false; } } } return false; } private static bool IsLocalTransformingZombieCharacter(Character character) { if (!((Object)(object)character == (Object)null)) { Plugin instance = Instance; if (instance != null && instance._switching) { try { PhotonView val = ResolveCharacterPhotonView(character); if ((Object)(object)val == (Object)null || val.Owner == null || (Object)(object)Player.localPlayer == (Object)null || (Object)(object)((MonoBehaviourPun)Player.localPlayer).photonView == (Object)null) { return false; } Player owner = ((MonoBehaviourPun)Player.localPlayer).photonView.Owner; if (owner == null || val.Owner.ActorNumber != owner.ActorNumber) { return false; } string value = (((Object)(object)((Component)character).gameObject != (Object)null) ? ((Object)((Component)character).gameObject).name : string.Empty); return ContainsOrdinalIgnoreCase(value, "MushroomZombie_Player") || ContainsOrdinalIgnoreCase(value, "MushroomZombie") || HasMushroomZombieComponent(character); } catch { return false; } } } return false; } private static void LogSkippedCharacterRegistration(Character character, bool inCreationRoot, bool inNetworkCreation, bool locallyControlled, bool imZombieSpawn, bool localTransformingZombie, bool localTransformingReplacement) { if (!((Object)(object)character == (Object)null) && _loggedSkippedCharacterRegistrationIds.Add(((Object)character).GetInstanceID())) { string text = (((Object)(object)((Component)character).gameObject != (Object)null) ? ((Object)((Component)character).gameObject).name : "unknown"); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Skipped PlayerHandler registration for " + text + " (creationRoot=" + inCreationRoot + ", networkCreation=" + inNetworkCreation + ", localControlled=" + locallyControlled + ", imZombieSpawn=" + imZombieSpawn + ", localTransforming=" + localTransformingZombie + ", localReplacement=" + localTransformingReplacement + ").")); } } } private static bool IsImZombieManagedCharacter(Character character) { if ((Object)(object)character == (Object)null) { return false; } int instanceID = ((Object)character).GetInstanceID(); if ((Object)(object)character == (Object)(object)_cameraOverrideCharacter || _controlledZombieCharacterInstanceIds.Contains(instanceID)) { return true; } PhotonView val = ResolveCharacterPhotonView(character); if ((Object)(object)val != (Object)null) { if (val.ViewID > 0 && _controlledZombieViewIds.Contains(val.ViewID)) { return true; } if (IsImZombieNetworkSpawn(val)) { return true; } } if (IsCharacterInControlledCreationRoot(character)) { return true; } MushroomZombie val2 = null; PlayerZombieController playerZombieController = null; try { val2 = ((Component)character).GetComponent(); playerZombieController = ((Component)character).GetComponent(); } catch { } if ((Object)(object)playerZombieController != (Object)null) { return true; } if ((Object)(object)val2 != (Object)null) { if (_controlledZombieInstanceIds.Contains(((Object)val2).GetInstanceID()) || PlayerZombieController.IsControlled(val2)) { return true; } if (IsCreatingControlledPlayerZombieNetworkResource()) { return true; } } if (!IsCreatingControlledPlayerZombieNetworkResource()) { return false; } string name = ((Object)((Component)character).gameObject).name; if (!string.IsNullOrWhiteSpace(name)) { if (!ContainsOrdinalIgnoreCase(name, "MushroomZombie_Player")) { return ContainsOrdinalIgnoreCase(name, "MushroomZombie"); } return true; } return false; } private static bool HasMushroomZombieComponent(Character character) { if ((Object)(object)character == (Object)null) { return false; } try { return (Object)(object)((Component)character).GetComponent() != (Object)null; } catch { return false; } } private static bool IsCharacterInControlledCreationRoot(Character character) { if ((Object)(object)_controlledZombieCreationRoot == (Object)null || (Object)(object)character == (Object)null) { return false; } try { Transform transform = ((Component)character).transform; return (Object)(object)transform == (Object)(object)_controlledZombieCreationRoot || transform.IsChildOf(_controlledZombieCreationRoot); } catch { return false; } } private static bool IsControlledZombieBeingCreated(MushroomZombie zombie) { if (IsCreatingControlledPlayerZombieNetworkResource()) { return true; } if ((Object)(object)_controlledZombieCreationRoot == (Object)null || (Object)(object)zombie == (Object)null) { return false; } try { Transform transform = ((Component)zombie).transform; return (Object)(object)transform == (Object)(object)_controlledZombieCreationRoot || transform.IsChildOf(_controlledZombieCreationRoot); } catch { return false; } } internal static bool IsControlledZombie(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null) { return false; } if (PlayerZombieController.IsControlled(zombie)) { return true; } Character component = ((Component)zombie).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component == (Object)(object)_cameraOverrideCharacter) { return true; } if (_controlledZombieInstanceIds.Contains(((Object)zombie).GetInstanceID())) { return true; } PhotonView photonView = ((MonoBehaviourPun)zombie).photonView; if ((Object)(object)photonView == (Object)null) { return false; } if (photonView.ViewID > 0 && _controlledZombieViewIds.Contains(photonView.ViewID)) { return true; } return TryRegisterControlledZombieFromInstantiationData(zombie, photonView); } internal static bool ShouldSuppressControlledZombieUpdate(MushroomZombie zombie) { if (_controlledZombieOriginalBehaviorDepth > 0) { return false; } if (!IsLocallyControlledZombie(zombie)) { return false; } ClearMushroomZombieSpawnSource(zombie); return true; } internal static bool ShouldSuppressControlledPhotonDestroy(GameObject target) { if (_controlledZombieDestroyDepth > 0 || _runtimePrefabBackupCreationDepth > 0 || (Object)(object)target == (Object)null) { return false; } try { if (IsRuntimeNetworkPrefabBackupObject(target)) { LogVerbose("Blocked PhotonNetwork.Destroy for runtime network prefab backup " + ((Object)target).name + "."); return true; } if (IsOriginalPlayerCharacterPrefabBackupObject(target)) { LogVerbose("Blocked PhotonNetwork.Destroy for original Character prefab backup " + ((Object)target).name + "."); return true; } MushroomZombie component = target.GetComponent(); if ((Object)(object)component != (Object)null && IsControlledZombie(component)) { LogSuppressedControlledPhotonDestroy(target, ((MonoBehaviourPun)component).photonView, "controlled zombie object"); return true; } Character component2 = target.GetComponent(); if ((Object)(object)component2 != (Object)null) { Plugin instance = Instance; if (instance != null && (instance._session?.IsSourceCharacter(component2)).GetValueOrDefault()) { LogSuppressedControlledPhotonDestroy(target, ResolveCharacterPhotonView(component2), "source character while transformed"); return true; } } } catch { } return false; } internal static bool ShouldSuppressControlledUnityDestroy(Object target) { if (_controlledZombieDestroyDepth > 0 || _runtimePrefabBackupCreationDepth > 0 || target == (Object)null) { return false; } try { GameObject val = ResolveUnityDestroyTargetGameObject(target); Component val2 = (Component)(object)((target is Component) ? target : null); if ((Object)(object)val == (Object)null && (Object)(object)val2 == (Object)null) { return false; } if (IsRuntimeNetworkPrefabBackupObject(val ?? val2.gameObject)) { LogVerbose("Blocked UnityEngine.Object.Destroy for runtime network prefab backup " + target.name + "."); return true; } if (IsOriginalPlayerCharacterPrefabBackupObject(val ?? val2.gameObject)) { LogVerbose("Blocked UnityEngine.Object.Destroy for original Character prefab backup " + target.name + "."); return true; } MushroomZombie val3 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); if ((Object)(object)val3 == (Object)null) { MushroomZombie val4 = (MushroomZombie)(object)((val2 is MushroomZombie) ? val2 : null); if (val4 != null) { val3 = val4; } } if ((Object)(object)val3 != (Object)null && IsControlledZombie(val3)) { LogSuppressedControlledUnityDestroy(target, ((MonoBehaviourPun)val3).photonView, "controlled zombie"); return true; } Character val5 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); if ((Object)(object)val5 == (Object)null) { Character val6 = (Character)(object)((val2 is Character) ? val2 : null); if (val6 != null) { val5 = val6; } } if ((Object)(object)val5 != (Object)null) { Plugin instance = Instance; if (instance != null && (instance._session?.IsSourceCharacter(val5)).GetValueOrDefault()) { goto IL_019c; } if ((Object)(object)_localSourceProxyCharacter != (Object)null && (Object)(object)val5 == (Object)(object)_localSourceProxyCharacter) { Plugin instance2 = Instance; if (instance2 != null && instance2._switching) { goto IL_019c; } } } goto end_IL_001c; IL_019c: LogSuppressedControlledUnityDestroy(target, ResolveCharacterPhotonView(val5), "source character while transforming"); return true; end_IL_001c:; } catch { } return false; } internal static bool ShouldSuppressControlledSetActive(GameObject target, bool active) { if (active || (Object)(object)target == (Object)null || _controlledZombieDestroyDepth > 0 || _runtimePrefabBackupCreationDepth > 0) { return false; } try { MushroomZombie component = target.GetComponent(); if (IsOriginalPlayerCharacterPrefabBackupObject(target)) { LogVerbose("Blocked GameObject.SetActive(false) for original Character prefab backup " + ((Object)target).name + "."); return true; } if ((Object)(object)component != (Object)null && IsControlledZombie(component)) { LogSuppressedControlledSetActive(target, ((MonoBehaviourPun)component).photonView, "controlled zombie"); return true; } Character component2 = target.GetComponent(); if ((Object)(object)component2 != (Object)null) { Plugin instance = Instance; if (instance != null && (instance._session?.IsSourceCharacter(component2)).GetValueOrDefault()) { goto IL_00ea; } if ((Object)(object)_localSourceProxyCharacter != (Object)null && (Object)(object)component2 == (Object)(object)_localSourceProxyCharacter) { Plugin instance2 = Instance; if (instance2 != null && instance2._switching) { goto IL_00ea; } } } goto end_IL_001f; IL_00ea: LogSuppressedControlledSetActive(target, ResolveCharacterPhotonView(component2), "source character while transforming"); return true; end_IL_001f:; } catch { } return false; } private static GameObject ResolveUnityDestroyTargetGameObject(Object target) { GameObject val = (GameObject)(object)((target is GameObject) ? target : null); if (val != null) { return val; } Component val2 = (Component)(object)((target is Component) ? target : null); if (val2 != null) { return val2.gameObject; } return null; } private static bool IsRuntimeNetworkPrefabBackupObject(GameObject target) { if ((Object)(object)target == (Object)null || _runtimeNetworkPrefabBackups.Count == 0) { return false; } Transform transform = target.transform; foreach (GameObject value in _runtimeNetworkPrefabBackups.Values) { if (!((Object)(object)value == (Object)null)) { Transform transform2 = value.transform; if ((Object)(object)transform == (Object)(object)transform2 || transform.IsChildOf(transform2)) { return true; } } } return false; } private static bool IsOriginalPlayerCharacterPrefabBackupObject(GameObject target) { if ((Object)(object)target == (Object)null || (Object)(object)_originalPlayerCharacterPrefabBackup == (Object)null) { return false; } try { Transform transform = target.transform; Transform transform2 = _originalPlayerCharacterPrefabBackup.transform; return (Object)(object)transform == (Object)(object)transform2 || transform.IsChildOf(transform2); } catch { return false; } } internal static bool ShouldSuppressControlledPhotonDestroy(PhotonView targetView) { if (_controlledZombieDestroyDepth > 0 || _runtimePrefabBackupCreationDepth > 0 || (Object)(object)targetView == (Object)null) { return false; } try { if (targetView.ViewID > 0 && _controlledZombieViewIds.Contains(targetView.ViewID)) { LogSuppressedControlledPhotonDestroy(((Component)targetView).gameObject, targetView, "controlled zombie view"); return true; } return ShouldSuppressControlledPhotonDestroy(((Component)targetView).gameObject); } catch { return false; } } internal static bool ShouldSuppressControlledPhotonDestroy(int viewId) { if (_controlledZombieDestroyDepth > 0 || _runtimePrefabBackupCreationDepth > 0 || viewId <= 0) { return false; } try { if (_controlledZombieViewIds.Contains(viewId)) { PhotonView photonView = PhotonNetwork.GetPhotonView(viewId); LogSuppressedControlledPhotonDestroy(((Object)(object)photonView != (Object)null) ? ((Component)photonView).gameObject : null, photonView, "controlled zombie view id"); return true; } return ShouldSuppressControlledPhotonDestroy(PhotonNetwork.GetPhotonView(viewId)); } catch { return false; } } private static void LogSuppressedControlledPhotonDestroy(GameObject target, PhotonView view, string reason) { int num = (((Object)(object)view != (Object)null) ? view.ViewID : (-1)); int num2 = ((num > 0) ? num : (((Object)(object)target != (Object)null) ? ((Object)target).GetInstanceID() : (-1))); if (num2 > 0 && _loggedSuppressedPhotonDestroyViewIds.Add(num2)) { string text = ((num > 0) ? num.ToString(CultureInfo.InvariantCulture) : "none"); string text2 = (((Object)(object)target != (Object)null) ? ((Object)target).name : "unknown"); LogVerbose("Blocked PhotonNetwork.Destroy for " + text2 + " ViewID " + text + " (" + reason + ")."); } } private static void LogSuppressedControlledUnityDestroy(Object target, PhotonView view, string reason) { int num = (((Object)(object)view != (Object)null) ? view.ViewID : (-1)); int num2 = ((num > 0) ? num : ((target != (Object)null) ? target.GetInstanceID() : (-1))); if (num2 > 0 && _loggedSuppressedUnityDestroyIds.Add(num2)) { string text = ((num > 0) ? num.ToString(CultureInfo.InvariantCulture) : "none"); string text2 = ((target != (Object)null) ? target.name : "unknown"); LogVerbose("Blocked UnityEngine.Object.Destroy for " + text2 + " ViewID " + text + " (" + reason + ")."); } } private static void LogSuppressedControlledSetActive(GameObject target, PhotonView view, string reason) { int num = (((Object)(object)view != (Object)null) ? view.ViewID : (-1)); int num2 = ((num > 0) ? num : (((Object)(object)target != (Object)null) ? ((Object)target).GetInstanceID() : (-1))); if (num2 > 0 && _loggedSuppressedSetActiveIds.Add(num2)) { string text = ((num > 0) ? num.ToString(CultureInfo.InvariantCulture) : "none"); string text2 = (((Object)(object)target != (Object)null) ? ((Object)target).name : "unknown"); LogVerbose("Blocked GameObject.SetActive(false) for " + text2 + " ViewID " + text + " (" + reason + ")."); } } private static void BeginControlledZombieDestroy() { _controlledZombieDestroyDepth++; } private static void EndControlledZombieDestroy() { _controlledZombieDestroyDepth = Mathf.Max(0, _controlledZombieDestroyDepth - 1); } internal static bool ShouldSuppressControlledZombieNetworkControl(MushroomZombie zombie) { if (IsLocallyControlledZombie(zombie)) { return _controlledZombieOriginalBehaviorDepth <= 0; } return false; } internal static void BeginControlledZombieOriginalBehavior() { _controlledZombieOriginalBehaviorDepth++; } internal static ControlledZombieOriginalBehaviorScope EnterControlledZombieOriginalBehaviorScope() { BeginControlledZombieOriginalBehavior(); return default(ControlledZombieOriginalBehaviorScope); } internal static void EndControlledZombieOriginalBehavior() { _controlledZombieOriginalBehaviorDepth = Mathf.Max(0, _controlledZombieOriginalBehaviorDepth - 1); } internal static bool ShouldRunControlledZombieOriginalBehavior(MushroomZombie zombie) { if (IsControlledZombie(zombie)) { return _controlledZombieOriginalBehaviorDepth > 0; } return true; } internal static void PrepareControlledZombieForOriginalAi(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null) { return; } ClearMushroomZombieSpawnSource(zombie); try { EnsureMushroomZombieNativeFields(zombie); } catch { } } internal static void EnsureControlledZombieRegistered(Character character) { if ((Object)(object)character == (Object)null) { return; } try { MushroomZombie component = ((Component)character).GetComponent(); if (!((Object)(object)component == (Object)null)) { PhotonView val = ((MonoBehaviourPun)component).photonView; if ((Object)(object)val == (Object)null) { val = ResolveCharacterPhotonView(character); } TryRegisterControlledZombieFromInstantiationData(component, val); } } catch { } } private static bool TryRegisterControlledZombieFromInstantiationData(MushroomZombie zombie, PhotonView view) { if ((Object)(object)zombie == (Object)null || (Object)(object)view == (Object)null || view.ViewID <= 0) { return false; } if (!TryReadNetworkZombieInstantiationData(view, out var sourceViewId)) { return false; } _controlledZombieInstanceIds.Add(((Object)zombie).GetInstanceID()); Character component = ((Component)zombie).GetComponent(); if ((Object)(object)component != (Object)null) { RegisterControlledZombieAsVanillaPlayerCharacter(component); RefreshCharacterAfflictionSceneState(component); _controlledZombieCharacterInstanceIds.Add(((Object)component).GetInstanceID()); } _controlledZombieViewIds.Add(view.ViewID); if (sourceViewId > 0) { _controlledZombieSourceViewIdsByViewId[view.ViewID] = sourceViewId; } EnsureControlledZombieVisualSync(zombie, component, view); ForcePlayerCharacterLookupForControlledZombie(zombie, component, view); return true; } internal static void RegisterControlledZombie(MushroomZombie zombie) { if (!((Object)(object)zombie == (Object)null)) { MarkControlledZombieForLocalSession(zombie); } } private static void MarkControlledZombieForLocalSession(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null) { return; } _controlledZombieInstanceIds.Add(((Object)zombie).GetInstanceID()); Character component = ((Component)zombie).GetComponent(); if ((Object)(object)component != (Object)null) { _controlledZombieCharacterInstanceIds.Add(((Object)component).GetInstanceID()); } PhotonView photonView = ((MonoBehaviourPun)zombie).photonView; if ((Object)(object)photonView != (Object)null && photonView.ViewID > 0) { _controlledZombieViewIds.Add(photonView.ViewID); if (TryReadNetworkZombieInstantiationData(photonView, out var sourceViewId) && sourceViewId > 0) { _controlledZombieSourceViewIdsByViewId[photonView.ViewID] = sourceViewId; } } EnsureControlledZombieVisualSync(zombie, component, photonView); ForcePlayerCharacterLookupForControlledZombie(zombie, component, photonView); } internal static void UnregisterControlledZombie(MushroomZombie zombie) { if (!((Object)(object)zombie == (Object)null)) { _controlledZombieInstanceIds.Remove(((Object)zombie).GetInstanceID()); _localMushroomGrowthInitializedZombieIds.Remove(((Object)zombie).GetInstanceID()); Character component = ((Component)zombie).GetComponent(); if ((Object)(object)component != (Object)null) { _controlledZombieCharacterInstanceIds.Remove(((Object)component).GetInstanceID()); UnregisterControlledZombieAsVanillaPlayerCharacter(component); } PhotonView photonView = ((MonoBehaviourPun)zombie).photonView; if ((Object)(object)photonView != (Object)null && photonView.ViewID > 0) { _controlledZombieViewIds.Remove(photonView.ViewID); _controlledZombieSourceViewIdsByViewId.Remove(photonView.ViewID); } } } private static void UnregisterControlledZombieIds(MushroomZombie zombie, Character character) { try { if ((Object)(object)zombie != (Object)null) { _controlledZombieInstanceIds.Remove(((Object)zombie).GetInstanceID()); _localMushroomGrowthInitializedZombieIds.Remove(((Object)zombie).GetInstanceID()); } if ((Object)(object)character != (Object)null) { _controlledZombieCharacterInstanceIds.Remove(((Object)character).GetInstanceID()); UnregisterControlledZombieAsVanillaPlayerCharacter(character); } PhotonView val = (((Object)(object)zombie != (Object)null) ? ((MonoBehaviourPun)zombie).photonView : ResolveCharacterPhotonView(character)); if ((Object)(object)val != (Object)null && val.ViewID > 0) { _controlledZombieViewIds.Remove(val.ViewID); _controlledZombieSourceViewIdsByViewId.Remove(val.ViewID); } } catch { } } internal static void UnregisterControlledZombieInstance(MushroomZombie zombie, Character character, PhotonView view) { try { UnregisterControlledZombieIds(zombie, character); if ((Object)(object)view != (Object)null && view.ViewID > 0) { _controlledZombieViewIds.Remove(view.ViewID); _controlledZombieSourceViewIdsByViewId.Remove(view.ViewID); } } catch { } } private static void EnsureControlledZombieVisualSync(MushroomZombie zombie, Character character, PhotonView view) { if ((Object)(object)zombie == (Object)null) { return; } try { GameObject gameObject = ((Component)zombie).gameObject; (gameObject.GetComponent() ?? gameObject.AddComponent()).Initialize(zombie, character ?? gameObject.GetComponent(), view ?? gameObject.GetComponent()); } catch (Exception ex) { LogVerbose("Failed to install controlled zombie visual sync: " + ex.Message); } } internal static void EnsureControlledZombieVisibleForRemoteViewers(MushroomZombie zombie, Character character, PhotonView view) { try { if ((Object)(object)zombie == (Object)null && (Object)(object)character != (Object)null) { zombie = ((Component)character).GetComponent(); } if ((Object)(object)zombie == (Object)null) { return; } if ((Object)(object)character == (Object)null) { character = ((Component)zombie).GetComponent(); } if ((Object)(object)view == (Object)null) { view = ((Component)zombie).GetComponent(); } if (IsControlledZombie(zombie)) { ForcePlayerCharacterLookupForControlledZombie(zombie, character, view); RestoreRendererVisibility(((Component)zombie).gameObject); HideTheBody[] componentsInChildren = ((Component)zombie).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { RefreshHideTheBodyVisuals(componentsInChildren[i]); } } } catch { } } private static void ForcePlayerCharacterLookupForControlledZombie(MushroomZombie zombie, Character character, PhotonView view) { if ((Object)(object)character == (Object)null || (Object)(object)zombie == (Object)null || !TryGetControlledZombieOwnerActorNumber(zombie, view ?? ResolveCharacterPhotonView(character), out var actorNumber) || actorNumber <= 0) { return; } try { object obj = PlayerHandlerInstanceProperty?.GetValue(null, null); if (PlayerHandlerCharacterLookupField?.GetValue(obj) is IDictionary dictionary) { PruneNullPlayerCharacterLookupEntries(dictionary); dictionary[actorNumber] = character; } } catch (Exception ex) { LogVerbose("Failed to bind controlled zombie to actor " + actorNumber.ToString(CultureInfo.InvariantCulture) + ": " + ex.Message); } } private static bool TryGetControlledZombieOwnerActorNumber(MushroomZombie zombie, PhotonView view, out int actorNumber) { actorNumber = -1; try { if ((Object)(object)view == (Object)null && (Object)(object)zombie != (Object)null) { view = ((Component)zombie).GetComponent(); } int value = -1; if ((Object)(object)view != (Object)null && view.ViewID > 0) { _controlledZombieSourceViewIdsByViewId.TryGetValue(view.ViewID, out value); if (value <= 0 && TryReadNetworkZombieInstantiationData(view, out var sourceViewId)) { value = sourceViewId; if (value > 0) { _controlledZombieSourceViewIdsByViewId[view.ViewID] = value; } } } if (value > 0) { PhotonView photonView = PhotonNetwork.GetPhotonView(value); if ((Object)(object)photonView != (Object)null && photonView.Owner != null) { actorNumber = photonView.Owner.ActorNumber; return actorNumber > 0; } } if ((Object)(object)view != (Object)null && view.Owner != null) { actorNumber = view.Owner.ActorNumber; return actorNumber > 0; } } catch { actorNumber = -1; } return false; } private static bool IsControlledZombieOwnedByActor(Character character, int actorNumber) { if ((Object)(object)character == (Object)null || actorNumber <= 0) { return false; } try { MushroomZombie component = ((Component)character).GetComponent(); PhotonView view = ResolveCharacterPhotonView(character); int actorNumber2; return (Object)(object)component != (Object)null && IsControlledZombie(component) && TryGetControlledZombieOwnerActorNumber(component, view, out actorNumber2) && actorNumber2 == actorNumber; } catch { return false; } } private static bool TryFindRegisteredControlledZombieForActor(int actorNumber, out Character controlledZombie) { controlledZombie = null; if (actorNumber <= 0) { return false; } foreach (int item in new List(_controlledZombieViewIds)) { PhotonView val = null; try { val = PhotonNetwork.GetPhotonView(item); } catch { val = null; } if ((Object)(object)val == (Object)null) { continue; } MushroomZombie component = ((Component)val).GetComponent(); Character component2 = ((Component)val).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null)) { TryRegisterControlledZombieFromInstantiationData(component, val); if (IsControlledZombieOwnedByActor(component2, actorNumber)) { controlledZombie = component2; EnsureControlledZombieVisibleForRemoteViewers(component, component2, val); return true; } } } try { List allCharacters = Character.AllCharacters; if (allCharacters == null) { return false; } for (int i = 0; i < allCharacters.Count; i++) { Character val2 = allCharacters[i]; if ((Object)(object)val2 == (Object)null || !HasMushroomZombieComponent(val2)) { continue; } PhotonView val3 = ResolveCharacterPhotonView(val2); MushroomZombie component3 = ((Component)val2).GetComponent(); if (!((Object)(object)component3 == (Object)null) && !((Object)(object)val3 == (Object)null) && TryReadNetworkZombieInstantiationData(val3, out var _)) { TryRegisterControlledZombieFromInstantiationData(component3, val3); if (IsControlledZombieOwnedByActor(val2, actorNumber)) { controlledZombie = val2; EnsureControlledZombieVisibleForRemoteViewers(component3, val2, val3); return true; } } } } catch { controlledZombie = null; } return false; } internal static void UnregisterControlledZombieInstance(Character character, PhotonView view) { if ((Object)(object)character != (Object)null) { _controlledZombieCharacterInstanceIds.Remove(((Object)character).GetInstanceID()); UnregisterControlledZombieAsVanillaPlayerCharacter(character); try { MushroomZombie component = ((Component)character).GetComponent(); if ((Object)(object)component != (Object)null) { _controlledZombieInstanceIds.Remove(((Object)component).GetInstanceID()); _localMushroomGrowthInitializedZombieIds.Remove(((Object)component).GetInstanceID()); } } catch { } } if ((Object)(object)view != (Object)null && view.ViewID > 0) { _controlledZombieViewIds.Remove(view.ViewID); _controlledZombieSourceViewIdsByViewId.Remove(view.ViewID); } } internal static Character GetControlledZombieCharacter() { if (Instance?._session != null && Instance._session.TryGetControlledCharacter(out var character)) { return character; } if (!IsLocallyControlledZombieCharacter(_cameraOverrideCharacter)) { return null; } return _cameraOverrideCharacter; } internal static bool TryGetControlledZombieForPhotonPlayer(Player photonPlayer, out Character controlledZombie) { controlledZombie = null; if (photonPlayer == null) { return false; } return TryGetControlledZombieForActor(photonPlayer.ActorNumber, out controlledZombie); } private static bool TryGetControlledZombieForActor(int actorNumber, out Character controlledZombie) { controlledZombie = null; if (actorNumber <= 0) { return false; } Character controlledZombieCharacter = GetControlledZombieCharacter(); if ((Object)(object)controlledZombieCharacter != (Object)null && IsControlledZombieOwnedByActor(controlledZombieCharacter, actorNumber)) { controlledZombie = controlledZombieCharacter; return true; } return TryFindRegisteredControlledZombieForActor(actorNumber, out controlledZombie); } internal static bool TryGetStableSourceCharacterForLocalPlayer(out Character sourceCharacter) { sourceCharacter = _localSourceProxyCharacter; if ((Object)(object)GetControlledZombieCharacter() != (Object)null || IsStashedSourceCharacter(sourceCharacter)) { sourceCharacter = null; return false; } if ((Object)(object)sourceCharacter == (Object)null || (Object)(object)Player.localPlayer == (Object)null || (Object)(object)((MonoBehaviourPun)Player.localPlayer).photonView == (Object)null) { return false; } return IsSamePhotonOwner(sourceCharacter, ((MonoBehaviourPun)Player.localPlayer).photonView.Owner); } internal static bool TryGetStableSourceCharacterForPhotonPlayer(Player photonPlayer, out Character sourceCharacter) { sourceCharacter = _localSourceProxyCharacter; if ((Object)(object)GetControlledZombieCharacter() != (Object)null || IsStashedSourceCharacter(sourceCharacter)) { sourceCharacter = null; return false; } if ((Object)(object)sourceCharacter == (Object)null || photonPlayer == null) { return false; } return IsSamePhotonOwner(sourceCharacter, photonPlayer); } private static bool TryFindOriginalCharacterForPhotonPlayer(Player photonPlayer, out Character sourceCharacter) { sourceCharacter = null; if (photonPlayer == null) { return false; } if (TryUseOriginalCharacterCandidate(Character.localCharacter, photonPlayer, out sourceCharacter)) { return true; } if (TryUseOriginalCharacterCandidate(_localSourceProxyCharacter, photonPlayer, out sourceCharacter)) { return true; } try { List allCharacters = Character.AllCharacters; if (allCharacters == null) { return false; } for (int i = 0; i < allCharacters.Count; i++) { if (TryUseOriginalCharacterCandidate(allCharacters[i], photonPlayer, out sourceCharacter)) { return true; } } } catch { sourceCharacter = null; } return false; } private static bool TryUseOriginalCharacterCandidate(Character candidate, Player photonPlayer, out Character sourceCharacter) { sourceCharacter = null; if (!IsUsableRegisteredCharacter(candidate) || IsImZombieManagedCharacter(candidate) || HasMushroomZombieComponent(candidate) || !IsSamePhotonOwner(candidate, photonPlayer)) { return false; } sourceCharacter = candidate; return true; } internal static bool TryGetStableSourceCharacterForActor(int actorNumber, out Character sourceCharacter) { sourceCharacter = _localSourceProxyCharacter; if ((Object)(object)GetControlledZombieCharacter() != (Object)null || IsStashedSourceCharacter(sourceCharacter)) { sourceCharacter = null; return false; } if ((Object)(object)sourceCharacter == (Object)null || actorNumber <= 0) { return false; } if (_localSourceProxyActorNumber == actorNumber) { return true; } PhotonView val = ResolveCharacterPhotonView(sourceCharacter); if ((Object)(object)val == (Object)null || val.Owner == null || val.Owner.ActorNumber != actorNumber) { return false; } _localSourceProxyActorNumber = actorNumber; return true; } internal static bool TryGetStableCharacterForActor(int actorNumber, out Character character) { if (TryGetControlledZombieForActor(actorNumber, out character)) { return true; } if (TryGetStableSourceCharacterForActor(actorNumber, out character)) { ForcePlayerCharacterLookup(character); return true; } character = Character.localCharacter; if (!IsUsableRegisteredCharacter(character) || actorNumber <= 0) { character = null; return false; } PhotonView val = ResolveCharacterPhotonView(character); if ((Object)(object)val == (Object)null || val.Owner == null || val.Owner.ActorNumber != actorNumber) { character = null; return false; } ForcePlayerCharacterLookup(character); return true; } internal static bool TryGetStableLocalCharacter(out Character character) { character = null; if ((Object)(object)Player.localPlayer != (Object)null && (Object)(object)((MonoBehaviourPun)Player.localPlayer).photonView != (Object)null && ((MonoBehaviourPun)Player.localPlayer).photonView.Owner != null && TryGetStableCharacterForActor(((MonoBehaviourPun)Player.localPlayer).photonView.Owner.ActorNumber, out character)) { return true; } character = Character.localCharacter; if (!IsUsableRegisteredCharacter(character)) { character = null; return false; } ForcePlayerCharacterLookup(character); return true; } internal static bool TrySuppressDuplicateLocalCharacterSpawn(out Character character) { character = null; if (Instance?._session == null) { Plugin instance = Instance; if ((instance == null || !instance._switching) && (Object)(object)_localSourceProxyCharacter == (Object)null) { return false; } } if (!TryGetStableLocalCharacter(out character)) { return false; } if (Time.unscaledTime >= _nextDuplicateSpawnSuppressionLogTime) { _nextDuplicateSpawnSuppressionLogTime = Time.unscaledTime + 1f; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[I'm Zombie] Suppressed duplicate local character spawn while zombie session is active."); } } return true; } internal static bool ShouldSuppressHostLocalCharacterSpawn() { if (!TrySuppressDuplicateLocalCharacterSpawn(out var character)) { return false; } Character.localCharacter = character; ForcePlayerCharacterLookup(character); return true; } internal static bool TryGetPlayerForSourceCharacter(Character sourceCharacter, out Player player) { player = null; if ((Object)(object)sourceCharacter == (Object)null) { return false; } PhotonView val = ResolveCharacterPhotonView(sourceCharacter); if ((Object)(object)val == (Object)null || val.Owner == null) { return false; } try { player = PlayerHandler.GetPlayer(val.Owner); } catch { player = null; } if ((Object)(object)player == (Object)null && (Object)(object)Player.localPlayer != (Object)null && (Object)(object)((MonoBehaviourPun)Player.localPlayer).photonView != (Object)null && ((MonoBehaviourPun)Player.localPlayer).photonView.Owner != null && ((MonoBehaviourPun)Player.localPlayer).photonView.Owner.ActorNumber == val.Owner.ActorNumber) { player = Player.localPlayer; } return (Object)(object)player != (Object)null; } private static void SetLocalSourceProxyCharacter(Character sourceCharacter) { if (!((Object)(object)sourceCharacter == (Object)null)) { _localSourceProxyCharacter = sourceCharacter; PhotonView val = ResolveCharacterPhotonView(sourceCharacter); if ((Object)(object)val != (Object)null && val.Owner != null) { _localSourceProxyActorNumber = val.Owner.ActorNumber; } } } private static void RestoreLocalSourceProxyCharacterActive() { Character localSourceProxyCharacter = _localSourceProxyCharacter; if ((Object)(object)localSourceProxyCharacter == (Object)null) { return; } try { if ((Object)(object)((Component)localSourceProxyCharacter).gameObject != (Object)null && !((Component)localSourceProxyCharacter).gameObject.activeSelf) { ((Component)localSourceProxyCharacter).gameObject.SetActive(true); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[I'm Zombie] Reactivated source character during zombie transform after a registration overwrite attempt."); } } ForcePlayerCharacterLookup(localSourceProxyCharacter); if (Instance?._session == null) { Plugin instance = Instance; if (instance != null && instance._switching) { Character.localCharacter = localSourceProxyCharacter; } } } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[I'm Zombie] Failed to reactivate source character during zombie transform: " + ex.Message)); } } } private static void ClearLocalSourceProxyCharacter(Character sourceCharacter) { if (!((Object)(object)_localSourceProxyCharacter == (Object)null) && ((Object)(object)sourceCharacter == (Object)null || (Object)(object)_localSourceProxyCharacter == (Object)(object)sourceCharacter)) { _localSourceProxyCharacter = null; _localSourceProxyActorNumber = -1; } } private static bool IsSamePhotonOwner(Character character, Player photonPlayer) { PhotonView val = ResolveCharacterPhotonView(character); if ((Object)(object)val != (Object)null && val.Owner != null && photonPlayer != null) { return val.Owner.ActorNumber == photonPlayer.ActorNumber; } return false; } private static bool IsUsableRegisteredCharacter(Character character) { if ((Object)(object)character == (Object)null) { return false; } try { return (Object)(object)((Component)character).gameObject != (Object)null && (Object)(object)((MonoBehaviourPun)character).photonView != (Object)null; } catch { return false; } } internal static bool ShouldForceShowControlledZombie(HideTheBody hideTheBody, Character fallbackCharacter) { if ((Object)(object)hideTheBody == (Object)null) { return false; } if (ShouldForceShowControlledZombie(fallbackCharacter)) { return true; } Character componentInParent = ((Component)hideTheBody).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return (Object)(object)componentInParent == (Object)(object)_cameraOverrideCharacter; } return false; } internal static void RefreshCameraAfterGameUpdate(object movement) { //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) //IL_0076: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_cameraOverrideCharacter != (Object)null) { RefreshControlledZombieCamera(movement); } else { if ((Object)(object)_cameraRestoreCharacter == (Object)null) { return; } if (Time.unscaledTime > _cameraRestoreUntil) { _cameraRestoreCharacter = null; _cameraRestoreUntil = 0f; } else { if ((Object)(object)_cameraRestoreCharacter.data == (Object)null) { return; } Character.localCharacter = _cameraRestoreCharacter; EnsureUsableLookState(_cameraRestoreCharacter); Vector3 val = ResolvePlayerCameraPosition(_cameraRestoreCharacter); Quaternion val2 = ResolvePlayerCameraRotation(_cameraRestoreCharacter); try { MainCameraSpecCharacterProperty?.SetValue(null, null, null); MainCameraIsSpectatingField?.SetValue(movement, false); MainCameraRagdollCamField?.SetValue(movement, 0f); MainCameraCurrentForwardOffsetField?.SetValue(movement, 0f); MainCameraTargetPlayerPovPositionField?.SetValue(movement, val); MainCameraPhysicsRotField?.SetValue(movement, val2); Component val3 = (Component)((movement is Component) ? movement : null); if (val3 != null) { val3.transform.SetPositionAndRotation(val, val2); } } catch { } } } } internal static void RefreshControlledZombieCamera(object movement) { //IL_0028: 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) //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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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) if (movement == null || (Object)(object)_cameraOverrideCharacter == (Object)null || (Object)(object)_cameraOverrideCharacter.data == (Object)null) { return; } Vector3 smoothedThirdPersonCameraPosition = GetSmoothedThirdPersonCameraPosition(_cameraOverrideCharacter); Quaternion smoothedThirdPersonCameraRotation = GetSmoothedThirdPersonCameraRotation(_cameraOverrideCharacter); try { MainCameraSpecCharacterProperty?.SetValue(null, null, null); MainCameraIsSpectatingField?.SetValue(movement, false); MainCameraRagdollCamField?.SetValue(movement, 0f); MainCameraCurrentForwardOffsetField?.SetValue(movement, 0f); MainCameraTargetPlayerPovPositionField?.SetValue(movement, smoothedThirdPersonCameraPosition); MainCameraPhysicsRotField?.SetValue(movement, smoothedThirdPersonCameraRotation); Component val = (Component)((movement is Component) ? movement : null); if (val != null) { val.transform.SetPositionAndRotation(smoothedThirdPersonCameraPosition, smoothedThirdPersonCameraRotation); } } catch { } } internal static void RefreshHideTheBodyVisuals(HideTheBody hideTheBody) { if ((Object)(object)hideTheBody == (Object)null) { return; } RevealRendererMaterials((Renderer)(object)hideTheBody.body); RevealRendererMaterials(hideTheBody.headRend); RevealRendererMaterials((Renderer)(object)hideTheBody.sash); if (hideTheBody.costumes != null) { SkinnedMeshRenderer[] costumes = hideTheBody.costumes; for (int i = 0; i < costumes.Length; i++) { RevealRendererMaterials((Renderer)(object)costumes[i]); } } } private static void RestoreRendererVisibility(GameObject obj) { if (!((Object)(object)obj == (Object)null)) { Renderer[] componentsInChildren = obj.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { RestoreRendererVisibility(componentsInChildren[i]); } } } private static void SetZombieRenderersVisible(GameObject obj, bool visible) { if ((Object)(object)obj == (Object)null) { return; } if (visible) { SetGameObjectActive(obj, active: true); RestoreRendererVisibility(obj); return; } Renderer[] componentsInChildren = obj.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { HideRenderer(componentsInChildren[i]); } } internal static void RefreshControlledZombieVisuals() { if (!((Object)(object)_viewZombieObject == (Object)null)) { MushroomZombie component = _viewZombieObject.GetComponent(); Character component2 = _viewZombieObject.GetComponent(); RestoreRendererVisibility(_viewZombieObject); ApplyControlledZombieNativePresentation(component, component2, null); HideTheBody[] componentsInChildren = _viewZombieObject.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { RefreshHideTheBodyVisuals(componentsInChildren[i]); } } } internal static void ApplyControlledZombieNativePresentation(MushroomZombie zombie, Character zombieCharacter, Character sourceCharacter) { if ((Object)(object)zombie == (Object)null) { return; } try { if ((Object)(object)zombieCharacter == (Object)null) { zombieCharacter = ((Component)zombie).GetComponent(); } ConfigureControlledZombieCustomization(zombieCharacter, sourceCharacter); ClearMushroomZombieSpawnSource(zombie); ApplyControlledZombieOutfit(zombie, zombieCharacter, sourceCharacter); MushroomZombieSetZombieEyesMethod?.Invoke(zombie, Array.Empty()); MushroomZombieSetMushroomManMethod?.Invoke(zombie, Array.Empty()); ApplyMushroomAppearance(zombie); EnsureLocalControlledZombieMushroomGrowth(zombie); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to apply native zombie presentation: " + ex.Message)); } } } private static void ClearMushroomZombieSpawnSource(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null || MushroomZombieSpawnedFromCharacterField == null) { return; } try { MushroomZombieSpawnedFromCharacterField.SetValue(zombie, null); } catch { } } internal static void UpdateControlledZombieNativeVisuals(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null) { return; } EnsureLocalControlledZombieMushroomGrowth(zombie); if (!ShouldShowMushroomVisuals(zombie)) { ApplyMushroomAppearance(zombie); return; } try { object obj = MushroomZombieMushroomsGrowingField?.GetValue(zombie); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { MushroomZombieUpdateMushroomGrowthMethod?.Invoke(zombie, Array.Empty()); } } catch { } } private static void ApplyMushroomAppearance(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null || zombie.mushroomVisuals == null) { return; } bool flag = ShouldShowMushroomVisuals(zombie); for (int i = 0; i < zombie.mushroomVisuals.Count; i++) { GameObject val = zombie.mushroomVisuals[i]; if (!((Object)(object)val == (Object)null)) { SetGameObjectActive(val, flag); if (flag) { RestoreRendererVisibility(val); } } } } private static void EnsureLocalControlledZombieMushroomGrowth(MushroomZombie zombie) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_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_0094: 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_0102: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)zombie == (Object)null || zombie.mushroomVisuals == null || !IsLocallyControlledZombie(zombie) || !ShouldShowMushroomVisuals(zombie)) { return; } int instanceID = ((Object)zombie).GetInstanceID(); if (!_localMushroomGrowthInitializedZombieIds.Add(instanceID)) { return; } try { List list = MushroomZombieMushroomGrowTimesField?.GetValue(zombie) as List; if (list == null) { list = new List(); MushroomZombieMushroomGrowTimesField?.SetValue(zombie, list); } list.Clear(); Vector2 minMaxMushroomGrowTime = zombie.minMaxMushroomGrowTime; float num = Mathf.Max(Mathf.Min(minMaxMushroomGrowTime.x, minMaxMushroomGrowTime.y), 0.05f); float num2 = Mathf.Max(Mathf.Max(minMaxMushroomGrowTime.x, minMaxMushroomGrowTime.y), num); foreach (GameObject mushroomVisual in zombie.mushroomVisuals) { list.Add(Random.Range(num, num2)); if (!((Object)(object)mushroomVisual == (Object)null)) { SetGameObjectActive(mushroomVisual, active: true); RestoreRendererVisibility(mushroomVisual); mushroomVisual.transform.localScale = new Vector3(0.001f, 0.001f, 0.001f); } } MushroomZombieMushroomsGrowingField?.SetValue(zombie, true); LogVerbose("Initialized local controlled zombie mushroom growth visuals."); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to initialize local mushroom growth visuals: " + ex.Message)); } } } private static bool ShouldShowMushroomVisuals(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null || IsMushroomManPresentation(zombie)) { return false; } if (!IsLocallyControlledZombie(zombie)) { if (ZombieMushroomAppearance != null) { return ZombieMushroomAppearance.Value; } return false; } return true; } private static bool IsMushroomManPresentation(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null || MushroomZombieIsMushroomManProperty == null) { return false; } try { object value = MushroomZombieIsMushroomManProperty.GetValue(zombie, null); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static void ApplyControlledZombieOutfit(MushroomZombie zombie, Character zombieCharacter, Character sourceCharacter) { if ((Object)(object)zombie == (Object)null) { return; } bool flag = ResolveControlledZombieWearingSkirt(zombie, zombieCharacter, sourceCharacter); try { if ((Object)(object)zombie.skirt != (Object)null && (Object)(object)zombie.shorts != (Object)null) { MushroomZombieSetOutfitMethod?.Invoke(zombie, new object[1] { flag }); } MushroomZombieWearingSkirtField?.SetValue(zombie, flag); SetGameObjectActive(zombie.skirt, flag); SetGameObjectActive(zombie.shorts, !flag); } catch { try { MushroomZombieWearingSkirtField?.SetValue(zombie, flag); SetGameObjectActive(zombie.skirt, flag); SetGameObjectActive(zombie.shorts, !flag); } catch { } } } private static bool ResolveControlledZombieWearingSkirt(MushroomZombie zombie, Character zombieCharacter, Character sourceCharacter) { if (TryResolveWearingSkirtFromZombie(zombie, out var wearingSkirt)) { return wearingSkirt; } if (TryResolveWearingSkirtFromCharacter(zombieCharacter, out wearingSkirt)) { return wearingSkirt; } if (TryResolveWearingSkirtFromCharacter(sourceCharacter, out wearingSkirt)) { return wearingSkirt; } return GetMushroomZombieWearingSkirt(zombie); } private static bool TryResolveWearingSkirtFromZombie(MushroomZombie zombie, out bool wearingSkirt) { wearingSkirt = false; if ((Object)(object)zombie == (Object)null || (Object)(object)zombie.skirt == (Object)null || (Object)(object)zombie.shorts == (Object)null) { return false; } bool activeSelf = zombie.skirt.activeSelf; bool activeSelf2 = zombie.shorts.activeSelf; if (activeSelf == activeSelf2) { return false; } wearingSkirt = activeSelf; return true; } private static bool TryResolveWearingSkirtFromCharacter(Character character, out bool wearingSkirt) { wearingSkirt = false; object obj = ResolveCharacterCustomization(character)?.refs; if (obj == null) { return false; } try { object? obj2 = CustomizationRefsSkirtField?.GetValue(obj); Renderer val = (Renderer)((obj2 is Renderer) ? obj2 : null); object? obj3 = CustomizationRefsShortsField?.GetValue(obj); Renderer val2 = (Renderer)((obj3 is Renderer) ? obj3 : null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return false; } bool activeSelf = ((Component)val).gameObject.activeSelf; bool activeSelf2 = ((Component)val2).gameObject.activeSelf; if (activeSelf == activeSelf2) { return false; } wearingSkirt = activeSelf; return true; } catch { return false; } } private static void RestoreRendererVisibility(Renderer renderer) { if (!((Object)(object)renderer == (Object)null)) { if (_rendererVisualStates.TryGetValue(((Object)renderer).GetInstanceID(), out var value)) { renderer.enabled = value.Enabled; renderer.forceRenderingOff = value.ForceRenderingOff; _rendererVisualStates.Remove(((Object)renderer).GetInstanceID()); } if (renderer.enabled && !renderer.forceRenderingOff) { RevealRendererMaterials(renderer); } } } private static void RevealRendererMaterials(Renderer renderer) { if (!((Object)(object)renderer == (Object)null)) { SetRendererMaterialFloat(renderer, "_VertexGhost", 0f); SetRendererMaterialFloat(renderer, "_Opacity", 1f); SetRendererMaterialFloat(renderer, "_Alpha", 1f); } } private static void HideRenderer(Renderer renderer) { if (!((Object)(object)renderer == (Object)null)) { int instanceID = ((Object)renderer).GetInstanceID(); if (!_rendererVisualStates.ContainsKey(instanceID)) { _rendererVisualStates[instanceID] = new RendererVisualState(renderer.enabled, renderer.forceRenderingOff); } renderer.enabled = false; renderer.forceRenderingOff = true; SetRendererMaterialFloat(renderer, "_VertexGhost", 1f); SetRendererMaterialFloat(renderer, "_Opacity", 0f); SetRendererMaterialFloat(renderer, "_Alpha", 0f); } } private static void HideSourceRenderers(GameObject obj) { if (!((Object)(object)obj == (Object)null)) { Renderer[] componentsInChildren = obj.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { HideSourceRenderer(componentsInChildren[i]); } } } private static void RestoreSourceRenderers(GameObject obj) { if (!((Object)(object)obj == (Object)null)) { Renderer[] componentsInChildren = obj.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { RestoreSourceRenderer(componentsInChildren[i]); } } } private static void HideSourceRenderer(Renderer renderer) { if (!((Object)(object)renderer == (Object)null)) { int instanceID = ((Object)renderer).GetInstanceID(); if (!_sourceRendererVisualStates.ContainsKey(instanceID)) { _sourceRendererVisualStates[instanceID] = new RendererVisualState(renderer.enabled, renderer.forceRenderingOff); } renderer.enabled = false; renderer.forceRenderingOff = true; SetRendererMaterialFloat(renderer, "_VertexGhost", 1f); SetRendererMaterialFloat(renderer, "_Opacity", 0f); SetRendererMaterialFloat(renderer, "_Alpha", 0f); } } private static void RestoreSourceRenderer(Renderer renderer) { if (!((Object)(object)renderer == (Object)null)) { int instanceID = ((Object)renderer).GetInstanceID(); if (_sourceRendererVisualStates.TryGetValue(instanceID, out var value)) { renderer.enabled = value.Enabled; renderer.forceRenderingOff = value.ForceRenderingOff; _sourceRendererVisualStates.Remove(instanceID); } if (renderer.enabled && !renderer.forceRenderingOff) { RevealRendererMaterials(renderer); } } } private static void SetRendererMaterialFloat(Renderer renderer, string propertyName, float value) { if ((Object)(object)renderer == (Object)null || string.IsNullOrWhiteSpace(propertyName)) { return; } Material[] materials = renderer.materials; for (int i = 0; i < materials.Length; i++) { if ((Object)(object)materials[i] != (Object)null && materials[i].HasProperty(propertyName)) { materials[i].SetFloat(propertyName, value); } } } private static void SetGameObjectActive(GameObject obj, bool active) { try { if ((Object)(object)obj != (Object)null && obj.activeSelf != active) { obj.SetActive(active); } } catch { } } private static Vector3 GetThirdPersonCameraPosition(Character character) { //IL_001b: 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_0020: 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_0022: 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_002c: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_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_005f: 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) Vector3 val = (((Object)(object)character.data != (Object)null) ? character.data.lookDirection_Flat : Vector3.zero); val = Vector3.ProjectOnPlane(val, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.ProjectOnPlane(((Component)character).transform.forward, Vector3.up); } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.forward; } ((Vector3)(ref val)).Normalize(); return GetThirdPersonLookTarget(character) - val * GetEffectiveThirdPersonDistance(); } private static Vector3 GetSmoothedThirdPersonCameraPosition(Character character) { //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_0020: 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_002c: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0059: Unknown result type (might be due to invalid IL or missing references) Vector3 thirdPersonCameraPosition = GetThirdPersonCameraPosition(character); if (!_hasSmoothedThirdPersonCameraPose || Vector3.Distance(_smoothedThirdPersonCameraPosition, thirdPersonCameraPosition) > 8f) { _smoothedThirdPersonCameraPosition = thirdPersonCameraPosition; _hasSmoothedThirdPersonCameraPose = true; return thirdPersonCameraPosition; } float exponentialLerp = GetExponentialLerp(IsCharacterClimbing(character) ? 8f : 16f); _smoothedThirdPersonCameraPosition = Vector3.Lerp(_smoothedThirdPersonCameraPosition, thirdPersonCameraPosition, exponentialLerp); return _smoothedThirdPersonCameraPosition; } private static Quaternion GetSmoothedThirdPersonCameraRotation(Character character) { //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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) Quaternion thirdPersonCameraRotation = GetThirdPersonCameraRotation(character); if (!_hasSmoothedThirdPersonCameraPose) { _smoothedThirdPersonCameraRotation = thirdPersonCameraRotation; return thirdPersonCameraRotation; } float exponentialLerp = GetExponentialLerp(IsCharacterClimbing(character) ? 10f : 22f); _smoothedThirdPersonCameraRotation = Quaternion.Slerp(_smoothedThirdPersonCameraRotation, thirdPersonCameraRotation, exponentialLerp); return _smoothedThirdPersonCameraRotation; } private static Vector3 GetThirdPersonLookTarget(Character character) { //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_0042: 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) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) Vector3 rawThirdPersonLookTarget = GetRawThirdPersonLookTarget(character); bool flag = IsCharacterClimbing(character); int instanceID = ((Object)character).GetInstanceID(); if (_smoothedThirdPersonCharacterId != instanceID) { _smoothedThirdPersonCharacterId = instanceID; _hasSmoothedThirdPersonCameraTarget = false; } if (!_hasSmoothedThirdPersonCameraTarget || Vector3.Distance(_smoothedThirdPersonCameraTarget, rawThirdPersonLookTarget) > 8f) { _smoothedThirdPersonCameraTarget = rawThirdPersonLookTarget; _hasSmoothedThirdPersonCameraTarget = true; return rawThirdPersonLookTarget; } float exponentialLerp = GetExponentialLerp(flag ? 7f : 18f); _smoothedThirdPersonCameraTarget = (flag ? SmoothClimbLookTarget(_smoothedThirdPersonCameraTarget, rawThirdPersonLookTarget, exponentialLerp) : Vector3.Lerp(_smoothedThirdPersonCameraTarget, rawThirdPersonLookTarget, exponentialLerp)); return _smoothedThirdPersonCameraTarget; } private static Vector3 SmoothClimbLookTarget(Vector3 current, Vector3 target, float horizontalLerp) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) Vector3 result = Vector3.Lerp(current, target, horizontalLerp); float num = Mathf.Abs(target.y - current.y); if (num <= 0.06f) { result.y = current.y; return result; } float sharpness = ((num >= 0.75f) ? 9f : 2.4f); result.y = Mathf.Lerp(current.y, target.y, GetExponentialLerp(sharpness)); return result; } private static Vector3 GetRawThirdPersonLookTarget(Character character) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_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_005d: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_002d: 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_006e: 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_0066: 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_003b: 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_0078: 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_00a4: 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_0087: 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_008e: 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_00b9: 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_00c5: Unknown result type (might be due to invalid IL or missing references) if (IsControlledZombieAttackCameraState(character)) { Vector3 val = character.Center + Vector3.up * Mathf.Max(0.45f, 0.1f); if (!IsFiniteVector(val)) { return ((Component)character).transform.position; } return val; } Vector3 val2 = character.Center + Vector3.up * GetEffectiveThirdPersonHeightOffset(); if (!IsCharacterClimbing(character)) { return val2; } Vector3 head = character.Head; if (IsFiniteVector(head)) { if (!(Vector3.Distance(val2, head) <= 3f)) { return val2; } return Vector3.Lerp(val2, head, 0.25f); } Transform val3 = ResolveHeadTransform(character); if ((Object)(object)val3 == (Object)null || Vector3.Distance(val2, val3.position) > 3f) { return val2; } return Vector3.Lerp(val2, val3.position, 0.25f); } private static bool IsCharacterClimbing(Character character) { if ((Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null) { if (!character.data.isClimbing && !character.data.isRopeClimbing) { return character.data.isVineClimbing; } return true; } return false; } private static Quaternion GetThirdPersonCameraRotation(Character character) { //IL_0017: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_0084: 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_005c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (((Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null) ? character.data.lookDirection : Vector3.zero); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = (((Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null) ? character.data.lookDirection_Flat : Vector3.zero); } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)character != (Object)null) { val = ((Component)character).transform.forward; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.forward; } return Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up); } private static bool IsControlledZombieAttackCameraState(Character character) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 if (!IsLocallyControlledZombieCharacter(character)) { return false; } try { MushroomZombie component = ((Component)character).GetComponent(); return (Object)(object)component != (Object)null && ((int)component.currentState == 4 || (int)component.currentState == 5); } catch { return false; } } private static void ResetThirdPersonCameraSmoothing() { //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) //IL_001c: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) _smoothedThirdPersonCharacterId = -1; _hasSmoothedThirdPersonCameraTarget = false; _smoothedThirdPersonCameraTarget = Vector3.zero; _hasSmoothedThirdPersonCameraPose = false; _smoothedThirdPersonCameraPosition = Vector3.zero; _smoothedThirdPersonCameraRotation = Quaternion.identity; } private static float GetExponentialLerp(float sharpness) { float num = ((Time.unscaledDeltaTime > 0f) ? Time.unscaledDeltaTime : Time.deltaTime); return Mathf.Clamp01(1f - Mathf.Exp((0f - Mathf.Max(sharpness, 0.01f)) * Mathf.Max(num, 0f))); } private static bool IsFiniteVector(Vector3 value) { //IL_0000: 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_001a: 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_0034: 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) if (!float.IsNaN(value.x) && !float.IsInfinity(value.x) && !float.IsNaN(value.y) && !float.IsInfinity(value.y) && !float.IsNaN(value.z)) { return !float.IsInfinity(value.z); } return false; } private static bool IsFiniteFloat(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } private static bool IsFiniteQuaternion(Quaternion value) { //IL_0000: 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_001a: 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) if (IsFiniteFloat(value.x) && IsFiniteFloat(value.y) && IsFiniteFloat(value.z)) { return IsFiniteFloat(value.w); } return false; } private static Quaternion NormalizeFiniteQuaternion(Quaternion value, Quaternion fallback) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0061: 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_0071: 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) if (!IsFiniteQuaternion(value)) { return fallback; } float num = Mathf.Sqrt(value.x * value.x + value.y * value.y + value.z * value.z + value.w * value.w); if (!IsFiniteFloat(num) || num < 0.0001f) { return fallback; } return new Quaternion(value.x / num, value.y / num, value.z / num, value.w / num); } private static Quaternion GetCharacterYaw(Character character) { //IL_001b: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0046: 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_003a: 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) //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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (((Object)(object)character.data != (Object)null) ? character.data.lookDirection_Flat : Vector3.zero); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = ((Component)character).transform.forward; } val = Vector3.ProjectOnPlane(val, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.forward; } return Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up); } private static void CopyLookStateForRestore(Character fromCharacter, Character toCharacter) { //IL_0018: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)toCharacter == (Object)null) && !((Object)(object)toCharacter.data == (Object)null)) { Vector3 val = Vector3.zero; Vector3 flatLook = Vector3.zero; Vector2 lookValues = toCharacter.data.lookValues; if ((Object)(object)fromCharacter != (Object)null && (Object)(object)fromCharacter.data != (Object)null) { val = fromCharacter.data.lookDirection; flatLook = fromCharacter.data.lookDirection_Flat; lookValues = fromCharacter.data.lookValues; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)Camera.main != (Object)null) { val = ((Component)Camera.main).transform.forward; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = ((Component)toCharacter).transform.forward; } if (((Vector3)(ref flatLook)).sqrMagnitude < 0.0001f) { flatLook = Vector3.ProjectOnPlane(val, Vector3.up); } if (((Vector3)(ref flatLook)).sqrMagnitude < 0.0001f) { flatLook = ((Component)toCharacter).transform.forward; } ApplyLookState(toCharacter, val, flatLook, lookValues); } } private static void CopyLookStateForZombieEnter(Character sourceCharacter, Character zombieCharacter, Quaternion fallbackRotation) { //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_0027: 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_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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00b8: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)sourceCharacter == (Object)null) && !((Object)(object)zombieCharacter == (Object)null) && !((Object)(object)zombieCharacter.data == (Object)null)) { Vector3 val = Vector3.zero; Vector3 flatLook = Vector3.zero; Vector2 lookValues = zombieCharacter.data.lookValues; if ((Object)(object)sourceCharacter.data != (Object)null) { val = sourceCharacter.data.lookDirection; flatLook = sourceCharacter.data.lookDirection_Flat; lookValues = sourceCharacter.data.lookValues; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = fallbackRotation * Vector3.forward; } if (((Vector3)(ref flatLook)).sqrMagnitude < 0.0001f) { flatLook = Vector3.ProjectOnPlane(val, Vector3.up); } if (((Vector3)(ref flatLook)).sqrMagnitude < 0.0001f) { flatLook = fallbackRotation * Vector3.forward; } ApplyLookState(zombieCharacter, val, flatLook, lookValues); } } private static void BeginCameraRestoreAssist(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { _cameraRestoreCharacter = null; _cameraRestoreUntil = 0f; return; } _cameraRestoreCharacter = character; _cameraRestoreUntil = Time.unscaledTime + 1.5f; Character.localCharacter = character; EnsureUsableLookState(character); ResetMainCameraState(character, snapCamera: true); } private static void ForcePlayerCharacterLookup(Character character) { if ((Object)(object)character == (Object)null) { return; } int num = ResolveCharacterLookupActorNumber(character); if (num <= 0) { return; } try { object obj = PlayerHandlerInstanceProperty?.GetValue(null, null); if (PlayerHandlerCharacterLookupField?.GetValue(obj) is IDictionary dictionary) { PruneNullPlayerCharacterLookupEntries(dictionary); dictionary[num] = character; } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to restore player character lookup: " + ex.Message)); } } } private static int ResolveCharacterLookupActorNumber(Character character) { PhotonView val = ResolveCharacterPhotonView(character); if ((Object)(object)val != (Object)null && val.Owner != null) { return val.Owner.ActorNumber; } if (IsLocallyControlledZombieCharacter(character) && (Object)(object)Player.localPlayer != (Object)null && (Object)(object)((MonoBehaviourPun)Player.localPlayer).photonView != (Object)null && ((MonoBehaviourPun)Player.localPlayer).photonView.Owner != null) { return ((MonoBehaviourPun)Player.localPlayer).photonView.Owner.ActorNumber; } if ((Object)(object)character == (Object)(object)Character.localCharacter && (Object)(object)Player.localPlayer != (Object)null && (Object)(object)((MonoBehaviourPun)Player.localPlayer).photonView != (Object)null && ((MonoBehaviourPun)Player.localPlayer).photonView.Owner != null) { return ((MonoBehaviourPun)Player.localPlayer).photonView.Owner.ActorNumber; } return -1; } private static void PruneNullPlayerCharacterLookupEntries(IDictionary lookup) { if (lookup == null || lookup.Count == 0) { return; } List list = null; foreach (KeyValuePair item in lookup) { if (!((Object)(object)item.Value != (Object)null)) { if (list == null) { list = new List(); } list.Add(item.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { lookup.Remove(list[i]); } } } private static void PruneImZombiePlayerCharacterLookupEntries(IDictionary lookup) { if (lookup == null || lookup.Count == 0) { return; } List list = null; foreach (KeyValuePair item in lookup) { Character value = item.Value; if (!((Object)(object)value == (Object)null) && (IsImZombieManagedCharacter(value) || IsStashedSourceCharacter(value))) { if (list == null) { list = new List(); } list.Add(item.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { lookup.Remove(list[i]); } } } private void MaintainLocalHumanPresentation() { if (_session != null || _switching || Time.unscaledTime < _nextHumanPresentationMaintenanceTime) { return; } _nextHumanPresentationMaintenanceTime = Time.unscaledTime + 0.4f; Character localCharacter = Character.localCharacter; if (!((Object)(object)localCharacter == (Object)null) && !((Object)(object)localCharacter.data == (Object)null) && !IsImZombieManagedCharacter(localCharacter)) { if ((Object)(object)_cameraOverrideCharacter != (Object)null && !IsImZombieManagedCharacter(_cameraOverrideCharacter)) { ClearCameraOverride(); } if (!localCharacter.isZombie && !localCharacter.data.zombified && !localCharacter.data.dead && HasResidualHumanZombiePresentation(localCharacter)) { RestoreCharacterHumanPresentation(localCharacter, resetCamera: true); } } } private static bool HasResidualHumanZombiePresentation(Character character) { CharacterCustomization val = ResolveCharacterCustomization(character); if ((Object)(object)val?.refs?.skeletonRenderer == (Object)null) { return false; } try { return ((Component)val.refs.skeletonRenderer).gameObject.activeSelf; } catch { return false; } } private static void EnsureUsableLookState(Character character) { //IL_0053: 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_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_005a: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null) && !(((Vector3)(ref character.data.lookDirection)).sqrMagnitude >= 0.0001f)) { Vector3 val = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform.forward : ((Component)character).transform.forward); Vector3 flatLook = Vector3.ProjectOnPlane(val, Vector3.up); ApplyLookState(character, val, flatLook, character.data.lookValues); } } private static void ApplyLookState(Character character, Vector3 lookDirection, Vector3 flatLook, Vector2 lookValues) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0046: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0077: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null)) { if (((Vector3)(ref lookDirection)).sqrMagnitude < 0.0001f) { lookDirection = Vector3.forward; } if (((Vector3)(ref flatLook)).sqrMagnitude < 0.0001f) { flatLook = Vector3.ProjectOnPlane(lookDirection, Vector3.up); } if (((Vector3)(ref flatLook)).sqrMagnitude < 0.0001f) { flatLook = Vector3.forward; } ((Vector3)(ref lookDirection)).Normalize(); Vector3 val = Vector3.ProjectOnPlane(flatLook, Vector3.up); flatLook = ((Vector3)(ref val)).normalized; character.data.lookValues = lookValues; character.data.lookDirection = lookDirection; character.data.lookDirection_Flat = flatLook; CharacterData data = character.data; val = Vector3.Cross(Vector3.up, lookDirection); data.lookDirection_Right = ((Vector3)(ref val)).normalized; CharacterData data2 = character.data; val = Vector3.Cross(lookDirection, character.data.lookDirection_Right); data2.lookDirection_Up = ((Vector3)(ref val)).normalized; ((Component)character).transform.rotation = Quaternion.LookRotation(flatLook, Vector3.up); } } private static void ApplyLookStateFromRotation(Character character, Quaternion rotation) { //IL_0018: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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) //IL_0042: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null)) { Vector3 val = Vector3.ProjectOnPlane(rotation * Vector3.forward, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = character.data.lookDirection_Flat; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = ((Component)character).transform.forward; } val = Vector3.ProjectOnPlane(val, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.forward; } ApplyLookState(character, ((Vector3)(ref val)).normalized, ((Vector3)(ref val)).normalized, character.data.lookValues); } } private static void ForceClearSpectatorState() { try { MainCameraSpecCharacterProperty?.SetValue(null, null, null); if (!(FindObjectsOfTypeByTypeMethod?.Invoke(null, new object[1] { typeof(MainCameraMovement) }) is Object[] array)) { return; } Object[] array2 = array; foreach (Object val in array2) { if (!(val == (Object)null)) { MainCameraIsSpectatingField?.SetValue(val, false); MainCameraRagdollCamField?.SetValue(val, 0f); MainCameraCurrentForwardOffsetField?.SetValue(val, 0f); } } } catch { } } private static void ResetMainCameraState(Character character, bool snapCamera) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return; } try { MainCameraSpecCharacterProperty?.SetValue(null, null, null); } catch { } Vector3 val = ResolvePlayerCameraPosition(character); Quaternion val2 = ResolvePlayerCameraRotation(character); try { if (!(FindObjectsOfTypeByTypeMethod?.Invoke(null, new object[1] { typeof(MainCameraMovement) }) is Object[] array)) { return; } Object[] array2 = array; foreach (Object val3 in array2) { if (!(val3 == (Object)null)) { MainCameraIsSpectatingField?.SetValue(val3, false); MainCameraRagdollCamField?.SetValue(val3, 0f); MainCameraCurrentForwardOffsetField?.SetValue(val3, 0f); MainCameraTargetPlayerPovPositionField?.SetValue(val3, val); MainCameraPhysicsRotField?.SetValue(val3, val2); } } } catch { } if (!snapCamera || (Object)(object)Camera.main == (Object)null) { return; } try { ((Component)Camera.main).transform.SetPositionAndRotation(val, val2); } catch { } } private static Vector3 ResolvePlayerCameraPosition(Character character) { //IL_0009: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null) { return Vector3.zero; } Transform val = ResolveHeadTransform(character); if ((Object)(object)val != (Object)null) { return val.TransformPoint(Vector3.up); } return character.Head; } private static Quaternion ResolvePlayerCameraRotation(Character character) { //IL_0017: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_0077: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (((Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null) ? character.data.lookDirection : Vector3.zero); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)Camera.main != (Object)null) { val = ((Component)Camera.main).transform.forward; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)character != (Object)null) { val = ((Component)character).transform.forward; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.forward; } return Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up); } internal static void DestroyZombieObject(GameObject zombieObject) { if ((Object)(object)zombieObject == (Object)null) { return; } try { MonoBehaviour[] componentsInChildren = zombieObject.GetComponentsInChildren(true); foreach (MonoBehaviour obj in componentsInChildren) { if (obj != null) { obj.StopAllCoroutines(); } } } catch { } PhotonView component = zombieObject.GetComponent(); if ((Object)(object)component != (Object)null && (PhotonNetwork.InRoom || PhotonNetwork.OfflineMode)) { try { if (component.ViewID > 0 && (component.IsMine || PhotonNetwork.IsMasterClient)) { BeginControlledZombieDestroy(); try { PhotonNetwork.Destroy(zombieObject); return; } finally { EndControlledZombieDestroy(); } } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Photon destroy failed: " + ex.Message)); } } } Object.Destroy((Object)(object)zombieObject); } private static void ForceDestroyControlledZombieObject(GameObject zombieObject) { if ((Object)(object)zombieObject == (Object)null) { return; } BeginControlledZombieDestroy(); try { PhotonView component = zombieObject.GetComponent(); if ((Object)(object)component != (Object)null && component.ViewID > 0 && (PhotonNetwork.InRoom || PhotonNetwork.OfflineMode) && (component.IsMine || PhotonNetwork.IsMasterClient)) { try { PhotonNetwork.Destroy(zombieObject); return; } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Forced Photon destroy failed for duplicate zombie: " + ex.Message)); } } } Object.Destroy((Object)(object)zombieObject); } finally { EndControlledZombieDestroy(); } } private void RegisterConfigChangeHandlers() { if (((BaseUnityPlugin)this).Config != null) { ((BaseUnityPlugin)this).Config.SettingChanged -= OnConfigSettingChanged; ((BaseUnityPlugin)this).Config.SettingChanged += OnConfigSettingChanged; } } private void UnregisterConfigChangeHandlers() { if (((BaseUnityPlugin)this).Config != null) { ((BaseUnityPlugin)this).Config.SettingChanged -= OnConfigSettingChanged; } } private void OnConfigSettingChanged(object sender, SettingChangedEventArgs e) { MarkConfigFileLocalizationDirty(saveConfigFile: false); } private void MarkConfigFileLocalizationDirty(bool saveConfigFile) { _pendingConfigFileLocalizationRefresh = true; _pendingConfigFileLocalizationSave |= saveConfigFile; } private void HandlePendingConfigFileLocalizationRefresh() { if (_pendingConfigFileLocalizationRefresh && !_isRefreshingLanguage) { bool pendingConfigFileLocalizationSave = _pendingConfigFileLocalizationSave; _pendingConfigFileLocalizationRefresh = false; _pendingConfigFileLocalizationSave = false; TryRefreshLocalizedConfigFile(_lastDetectedChineseLanguage, pendingConfigFileLocalizationSave); } } private void HandleLanguageChangeIfNeeded() { bool flag = DetectChineseLanguage(); if (flag != _lastDetectedChineseLanguage) { ReinitializeLocalizedConfig(flag); } } private void ReinitializeLocalizedConfig(bool isChineseLanguage) { if (_isRefreshingLanguage) { return; } _isRefreshingLanguage = true; try { _lastDetectedChineseLanguage = isChineseLanguage; ApplyLocalizedConfigMetadata(isChineseLanguage); MarkConfigFileLocalizationDirty(saveConfigFile: true); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[I'm Zombie] Config language changed: " + (isChineseLanguage ? "Chinese" : "English"))); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] Failed to update config language: " + ex.Message)); } finally { _isRefreshingLanguage = false; } } private void ApplyLocalizedConfigMetadata(bool isChineseLanguage) { try { ConfigEntryBase[] configEntriesSnapshot = GetConfigEntriesSnapshot(((BaseUnityPlugin)this).Config); foreach (ConfigEntryBase val in configEntriesSnapshot) { if (!(((val != null) ? val.Definition : null) == (ConfigDefinition)null) && val.Description != null && TryGetConfigKey(val.Definition.Key, out var configKey)) { string localizedDescription = GetLocalizedDescription(configKey, isChineseLanguage); if (!string.IsNullOrWhiteSpace(localizedDescription)) { SetPrivateField(val.Description, "k__BackingField", localizedDescription); } } } TryLocalizeVisibleModConfigUi(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] Failed to apply localized config metadata: " + ex.Message)); } } private static ConfigEntryBase[] GetConfigEntriesSnapshot(ConfigFile configFile) { if (configFile == null || !(ConfigFileEntriesProperty?.GetValue(configFile) is IDictionary dictionary) || dictionary.Count == 0) { return Array.Empty(); } List list = new List(); foreach (DictionaryEntry item in dictionary) { object? value = item.Value; ConfigEntryBase val = (ConfigEntryBase)((value is ConfigEntryBase) ? value : null); if (val != null) { list.Add(val); } } return list.ToArray(); } private static void SetPrivateField(object target, string fieldName, object value) { if (target != null && !string.IsNullOrWhiteSpace(fieldName)) { target.GetType().GetField(fieldName, InstanceBindingFlags)?.SetValue(target, value); } } private static bool TryGetConfigKey(string keyName, out ConfigKey configKey) { foreach (ConfigKey value in Enum.GetValues(typeof(ConfigKey))) { if (string.Equals(keyName, GetConfigKeyName(value), StringComparison.OrdinalIgnoreCase) || string.Equals(keyName, GetKeyName(value, isChineseLanguage: true), StringComparison.OrdinalIgnoreCase)) { configKey = value; return true; } } configKey = ConfigKey.ToggleKey; return false; } private void TryRefreshLocalizedConfigFile(bool isChineseLanguage, bool saveConfigFile) { try { if (((BaseUnityPlugin)this).Config != null && !string.IsNullOrWhiteSpace(((BaseUnityPlugin)this).Config.ConfigFilePath)) { if (saveConfigFile) { ((BaseUnityPlugin)this).Config.Save(); } RewriteConfigFileLocalization(((BaseUnityPlugin)this).Config.ConfigFilePath, isChineseLanguage); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm Zombie] Failed to refresh localized config file: " + ex.Message)); } } private static void RewriteConfigFileLocalization(string configFilePath, bool isChineseLanguage) { if (!string.IsNullOrWhiteSpace(configFilePath) && File.Exists(configFilePath)) { string[] array = File.ReadAllLines(configFilePath); string[] array2 = new string[array.Length]; bool flag = false; for (int i = 0; i < array.Length; i++) { string text = array[i] ?? string.Empty; flag |= !string.Equals(text, array2[i] = RewriteConfigFileLine(text, isChineseLanguage), StringComparison.Ordinal); } if (flag) { File.WriteAllLines(configFilePath, array2); } } } private static string RewriteConfigFileLine(string line, bool isChineseLanguage) { if (string.IsNullOrWhiteSpace(line)) { return line ?? string.Empty; } string text = line.Trim(); if (text.StartsWith("[", StringComparison.Ordinal) && text.EndsWith("]", StringComparison.Ordinal)) { if (!TryGetLocalizedSectionName(text.Substring(1, text.Length - 2).Trim(), isChineseLanguage, out var localizedSectionName)) { return line; } int num = line.IndexOf('['); int num2 = line.LastIndexOf(']'); if (num < 0 || num2 < num) { return line; } return line.Substring(0, num + 1) + localizedSectionName + line.Substring(num2); } if (text.StartsWith("#", StringComparison.Ordinal) || text.StartsWith(";", StringComparison.Ordinal)) { return line; } int num3 = line.IndexOf('='); if (num3 <= 0) { return line; } int i; for (i = 0; i < num3 && char.IsWhiteSpace(line[i]); i++) { } int num4 = num3 - 1; while (num4 >= i && char.IsWhiteSpace(line[num4])) { num4--; } if (num4 < i) { return line; } if (!TryGetConfigKey(line.Substring(i, num4 - i + 1), out var configKey)) { return line; } string keyName = GetKeyName(configKey, isChineseLanguage); return line.Substring(0, i) + keyName + line.Substring(num4 + 1); } private static bool TryGetLocalizedSectionName(string sectionName, bool isChineseLanguage, out string localizedSectionName) { if (MatchesSectionName(sectionName, "Controls", "控制")) { localizedSectionName = (isChineseLanguage ? "控制" : "Controls"); return true; } if (MatchesSectionName(sectionName, "Zombie Control", "僵尸控制")) { localizedSectionName = (isChineseLanguage ? "僵尸控制" : "Zombie Control"); return true; } if (MatchesSectionName(sectionName, "Player Restore", "玩家恢复")) { localizedSectionName = (isChineseLanguage ? "玩家恢复" : "Player Restore"); return true; } if (MatchesSectionName(sectionName, "Diagnostics", "诊断")) { localizedSectionName = (isChineseLanguage ? "诊断" : "Diagnostics"); return true; } localizedSectionName = string.Empty; return false; } private static bool MatchesSectionName(string sectionName, string englishName, string chineseName) { if (!string.Equals(sectionName, englishName, StringComparison.OrdinalIgnoreCase)) { return string.Equals(sectionName, chineseName, StringComparison.Ordinal); } return true; } private void MigrateLocalizedConfigEntries() { IDictionary orphanedEntries = GetOrphanedEntries(((BaseUnityPlugin)this).Config); if (orphanedEntries != null && orphanedEntries.Count != 0) { int num = 0 | (TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)ToggleKey, ConfigKey.ToggleKey, orphanedEntries) ? 1 : 0) | (TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)ZombieMushroomAppearance, ConfigKey.ZombieMushroomAppearance, orphanedEntries) ? 1 : 0) | (TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)SprintStaminaRefill, ConfigKey.SprintStaminaRefill, orphanedEntries) ? 1 : 0) | (TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)ControlledJitterChance, ConfigKey.ControlledJitterChance, orphanedEntries) ? 1 : 0) | (TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)ControlledJitterIntensity, ConfigKey.ControlledJitterIntensity, orphanedEntries) ? 1 : 0) | (TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)ControlledJitterDuration, ConfigKey.ControlledJitterDuration, orphanedEntries) ? 1 : 0) | (TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)ThirdPersonHeightOffset, ConfigKey.ThirdPersonHeightOffset, orphanedEntries) ? 1 : 0) | (TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)ThirdPersonDistance, ConfigKey.ThirdPersonDistance, orphanedEntries) ? 1 : 0) | (TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)SourceStashDistance, ConfigKey.SourceStashDistance, orphanedEntries) ? 1 : 0) | (TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)VerboseLogs, ConfigKey.VerboseLogs, orphanedEntries) ? 1 : 0); bool flag = RemoveObsoleteConfigValues(orphanedEntries); if (((uint)num | (flag ? 1u : 0u)) != 0) { ((BaseUnityPlugin)this).Config.Save(); } } } private static bool RemoveObsoleteConfigValues(IDictionary orphanedEntries) { if (orphanedEntries == null || orphanedEntries.Count == 0) { return false; } bool result = false; foreach (ConfigKey obsoleteConfigKey in GetObsoleteConfigKeys()) { foreach (ConfigDefinition aliasDefinition in GetAliasDefinitions(obsoleteConfigKey)) { if (orphanedEntries.Contains(aliasDefinition)) { orphanedEntries.Remove(aliasDefinition); result = true; } } } return result; } [IteratorStateMachine(typeof(d__721))] private static IEnumerable GetObsoleteConfigKeys() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__721(-2); } private void MigrateThirdPersonCameraDefaults() { if (false | TryReplaceFloatConfigValue(ThirdPersonHeightOffset, 1.45f, 0.85f) | TryReplaceFloatConfigValue(ThirdPersonDistance, 4.2f, 2.8f)) { ((BaseUnityPlugin)this).Config.Save(); } } private static bool TryReplaceFloatConfigValue(ConfigEntry entry, float oldValue, float newValue) { if (entry == null || Mathf.Abs(entry.Value - oldValue) > 0.001f) { return false; } entry.Value = newValue; return true; } private static bool TryMigrateLocalizedConfigValue(ConfigEntryBase entry, ConfigKey configKey, IDictionary orphanedEntries) { if (((entry != null) ? entry.Definition : null) == (ConfigDefinition)null || orphanedEntries == null) { return false; } bool flag = false; foreach (ConfigDefinition aliasDefinition in GetAliasDefinitions(configKey)) { if (DefinitionsEqual(aliasDefinition, entry.Definition) || !orphanedEntries.Contains(aliasDefinition)) { continue; } if (!flag) { object obj = orphanedEntries[aliasDefinition]; if (obj != null) { entry.SetSerializedValue(obj.ToString()); } flag = true; } orphanedEntries.Remove(aliasDefinition); } return flag; } [IteratorStateMachine(typeof(d__725))] private static IEnumerable GetAliasDefinitions(ConfigKey configKey) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__725(-2) { <>3__configKey = configKey }; } private static IDictionary GetOrphanedEntries(ConfigFile configFile) { return ((object)configFile)?.GetType().GetProperty("OrphanedEntries", InstanceBindingFlags)?.GetValue(configFile) as IDictionary; } private static bool DefinitionsEqual(ConfigDefinition left, ConfigDefinition right) { if (string.Equals((left != null) ? left.Section : null, (right != null) ? right.Section : null, StringComparison.Ordinal)) { return string.Equals((left != null) ? left.Key : null, (right != null) ? right.Key : null, StringComparison.Ordinal); } return false; } private static void ClampConfigValues() { ClampFloat(SprintStaminaRefill, 1f, 3f); ClampFloat(ControlledJitterChance, 0f, 0.5f); ClampFloat(ControlledJitterIntensity, 0f, 2.5f); ClampFloat(ControlledJitterDuration, 0.05f, 0.6f); ClampFloat(ThirdPersonHeightOffset, 0.3f, 1.8f); ClampFloat(ThirdPersonDistance, 1.5f, 6f); ClampFloat(SourceStashDistance, 10f, 2000f); } private static void ClampFloat(ConfigEntry entry, float min, float max) { if (entry != null) { entry.Value = Mathf.Clamp(entry.Value, min, max); } } internal static float GetEffectiveSprintStaminaRefill() { return GetClampedConfigValue(SprintStaminaRefill, 1f, 1f, 3f); } internal static float GetEffectiveControlledJitterChance() { return GetClampedConfigValue(ControlledJitterChance, 0f, 0f, 0.5f); } internal static float GetEffectiveControlledJitterIntensity() { return GetClampedConfigValue(ControlledJitterIntensity, 1f, 0f, 2.5f); } internal static float GetEffectiveControlledJitterDuration() { return GetClampedConfigValue(ControlledJitterDuration, 0.22f, 0.05f, 0.6f); } internal static float GetEffectiveThirdPersonHeightOffset() { return GetClampedConfigValue(ThirdPersonHeightOffset, 0.85f, 0.3f, 1.8f); } internal static float GetEffectiveThirdPersonDistance() { return GetClampedConfigValue(ThirdPersonDistance, 2.8f, 1.5f, 6f); } internal static float GetEffectiveSourceStashDistance() { return GetClampedConfigValue(SourceStashDistance, 600f, 10f, 2000f); } private static float GetClampedConfigValue(ConfigEntry entry, float fallbackValue, float min, float max) { return Mathf.Clamp(entry?.Value ?? fallbackValue, min, max); } private static bool DetectChineseLanguage() { bool isChineseLanguage; bool num = TryGetConfiguredGameLanguage(out isChineseLanguage); string languageName; bool flag = TryGetLocalizedTextLanguageName(out languageName); if (num && isChineseLanguage) { return true; } if (flag && IsChineseLanguageName(languageName)) { return true; } return false; } private static string BuildLanguageDetectionSummary(bool isChineseLanguage) { bool isChineseLanguage2; string languageValueText; string text = (TryGetConfiguredGameLanguage(out isChineseLanguage2, out languageValueText) ? (languageValueText + "/" + (isChineseLanguage2 ? "Chinese" : "English")) : "unknown"); string languageName; string text2 = (TryGetLocalizedTextLanguageName(out languageName) ? languageName : "unknown"); return (isChineseLanguage ? "Chinese" : "English") + " (prefs=" + text + ", runtime=" + text2 + ")"; } private static bool TryGetConfiguredGameLanguage(out bool isChineseLanguage) { string languageValueText; return TryGetConfiguredGameLanguage(out isChineseLanguage, out languageValueText); } private static bool TryGetConfiguredGameLanguage(out bool isChineseLanguage, out string languageValueText) { isChineseLanguage = false; languageValueText = string.Empty; try { if (!PlayerPrefs.HasKey("LanguageSetting")) { return false; } int result = PlayerPrefs.GetInt("LanguageSetting", int.MinValue); if (result != int.MinValue) { languageValueText = result.ToString(CultureInfo.InvariantCulture); isChineseLanguage = IsChineseLanguageIndex(result); return true; } string text = (languageValueText = PlayerPrefs.GetString("LanguageSetting", string.Empty)); if (string.IsNullOrWhiteSpace(text)) { return false; } if (int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) { isChineseLanguage = IsChineseLanguageIndex(result); return true; } isChineseLanguage = IsChineseLanguageName(text); return true; } catch { return false; } } private static bool TryGetLocalizedTextLanguageName(out string languageName) { languageName = string.Empty; try { languageName = ((object)(Language)(ref LocalizedText.CURRENT_LANGUAGE)).ToString(); return !string.IsNullOrWhiteSpace(languageName); } catch { return false; } } private static bool IsChineseLanguageName(string languageName) { if (string.IsNullOrWhiteSpace(languageName)) { return false; } if (int.TryParse(languageName.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return IsChineseLanguageIndex(result); } if (languageName.IndexOf("Chinese", StringComparison.OrdinalIgnoreCase) < 0 && languageName.IndexOf("中文", StringComparison.OrdinalIgnoreCase) < 0) { return languageName.StartsWith("zh", StringComparison.OrdinalIgnoreCase); } return true; } private static bool IsChineseLanguageIndex(int languageValue) { if (languageValue != 9) { return languageValue == 10; } return true; } private static string GetConfigSectionName(ConfigKey configKey) { return GetSectionName(configKey, isChineseLanguage: false); } private static string GetSectionName(ConfigKey configKey, bool isChineseLanguage) { switch (configKey) { case ConfigKey.ToggleKey: case ConfigKey.MoveForwardKey: case ConfigKey.MoveBackwardKey: case ConfigKey.MoveLeftKey: case ConfigKey.MoveRightKey: case ConfigKey.JumpKey: case ConfigKey.SprintKey: case ConfigKey.ClimbKey: case ConfigKey.PounceKey: case ConfigKey.ChaseToggleKey: case ConfigKey.ViewToggleKey: case ConfigKey.ControlledJitterChance: case ConfigKey.ControlledJitterIntensity: case ConfigKey.ControlledJitterDuration: if (!isChineseLanguage) { return "Zombie Control"; } return "僵尸控制"; case ConfigKey.ThirdPersonHeightOffset: case ConfigKey.ThirdPersonDistance: if (!isChineseLanguage) { return "Third Person Camera"; } return "第三人称视角"; case ConfigKey.PounceDuration: case ConfigKey.PounceCooldown: case ConfigKey.PounceForwardVelocity: case ConfigKey.PounceUpVelocity: if (!isChineseLanguage) { return "Original Pounce"; } return "原版扑击"; case ConfigKey.PounceSfxEnabled: if (!isChineseLanguage) { return "Original Zombie SFX"; } return "原版行为音效"; case ConfigKey.ZombieMushroomAppearance: if (!isChineseLanguage) { return "Zombie Appearance"; } return "僵尸外观"; case ConfigKey.SprintStaminaRefill: case ConfigKey.SourceStashDistance: case ConfigKey.RestoreAtZombiePosition: case ConfigKey.RestoreGroundOffset: if (!isChineseLanguage) { return "Player Restore"; } return "玩家恢复"; case ConfigKey.VerboseLogs: if (!isChineseLanguage) { return "Diagnostics"; } return "诊断"; default: if (!isChineseLanguage) { return "Zombie Control"; } return "僵尸控制"; } } private static string GetConfigKeyName(ConfigKey configKey) { return GetKeyName(configKey, isChineseLanguage: false); } private static string GetKeyName(ConfigKey configKey, bool isChineseLanguage) { if (isChineseLanguage) { switch (configKey) { case ConfigKey.ToggleKey: return "变身按键"; case ConfigKey.MoveForwardKey: return "前进按键"; case ConfigKey.MoveBackwardKey: return "后退按键"; case ConfigKey.MoveLeftKey: return "左移按键"; case ConfigKey.MoveRightKey: return "右移按键"; case ConfigKey.JumpKey: return "跳跃按键"; case ConfigKey.SprintKey: return "冲刺按键"; case ConfigKey.ClimbKey: return "攀爬按键"; case ConfigKey.PounceKey: return "扑击按键"; case ConfigKey.ChaseToggleKey: return "追击切换按键"; case ConfigKey.ViewToggleKey: return "视角切换按键"; case ConfigKey.ControlledJitterChance: return "控制抖动概率"; case ConfigKey.ControlledJitterIntensity: return "控制抖动强度"; case ConfigKey.ControlledJitterDuration: return "控制抖动持续时间"; case ConfigKey.PounceDuration: return "扑击持续时间"; case ConfigKey.PounceCooldown: return "扑击冷却时间"; case ConfigKey.PounceForwardVelocity: return "扑击前向速度"; case ConfigKey.PounceUpVelocity: return "扑击向上速度"; case ConfigKey.PounceSfxEnabled: return "扑击音效"; case ConfigKey.ZombieMushroomAppearance: return "蘑菇外观"; case ConfigKey.SprintStaminaRefill: return "体力保持值"; case ConfigKey.FirstPersonHeightOffset: return "第一人称高度偏移"; case ConfigKey.ThirdPersonHeightOffset: return "第三人称高度偏移"; case ConfigKey.ThirdPersonDistance: return "第三人称距离"; case ConfigKey.StartInThirdPerson: return "默认第三人称"; case ConfigKey.SourceStashDistance: return "原玩家隐藏距离"; case ConfigKey.RestoreAtZombiePosition: return "恢复到僵尸位置"; case ConfigKey.RestoreGroundOffset: return "恢复离地高度"; case ConfigKey.VerboseLogs: return "详细日志"; } } return configKey switch { ConfigKey.ToggleKey => "ToggleZombieKey", ConfigKey.MoveForwardKey => "MoveForwardKey", ConfigKey.MoveBackwardKey => "MoveBackwardKey", ConfigKey.MoveLeftKey => "MoveLeftKey", ConfigKey.MoveRightKey => "MoveRightKey", ConfigKey.JumpKey => "JumpKey", ConfigKey.SprintKey => "SprintKey", ConfigKey.ClimbKey => "ClimbKey", ConfigKey.PounceKey => "PounceKey", ConfigKey.ChaseToggleKey => "ChaseToggleKey", ConfigKey.ViewToggleKey => "ViewToggleKey", ConfigKey.ControlledJitterChance => "ControlledJitterChance", ConfigKey.ControlledJitterIntensity => "ControlledJitterIntensity", ConfigKey.ControlledJitterDuration => "ControlledJitterDuration", ConfigKey.PounceDuration => "PounceDuration", ConfigKey.PounceCooldown => "PounceCooldown", ConfigKey.PounceForwardVelocity => "PounceForwardVelocity", ConfigKey.PounceUpVelocity => "PounceUpVelocity", ConfigKey.PounceSfxEnabled => "PounceSfxEnabled", ConfigKey.ZombieMushroomAppearance => "ZombieMushroomAppearance", ConfigKey.SprintStaminaRefill => "SprintStaminaRefill", ConfigKey.FirstPersonHeightOffset => "FirstPersonHeightOffset", ConfigKey.ThirdPersonHeightOffset => "ThirdPersonHeightOffset", ConfigKey.ThirdPersonDistance => "ThirdPersonDistance", ConfigKey.StartInThirdPerson => "StartInThirdPerson", ConfigKey.SourceStashDistance => "SourceStashDistance", ConfigKey.RestoreAtZombiePosition => "RestoreAtZombiePosition", ConfigKey.RestoreGroundOffset => "RestoreGroundOffset", ConfigKey.VerboseLogs => "VerboseLogs", _ => string.Empty, }; } private static string GetLocalizedDescription(ConfigKey configKey, bool isChineseLanguage) { if (isChineseLanguage) { switch (configKey) { case ConfigKey.PounceSfxEnabled: return "右键扑击开始时播放 MushroomZombie 原版音效。"; case ConfigKey.ZombieMushroomAppearance: return "开启后显示僵尸的蘑菇外观;关闭后只隐藏 mushroomVisuals,不会强制打开其它状态模型。"; case ConfigKey.RestoreGroundOffset: return "恢复玩家时,在检测到的地面上方保留的高度,避免穿过地面碰撞体。"; case ConfigKey.ToggleKey: return "按下后变成 MushroomZombie,再按一次恢复玩家身体。僵尸控制固定为 WASD、Shift、左键攀爬、右键攻击、中键原版 AI、C 切视角。默认 F。"; case ConfigKey.MoveForwardKey: return "变身后控制僵尸前进的按键。默认 W。"; case ConfigKey.MoveBackwardKey: return "变身后控制僵尸后退的按键。默认 S。"; case ConfigKey.MoveLeftKey: return "变身后控制僵尸左移的按键。默认 A。"; case ConfigKey.MoveRightKey: return "变身后控制僵尸右移的按键。默认 D。"; case ConfigKey.JumpKey: return "变身后控制僵尸跳跃的按键。默认空格。"; case ConfigKey.SprintKey: return "变身后控制僵尸冲刺跑的按键。默认左 Shift。"; case ConfigKey.ClimbKey: return "变身后转发为攀爬/主使用输入的按键。默认鼠标左键。"; case ConfigKey.PounceKey: return "变身后触发僵尸扑击的按键。默认鼠标右键。"; case ConfigKey.ChaseToggleKey: return "锁定准星指向的存活玩家并让僵尸追击,再按一次取消。默认鼠标中键。"; case ConfigKey.ViewToggleKey: return "切换僵尸第一人称和第三人称视角。默认 C。"; case ConfigKey.ControlledJitterChance: return "玩家控制僵尸时每秒触发短促抖动的概率。0 表示关闭,建议保持在 0~0.25。"; case ConfigKey.ControlledJitterIntensity: return "玩家控制僵尸时随机抖动的强度。1 为默认;过高会明显影响稳定性。"; case ConfigKey.ControlledJitterDuration: return "每次随机抖动持续的时间,范围 0.05~0.6 秒。"; case ConfigKey.PounceDuration: return "扑击输入持续时间,范围 0.05~5 秒。"; case ConfigKey.PounceCooldown: return "两次扑击之间的最短间隔,范围 0~5 秒。"; case ConfigKey.PounceForwardVelocity: return "扑击开始时向前施加的速度,范围 0~50。"; case ConfigKey.PounceUpVelocity: return "扑击开始时向上施加的速度,范围 0~20。"; case ConfigKey.SprintStaminaRefill: return "变身期间保持的体力值,范围 1~3。1 表示可以持续 Shift 冲刺,通常不需要调得更高。"; case ConfigKey.FirstPersonHeightOffset: return "第一人称相机高度微调。0 会尽量保持原玩家相机高度。"; case ConfigKey.ThirdPersonHeightOffset: return "第三人称相机看向僵尸时的目标高度。范围已限制到更稳定的 0.3~1.8。"; case ConfigKey.ThirdPersonDistance: return "第三人称相机与僵尸的距离。范围已限制到更稳定的 1.5~6。"; case ConfigKey.StartInThirdPerson: return "变身完成后默认切到第三人称,这样能立刻看到自己的僵尸外观。关闭后会保持第一人称。"; case ConfigKey.SourceStashDistance: return "变身期间把原玩家身体临时移到脚下多远,避免同时看到玩家和僵尸。"; case ConfigKey.RestoreAtZombiePosition: return "恢复时是否把玩家身体移动到僵尸当前位置。"; case ConfigKey.VerboseLogs: return "输出更详细的诊断日志。"; } } return configKey switch { ConfigKey.PounceSfxEnabled => "Plays the original MushroomZombie sound when pounce starts. Disable this if the sound is too frequent.", ConfigKey.ZombieMushroomAppearance => "Shows the zombie mushroom visuals. When disabled, only mushroomVisuals are hidden; other state renderers are not forced on.", ConfigKey.RestoreGroundOffset => "Height kept above the detected ground when restoring the player, reducing ground clipping after returning from zombie form.", ConfigKey.ToggleKey => "Turns the local player into MushroomZombie, then restores the player on the next press. Zombie controls are fixed to WASD, Shift, left-click climb, right-click attack, middle-click original AI, and C for camera. Default: F.", ConfigKey.MoveForwardKey => "Moves the controlled zombie forward while transformed. Default: W.", ConfigKey.MoveBackwardKey => "Moves the controlled zombie backward while transformed. Default: S.", ConfigKey.MoveLeftKey => "Moves the controlled zombie left while transformed. Default: A.", ConfigKey.MoveRightKey => "Moves the controlled zombie right while transformed. Default: D.", ConfigKey.JumpKey => "Jump input for the controlled zombie. Default: Space.", ConfigKey.SprintKey => "Sprint input for the controlled zombie. Default: Left Shift.", ConfigKey.ClimbKey => "Primary-use/climb input forwarded to the controlled zombie. Default: left mouse button.", ConfigKey.PounceKey => "Hotkey used to trigger the controlled zombie pounce. Default: right mouse button.", ConfigKey.ChaseToggleKey => "Locks onto the living player under your crosshair and lets the zombie chase them. Press again to cancel. Default: middle mouse button.", ConfigKey.ViewToggleKey => "Switches between first-person and third-person zombie camera. Default: C.", ConfigKey.ControlledJitterChance => "Per-second chance for short random shaking while the player controls the zombie. 0 disables it; keeping it in the 0 to 0.25 range is recommended.", ConfigKey.ControlledJitterIntensity => "Strength of random shaking while the player controls the zombie. 1 is the default; excessive values noticeably reduce stability.", ConfigKey.ControlledJitterDuration => "How long each random shake burst lasts. Range: 0.05 to 0.6 seconds.", ConfigKey.PounceDuration => "How long pounce input stays active. Range: 0.05 to 5 seconds.", ConfigKey.PounceCooldown => "Minimum delay between pounces. The effective cooldown is never shorter than PounceDuration. Range: 0 to 5 seconds.", ConfigKey.PounceForwardVelocity => "Forward velocity applied when pounce starts. Range: 0 to 50.", ConfigKey.PounceUpVelocity => "Upward velocity applied when pounce starts. Range: 0 to 20.", ConfigKey.SprintStaminaRefill => "Stamina value maintained while transformed. Range: 1 to 3. A value of 1 already allows continuous Shift sprinting.", ConfigKey.FirstPersonHeightOffset => "Fine-tunes first-person camera height. 0 keeps the original player camera height as closely as possible.", ConfigKey.ThirdPersonHeightOffset => "Target height used when the third-person camera looks at the zombie. The range is limited to a more stable 0.3 to 1.8.", ConfigKey.ThirdPersonDistance => "Distance between the third-person camera and the zombie. The range is limited to a more stable 1.5 to 6.", ConfigKey.StartInThirdPerson => "Starts transformed zombie control in third person so you can immediately see your zombie appearance. Disable this to stay in first person.", ConfigKey.SourceStashDistance => "How far below the map the original player body is moved while transformed, preventing others from seeing both bodies at once.", ConfigKey.RestoreAtZombiePosition => "When enabled, restoring moves the player body to the zombie's current position.", ConfigKey.VerboseLogs => "Writes additional diagnostic log messages.", _ => string.Empty, }; } private void TryLocalizeVisibleModConfigUiThrottled() { if (!(Time.unscaledTime < _nextModConfigUiLocalizationTime)) { _nextModConfigUiLocalizationTime = Time.unscaledTime + 0.25f; TryLocalizeVisibleModConfigUi(); } } private void TryLocalizeVisibleModConfigUi() { if (!TryGetModConfigMenuInstance(out var menuType, out var menuInstance)) { return; } Behaviour val = (Behaviour)((menuInstance is Behaviour) ? menuInstance : null); if (val == null || (Object)(object)val == (Object)null) { return; } try { if (!val.isActiveAndEnabled || !((Component)val).gameObject.activeInHierarchy) { return; } } catch { return; } Dictionary map = BuildModConfigUiLocalizationMap(DetectChineseLanguage()); foreach (Transform item in EnumerateModConfigUiRoots(menuInstance, menuType)) { ApplyTextLocalizationToRoot(item, map); } ApplyTextLocalizationToLoadedUi(map); } private static bool TryGetModConfigMenuInstance(out Type menuType, out object menuInstance) { menuType = null; menuInstance = null; if (!Chainloader.PluginInfos.TryGetValue("com.github.PEAKModding.PEAKLib.ModConfig", out var value) || (Object)(object)((value != null) ? value.Instance : null) == (Object)null) { return false; } Assembly assembly = ((object)value.Instance).GetType().Assembly; menuType = assembly.GetType("PEAKLib.ModConfig.Components.ModdedSettingsMenu"); menuInstance = menuType?.GetProperty("Instance", StaticBindingFlags)?.GetValue(null); if (menuType != null) { return menuInstance != null; } return false; } [IteratorStateMachine(typeof(d__753))] private static IEnumerable EnumerateModConfigUiRoots(object menuInstance, Type menuType) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__753(-2) { <>3__menuInstance = menuInstance, <>3__menuType = menuType }; } [IteratorStateMachine(typeof(d__754))] private static IEnumerable EnumerateCandidateTransforms(object menuInstance, Type menuType) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__754(-2) { <>3__menuInstance = menuInstance, <>3__menuType = menuType }; } private static void ApplyTextLocalizationToRoot(Transform root, Dictionary map) { if (!((Object)(object)root == (Object)null) && map != null && map.Count != 0) { TMP_Text[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ApplyTextLocalization(componentsInChildren[i], map); } } } private static void ApplyTextLocalizationToLoadedUi(Dictionary map) { //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) if (map == null || map.Count == 0) { return; } try { TMP_Text[] array = Resources.FindObjectsOfTypeAll(); foreach (TMP_Text val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null)) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { ApplyTextLocalization(val, map); } } } } catch { } } private static void ApplyTextLocalization(TMP_Text text, Dictionary map) { if (!((Object)(object)text == (Object)null) && map != null && map.Count != 0) { string text2 = text.text?.Trim(); if (!string.IsNullOrWhiteSpace(text2) && map.TryGetValue(text2, out var value) && !string.Equals(text2, value, StringComparison.Ordinal)) { text.text = value; } } } private static Dictionary BuildModConfigUiLocalizationMap(bool isChineseLanguage) { Dictionary dictionary = new Dictionary(StringComparer.Ordinal); AddUiLocalizationPair(dictionary, "I'm Zombie", GetLocalizedModDisplayName(isChineseLanguage)); AddUiLocalizationPair(dictionary, "ImZombie", GetLocalizedModDisplayName(isChineseLanguage)); AddUiLocalizationPair(dictionary, "I'm Zombie", GetLocalizedModDisplayName(isChineseLanguage)); foreach (ConfigKey value in Enum.GetValues(typeof(ConfigKey))) { string sectionName = GetSectionName(value, isChineseLanguage); string keyName = GetKeyName(value, isChineseLanguage); AddUiLocalizationPair(dictionary, GetConfigSectionName(value), sectionName); AddUiLocalizationPair(dictionary, GetSectionName(value, isChineseLanguage: true), sectionName); AddUiLocalizationPair(dictionary, GetConfigKeyName(value), keyName); AddUiLocalizationPair(dictionary, ToReadableName(GetConfigKeyName(value)), keyName); AddUiLocalizationPair(dictionary, GetKeyName(value, isChineseLanguage: true), keyName); AddUiLocalizationPair(dictionary, GetLocalizedDescription(value, isChineseLanguage: false), GetLocalizedDescription(value, isChineseLanguage)); AddUiLocalizationPair(dictionary, GetLocalizedDescription(value, isChineseLanguage: true), GetLocalizedDescription(value, isChineseLanguage)); } return dictionary; } private static void AddUiLocalizationPair(Dictionary map, string source, string localized) { if (map != null && !string.IsNullOrWhiteSpace(source) && !string.IsNullOrWhiteSpace(localized)) { string text = source.Trim(); string text3 = (map[text] = localized.Trim()); map[text3] = text3; string key = text.Replace(" ", string.Empty); string key2 = text3.Replace(" ", string.Empty); if (!map.ContainsKey(key)) { map[key] = text3; } if (!map.ContainsKey(key2)) { map[key2] = text3; } map[text.ToUpperInvariant()] = text3; map[text3.ToUpperInvariant()] = text3; } } private static string ToReadableName(string keyName) { if (string.IsNullOrWhiteSpace(keyName)) { return string.Empty; } List list = new List(keyName.Length + 8); for (int i = 0; i < keyName.Length; i++) { char c = keyName[i]; if (i > 0 && char.IsUpper(c) && !char.IsWhiteSpace(keyName[i - 1]) && !char.IsUpper(keyName[i - 1])) { list.Add(' '); } list.Add(c); } return new string(list.ToArray()); } private static string GetLocalizedModDisplayName(bool isChineseLanguage) { if (!isChineseLanguage) { return "I'm Zombie"; } return "我是僵尸"; } private static bool HasNetworkView(PhotonView view) { if ((Object)(object)view != (Object)null && view.ViewID > 0 && view.IsMine) { if (!PhotonNetwork.InRoom) { return PhotonNetwork.OfflineMode; } return true; } return false; } private static void LogVerbose(string message) { if (VerboseLogs.Value) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] " + message)); } } } } public sealed class ControlledZombieVisualSync : MonoBehaviour { private Character _character; private MushroomZombie _zombie; private PhotonView _view; private float _nextRefreshTime; public void Initialize(MushroomZombie zombie, Character character, PhotonView view) { _zombie = (((Object)(object)zombie != (Object)null) ? zombie : ((Component)this).GetComponent()); _character = (((Object)(object)character != (Object)null) ? character : ((Component)this).GetComponent()); _view = (((Object)(object)view != (Object)null) ? view : ((Component)this).GetComponent()); } private void Awake() { Initialize(_zombie, _character, _view); } private void Update() { if ((Object)(object)_zombie == (Object)null) { _zombie = ((Component)this).GetComponent(); } if ((Object)(object)_character == (Object)null) { _character = ((Component)this).GetComponent(); } if ((Object)(object)_view == (Object)null) { _view = ((Component)this).GetComponent(); } if ((Object)(object)_character != (Object)null) { Plugin.EnsureControlledZombieRegistered(_character); } if (Time.unscaledTime >= _nextRefreshTime) { _nextRefreshTime = Time.unscaledTime + 0.5f; Plugin.EnsureControlledZombieVisibleForRemoteViewers(_zombie, _character, _view); } } private void OnDestroy() { Plugin.UnregisterControlledZombieInstance(_zombie, _character, _view); } } public sealed class PlayerZombieController : MonoBehaviour { private static readonly BindingFlags PrivateInstanceFlags = BindingFlags.Instance | BindingFlags.NonPublic; private static readonly MethodInfo CalcVarsMethod = typeof(MushroomZombie).GetMethod("CalcVars", PrivateInstanceFlags); private static readonly MethodInfo ChaseMethod = typeof(MushroomZombie).GetMethod("DoChasing", PrivateInstanceFlags); private static readonly MethodInfo StartLungingMethod = typeof(MushroomZombie).GetMethod("StartLunging", PrivateInstanceFlags); private static readonly MethodInfo DoLungingMethod = typeof(MushroomZombie).GetMethod("DoLunging", PrivateInstanceFlags); private static readonly MethodInfo DoLungeRecoveryMethod = typeof(MushroomZombie).GetMethod("DoLungeRecovery", PrivateInstanceFlags); private static readonly MethodInfo ZombieUpdateMethod = typeof(MushroomZombie).GetMethod("Update", PrivateInstanceFlags); private static readonly MethodInfo ZombieFixedUpdateMethod = typeof(MushroomZombie).GetMethod("FixedUpdate", PrivateInstanceFlags); private static readonly MethodInfo UpdateMouthMethod = typeof(MushroomZombie).GetMethod("UpdateMouth", PrivateInstanceFlags); private static readonly MethodInfo CanSeeTargetMethod = typeof(MushroomZombie).GetMethod("CanSeeTarget", PrivateInstanceFlags); private static readonly MethodInfo CalculateWorldMovementDirMethod = typeof(Character).GetMethod("CalculateWorldMovementDir", PrivateInstanceFlags); private static readonly MethodInfo RecalculateLookDirectionsMethod = typeof(Character).GetMethod("RecalculateLookDirections", PrivateInstanceFlags); private static readonly MethodInfo SetRotationMethod = typeof(Character).GetMethod("SetRotation", PrivateInstanceFlags); private static readonly FieldInfo BodypartCharacterField = typeof(Bodypart).GetField("character", PrivateInstanceFlags); private static readonly FieldInfo CurrentTargetField = typeof(MushroomZombie).GetField("_currentTarget", PrivateInstanceFlags); private static readonly FieldInfo CurrentStateField = typeof(MushroomZombie).GetField("_currentState", PrivateInstanceFlags); private static readonly FieldInfo LungeTargetForwardField = typeof(MushroomZombie).GetField("lungeTargetForward", PrivateInstanceFlags); private static readonly FieldInfo TimeSpentLungingField = typeof(MushroomZombie).GetField("timeSpentLunging", PrivateInstanceFlags); private static readonly FieldInfo TimeSpentRecoveringFromLungeField = typeof(MushroomZombie).GetField("timeSpentRecoveringFromLunge", PrivateInstanceFlags); private const float ChaseSelectDistance = 80f; private const float ChaseSelectRadius = 0.8f; private const float OriginalChaseRetryCooldownSeconds = 1.5f; private const float OriginalAiToggleCooldownSeconds = 0.2f; private const float MovementInputSharpness = 22f; private const float MaxControlledAngularVelocity = 8f; private const float PounceAngularDamping = 0.88f; private const float NonPounceAngularDamping = 0.82f; private const float NonPounceLinearDamping = 1f; private const float MaxControlledLinearVelocity = 18f; private const float NativePounceCooldownSeconds = 0.9f; private const float NativePounceFallbackDuration = 0.8f; private const float NativePounceRecoveryPaddingSeconds = 0.15f; private const float LegacyPounceMinimumLungeSeconds = 0.78f; private const float LegacyPounceMinimumRecoverySeconds = 0.85f; private const float LegacyPounceMaximumRecoverySeconds = 1.05f; private const float LegacyPounceRecoveryPaddingSeconds = 0.05f; private const float LegacyPounceRecoveryMovementLockSeconds = 0.32f; private const float LegacyPounceRecoveryControlFullSeconds = 0.45f; private const float LegacyPounceFakeTargetDistance = 100f; private const float LegacyPounceFakeTargetDrop = 6f; private const float LegacyPounceActiveForwardSpeed = 24f; private const float LegacyPounceRecoveryForwardSpeed = 2.4f; private const float LegacyPounceRecoveryCarrySeconds = 0.32f; private const float LegacyPounceLowPoseForce = 14f; private const float LegacyPounceActiveRagdollControl = 0.58f; private const float LegacyPounceRecoveryRagdollControl = 0.35f; private const float LegacyPounceActiveVelocityBlend = 0.58f; private const float LegacyPounceRecoveryVelocityBlend = 0.42f; private const float LegacyPounceExitMaxGroundSpeed = 0.35f; private const float LegacyPounceOriginalMoveInput = 2f; private const float PounceTargetPadding = 1.5f; private const float PounceTargetMinimumDistance = 4f; private const float PounceAimAssistRadius = 1.8f; private const float PounceAimAssistMinimumDot = 0.72f; private const KeyCode FixedMoveForwardKey = 119; private const KeyCode FixedMoveBackwardKey = 115; private const KeyCode FixedMoveLeftKey = 97; private const KeyCode FixedMoveRightKey = 100; private const KeyCode FixedJumpKey = 32; private const KeyCode FixedSprintKey = 304; private const KeyCode FixedClimbKey = 323; private const KeyCode FixedPounceKey = 324; private const KeyCode FixedChaseToggleKey = 325; private const float ClearBoostReticleTimer = 10f; private const float ControlledWalkSpeed = 4.2f; private const float ControlledSprintSpeed = 6.8f; private const float ControlledAcceleration = 22f; private const float ControlledAirAcceleration = 8f; private const float ControlledGravity = 22f; private const float ControlledMaxFallSpeed = 24f; private const float ControlledGroundSnapSpeed = 18f; private const float JitterRollInterval = 0.2f; private const float JitterBaseAngularVelocity = 4.5f; private const float LocalJumpVelocity = 8.5f; private const float GroundProbeUpDistance = 3f; private const float GroundProbeDownDistance = 18f; private const float ForcedGroundProbeDownDistance = 80f; private const float DesiredGroundClearance = 0.03f; private const float DesiredFootGroundHeight = 0.06f; private const float MaxGroundSnapDownDistance = 1.25f; private const float MaxForcedGroundSnapDownDistance = 80f; private const float MaxGroundSnapUpDistance = 0.45f; private const float MaxForcedGroundSnapUpDistance = 8f; private const float MaxUpwardVelocityForGroundSnap = 0.25f; private const float GroundContactTolerance = 0.12f; private const float GroundVelocityTolerance = 0.2f; private const float GroundClipProbeUpDistance = 8f; private const float GroundClipProbeDownDistance = 28f; private const float GroundClipPenetrationTolerance = 0.35f; private const float GroundClipAllowedGroundAboveCenter = 0.65f; private const float MaxGroundClipLift = 8f; private const float MaxRecentGroundHorizontalDrift = 8f; private const float ClimbAttemptCooldownSeconds = 0.14f; private const float ClimbRepeatedHitDistance = 0.28f; private const float ClimbRepeatedNormalDot = 0.94f; private const float OriginalZombieClimbInput = 1f; private const float ClimbRagdollControl = 0.95f; private const float ClimbMaxLinearVelocity = 9f; private const float ClimbMaxAngularVelocity = 8f; private const float ClimbSurfaceProbeDistance = 2.25f; private const float ClimbLedgeAssistProbeUp = 1.35f; private const float ClimbLedgeAssistProbeDown = 2.25f; private const float ClimbLedgeAssistForwardProbe = 0.75f; private const float ClimbLedgeAssistForwardStep = 0.045f; private const float ClimbLedgeAssistMaxLiftStep = 0.075f; private const float ClimbLedgeAssistMaxTopDelta = 1.35f; private const float ClimbLedgeAssistMinTopNormalY = 0.65f; private const float NetworkRpcWarmupSeconds = 1f; private const float FaintDurationSeconds = 2.4f; private const float FaintCooldownSeconds = 3f; private Character _sourceCharacter; private MushroomZombie _zombie; private Character _character; private Character _chaseTarget; private float _pounceUntil; private float _nextPounceTime; private float _jitterUntil; private float _nextJitterRollTime; private State _lastSyncedState = (State)(-1); private bool _lastSyncedSprint; private bool _chaseEnabled; private bool _originalAiEnabled; private float _nextOriginalChaseRetryTime; private float _nextOriginalAiToggleTime; private float _originalAiInputGraceUntil; private Character _lastSyncedChaseTarget; private bool _pounceUsesOriginal; private bool _pounceUsesSyntheticOriginal; private float _legacyPounceStartedAt; private float _legacyPounceLungeUntil; private Vector3 _legacyPounceForward = Vector3.forward; private Vector2 _smoothedMovementInput; private Vector3 _controlledHorizontalVelocity; private float _controlledVerticalVelocity; private float _networkRpcAllowedAt; private float _nextClimbAttemptTime; private float _faintUntil; private float _nextFaintTime; private bool _hasLastClimbStart; private Vector3 _lastClimbStartPoint; private Vector3 _lastClimbStartNormal = Vector3.forward; private readonly List _disabledAiInputComponents = new List(); internal bool IsOriginalAiEnabled => _originalAiEnabled; private bool IsFainting => Time.time < _faintUntil; private bool IsPouncing { get { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 if (Time.time < _pounceUntil) { return true; } if (_pounceUsesOriginal && (Object)(object)_zombie != (Object)null) { if ((int)_zombie.currentState != 4) { return (int)_zombie.currentState == 5; } return true; } return false; } } private bool IsLegacyPounceActive { get { if (Time.time >= _pounceUntil) { return false; } if (_pounceUsesOriginal) { return _pounceUsesSyntheticOriginal; } return true; } } public static bool IsControlled(MushroomZombie zombie) { if ((Object)(object)zombie == (Object)null) { return false; } PlayerZombieController component = ((Component)zombie).GetComponent(); if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled) { return (Object)(object)component._zombie == (Object)(object)zombie; } return false; } public void Initialize(Character sourceCharacter, MushroomZombie zombie, Character character) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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) //IL_0087: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) _sourceCharacter = sourceCharacter; _zombie = zombie; _character = character; _smoothedMovementInput = Vector2.zero; _jitterUntil = 0f; _nextJitterRollTime = 0f; _originalAiEnabled = false; _controlledHorizontalVelocity = Vector3.zero; _controlledVerticalVelocity = 0f; _nextClimbAttemptTime = 0f; _nextOriginalChaseRetryTime = 0f; _nextOriginalAiToggleTime = 0f; _originalAiInputGraceUntil = 0f; _hasLastClimbStart = false; _lastClimbStartPoint = Vector3.zero; _lastClimbStartNormal = Vector3.forward; _pounceUsesOriginal = false; _pounceUsesSyntheticOriginal = false; _pounceUntil = 0f; _legacyPounceStartedAt = 0f; _legacyPounceLungeUntil = 0f; _legacyPounceForward = Vector3.forward; _networkRpcAllowedAt = Time.time + 1f; _faintUntil = 0f; _nextFaintTime = 0f; ((Behaviour)this).enabled = true; } internal void ActivateDynamicRagdollControl() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_character == (Object)null || _character.refs?.ragdoll?.partList == null) { return; } try { foreach (Bodypart part in _character.refs.ragdoll.partList) { Rigidbody val = (((Object)(object)part != (Object)null) ? part.Rig : null); if (!((Object)(object)val == (Object)null)) { val.linearVelocity = Vector3.zero; val.angularVelocity = Vector3.zero; val.detectCollisions = true; val.useGravity = true; val.isKinematic = false; val.WakeUp(); } } } catch { } } private void Update() { if (IsReady()) { ControlTick(); if (!_originalAiEnabled) { UpdateOriginalZombieFace(); } Plugin.UpdateControlledZombieNativeVisuals(_zombie); } } private void LateUpdate() { IsReady(); } private void FixedUpdate() { //IL_007c: 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) if (!IsReady()) { return; } if (Plugin.IsControlledZombieIncapacitated(_character) && !IsFainting) { MaintainExternalIncapacitationState(); UpdateControlledCharacterTimers(); PreventGroundClipping(); return; } if (_originalAiEnabled) { KeepAliveForOriginalAi(); RunOriginalAiFixedUpdate(); return; } if (IsFainting) { MaintainFaintState(); UpdateControlledCharacterTimers(); PreventGroundClipping(); return; } StabilizeControlledBody(); if (IsCharacterClimbing()) { StabilizeControlledClimb(); AssistClimbOntoTopSurface(); _controlledHorizontalVelocity = Vector3.zero; _controlledVerticalVelocity = 0f; return; } if (Plugin.ShouldUseControlledZombieKinematicLocomotion(_character)) { ApplyKinematicLocomotion(); UpdateControlledCharacterTimers(); } if (IsLegacyPounceActive) { ApplyLegacyPouncePhysics(); } PreventGroundClipping(); ApplyControlledJitter(); } internal void ForceGroundSnap() { if (IsReady()) { MaintainGroundContact(force: true); PreventGroundClipping(); } } internal void ControlTick() { if (!IsReady()) { return; } if (Plugin.IsControlledZombieIncapacitated(_character) && !IsFainting) { MaintainExternalIncapacitationState(); SyncStateIfNeeded(); return; } HandleOriginalAiToggle(); if (_originalAiEnabled) { if (!ShouldExitOriginalAiForPlayerControl()) { KeepAliveForOriginalAi(); RunOriginalAiUpdate(); return; } DisableOriginalAi(); } KeepAliveAndControllable(); ForwardEmoteInput(); if (IsFainting) { MaintainFaintState(); SyncStateIfNeeded(); return; } ForwardMovementInput(); ForwardJumpInput(); ForwardClimbInput(); if (!IsClimbInputHeld() && IsCharacterClimbing()) { Plugin.StopControlledZombieClimb(_character.refs?.climbing, _character, 0f); } else if (IsCharacterClimbing()) { ApplyOriginalZombieClimbInput(); } EnsureClimbSurfaceStillValid(); if (PouncePressed() && Time.time >= _nextPounceTime) { StartPounce(); } if (IsPouncing) { RunOriginalPounceState(); } else if (_chaseEnabled) { ApplyChaseInput(); } else { SetState((State)2); SetBiteCollider(active: false); } SyncStateIfNeeded(); } private bool IsReady() { if ((Object)(object)_zombie != (Object)null && (Object)(object)_character != (Object)null && (Object)(object)_character.data != (Object)null) { return _character.refs != null; } return false; } internal bool TryTriggerFaint() { //IL_0054: 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 (!IsReady() || Time.time < _nextFaintTime) { return false; } if (_originalAiEnabled) { DisableOriginalAi(); } StopChase(); EndPounce(); _faintUntil = Time.time + 2.4f; _nextFaintTime = Time.time + 3f; _controlledHorizontalVelocity = Vector3.zero; _controlledVerticalVelocity = 0f; SetState((State)5); SetBiteCollider(active: false); MaintainFaintState(); Plugin.PlayControlledZombieSfx(_zombie, 1); SyncState(force: true); return true; } private void MaintainFaintState() { if (IsReady()) { float num = Mathf.Max(_faintUntil - Time.time, 0f); _character.isZombie = true; _character.data.dead = false; _character.data.zombified = false; _character.data.fullyPassedOut = false; _character.data.passedOut = num > 0f; _character.data.fallSeconds = num; _character.data.currentRagdollControll = ((num > 0f) ? 0f : 1f); _character.data.isSprinting = false; ClearControlledInput(); if (num <= 0f) { SetState((State)2); SyncState(force: true); } } } private void ClearControlledInput() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_character?.input == (Object)null)) { _character.input.movementInput = Vector2.zero; _character.input.sprintIsPressed = false; _character.input.sprintWasPressed = false; _character.input.sprintToggleIsPressed = false; _character.input.sprintToggleWasPressed = false; _character.input.jumpWasPressed = false; _character.input.jumpIsPressed = false; _character.input.usePrimaryWasPressed = false; _character.input.usePrimaryIsPressed = false; _character.input.usePrimaryWasReleased = false; _character.input.useSecondaryWasPressed = false; _character.input.useSecondaryIsPressed = false; _character.input.useSecondaryWasReleased = false; _character.input.crouchWasPressed = false; _character.input.crouchIsPressed = false; _character.input.crouchToggleWasPressed = false; _character.input.dropWasPressed = false; _character.input.dropIsPressed = false; _character.input.dropWasReleased = false; } } private static bool OriginalAiTogglePressed() { return KeyWasPressed((KeyCode)325); } private void HandleOriginalAiToggle() { if (OriginalAiTogglePressed() && !(Time.time < _nextOriginalAiToggleTime)) { _nextOriginalAiToggleTime = Time.time + 0.2f; Character val = FindRaycastChaseTarget(); if (IsValidChaseTarget(val)) { EnableOriginalAi(val); } else if (_originalAiEnabled) { DisableOriginalAi(); } else { EnableOriginalAi(); } } } private void EnableOriginalAi() { EnableOriginalAi(null); } private void EnableOriginalAi(Character target) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) StopManualBehaviorsForOriginalAi(); _originalAiEnabled = true; _originalAiInputGraceUntil = Time.time + 0.35f; _nextOriginalChaseRetryTime = 0f; _lastSyncedState = (State)(-1); Plugin.PrepareControlledZombieForOriginalAi(_zombie); if (!IsValidChaseTarget(target)) { _zombie.sinceLookForTarget = 99f; SetState((State)2); } LockOriginalAiTarget(target); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[I'm Zombie] Original zombie AI enabled."); } } private void DisableOriginalAi() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) _originalAiEnabled = false; _originalAiInputGraceUntil = 0f; _nextOriginalChaseRetryTime = 0f; _controlledHorizontalVelocity = Vector3.zero; _controlledVerticalVelocity = 0f; _smoothedMovementInput = Vector2.zero; ClearOriginalZombieControlState(keepChaseTarget: false); if ((Object)(object)_character != (Object)null && (Object)(object)_character.input != (Object)null && (Object)(object)_character.data != (Object)null) { _character.input.movementInput = Vector2.zero; _character.input.sprintIsPressed = false; _character.input.sprintWasPressed = false; _character.input.jumpWasPressed = false; _character.input.jumpIsPressed = false; _character.data.isSprinting = false; } SetState((State)2); SetBiteCollider(active: false); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[I'm Zombie] Original zombie AI disabled."); } } private void StopManualBehaviorsForOriginalAi() { if (_chaseEnabled) { StopChase(); } if (IsPouncing) { EndPounce(); } if (IsCharacterClimbing()) { Plugin.StopControlledZombieClimb(_character.refs?.climbing, _character, 0f); } } private bool ShouldExitOriginalAiForPlayerControl() { if (Time.time < _originalAiInputGraceUntil) { return false; } try { return KeyWasPressed((KeyCode)119) || KeyWasPressed((KeyCode)115) || KeyWasPressed((KeyCode)97) || KeyWasPressed((KeyCode)100) || KeyWasPressed((KeyCode)32) || KeyWasPressed((KeyCode)304) || KeyWasPressed((KeyCode)323) || KeyWasPressed((KeyCode)324); } catch { return false; } } private void KeepAliveForOriginalAi() { Plugin.PrepareControlledZombieForOriginalAi(_zombie); _zombie.isNPCZombie = true; _zombie.targetForcedUntil = 0f; _zombie.initialWakeUpTime = 0f; _zombie.lifetime = float.PositiveInfinity; _character.isZombie = true; _character.data.dead = false; _character.data.zombified = false; _character.data.passedOut = false; _character.data.fullyPassedOut = false; _character.data.fallSeconds = 0f; float effectiveSprintStaminaRefill = Plugin.GetEffectiveSprintStaminaRefill(); _character.data.currentStamina = effectiveSprintStaminaRefill; _character.data.extraStamina = effectiveSprintStaminaRefill; ClearAssistJumpState(_character); Plugin.RefreshCharacterAfflictionSceneState(_character); if ((Object)(object)_sourceCharacter != (Object)null) { _sourceCharacter.data.dead = false; _sourceCharacter.data.zombified = false; ClearAssistJumpState(_sourceCharacter); Plugin.RefreshCharacterAfflictionSceneState(_sourceCharacter); } } private void LockOriginalAiTarget(Character target) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!IsValidChaseTarget(target)) { return; } try { AssignChaseTarget(target); _zombie.distanceToTarget = Vector3.Distance(_character.Center, target.Center); _zombie.chaseTimeBeforeSprint = -1f; _zombie.targetForcedUntil = Time.time + 2f; _zombie.sinceLookForTarget = 0f; SetState((State)3); SetBiteCollider(active: false); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[I'm Zombie] Original AI locked target: " + target.characterName)); } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[I'm Zombie] Failed to lock original AI target: " + ex.Message)); } } } private void RunOriginalAiUpdate() { if ((Object)(object)_zombie == (Object)null || ZombieUpdateMethod == null) { return; } try { using (Plugin.EnterControlledZombieOriginalBehaviorScope()) { ZombieUpdateMethod.Invoke(_zombie, null); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Original zombie AI update failed: " + ex.Message)); } DisableOriginalAi(); } } private void RunOriginalAiFixedUpdate() { if ((Object)(object)_zombie == (Object)null || ZombieFixedUpdateMethod == null) { return; } try { using (Plugin.EnterControlledZombieOriginalBehaviorScope()) { ZombieFixedUpdateMethod.Invoke(_zombie, null); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Original zombie AI fixed update failed: " + ex.Message)); } DisableOriginalAi(); } } private void UpdateOriginalZombieFace() { if ((Object)(object)_zombie == (Object)null || UpdateMouthMethod == null) { return; } try { using (Plugin.EnterControlledZombieOriginalBehaviorScope()) { UpdateMouthMethod.Invoke(_zombie, null); } } catch { } } private void KeepAliveAndControllable() { _zombie.isNPCZombie = false; if (!_chaseEnabled) { AssignChaseTarget(null); } _zombie.targetForcedUntil = 0f; _zombie.initialWakeUpTime = 0f; _zombie.lifetime = float.PositiveInfinity; _character.isZombie = true; _character.data.dead = false; _character.data.zombified = false; if (!Plugin.IsControlledZombieIncapacitated(_character)) { _character.data.passedOut = false; _character.data.fullyPassedOut = false; _character.data.fallSeconds = 0f; _character.data.currentRagdollControll = 1f; Plugin.ClearControlledZombieExternalPassOutState(_character); } ApplyLegacyPounceRagdollControl(); float effectiveSprintStaminaRefill = Plugin.GetEffectiveSprintStaminaRefill(); _character.data.currentStamina = effectiveSprintStaminaRefill; _character.data.extraStamina = effectiveSprintStaminaRefill; if ((Object)(object)_character.input != (Object)null) { _character.input.useSecondaryWasPressed = false; _character.input.useSecondaryIsPressed = false; _character.input.useSecondaryWasReleased = false; } ClearAssistJumpState(_character); if ((Object)(object)_sourceCharacter != (Object)null) { _sourceCharacter.data.dead = false; _sourceCharacter.data.zombified = false; ClearAssistJumpState(_sourceCharacter); } } private void MaintainExternalIncapacitationState() { if (!((Object)(object)_character?.data == (Object)null)) { _zombie.isNPCZombie = false; _zombie.targetForcedUntil = 0f; _zombie.initialWakeUpTime = 0f; _zombie.lifetime = float.PositiveInfinity; _character.isZombie = true; _character.data.dead = false; _character.data.zombified = false; _character.data.isSprinting = false; ClearControlledInput(); if (_originalAiEnabled) { _originalAiEnabled = false; } if (_chaseEnabled) { StopChase(); } if (IsPouncing) { EndPounce(); } SetBiteCollider(active: false); _character.data.currentRagdollControll = Mathf.Clamp01(_character.data.currentRagdollControll); } } private void ForwardJumpInput() { if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.input == (Object)null)) { bool flag = false; bool flag2 = false; try { flag = KeyWasPressed((KeyCode)32); flag2 = KeyIsPressed((KeyCode)32); } catch { } if (flag) { _character.input.jumpWasPressed = true; } if (flag2 || flag) { _character.input.jumpIsPressed = true; } } } private void ForwardEmoteInput() { if ((Object)(object)_character == (Object)null || (Object)(object)_character.input == (Object)null) { return; } try { if (CharacterInput.action_emote != null) { _character.input.emoteIsPressed = CharacterInput.action_emote.IsPressed(); } else { _character.input.emoteIsPressed = Input.GetKey((KeyCode)114); } if (CharacterInput.action_selectSlotForward != null) { _character.input.selectSlotForwardWasPressed = CharacterInput.action_selectSlotForward.WasPressedThisFrame(); } if (CharacterInput.action_selectSlotBackward != null) { _character.input.selectSlotBackwardWasPressed = CharacterInput.action_selectSlotBackward.WasPressedThisFrame(); } } catch { _character.input.emoteIsPressed = Input.GetKey((KeyCode)114); } } private void ForwardMovementInput() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.input == (Object)null) && !((Object)(object)_character.data == (Object)null) && !IsPouncing && !_chaseEnabled) { Vector2 val = Vector2.zero; if (KeyIsPressed((KeyCode)119)) { val.y += 1f; } if (KeyIsPressed((KeyCode)115)) { val.y -= 1f; } if (KeyIsPressed((KeyCode)97)) { val.x -= 1f; } if (KeyIsPressed((KeyCode)100)) { val.x += 1f; } val = Vector2.ClampMagnitude(val, 1f); float num = 22f * Mathf.Max(Time.deltaTime, 0.001f); _smoothedMovementInput = Vector2.MoveTowards(_smoothedMovementInput, val, num); _character.input.movementInput = _smoothedMovementInput; bool flag = KeyIsPressed((KeyCode)304); _character.input.sprintWasPressed = KeyWasPressed((KeyCode)304); _character.input.sprintIsPressed = flag; _character.data.isSprinting = flag && ((Vector2)(ref val)).sqrMagnitude > 0.001f; } } private static bool PouncePressed() { return KeyWasPressed((KeyCode)324); } private static bool ChaseTogglePressed() { return KeyWasPressed((KeyCode)325); } private void ForwardClimbInput() { bool flag = false; bool flag2 = false; bool flag3 = false; try { flag = KeyWasPressed((KeyCode)323); flag2 = KeyIsPressed((KeyCode)323); flag3 = KeyWasReleased((KeyCode)323); } catch { } if (flag) { _character.input.usePrimaryWasPressed = true; } else { _character.input.usePrimaryWasPressed = false; } if (flag2 || flag) { _character.input.usePrimaryIsPressed = true; try { if ((Object)(object)_character.data.currentItem == (Object)null) { _character.data.sincePressClimb = 0f; } } catch { } if (!IsCharacterClimbing() && (flag || Time.time >= _nextClimbAttemptTime)) { _nextClimbAttemptTime = Time.time + 0.14f; TryStartLocalClimb(); } } else { _character.input.usePrimaryIsPressed = false; } if (flag3) { _character.input.usePrimaryIsPressed = false; _character.input.usePrimaryWasReleased = true; _hasLastClimbStart = false; if (IsCharacterClimbing()) { Plugin.StopControlledZombieClimb(_character.refs?.climbing, _character, 0f); } } else { _character.input.usePrimaryWasReleased = false; } } private void ApplyOriginalZombieClimbInput() { //IL_0039: 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_0041: 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_0062: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_character?.input == (Object)null) && !((Object)(object)_character.data == (Object)null)) { Vector2 movementInput = _character.input.movementInput; movementInput.y = Mathf.Max(movementInput.y, 1f); _character.input.movementInput = movementInput; _character.data.currentStamina = Mathf.Max(_character.data.currentStamina, Plugin.GetEffectiveSprintStaminaRefill()); } } private bool IsClimbInputHeld() { bool result = false; try { result = KeyIsPressed((KeyCode)323); } catch { } return result; } private bool TryStartLocalClimb() { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: 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_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_character == (Object)null || (Object)(object)_character.data == (Object)null || (Object)(object)_character.refs?.climbing == (Object)null) { return false; } if (_character.data.isClimbing || _character.data.isRopeClimbing || _character.data.isVineClimbing) { return true; } if ((Object)(object)_character.data.currentItem != (Object)null) { return false; } CharacterClimbing climbing = _character.refs.climbing; if (!Plugin.CanControlledZombieClimb(climbing)) { return false; } Vector3 center = _character.Center; Vector3 forward = Vector3.zero; if ((Object)(object)Camera.main != (Object)null) { forward = ((Component)Camera.main).transform.forward; } if (((Vector3)(ref forward)).sqrMagnitude < 0.0001f) { forward = ((Component)_character).transform.forward; } if (((Vector3)(ref forward)).sqrMagnitude < 0.0001f) { forward = _character.data.lookDirection; } if (((Vector3)(ref forward)).sqrMagnitude < 0.0001f) { forward = _character.data.lookDirection_Flat; } ((Vector3)(ref forward)).Normalize(); if (!TryFindLocalClimbHit(center, forward, 1.65f, out var climbHit)) { _nextClimbAttemptTime = Time.time + 0.14f; return false; } if (IsRepeatedClimbStart(((RaycastHit)(ref climbHit)).point, ((RaycastHit)(ref climbHit)).normal)) { _nextClimbAttemptTime = Time.time + 0.14f; return true; } _nextClimbAttemptTime = Time.time + 0.14f; bool num = Plugin.TryStartControlledZombieClimb(climbing, _character, ((RaycastHit)(ref climbHit)).point, ((RaycastHit)(ref climbHit)).normal, "Local climb"); if (num) { RecordClimbStart(((RaycastHit)(ref climbHit)).point, ((RaycastHit)(ref climbHit)).normal); } return num; } private bool IsRepeatedClimbStart(Vector3 point, Vector3 normal) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0060: Unknown result type (might be due to invalid IL or missing references) if (!_hasLastClimbStart) { return false; } if (Vector3.Distance(_lastClimbStartPoint, point) > 0.28f) { return false; } Vector3 val = ((((Vector3)(ref _lastClimbStartNormal)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref _lastClimbStartNormal)).normalized : Vector3.forward); Vector3 val2 = ((((Vector3)(ref normal)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref normal)).normalized : Vector3.forward); return Vector3.Dot(val, val2) >= 0.94f; } private void RecordClimbStart(Vector3 point, Vector3 normal) { //IL_0008: 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_0026: 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_002b: Unknown result type (might be due to invalid IL or missing references) _hasLastClimbStart = true; _lastClimbStartPoint = point; _lastClimbStartNormal = ((((Vector3)(ref normal)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref normal)).normalized : Vector3.forward); } private bool TryFindLocalClimbHit(Vector3 origin, Vector3 forward, out RaycastHit climbHit) { //IL_0001: 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) return TryFindLocalClimbHit(origin, forward, 1.65f, out climbHit); } private bool TryFindLocalClimbHit(Vector3 origin, Vector3 forward, float distance, out RaycastHit climbHit) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) climbHit = default(RaycastHit); RaycastHit[] array; try { array = Physics.RaycastAll(origin, forward, Mathf.Max(distance, 0.25f), -1, (QueryTriggerInteraction)1); } catch { return false; } if (array == null || array.Length == 0) { return false; } Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance)); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val = array2[i]; if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !((RaycastHit)(ref val)).collider.isTrigger) { Character val2 = ResolveHitCharacter(val); if (!((Object)(object)val2 == (Object)(object)_character) && !((Object)(object)val2 == (Object)(object)_sourceCharacter) && !(Vector3.Dot(((RaycastHit)(ref val)).normal, Vector3.up) > 0.75f)) { climbHit = val; return true; } } } return false; } private void EnsureClimbSurfaceStillValid() { //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_005a: Unknown result type (might be due to invalid IL or missing references) if (IsCharacterClimbing() && !((Object)(object)_character.refs?.climbing == (Object)null) && !_character.data.isRopeClimbing && !_character.data.isVineClimbing) { Vector3 center = _character.Center; if (TryFindCurrentClimbSurface(center)) { _character.data.sinceCanClimb = 0f; } } } private bool TryFindCurrentClimbSurface(Vector3 origin) { //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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_008b: Unknown result type (might be due to invalid IL or missing references) Vector3[] array = (Vector3[])(object)new Vector3[4] { -_character.data.climbNormal, _character.data.lookDirection, _character.data.lookDirection_Flat, ((Component)_character).transform.forward }; for (int i = 0; i < array.Length; i++) { Vector3 forward = array[i]; if (!(((Vector3)(ref forward)).sqrMagnitude < 0.0001f)) { ((Vector3)(ref forward)).Normalize(); if (TryFindLocalClimbHit(origin, forward, 2.25f, out var _)) { return true; } } } return false; } private void HandleChaseToggle() { if (ChaseTogglePressed()) { if (_chaseEnabled) { StopChase(); } else { StartChase(); } } } private void StartChase() { Character val = FindRaycastChaseTarget(); if ((Object)(object)val == (Object)null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[I'm Zombie] Middle-click ray did not select a valid player."); } return; } _chaseEnabled = true; _chaseTarget = val; _nextOriginalChaseRetryTime = 0f; _zombie.chaseTimeBeforeSprint = -1f; AssignChaseTarget(val); SetState((State)3); SetBiteCollider(active: false); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[I'm Zombie] Chase enabled: " + val.characterName)); } } private void StopChase() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_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) bool chaseEnabled = _chaseEnabled; _chaseEnabled = false; _chaseTarget = null; _smoothedMovementInput = Vector2.zero; AssignChaseTarget(null); _character.input.movementInput = Vector2.zero; _character.input.sprintIsPressed = false; _character.input.sprintWasPressed = false; _character.data.isSprinting = false; SetState((State)2); SetBiteCollider(active: false); if (chaseEnabled) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[I'm Zombie] Chase disabled."); } } } private void ApplyChaseInput() { if (!IsValidChaseTarget(_chaseTarget)) { StopChase(); return; } AssignChaseTarget(_chaseTarget); SetState((State)3); SetBiteCollider(active: false); if (!TryApplyOriginalChase()) { ApplyFallbackChase(); } CalculateWorldMovementDirection(); } private bool TryApplyOriginalChase() { if (ChaseMethod == null || Time.time < _nextOriginalChaseRetryTime) { return false; } try { using (Plugin.EnterControlledZombieOriginalBehaviorScope()) { CalcVarsMethod?.Invoke(_zombie, null); ChaseMethod.Invoke(_zombie, null); } _nextOriginalChaseRetryTime = 0f; return true; } catch (Exception ex) { _nextOriginalChaseRetryTime = Time.time + 1.5f; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Original chase failed, falling back temporarily: " + ex.Message)); } return false; } } private void ApplyFallbackChase() { //IL_0006: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) Vector3 val = _chaseTarget.Center - _character.Center; Vector3 val2 = Vector3.ProjectOnPlane(val, Vector3.up); if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f) { Vector3 normalized = ((Vector3)(ref val2)).normalized; Vector3 val3 = _chaseTarget.Head - _character.Head; ApplyLookDirection(((Vector3)(ref val3)).normalized, normalized); } _character.input.movementInput = Vector2.up; _character.input.sprintIsPressed = true; _character.input.sprintWasPressed = true; _character.data.isSprinting = true; if (val.y > 1.25f && ((Vector3)(ref val2)).sqrMagnitude < 16f && _character.data.sinceJump > 0.4f) { _character.input.jumpWasPressed = true; } } private Character FindRaycastChaseTarget() { //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_0019: 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) Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return null; } Ray selectionRay = GetSelectionRay(main); float blockingDistance; Character val = FindPhysicsRaycastTarget(selectionRay, out blockingDistance); if (!((Object)(object)val != (Object)null)) { return FindApproximateRayTarget(selectionRay, blockingDistance); } return val; } private static Ray GetSelectionRay(Camera camera) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0018: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) try { if ((int)Cursor.lockState == 1) { return camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f)); } } catch { } return camera.ScreenPointToRay(Input.mousePosition); } private Character FindPhysicsRaycastTarget(Ray ray, out float blockingDistance) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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) blockingDistance = 80f; RaycastHit[] array; try { array = Physics.RaycastAll(ray, 80f, -1, (QueryTriggerInteraction)2); } catch { return null; } Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit hit = array2[i]; Character val = ResolveHitCharacter(hit); if (IsValidChaseTarget(val)) { return val; } if (!((Object)(object)val == (Object)(object)_character) && !((Object)(object)val == (Object)(object)_sourceCharacter) && !((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null) && !((RaycastHit)(ref hit)).collider.isTrigger) { blockingDistance = Mathf.Clamp(((RaycastHit)(ref hit)).distance, 0f, 80f); return null; } } return null; } private Character ResolveHitCharacter(RaycastHit hit) { if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null) { return null; } Character componentInParent = ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } Bodypart componentInParent2 = ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent(); if ((Object)(object)componentInParent2 == (Object)null || BodypartCharacterField == null) { return null; } try { object? value = BodypartCharacterField.GetValue(componentInParent2); return (Character)((value is Character) ? value : null); } catch { return null; } } private Character FindApproximateRayTarget(Ray ray, float maxDistance) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (Character.AllCharacters == null) { return null; } Character result = null; float num = float.PositiveInfinity; foreach (Character allCharacter in Character.AllCharacters) { if (IsValidChaseTarget(allCharacter) && RayIntersectsCharacter(allCharacter, ray, maxDistance, out var distanceAlongRay) && distanceAlongRay < num) { num = distanceAlongRay; result = allCharacter; } } return result; } private static bool RayIntersectsCharacter(Character candidate, Ray ray, float maxDistance, out float distanceAlongRay) { //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_001b: 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) distanceAlongRay = float.PositiveInfinity; float distanceAlongRay2; bool num = RayIntersectsSphere(ray, candidate.Center, 0.8f, maxDistance, out distanceAlongRay2); float distanceAlongRay3; bool flag = RayIntersectsSphere(ray, candidate.Head, 0.52f, maxDistance, out distanceAlongRay3); if (!num && !flag) { return false; } distanceAlongRay = Mathf.Min(distanceAlongRay2, distanceAlongRay3); return true; } private static bool RayIntersectsSphere(Ray ray, Vector3 center, float radius, float maxDistance, out float distanceAlongRay) { //IL_0008: 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_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_0016: 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) distanceAlongRay = float.PositiveInfinity; Vector3 val = center - ((Ray)(ref ray)).origin; float num = Vector3.Dot(val, ((Ray)(ref ray)).direction); if (num < 0f || num > maxDistance) { return false; } float num2 = ((Vector3)(ref val)).sqrMagnitude - num * num; float num3 = radius * radius; if (num2 > num3) { return false; } distanceAlongRay = num - Mathf.Sqrt(Mathf.Max(num3 - num2, 0f)); return true; } private bool IsValidChaseTarget(Character candidate) { if ((Object)(object)candidate == (Object)null || (Object)(object)candidate == (Object)(object)_character || (Object)(object)candidate == (Object)(object)_sourceCharacter) { return false; } if ((Object)(object)candidate.data == (Object)null || candidate.refs == null) { return false; } if (candidate.isBot || candidate.isZombie) { return false; } if (candidate.data.dead || candidate.data.passedOut || candidate.data.fullyPassedOut) { return false; } return ((Component)candidate).gameObject.activeInHierarchy; } private void AssignChaseTarget(Character target) { if ((Object)(object)_zombie.currentTarget != (Object)(object)target) { _zombie.currentTarget = target; } if (!((Object)(object)_lastSyncedChaseTarget == (Object)(object)target) && CanSendNetworkRpc()) { _lastSyncedChaseTarget = target; PhotonView stableZombieView = GetStableZombieView(); if (!((Object)(object)stableZombieView == (Object)null)) { int characterViewId = GetCharacterViewId(target); stableZombieView.RPC("RPCA_SetCurrentTarget", (RpcTarget)1, new object[2] { characterViewId, 0f }); } } } private void StartPounce() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) if (!IsReady() || (Object)(object)_character.input == (Object)null) { return; } try { _pounceUsesOriginal = false; _pounceUsesSyntheticOriginal = false; if (IsCharacterClimbing()) { Plugin.StopControlledZombieClimb(_character.refs?.climbing, _character, 0f); } Character val = FindPounceTarget(); if ((Object)(object)val == (Object)null) { _nextPounceTime = Time.time + 0.9f; return; } AssignChaseTarget(val); _zombie.distanceToTarget = Vector3.Distance(_character.Center, val.Center); _zombie.chaseTimeBeforeSprint = -1f; if (TryStartOriginalLunge(val)) { _pounceUsesOriginal = true; _pounceUntil = Time.time + GetNativePounceLockDuration(); _nextPounceTime = Time.time + 0.9f; SyncState(force: true); } else { _nextPounceTime = Time.time + 0.9f; } } catch (Exception ex) { _pounceUntil = 0f; _pounceUsesOriginal = false; _pounceUsesSyntheticOriginal = false; SetState((State)2); SetBiteCollider(active: false); ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Failed to start pounce: " + ex.Message)); } } } private void TriggerPounceStartupJump() { if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.input == (Object)null)) { _character.input.jumpWasPressed = true; _character.input.jumpIsPressed = true; ApplyLocalJumpVelocity(); } } private Character FindPounceTarget() { Character val = FindRaycastChaseTarget(); if (IsValidPounceTarget(val)) { return val; } return FindAimAssistPounceTarget(); } private Character FindAimAssistPounceTarget() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) if (Character.AllCharacters == null) { return null; } Camera main = Camera.main; Vector3 val = (((Object)(object)main != (Object)null) ? ((Component)main).transform.position : _character.Head); Vector3 val2 = (((Object)(object)main != (Object)null) ? ((Component)main).transform.forward : _character.data.lookDirection); if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f) { val2 = _character.data.lookDirection_Flat; } if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f) { val2 = ((Component)_character).transform.forward; } if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f) { val2 = Vector3.forward; } ((Vector3)(ref val2)).Normalize(); float pounceTargetDistance = GetPounceTargetDistance(); Character result = null; float num = float.PositiveInfinity; foreach (Character allCharacter in Character.AllCharacters) { if (!IsValidPounceTarget(allCharacter)) { continue; } Vector3 val3 = allCharacter.Center - val; float magnitude = ((Vector3)(ref val3)).magnitude; if (magnitude <= 0.001f || magnitude > pounceTargetDistance + 1.5f) { continue; } Vector3 val4 = val3 / magnitude; float num2 = Vector3.Dot(val2, val4); if (num2 < 0.72f) { continue; } Vector3 val5 = Vector3.Cross(val2, val3); float magnitude2 = ((Vector3)(ref val5)).magnitude; if (!(magnitude2 > 1.8f)) { float num3 = magnitude2 + magnitude * 0.04f - num2; if (num3 < num) { num = num3; result = allCharacter; } } } return result; } private bool IsValidPounceTarget(Character target) { //IL_0011: 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) if (!IsValidChaseTarget(target)) { return false; } if (Vector3.Distance(_character.Center, target.Center) > GetPounceTargetDistance() + 1.5f) { return false; } return CanOriginalSeeTarget(target); } private float GetPounceTargetDistance() { return Mathf.Max(((Object)(object)_zombie != (Object)null) ? _zombie.zombieLungeDistance : 0f, 4f); } private bool CanOriginalSeeTarget(Character target) { if ((Object)(object)target == (Object)null) { return false; } if (CanSeeTargetMethod == null || (Object)(object)_zombie == (Object)null) { return true; } try { return (bool)CanSeeTargetMethod.Invoke(_zombie, new object[1] { target }); } catch { return true; } } private void StartLegacyPounce(Character pounceTarget) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) _pounceUsesSyntheticOriginal = true; _legacyPounceStartedAt = Time.time; _legacyPounceForward = GetLegacyPounceForward(pounceTarget); float legacyPounceLungeDuration = GetLegacyPounceLungeDuration(); float legacyPounceRecoveryDuration = GetLegacyPounceRecoveryDuration(); _legacyPounceLungeUntil = _legacyPounceStartedAt + legacyPounceLungeDuration; _pounceUntil = _legacyPounceStartedAt + legacyPounceLungeDuration + legacyPounceRecoveryDuration + 0.05f; _pounceUsesOriginal = TryStartSyntheticOriginalPounce(pounceTarget); if (!_pounceUsesOriginal) { SetState((State)4); SetOriginalPounceTimers(0f, 0f); } SetBiteCollider(active: true); ApplyPounceInput(); ApplyLegacyPouncePhysics(); PlayPounceSfx(); } private float GetNativePounceLockDuration() { float num = (((Object)(object)_zombie != (Object)null) ? Mathf.Max(_zombie.lungeTime, 0.05f) : 0.8f); float num2 = (((Object)(object)_zombie != (Object)null) ? Mathf.Max(_zombie.lungeRecoveryTime, 0f) : 0f); return Mathf.Max(num + num2 + 0.15f, 0.8f); } private float GetLegacyPounceLungeDuration() { return Mathf.Max(((Object)(object)_zombie != (Object)null) ? Mathf.Max(_zombie.lungeTime, 0f) : 0f, 0.78f); } private float GetLegacyPounceRecoveryDuration() { float num = (((Object)(object)_zombie != (Object)null) ? Mathf.Max(_zombie.lungeRecoveryTime, 0f) : 0f); if (num <= 0f) { return 0.85f; } return Mathf.Clamp(num, 0.85f, 1.05f); } private bool TryStartSyntheticOriginalPounce(Character pounceTarget) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_zombie == (Object)null || (Object)(object)_character == (Object)null) { return false; } try { Plugin.BeginControlledZombieOriginalBehavior(); SetSyntheticPounceTarget(pounceTarget); SetState((State)4); SetOriginalLungeTarget(BuildLegacyLungeTarget(pounceTarget, _legacyPounceForward)); SetOriginalPounceTimers(0f, 0f); _zombie.chaseTimeBeforeSprint = -1f; if ((Object)(object)_character.input != (Object)null) { _character.input.jumpWasPressed = true; } return DoLungingMethod != null; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Synthetic original pounce setup failed: " + ex.Message)); } return false; } finally { Plugin.EndControlledZombieOriginalBehavior(); } } private void SetSyntheticPounceTarget(Character pounceTarget) { //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) if (!((Object)(object)_zombie == (Object)null)) { _zombie.currentTarget = pounceTarget; if ((Object)(object)pounceTarget != (Object)null && (Object)(object)_character != (Object)null) { _zombie.distanceToTarget = Vector3.Distance(_character.Center, pounceTarget.Center); } else { _zombie.distanceToTarget = Mathf.Max(GetPounceTargetDistance(), 4f); } } } private void SetOriginalLungeTarget(Vector3 target) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!(LungeTargetForwardField == null) && !((Object)(object)_zombie == (Object)null) && IsFiniteVector(target)) { LungeTargetForwardField.SetValue(_zombie, target); } } private void SetOriginalPounceTimers(float lunging, float recovering) { if (!((Object)(object)_zombie == (Object)null)) { TimeSpentLungingField?.SetValue(_zombie, Mathf.Max(lunging, 0f)); TimeSpentRecoveringFromLungeField?.SetValue(_zombie, Mathf.Max(recovering, 0f)); } } private Vector3 BuildLegacyLungeTarget(Character pounceTarget, Vector3 forward) { //IL_0021: 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_0026: 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_0063: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0090: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_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) Vector3 val = (((Object)(object)_character != (Object)null) ? _character.Center : ((Component)this).transform.position); if ((Object)(object)pounceTarget != (Object)null) { Vector3 val2 = pounceTarget.Head - val; if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f) { return val + val2 * 100f; } } Vector3 val3 = GetLegacyPounceLookDirection(); if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f) { val3 = forward; } if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f) { val3 = Vector3.forward; } ((Vector3)(ref val3)).Normalize(); Vector3 val4 = Vector3.ProjectOnPlane(val3, Vector3.up); if (((Vector3)(ref val4)).sqrMagnitude < 0.0001f) { val4 = forward; } if (((Vector3)(ref val4)).sqrMagnitude < 0.0001f) { val4 = Vector3.forward; } ((Vector3)(ref val4)).Normalize(); return val + val4 * 100f + Vector3.down * 6f; } private Vector3 GetLegacyPounceForward(Character pounceTarget) { //IL_0021: 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_0026: 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_0063: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0046: 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_00f3: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (((Object)(object)_character != (Object)null) ? _character.Center : ((Component)this).transform.position); if ((Object)(object)pounceTarget != (Object)null) { Vector3 val2 = Vector3.ProjectOnPlane(pounceTarget.Center - val, Vector3.up); if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f) { return ((Vector3)(ref val2)).normalized; } } Vector3 val3 = GetLegacyPounceLookDirection(); val3 = Vector3.ProjectOnPlane(val3, Vector3.up); if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f && (Object)(object)_character != (Object)null && (Object)(object)_character.data != (Object)null) { val3 = _character.data.lookDirection_Flat; } if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f && (Object)(object)_character != (Object)null) { val3 = ((Component)_character).transform.forward; } if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f) { val3 = Vector3.forward; } return ((Vector3)(ref val3)).normalized; } private Vector3 GetLegacyPounceLookDirection() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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) //IL_00f7: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Camera.main != (Object)null) { Vector3 forward = ((Component)Camera.main).transform.forward; if (((Vector3)(ref forward)).sqrMagnitude > 0.0001f) { return ((Vector3)(ref forward)).normalized; } } if ((Object)(object)_character != (Object)null && (Object)(object)_character.data != (Object)null && ((Vector3)(ref _character.data.lookDirection)).sqrMagnitude > 0.0001f) { return ((Vector3)(ref _character.data.lookDirection)).normalized; } if ((Object)(object)_character != (Object)null && (Object)(object)_character.data != (Object)null && ((Vector3)(ref _character.data.lookDirection_Flat)).sqrMagnitude > 0.0001f) { return ((Vector3)(ref _character.data.lookDirection_Flat)).normalized; } if ((Object)(object)_character != (Object)null) { Vector3 forward2 = ((Component)_character).transform.forward; if (((Vector3)(ref forward2)).sqrMagnitude > 0.0001f) { return ((Vector3)(ref forward2)).normalized; } } return Vector3.forward; } private void PlayPounceSfx() { if ((Object)(object)_zombie == (Object)null) { return; } try { PhotonView stableZombieView = GetStableZombieView(); if ((Object)(object)stableZombieView != (Object)null && CanSendNetworkRpc() && (PhotonNetwork.InRoom || PhotonNetwork.OfflineMode)) { stableZombieView.RPC("RPC_PlaySFX", (RpcTarget)0, new object[1] { 0 }); } else { Plugin.PlayControlledZombieSfx(_zombie, 0); } } catch { } } private void ApplyPounceInput() { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Invalid comparison between Unknown and I4 //IL_005a: 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) if (_pounceUsesSyntheticOriginal) { ApplySyntheticOriginalPounceInput(); } else if (!_pounceUsesOriginal) { if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.input == (Object)null) && !((Object)(object)_character.data == (Object)null)) { _character.input.movementInput = Vector2.up; _character.input.sprintIsPressed = true; _character.input.sprintWasPressed = true; _character.data.isSprinting = true; SetState((State)4); SetBiteCollider(active: true); } } else if ((Object)(object)_zombie != (Object)null) { SetBiteCollider((int)_zombie.currentState == 4); } } private void ApplySyntheticOriginalPounceInput() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.input == (Object)null) && !((Object)(object)_character.data == (Object)null) && !((Object)(object)_zombie == (Object)null)) { bool flag = (int)_zombie.currentState == 4; _character.input.movementInput = (Vector2)(flag ? new Vector2(0f, 2f) : Vector2.zero); _character.input.sprintIsPressed = flag; _character.input.sprintWasPressed = flag; _character.data.isSprinting = flag; SetBiteCollider(flag); ApplyLegacyPounceRagdollControl(); } } private void RunOriginalPounceState() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Invalid comparison between Unknown and I4 if (_pounceUsesSyntheticOriginal) { RunSyntheticOriginalPounceState(); return; } if (!_pounceUsesOriginal) { if (Time.time >= _pounceUntil) { EndPounce(); } else { ApplyPounceInput(); } return; } if ((Object)(object)_zombie == (Object)null) { EndPounce(); return; } State currentState = _zombie.currentState; bool flag = (((int)currentState == 4) ? TryApplyOriginalLunge() : ((int)currentState == 5 && TryApplyOriginalLungeRecovery())); ApplyPounceInput(); if (!flag) { EndPounce(); } } private void RunSyntheticOriginalPounceState() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 if ((Object)(object)_zombie == (Object)null || Time.time >= _pounceUntil) { EndPounce(); return; } if ((int)_zombie.currentState == 4 && Time.time < _legacyPounceLungeUntil) { if (_pounceUsesOriginal && TryApplyOriginalLunge()) { ApplyPounceInput(); return; } RunManualLegacyPounceLunge(); ApplyPounceInput(); return; } EnterLegacyPounceRecovery(); RunManualLegacyPounceRecovery(); if (ShouldReleaseSyntheticPounceForMovement()) { EndPounce(); ForwardMovementInput(); } else { ApplyPounceInput(); } } private void RunManualLegacyPounceLunge() { if (!((Object)(object)_zombie == (Object)null)) { SetState((State)4); float lunging = Mathf.Max(Time.time - _legacyPounceStartedAt, 0f); SetOriginalPounceTimers(lunging, 0f); if (Time.time >= _legacyPounceLungeUntil) { EnterLegacyPounceRecovery(); } } } private void EnterLegacyPounceRecovery() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 if (!((Object)(object)_zombie == (Object)null)) { if ((int)_zombie.currentState != 5) { SetState((State)5); SetOriginalPounceTimers(0f, 0f); } SetBiteCollider(active: false); if ((Object)(object)_character != (Object)null && (Object)(object)_character.data != (Object)null) { _character.data.fallSeconds = 0f; _character.data.passedOut = false; _character.data.fullyPassedOut = false; _character.data.sinceFallSlide = 0f; } } } private void RunManualLegacyPounceRecovery() { float recovering = Mathf.Max(Time.time - _legacyPounceLungeUntil, 0f); SetOriginalPounceTimers(0f, recovering); } private bool ShouldReleaseSyntheticPounceForMovement() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 if (!_pounceUsesSyntheticOriginal || (Object)(object)_zombie == (Object)null || (int)_zombie.currentState != 5) { return false; } if (Time.time - _legacyPounceLungeUntil >= 0.32f) { return HasFixedMovementInputHeld(); } return false; } private void EndPounce() { //IL_008b: 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) if (_pounceUsesSyntheticOriginal) { StopLegacyPounceGroundSlide(); } _pounceUntil = 0f; _pounceUsesOriginal = false; _pounceUsesSyntheticOriginal = false; _legacyPounceStartedAt = 0f; _legacyPounceLungeUntil = 0f; ClearOriginalZombieControlState(_chaseEnabled); if ((Object)(object)_character != (Object)null && (Object)(object)_character.input != (Object)null && (Object)(object)_character.data != (Object)null) { _character.input.movementInput = Vector2.zero; _character.input.sprintWasPressed = false; _character.input.sprintIsPressed = false; _character.data.isSprinting = false; _character.data.currentRagdollControll = 1f; } SetBiteCollider(active: false); if (!_chaseEnabled) { SetState((State)2); } } private void StopLegacyPounceGroundSlide() { //IL_00e6: 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_00ed: 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_00f4: 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_0138: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010f: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_character == (Object)null || _character.refs?.ragdoll?.partList == null) { return; } bool num = (Object)(object)_character.data == (Object)null || _character.data.isGrounded || _character.data.sinceGrounded <= 0.2f; bool flag = HasFixedMovementInputHeld(); float num2 = ((!num) ? 2.4f : (flag ? 4.2f : 0.35f)); try { foreach (Bodypart part in _character.refs.ragdoll.partList) { Rigidbody val = (((Object)(object)part != (Object)null) ? part.Rig : null); if (!((Object)(object)val == (Object)null) && !val.isKinematic) { Vector3 linearVelocity = val.linearVelocity; Vector3 val2 = Vector3.ProjectOnPlane(linearVelocity, Vector3.up); if (((Vector3)(ref val2)).sqrMagnitude > num2 * num2) { val2 = ((Vector3)(ref val2)).normalized * num2; val.linearVelocity = val2 + Vector3.up * linearVelocity.y; } val.angularVelocity *= 0.35f; } } } catch { } } private bool TryStartOriginalLunge(Character pounceTarget) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Invalid comparison between Unknown and I4 if (StartLungingMethod == null || (Object)(object)_zombie == (Object)null || (Object)(object)pounceTarget == (Object)null) { return false; } try { Plugin.BeginControlledZombieOriginalBehavior(); _zombie.currentTarget = pounceTarget; _zombie.distanceToTarget = Vector3.Distance(_character.Center, pounceTarget.Center); SetState((State)3); CalcVarsMethod?.Invoke(_zombie, null); StartLungingMethod.Invoke(_zombie, null); return (int)_zombie.currentState == 4; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Original start lunge failed: " + ex.Message)); } return false; } finally { Plugin.EndControlledZombieOriginalBehavior(); } } private bool TryApplyOriginalLunge() { if (DoLungingMethod == null || (Object)(object)_zombie == (Object)null) { return false; } try { Plugin.BeginControlledZombieOriginalBehavior(); CalcVarsMethod?.Invoke(_zombie, null); DoLungingMethod.Invoke(_zombie, null); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Original lunge failed: " + ex.Message)); } return false; } finally { Plugin.EndControlledZombieOriginalBehavior(); } } private bool TryApplyOriginalLungeRecovery() { if (DoLungeRecoveryMethod == null || (Object)(object)_zombie == (Object)null) { return false; } try { Plugin.BeginControlledZombieOriginalBehavior(); CalcVarsMethod?.Invoke(_zombie, null); DoLungeRecoveryMethod.Invoke(_zombie, null); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Original lunge recovery failed: " + ex.Message)); } return false; } finally { Plugin.EndControlledZombieOriginalBehavior(); } } private void ApplyLocalJumpVelocity() { //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) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_character == (Object)null || (Object)(object)_character.data == (Object)null || _character.refs?.ragdoll?.partList == null || (!_character.data.isGrounded && _character.data.sinceGrounded > 0.2f)) { return; } try { foreach (Bodypart part in _character.refs.ragdoll.partList) { if (!((Object)(object)part == (Object)null) && !((Object)(object)part.Rig == (Object)null) && !part.Rig.isKinematic) { Vector3 linearVelocity = part.Rig.linearVelocity; if (linearVelocity.y < 8.5f) { part.Rig.linearVelocity = new Vector3(linearVelocity.x, 8.5f, linearVelocity.z); } } } _character.data.sinceJump = 0f; _character.data.isJumping = true; _character.data.isGrounded = false; _character.data.sinceGrounded = 0.25f; } catch { } } private void ApplyLegacyPounceRagdollControl() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Invalid comparison between Unknown and I4 if (_pounceUsesSyntheticOriginal && !((Object)(object)_character == (Object)null) && !((Object)(object)_character.data == (Object)null) && !(Time.time >= _pounceUntil)) { float currentRagdollControll = (((Object)(object)_zombie != (Object)null && (int)_zombie.currentState == 5) ? Mathf.Lerp(0.35f, 1f, Mathf.SmoothStep(0f, 1f, GetLegacyPounceRecoveryControl01())) : 0.58f); _character.data.currentRagdollControll = currentRagdollControll; _character.data.fallSeconds = 0f; _character.data.passedOut = false; _character.data.fullyPassedOut = false; } } private float GetLegacyPounceRecovery01() { if (_pounceUntil <= _legacyPounceLungeUntil) { return 0f; } float num = Mathf.Max(_pounceUntil - _legacyPounceLungeUntil, 0.001f); return Mathf.Clamp01((Time.time - _legacyPounceLungeUntil) / num); } private float GetLegacyPounceRecoveryControl01() { return Mathf.Clamp01(Mathf.Max(Time.time - _legacyPounceLungeUntil, 0f) / 0.45f); } private void ApplyLegacyPouncePhysics() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0087: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Invalid comparison between Unknown and I4 //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: 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_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: 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_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_020b: 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_0240: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) if (!_pounceUsesSyntheticOriginal || (Object)(object)_character == (Object)null || _character.refs?.ragdoll?.partList == null || Time.time >= _pounceUntil) { return; } Vector3 val = _legacyPounceForward; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = (_legacyPounceForward = GetLegacyPounceForward(null)); } val = Vector3.ProjectOnPlane(val, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.forward; } ((Vector3)(ref val)).Normalize(); bool flag = (Object)(object)_zombie != (Object)null && (int)_zombie.currentState == 5; float num = (flag ? GetLegacyPounceRecovery01() : 0f); float num2 = (flag ? (1f - Mathf.Clamp01((Time.time - _legacyPounceLungeUntil) / 0.32f)) : 1f); float num3 = (flag ? (2.4f * num2 * (1f - num)) : 24f); float num4 = (flag ? Mathf.Lerp(0.42f, 0.55f, num) : 0.58f); float num5 = 14f * (flag ? Mathf.Lerp(1f, 0.2f, num) : 1f); ApplyLegacyPounceRagdollControl(); try { foreach (Bodypart part in _character.refs.ragdoll.partList) { Rigidbody val2 = (((Object)(object)part != (Object)null) ? part.Rig : null); if (!((Object)(object)val2 == (Object)null) && !val2.isKinematic) { float legacyPounceUpperBodyWeight = GetLegacyPounceUpperBodyWeight(part.partType); Vector3 linearVelocity = val2.linearVelocity; Vector3 val3 = val * num3; val3.y = (flag ? Mathf.Min(linearVelocity.y, 0.25f) : Mathf.Min(linearVelocity.y, -0.5f)); val2.linearVelocity = Vector3.Lerp(linearVelocity, val3, num4); if (flag) { Vector3 linearVelocity2 = val2.linearVelocity; float num6 = Mathf.Lerp(0.7f, 0.45f, num); linearVelocity2.x *= num6; linearVelocity2.z *= num6; val2.linearVelocity = linearVelocity2; } val2.linearVelocity = Vector3.ClampMagnitude(val2.linearVelocity, 18f); val2.AddForce(Vector3.down * num5 * legacyPounceUpperBodyWeight, (ForceMode)5); if (!flag) { val2.AddForce(val * num5 * 0.3f, (ForceMode)5); } val2.angularVelocity *= (flag ? 0.82f : 0.88f); val2.angularVelocity = Vector3.ClampMagnitude(val2.angularVelocity, 8f); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[I'm Zombie] Legacy pounce physics failed: " + ex.Message)); } } } private static float GetLegacyPounceUpperBodyWeight(BodypartType partType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected I4, but got Unknown switch ((int)partType) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 25: case 26: return 1f; case 11: case 12: case 13: case 14: case 15: case 16: case 27: case 28: return 0.35f; default: return 0.6f; } } private void SetState(State state) { //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_0039: 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) if (_zombie.currentState != state) { if (CurrentStateField != null) { CurrentStateField.SetValue(_zombie, state); } else { _zombie.currentState = state; } } } private void SetBiteCollider(bool active) { if ((Object)(object)_zombie.biteColliderObject != (Object)null && _zombie.biteColliderObject.activeSelf != active) { _zombie.biteColliderObject.SetActive(active); } } private void SyncStateIfNeeded() { //IL_0017: 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) bool isSprinting = _character.data.isSprinting; if (_zombie.currentState != _lastSyncedState || isSprinting != _lastSyncedSprint) { SyncState(force: true); } } private void SyncState(bool force) { //IL_0024: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected I4, but got Unknown if (force && CanSendNetworkRpc()) { PhotonView stableZombieView = GetStableZombieView(); if (!((Object)(object)stableZombieView == (Object)null)) { _lastSyncedState = _zombie.currentState; _lastSyncedSprint = _character.data.isSprinting; stableZombieView.RPC("RPC_SyncState", (RpcTarget)1, new object[4] { (int)_zombie.currentState, _character.data.isSprinting, _character.data.fallSeconds, _character.data.passedOut }); } } } private bool CanSendNetworkRpc() { PhotonView stableZombieView = GetStableZombieView(); if ((Object)(object)stableZombieView != (Object)null && stableZombieView.ViewID > 0 && stableZombieView.IsMine) { return Time.time >= _networkRpcAllowedAt; } return false; } private PhotonView GetStableZombieView() { try { if ((Object)(object)_character != (Object)null) { PhotonView component = ((Component)_character).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } } } catch { } try { return ((Object)(object)_zombie != (Object)null) ? ((Component)_zombie).GetComponent() : null; } catch { return null; } } private static int GetCharacterViewId(Character character) { if ((Object)(object)character == (Object)null) { return -1; } try { PhotonView component = ((Component)character).GetComponent(); return ((Object)(object)component != (Object)null) ? component.ViewID : (-1); } catch { return -1; } } private void ApplyCurrentLookValues() { //IL_0028: 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) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) try { RecalculateLookDirectionsMethod?.Invoke(_character, null); } catch { } Vector3 val = _character.data.lookDirection_Flat; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = ((Component)_character).transform.forward; } val = Vector3.ProjectOnPlane(val, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude > 0.0001f) { ApplyCharacterVisualRotation(); } } private void ApplyLookDirection(Vector3 lookDirection, Vector3 flatLook) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //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_001a: 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_0022: 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_0047: 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_0058: 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_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_0082: 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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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) if (!(((Vector3)(ref flatLook)).sqrMagnitude < 0.0001f)) { Vector3 val = Vector3.ProjectOnPlane(flatLook, Vector3.up); flatLook = ((Vector3)(ref val)).normalized; if (((Vector3)(ref lookDirection)).sqrMagnitude < 0.0001f) { lookDirection = flatLook; } _character.data.lookDirection = ((Vector3)(ref lookDirection)).normalized; _character.data.lookDirection_Flat = flatLook; CharacterData data = _character.data; val = Vector3.Cross(Vector3.up, _character.data.lookDirection); data.lookDirection_Right = ((Vector3)(ref val)).normalized; CharacterData data2 = _character.data; val = Vector3.Cross(_character.data.lookDirection, _character.data.lookDirection_Right); data2.lookDirection_Up = ((Vector3)(ref val)).normalized; ApplyCharacterVisualRotation(); } } private void RefreshLookAfterAutomatedMovement() { try { RecalculateLookDirectionsMethod?.Invoke(_character, null); } catch { } ApplyCharacterVisualRotation(); } private void ApplyCharacterVisualRotation() { //IL_002d: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_character == (Object)null || (Object)(object)_character.data == (Object)null) { return; } Vector3 val = Vector3.ProjectOnPlane(_character.data.lookDirection_Flat, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f || IsCharacterClimbing() || !(SetRotationMethod != null)) { return; } try { SetRotationMethod.Invoke(_character, null); } catch { } } private void CalculateWorldMovementDirection() { try { CalculateWorldMovementDirMethod?.Invoke(_character, null); } catch { } } private void ClearOriginalZombieControlState(bool keepChaseTarget) { try { _zombie.isNPCZombie = false; _zombie.targetForcedUntil = 0f; _zombie.distanceToTarget = 0f; _zombie.sinceLookForTarget = 0f; if (!keepChaseTarget) { _zombie.currentTarget = null; CurrentTargetField?.SetValue(_zombie, null); _lastSyncedChaseTarget = null; } } catch { } } private void ApplyKinematicLocomotion() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0189: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: 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_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(Time.fixedDeltaTime, 0.001f); RaycastHit groundHit; bool flag = TryFindGroundUnderCharacter(80f, out groundHit); float bottomY; float desiredGroundClearance; bool flag2 = TryGetControlledBottomY(out bottomY, out desiredGroundClearance); float num2 = (flag ? (((RaycastHit)(ref groundHit)).point.y + desiredGroundClearance) : bottomY); float num3 = ((flag && flag2) ? (num2 - bottomY) : 0f); bool flag3 = flag && flag2 && num3 <= 0.12f && num3 >= -0.24f; Vector3 desiredHorizontalVelocity = GetDesiredHorizontalVelocity(); float num4 = (_character.data.isGrounded ? 22f : 8f); _controlledHorizontalVelocity = Vector3.MoveTowards(_controlledHorizontalVelocity, desiredHorizontalVelocity, num4 * num); if (!IsPouncing && (Object)(object)_character.input != (Object)null && _character.input.jumpWasPressed && flag3) { StartLocalJump(8.5f); flag3 = false; } if (flag3 && _controlledVerticalVelocity <= 0f) { _controlledVerticalVelocity = 0f; MarkGrounded(((RaycastHit)(ref groundHit)).point); } else { MarkAirborne(); _controlledVerticalVelocity = Mathf.Max(_controlledVerticalVelocity - 22f * num, -24f); if (!IsPouncing && flag && flag2 && num3 < -0.75f) { _controlledVerticalVelocity = Mathf.Min(_controlledVerticalVelocity, -18f); } } Vector3 val = _controlledHorizontalVelocity * num + Vector3.up * (_controlledVerticalVelocity * num); if (flag && flag2 && _controlledVerticalVelocity <= 0f) { float num5 = bottomY + val.y; if (num5 <= num2 + 0.12f) { val.y += num2 - num5; _controlledVerticalVelocity = 0f; MarkGrounded(((RaycastHit)(ref groundHit)).point); } } ShiftControlledCharacter(val); Vector3 avarageVelocity = val / num; _character.data.avarageLastFrameVelocity = _character.data.avarageVelocity; _character.data.avarageVelocity = avarageVelocity; _character.data.worldMovementInput_Grounded = Vector3.ProjectOnPlane(_controlledHorizontalVelocity, Vector3.up); _character.data.currentRagdollControll = 1f; } private Vector3 GetDesiredHorizontalVelocity() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_00d7: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_00fe: 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_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = _character.data.lookDirection_Flat; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)Camera.main != (Object)null) { val = Vector3.ProjectOnPlane(((Component)Camera.main).transform.forward, Vector3.up); } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = ((Component)_character).transform.forward; } Vector3 val2 = Vector3.ProjectOnPlane(val, Vector3.up); val = ((Vector3)(ref val2)).normalized; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.forward; } if (IsPouncing) { return Vector3.zero; } Vector2 val3 = (((Object)(object)_character.input != (Object)null) ? Vector2.ClampMagnitude(_character.input.movementInput, 1f) : Vector2.zero); val2 = Vector3.Cross(Vector3.up, val); Vector3 normalized = ((Vector3)(ref val2)).normalized; Vector3 val4 = val * val3.y + normalized * val3.x; if (((Vector3)(ref val4)).sqrMagnitude > 1f) { ((Vector3)(ref val4)).Normalize(); } float num = (_character.data.isSprinting ? 6.8f : 4.2f); return val4 * num; } private bool TryGetControlledBottomY(out float bottomY, out float desiredGroundClearance) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (TryGetFootAnchorY(out bottomY)) { desiredGroundClearance = 0.06f; return true; } if (TryGetCharacterBottomY(out bottomY)) { desiredGroundClearance = 0.03f; return true; } bottomY = _character.Center.y; desiredGroundClearance = 0.8f; return IsFiniteFloat(bottomY); } private void StartLocalJump(float verticalVelocity) { _controlledVerticalVelocity = Mathf.Max(_controlledVerticalVelocity, verticalVelocity); _character.data.sinceJump = 0f; _character.data.isJumping = true; MarkAirborne(); } private void StabilizeControlledBody() { try { _character.data.fallSeconds = 0f; _character.data.passedOut = false; _character.data.fullyPassedOut = false; _character.data.currentRagdollControll = 1f; Plugin.ClearControlledZombieExternalPassOutState(_character); ApplyLegacyPounceRagdollControl(); } catch { } } private void StabilizeControlledClimb() { //IL_0136: 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_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_character == (Object)null || (Object)(object)_character.data == (Object)null) { return; } try { _character.data.currentRagdollControll = 0.95f; _character.data.fallSeconds = 0f; _character.data.passedOut = false; _character.data.fullyPassedOut = false; _character.data.isGrounded = false; _character.data.sinceGrounded = 0f; _character.data.sinceCanClimb = 0f; _character.data.sincePressClimb = 0f; } catch { } if (_character.refs?.ragdoll?.partList == null) { return; } try { foreach (Bodypart part in _character.refs.ragdoll.partList) { Rigidbody val = (((Object)(object)part != (Object)null) ? part.Rig : null); if (!((Object)(object)val == (Object)null) && !val.isKinematic) { val.linearVelocity = Vector3.ClampMagnitude(val.linearVelocity, 9f); val.angularVelocity = Vector3.ClampMagnitude(val.angularVelocity, 8f); } } } catch { } } private void AssistClimbOntoTopSurface() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_0090: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) if (!IsClimbInputHeld() || (Object)(object)_character?.data == (Object)null || _character.refs?.ragdoll?.partList == null || _character.data.isRopeClimbing || _character.data.isVineClimbing) { return; } Vector3 val = ResolveClimbInwardDirection(); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { return; } Vector3 center = _character.Center; Vector3 probeOrigin = center + Vector3.up * 1.35f + val * 0.75f; if (!TryFindClimbTopSurface(probeOrigin, out var topHit)) { return; } float num = ((RaycastHit)(ref topHit)).point.y - center.y; if (num < -0.2f || num > 1.35f) { return; } Vector3 val2 = val * 0.045f; if (TryGetControlledBottomY(out var bottomY, out var desiredGroundClearance)) { float num2 = ((RaycastHit)(ref topHit)).point.y + desiredGroundClearance - bottomY; if (num2 > 0f) { val2 += Vector3.up * Mathf.Clamp(num2, 0f, 0.075f); } } else if (num > 0f) { val2 += Vector3.up * Mathf.Min(num, 0.075f); } ShiftControlledCharacter(val2); _character.data.sinceCanClimb = 0f; _character.data.sincePressClimb = 0f; } private Vector3 ResolveClimbInwardDirection() { //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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: 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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.zero; if ((Object)(object)_character?.data != (Object)null && ((Vector3)(ref _character.data.climbNormal)).sqrMagnitude > 0.0001f) { val = Vector3.ProjectOnPlane(-_character.data.climbNormal, Vector3.up); } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)_character?.data != (Object)null) { val = Vector3.ProjectOnPlane(_character.data.lookDirection, Vector3.up); } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)_character?.data != (Object)null) { val = _character.data.lookDirection_Flat; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)_character != (Object)null) { val = Vector3.ProjectOnPlane(((Component)_character).transform.forward, Vector3.up); } if (!(((Vector3)(ref val)).sqrMagnitude > 0.0001f)) { return Vector3.zero; } return ((Vector3)(ref val)).normalized; } private bool TryFindClimbTopSurface(Vector3 probeOrigin, out RaycastHit topHit) { //IL_0001: 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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) topHit = default(RaycastHit); RaycastHit[] array; try { array = Physics.RaycastAll(probeOrigin, Vector3.down, 3.6f, -1, (QueryTriggerInteraction)1); } catch { return false; } if (array == null || array.Length == 0) { return false; } Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance)); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val = array2[i]; if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && !((RaycastHit)(ref val)).collider.isTrigger) { Character val2 = ResolveHitCharacter(val); if (!((Object)(object)val2 == (Object)(object)_character) && !((Object)(object)val2 == (Object)(object)_sourceCharacter) && !(((RaycastHit)(ref val)).normal.y < 0.65f)) { topHit = val; return true; } } } return false; } private void ApplyControlledJitter() { //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) if (_character.refs?.ragdoll?.partList == null) { return; } float effectiveControlledJitterChance = Plugin.GetEffectiveControlledJitterChance(); float effectiveControlledJitterIntensity = Plugin.GetEffectiveControlledJitterIntensity(); if (effectiveControlledJitterChance <= 0f || effectiveControlledJitterIntensity <= 0f || IsPouncing || IsCharacterClimbing()) { _jitterUntil = 0f; return; } float time = Time.time; if (time >= _jitterUntil && time >= _nextJitterRollTime) { _nextJitterRollTime = time + 0.2f; float num = 1f - Mathf.Pow(1f - effectiveControlledJitterChance, 0.2f); if (Random.value < num) { _jitterUntil = time + Plugin.GetEffectiveControlledJitterDuration(); } } if (time >= _jitterUntil) { return; } float num2 = Mathf.Max(Time.fixedDeltaTime, 0.005f); float num3 = 4.5f * effectiveControlledJitterIntensity * num2; try { foreach (Bodypart part in _character.refs.ragdoll.partList) { if (!((Object)(object)part == (Object)null) && !((Object)(object)part.Rig == (Object)null) && !part.Rig.isKinematic) { Vector3 insideUnitSphere = Random.insideUnitSphere; part.Rig.AddTorque(insideUnitSphere * num3, (ForceMode)2); part.Rig.angularVelocity = Vector3.ClampMagnitude(part.Rig.angularVelocity, 8f); } } } catch { } } private void PreventGroundClipping() { //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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_0126: 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_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0184: 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) if ((Object)(object)_character == (Object)null || (Object)(object)_character.data == (Object)null || IsCharacterClimbing()) { return; } Vector3 center = _character.Center; if (!IsFiniteVector(center) || !TryGetControlledBottomY(out var bottomY, out var desiredGroundClearance)) { return; } Vector3 groundPoint; bool flag = TryGetRecentGroundPoint(center, out groundPoint) && IsRecentGroundStillTrustworthy() && bottomY < groundPoint.y + desiredGroundClearance - 0.35f; Vector3 val = center + Vector3.up * 8f; RaycastHit[] array; try { array = Physics.RaycastAll(val, Vector3.down, 36f, -1, (QueryTriggerInteraction)1); } catch { return; } if (array == null || array.Length == 0) { if (flag) { ApplyGroundClipCorrection(groundPoint, bottomY, desiredGroundClearance); } return; } Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance)); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit hit = array2[i]; if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null || ((RaycastHit)(ref hit)).collider.isTrigger || Vector3.Dot(((RaycastHit)(ref hit)).normal, Vector3.up) < 0.2f) { continue; } Character val2 = ResolveHitCharacter(hit); if (!((Object)(object)val2 == (Object)(object)_character) && !((Object)(object)val2 == (Object)(object)_sourceCharacter) && (!(((RaycastHit)(ref hit)).point.y > center.y + 0.65f) || flag)) { if (!(((RaycastHit)(ref hit)).point.y + desiredGroundClearance - bottomY <= 0.35f)) { ApplyGroundClipCorrection(((RaycastHit)(ref hit)).point, bottomY, desiredGroundClearance); } return; } } if (flag) { ApplyGroundClipCorrection(groundPoint, bottomY, desiredGroundClearance); } } private bool TryGetRecentGroundPoint(Vector3 center, out Vector3 groundPoint) { //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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) groundPoint = Vector3.zero; if ((Object)(object)_character == (Object)null || (Object)(object)_character.data == (Object)null) { return false; } groundPoint = _character.data.groundPos; if (!IsFiniteVector(groundPoint)) { return false; } Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(groundPoint.x - center.x, groundPoint.z - center.z); return ((Vector2)(ref val)).sqrMagnitude <= 64f; } private bool IsRecentGroundStillTrustworthy() { if ((Object)(object)_character == (Object)null || (Object)(object)_character.data == (Object)null) { return false; } if (_character.data.isGrounded || _character.data.groundedFor > 0f) { return true; } float sinceGrounded = _character.data.sinceGrounded; if (IsFiniteFloat(sinceGrounded)) { return sinceGrounded <= Mathf.Max(Time.fixedDeltaTime * 2f, 0.08f); } return false; } private void ApplyGroundClipCorrection(Vector3 groundPoint, float currentBottomY, float desiredGroundClearance) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.data == (Object)null) && IsFiniteVector(groundPoint) && IsFiniteVector(_character.Center)) { float num = groundPoint.y + desiredGroundClearance - currentBottomY; if (!(num <= 0.35f)) { ShiftControlledCharacter(Vector3.up * Mathf.Clamp(num, 0f, 8f)); _controlledVerticalVelocity = Mathf.Max(_controlledVerticalVelocity, 0f); MarkGrounded(groundPoint); ClearGroundedVerticalVelocity(); } } } private void MaintainGroundContact(bool force) { //IL_0056: 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_00b7: 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_00cb: 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_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_character == (Object)null || (Object)(object)_character.data == (Object)null || (!force && ShouldStayAirborne()) || !TryFindGroundUnderCharacter(force ? 80f : 18f, out var groundHit)) { return; } float num; float num2; if (TryGetFootAnchorY(out var footY)) { num = footY; num2 = ((RaycastHit)(ref groundHit)).point.y + 0.06f; } else { if (!TryGetCharacterBottomY(out var bottomY)) { return; } num = bottomY; num2 = ((RaycastHit)(ref groundHit)).point.y + 0.03f; } float num3 = num2 - num; if (num3 < -0.12f) { float num4 = 0f - num3; float num5 = (force ? 80f : 1.25f); if (num4 <= num5) { ShiftControlledCharacter(Vector3.down * num4); MarkGrounded(((RaycastHit)(ref groundHit)).point); ClearGroundedVerticalVelocity(); } return; } float num6 = (force ? 8f : 0.45f); if (num3 > 0.12f && num3 <= num6) { ShiftControlledCharacter(Vector3.up * num3); MarkGrounded(((RaycastHit)(ref groundHit)).point); ClearGroundedVerticalVelocity(); } else if (Mathf.Abs(num3) <= 0.12f) { MarkGrounded(((RaycastHit)(ref groundHit)).point); ClearGroundedVerticalVelocity(); } } private bool ShouldStayAirborne() { if (IsPouncing || IsCharacterClimbing()) { return true; } if ((Object)(object)_character.input != (Object)null && (_character.input.jumpIsPressed || _character.input.jumpWasPressed)) { return true; } return GetAverageVerticalVelocity() > 0.25f; } private void UpdateControlledCharacterTimers() { //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.data == (Object)null)) { float num = Mathf.Max(Time.fixedDeltaTime, 0f); if (_character.data.isGrounded) { CharacterData data = _character.data; data.groundedFor += num; _character.data.sinceGrounded = 0f; _character.data.lastGroundedHeight = _character.Center.y; } else { _character.data.groundedFor = 0f; CharacterData data2 = _character.data; data2.sinceGrounded += num; } CharacterData data3 = _character.data; data3.sinceJump += num; CharacterData data4 = _character.data; data4.sinceClimbJump += num; CharacterData data5 = _character.data; data5.sinceFallSlide += num; CharacterData data6 = _character.data; data6.sincePressClimb += num; CharacterData data7 = _character.data; data7.sincePressReach += num; CharacterData data8 = _character.data; data8.sinceUseStamina += num; CharacterData data9 = _character.data; data9.sinceClimb += num; CharacterData data10 = _character.data; data10.sinceCanClimb += num; CharacterData data11 = _character.data; data11.sinceItemAttach += num; _character.data.sincePalJump = Mathf.Max(_character.data.sincePalJump + num, 10f); _character.data.sinceStandOnPlayer = Mathf.Max(_character.data.sinceStandOnPlayer + num, 10f); _character.data.lastStoodOnPlayer = null; _character.data.launchedByCannon = false; CharacterData data12 = _character.data; data12.overrideIKForSeconds -= num; } } private static void ClearAssistJumpState(Character character) { if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null)) { character.data.sincePalJump = 10f; character.data.sinceStandOnPlayer = 10f; character.data.lastStoodOnPlayer = null; character.data.launchedByCannon = false; } } private bool TryFindGroundUnderCharacter(float downDistance, out RaycastHit groundHit) { //IL_0001: 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_001c: 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_0026: 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_0034: 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) //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_00c9: 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_00f3: Unknown result type (might be due to invalid IL or missing references) groundHit = default(RaycastHit); Vector3 val = _character.Center + Vector3.up * 3f; float num = Mathf.Max(downDistance, 18f); RaycastHit[] array; try { array = Physics.RaycastAll(val, Vector3.down, 3f + num, -1, (QueryTriggerInteraction)1); } catch { return false; } if (array == null || array.Length == 0) { return false; } Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance)); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val2 = array2[i]; if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !((RaycastHit)(ref val2)).collider.isTrigger && !(Vector3.Dot(((RaycastHit)(ref val2)).normal, Vector3.up) < 0.2f)) { Character val3 = ResolveHitCharacter(val2); if (!((Object)(object)val3 == (Object)(object)_character) && !((Object)(object)val3 == (Object)(object)_sourceCharacter)) { groundHit = val2; return true; } } } return false; } private bool TryGetCharacterBottomY(out float bottomY) { bottomY = float.PositiveInfinity; if (TryGetRendererBottomY(ref bottomY) | TryGetColliderBottomY(ref bottomY) | TryGetBodypartBottomY(ref bottomY)) { return IsFiniteFloat(bottomY); } return false; } private bool TryGetFootAnchorY(out float footY) { footY = float.PositiveInfinity; if (false | TryGetBodypartAnchorY((BodypartType)13, ref footY) | TryGetBodypartAnchorY((BodypartType)16, ref footY) | TryGetBodypartAnchorY((BodypartType)27, ref footY) | TryGetBodypartAnchorY((BodypartType)28, ref footY)) { return IsFiniteFloat(footY); } return false; } private bool TryGetBodypartAnchorY(BodypartType bodypartType, ref float anchorY) { //IL_0058: 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) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) if (_character.refs?.ragdoll?.partList == null) { return false; } bool result = false; foreach (Bodypart part in _character.refs.ragdoll.partList) { if (!((Object)(object)part == (Object)null) && part.partType == bodypartType) { Vector3 val = (((Object)(object)part.Rig != (Object)null) ? part.Rig.position : ((Component)part).transform.position); if (IsFiniteFloat(val.y)) { anchorY = Mathf.Min(anchorY, val.y); result = true; } } } return result; } private bool TryGetRendererBottomY(ref float bottomY) { //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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) bool result = false; try { Renderer[] componentsInChildren = ((Component)_character).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val.enabled && !val.forceRenderingOff) { Bounds bounds = val.bounds; if (IsFiniteFloat(((Bounds)(ref bounds)).min.y)) { bottomY = Mathf.Min(bottomY, ((Bounds)(ref bounds)).min.y); result = true; } } } } catch { } return result; } private bool TryGetColliderBottomY(ref float bottomY) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) bool result = false; try { Collider[] componentsInChildren = ((Component)_character).GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !val.isTrigger) { Bounds bounds = val.bounds; if (IsFiniteFloat(((Bounds)(ref bounds)).min.y)) { bottomY = Mathf.Min(bottomY, ((Bounds)(ref bounds)).min.y); result = true; } } } } catch { } return result; } private bool TryGetBodypartBottomY(ref float bottomY) { //IL_0078: 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_007d: 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) if (_character.refs?.ragdoll?.partList == null) { return false; } bool result = false; foreach (Bodypart part in _character.refs.ragdoll.partList) { if (!((Object)(object)part == (Object)null)) { Vector3 val = (((Object)(object)part.Rig != (Object)null) ? part.Rig.position : ((Component)part).transform.position); if (IsFiniteFloat(val.y)) { bottomY = Mathf.Min(bottomY, val.y - 0.08f); result = true; } } } return result; } private float GetAverageVerticalVelocity() { //IL_0083: Unknown result type (might be due to invalid IL or missing references) if (_character.refs?.ragdoll?.partList == null) { return 0f; } float num = 0f; int num2 = 0; foreach (Bodypart part in _character.refs.ragdoll.partList) { if (!((Object)(object)part == (Object)null) && !((Object)(object)part.Rig == (Object)null) && !part.Rig.isKinematic) { num += part.Rig.linearVelocity.y; num2++; } } if (num2 <= 0) { return 0f; } return num / (float)num2; } private void MarkGrounded(Vector3 groundPoint) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) _character.data.isGrounded = true; _character.data.sinceGrounded = 0f; _character.data.groundedFor = Mathf.Max(_character.data.groundedFor, Time.fixedDeltaTime); _character.data.isJumping = false; _character.data.jumpsRemaining = Mathf.Max(_character.data.jumpsRemaining, 1); _character.data.groundPos = groundPoint; _character.data.lastGroundedHeight = _character.Center.y; } private void MarkAirborne() { _character.data.isGrounded = false; _character.data.groundedFor = 0f; } private void ClearGroundedVerticalVelocity() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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) if (_character.refs?.ragdoll?.partList == null) { return; } foreach (Bodypart part in _character.refs.ragdoll.partList) { if (!((Object)(object)part == (Object)null) && !((Object)(object)part.Rig == (Object)null) && !part.Rig.isKinematic) { Vector3 linearVelocity = part.Rig.linearVelocity; if (linearVelocity.y < 0f || Mathf.Abs(linearVelocity.y) <= 0.2f) { part.Rig.linearVelocity = new Vector3(linearVelocity.x, 0f, linearVelocity.z); } } } } private static bool IsFiniteFloat(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } private static bool IsFiniteVector(Vector3 value) { //IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references) if (IsFiniteFloat(value.x) && IsFiniteFloat(value.y)) { return IsFiniteFloat(value.z); } return false; } private bool IsCharacterClimbing() { if ((Object)(object)_character != (Object)null && (Object)(object)_character.data != (Object)null) { if (!_character.data.isClimbing && !_character.data.isRopeClimbing) { return _character.data.isVineClimbing; } return true; } return false; } private void ShiftControlledCharacter(Vector3 delta) { //IL_001c: 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_0022: 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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) if (((Vector3)(ref delta)).sqrMagnitude < 1E-06f) { return; } try { Transform transform = ((Component)_character).transform; transform.position += delta; if (_character.refs?.ragdoll?.partList == null) { return; } foreach (Bodypart part in _character.refs.ragdoll.partList) { if ((Object)(object)part == (Object)null) { continue; } if ((Object)(object)part.Rig != (Object)null) { Rigidbody rig = part.Rig; rig.position += delta; if (!part.Rig.isKinematic && part.Rig.linearVelocity.y < 0f) { part.Rig.linearVelocity = new Vector3(part.Rig.linearVelocity.x, 0f, part.Rig.linearVelocity.z); } } else { Transform transform2 = ((Component)part).transform; transform2.position += delta; } } } catch { } } private static bool HasFixedMovementInputHeld() { if (!KeyIsPressed((KeyCode)119) && !KeyIsPressed((KeyCode)115) && !KeyIsPressed((KeyCode)97)) { return KeyIsPressed((KeyCode)100); } return true; } private static bool KeyIsPressed(KeyCode key) { //IL_0000: 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_000e: Unknown result type (might be due to invalid IL or missing references) if ((int)key == 0) { return false; } try { return Input.GetKey(key) || InputSystemKeyIsPressed(key); } catch { return false; } } private static bool KeyWasPressed(KeyCode key) { //IL_0000: 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_000e: Unknown result type (might be due to invalid IL or missing references) if ((int)key == 0) { return false; } try { return Input.GetKeyDown(key) || InputSystemKeyWasPressed(key); } catch { return false; } } private static bool KeyWasReleased(KeyCode key) { //IL_0000: 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_000e: Unknown result type (might be due to invalid IL or missing references) if ((int)key == 0) { return false; } try { return Input.GetKeyUp(key) || InputSystemKeyWasReleased(key); } catch { return false; } } private static bool InputSystemKeyIsPressed(KeyCode key) { //IL_0055: 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_000d: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 try { if (Mouse.current != null) { if ((int)key == 323) { return Mouse.current.leftButton.isPressed; } if ((int)key == 324) { return Mouse.current.rightButton.isPressed; } if ((int)key == 325) { return Mouse.current.middleButton.isPressed; } } Key? val = ToInputSystemKey(key); return val.HasValue && Keyboard.current != null && ((ButtonControl)Keyboard.current[val.Value]).isPressed; } catch { return false; } } private static bool InputSystemKeyWasPressed(KeyCode key) { //IL_0055: 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_000d: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 try { if (Mouse.current != null) { if ((int)key == 323) { return Mouse.current.leftButton.wasPressedThisFrame; } if ((int)key == 324) { return Mouse.current.rightButton.wasPressedThisFrame; } if ((int)key == 325) { return Mouse.current.middleButton.wasPressedThisFrame; } } Key? val = ToInputSystemKey(key); return val.HasValue && Keyboard.current != null && ((ButtonControl)Keyboard.current[val.Value]).wasPressedThisFrame; } catch { return false; } } private static bool InputSystemKeyWasReleased(KeyCode key) { //IL_0055: 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_000d: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 try { if (Mouse.current != null) { if ((int)key == 323) { return Mouse.current.leftButton.wasReleasedThisFrame; } if ((int)key == 324) { return Mouse.current.rightButton.wasReleasedThisFrame; } if ((int)key == 325) { return Mouse.current.middleButton.wasReleasedThisFrame; } } Key? val = ToInputSystemKey(key); return val.HasValue && Keyboard.current != null && ((ButtonControl)Keyboard.current[val.Value]).wasReleasedThisFrame; } catch { return false; } } private static Key? ToInputSystemKey(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 //IL_000a: 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_002b: Expected I4, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 if ((int)key <= 114) { if ((int)key == 32) { return (Key)1; } switch (key - 97) { default: if ((int)key != 114) { break; } return (Key)32; case 0: return (Key)15; case 3: return (Key)18; case 5: return (Key)20; case 2: return (Key)17; case 1: case 4: break; } } else if ((int)key <= 119) { if ((int)key == 115) { return (Key)33; } if ((int)key == 119) { return (Key)37; } } else { if ((int)key == 303) { return (Key)52; } if ((int)key == 304) { return (Key)51; } } return null; } } [HarmonyPatch] public static class ZombieHarmonyPatches { [HarmonyPatch] private static class MushroomZombieArisePatch { [HarmonyPrepare] private static bool Prepare() { return Plugin.FindMushroomZombieAriseMethod() != null; } [HarmonyTargetMethod] private static MethodBase TargetMethod() { return Plugin.FindMushroomZombieAriseMethod(); } [HarmonyPrefix] private static void Prefix(MushroomZombie __instance, object[] __args, ref int __state) { __state = Plugin.GetMushroomZombieAriseSourceViewId(__args); if (Plugin.ShouldSuppressNetworkAriseFinishZombifying(__instance, __state)) { Plugin.BeginNativeAriseSuppressionByViewId(__state); Plugin.ExtendNativeAriseSuppressionByViewId(__state); } else { __state = -1; } } [HarmonyPostfix] private static void Postfix(int __state) { if (__state > 0) { Plugin.EndNativeAriseSuppressionByViewId(__state); } } } [HarmonyPatch] private static class MushroomZombieAwakeRoutinePatch { [HarmonyPrepare] private static bool Prepare() { return Plugin.FindMushroomZombieAwakeRoutineMoveNextMethod() != null; } [HarmonyTargetMethod] private static MethodBase TargetMethod() { return Plugin.FindMushroomZombieAwakeRoutineMoveNextMethod(); } [HarmonyPrefix] private static bool Prefix(object __instance, ref bool __result) { return !Plugin.TrySkipControlledZombieAwakeRoutine(__instance, ref __result); } [HarmonyFinalizer] private static Exception Finalizer(object __instance, Exception __exception) { return Plugin.FinalizeControlledZombieAwakeRoutine(__instance, __exception); } } private static Character ResolveCharacter(Component component, Character fieldCharacter) { if ((Object)(object)fieldCharacter != (Object)null) { return fieldCharacter; } if (!((Object)(object)component != (Object)null)) { return null; } return component.GetComponent(); } [HarmonyPatch(typeof(PlayerHandler), "RegisterCharacter")] [HarmonyPrefix] private static bool PlayerHandlerRegisterCharacterPrefix(Character character) { return !Plugin.ShouldSkipCharacterRegistration(character); } [HarmonyPatch(typeof(PlayerHandler), "TryGetCharacter")] [HarmonyPrefix] private static bool PlayerHandlerTryGetCharacterPrefix(int actorID, ref Character character, ref bool __result) { if (!Plugin.TryGetStableCharacterForActor(actorID, out var character2)) { return true; } character = character2; __result = true; return false; } [HarmonyPatch(typeof(CharacterSpawner), "SpawnMyPlayerCharacter")] [HarmonyPrefix] private static bool CharacterSpawnerSpawnMyPlayerCharacterPrefix(ref Character __result) { Plugin.PrepareForOriginalLocalCharacterSpawn(); if (!Plugin.TrySuppressDuplicateLocalCharacterSpawn(out var character)) { return true; } __result = character; return false; } [HarmonyPatch(typeof(CharacterSpawner), "SpawnMyPlayerCharacter")] [HarmonyPostfix] private static void CharacterSpawnerSpawnMyPlayerCharacterPostfix(Character __result) { Plugin.CompleteOriginalLocalCharacterSpawn(__result); } [HarmonyPatch(typeof(CharacterSpawner), "SpawnMyPlayerCharacter")] [HarmonyFinalizer] private static Exception CharacterSpawnerSpawnMyPlayerCharacterFinalizer(CharacterSpawner __instance, Exception __exception) { return Plugin.HandleOriginalLocalCharacterSpawnException(__instance, __exception); } [HarmonyPatch(typeof(CharacterSpawner), "SpawnHostCharacter")] [HarmonyPrefix] private static bool CharacterSpawnerSpawnHostCharacterPrefix() { Plugin.PrepareForOriginalLocalCharacterSpawn(); return !Plugin.ShouldSuppressHostLocalCharacterSpawn(); } [HarmonyPatch(typeof(CharacterSpawner), "SpawnHostCharacter")] [HarmonyFinalizer] private static Exception CharacterSpawnerSpawnHostCharacterFinalizer(CharacterSpawner __instance, Exception __exception) { return Plugin.HandleOriginalLocalCharacterSpawnException(__instance, __exception); } [HarmonyPatch(typeof(PhotonNetwork), "Destroy", new Type[] { typeof(GameObject) })] [HarmonyPrefix] private static bool PhotonNetworkDestroyGameObjectPrefix(GameObject targetGo) { return !Plugin.ShouldSuppressControlledPhotonDestroy(targetGo); } [HarmonyPatch(typeof(PhotonNetwork), "Destroy", new Type[] { typeof(PhotonView) })] [HarmonyPrefix] private static bool PhotonNetworkDestroyPhotonViewPrefix(PhotonView targetView) { return !Plugin.ShouldSuppressControlledPhotonDestroy(targetView); } [HarmonyPatch(typeof(GameObject), "SetActive")] [HarmonyPrefix] private static bool GameObjectSetActivePrefix(GameObject __instance, bool value) { return !Plugin.ShouldSuppressControlledSetActive(__instance, value); } [HarmonyPatch(typeof(Object), "Destroy", new Type[] { typeof(Object) })] [HarmonyPrefix] private static bool UnityObjectDestroyPrefix(Object obj) { return !Plugin.ShouldSuppressControlledUnityDestroy(obj); } [HarmonyPatch(typeof(Object), "Destroy", new Type[] { typeof(Object), typeof(float) })] [HarmonyPrefix] private static bool UnityObjectDestroyDelayedPrefix(Object obj) { return !Plugin.ShouldSuppressControlledUnityDestroy(obj); } [HarmonyPatch(typeof(Object), "DestroyImmediate", new Type[] { typeof(Object) })] [HarmonyPrefix] private static bool UnityObjectDestroyImmediatePrefix(Object obj) { return !Plugin.ShouldSuppressControlledUnityDestroy(obj); } [HarmonyPatch(typeof(Object), "DestroyImmediate", new Type[] { typeof(Object), typeof(bool) })] [HarmonyPrefix] private static bool UnityObjectDestroyImmediateAllowAssetsPrefix(Object obj) { return !Plugin.ShouldSuppressControlledUnityDestroy(obj); } [HarmonyPatch(typeof(Character), "Awake")] [HarmonyPrefix] private static bool CharacterAwakePrefix(Character __instance) { Plugin.EnsureControlledZombieRegistered(__instance); if (!Plugin.ShouldUseIsolatedCharacterLifecycle(__instance)) { return true; } Plugin.RunIsolatedCharacterAwake(__instance); return false; } [HarmonyPatch(typeof(Character), "Start")] [HarmonyPrefix] private static bool CharacterStartPrefix(Character __instance) { Plugin.EnsureControlledZombieRegistered(__instance); if (!Plugin.ShouldUseIsolatedCharacterLifecycle(__instance)) { return true; } Plugin.RunIsolatedCharacterStart(__instance); return false; } [HarmonyPatch(typeof(CharacterData), "Awake")] [HarmonyPrefix] private static bool CharacterDataAwakePrefix(CharacterData __instance) { Character character = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent() : null); Plugin.EnsureControlledZombieRegistered(character); if (!Plugin.ShouldUseIsolatedCharacterLifecycle(character)) { return true; } Plugin.RunIsolatedCharacterDataAwake(__instance, character); return false; } [HarmonyPatch(typeof(CharacterData), "SetBadgeStatus")] [HarmonyPrefix] private static bool CharacterDataSetBadgeStatusPrefix(CharacterData __instance) { return !Plugin.ShouldSkipControlledZombieBadgeStatus(__instance); } [HarmonyPatch(typeof(CharacterCustomization), "Start")] [HarmonyPrefix] private static bool CharacterCustomizationStartPrefix(CharacterCustomization __instance) { return !Plugin.ShouldSkipControlledZombieCustomizationStart(__instance); } [HarmonyPatch(typeof(CharacterCustomization), "OnDestroy")] [HarmonyPrefix] private static bool CharacterCustomizationOnDestroyPrefix(CharacterCustomization __instance) { return !Plugin.ShouldSkipControlledZombieCustomizationDestroy(__instance); } [HarmonyPatch(typeof(MushroomZombie), "Update")] [HarmonyPrefix] private static bool MushroomZombieUpdatePrefix(MushroomZombie __instance) { return !Plugin.ShouldSuppressControlledZombieUpdate(__instance); } [HarmonyPatch(typeof(MushroomZombie), "FixedUpdate")] [HarmonyPrefix] private static bool MushroomZombieFixedUpdatePrefix(MushroomZombie __instance) { return Plugin.ShouldRunControlledZombieOriginalBehavior(__instance); } [HarmonyPatch(typeof(MushroomZombie), "OnPlayerEnteredRoom")] [HarmonyPrefix] private static bool MushroomZombieOnPlayerEnteredRoomPrefix(MushroomZombie __instance, ref bool __state) { __state = false; if (!Plugin.IsControlledZombie(__instance)) { return true; } Plugin.BeginControlledZombieOriginalBehavior(); __state = true; return true; } [HarmonyPatch(typeof(MushroomZombie), "OnPlayerEnteredRoom")] [HarmonyPostfix] private static void MushroomZombieOnPlayerEnteredRoomPostfix(bool __state) { if (__state) { Plugin.EndControlledZombieOriginalBehavior(); } } [HarmonyPatch(typeof(MushroomZombie), "RPC_SetOutfit")] [HarmonyPrefix] private static bool MushroomZombieSetOutfitPrefix(MushroomZombie __instance) { return !Plugin.ShouldSuppressControlledZombieNetworkControl(__instance); } [HarmonyPatch(typeof(MushroomZombie), "StartLunging")] [HarmonyPrefix] private static bool StartLungingPrefix(MushroomZombie __instance) { return Plugin.ShouldRunControlledZombieOriginalBehavior(__instance); } [HarmonyPatch(typeof(MushroomZombie), "DoLunging")] [HarmonyPrefix] private static bool DoLungingPrefix(MushroomZombie __instance) { return Plugin.ShouldRunControlledZombieOriginalBehavior(__instance); } [HarmonyPatch(typeof(MushroomZombie), "DoLungeRecovery")] [HarmonyPrefix] private static bool DoLungeRecoveryPrefix(MushroomZombie __instance) { return Plugin.ShouldRunControlledZombieOriginalBehavior(__instance); } [HarmonyPatch(typeof(MushroomZombie), "StartChasing")] [HarmonyPrefix] private static bool StartChasingPrefix(MushroomZombie __instance) { return Plugin.ShouldRunControlledZombieOriginalBehavior(__instance); } [HarmonyPatch(typeof(MushroomZombie), "DoChasing")] [HarmonyPrefix] private static bool DoChasingPrefix(MushroomZombie __instance) { return Plugin.ShouldRunControlledZombieOriginalBehavior(__instance); } [HarmonyPatch(typeof(MushroomZombie), "TryLunge")] [HarmonyPrefix] private static bool TryLungePrefix(MushroomZombie __instance) { return Plugin.ShouldRunControlledZombieOriginalBehavior(__instance); } [HarmonyPatch(typeof(MushroomZombie), "WalkTowards")] [HarmonyPrefix] private static bool WalkTowardsPrefix(MushroomZombie __instance) { return Plugin.ShouldRunControlledZombieOriginalBehavior(__instance); } [HarmonyPatch(typeof(MushroomZombie), "ClimbTowards")] [HarmonyPrefix] private static bool ClimbTowardsPrefix(MushroomZombie __instance) { return Plugin.ShouldRunControlledZombieOriginalBehavior(__instance); } [HarmonyPatch(typeof(MushroomZombie), "TestCharacterFell")] [HarmonyPrefix] private static bool TestCharacterFellPrefix(MushroomZombie __instance) { return !Plugin.IsControlledZombie(__instance); } [HarmonyPatch(typeof(MushroomZombie), "TestCharacterPassedOut")] [HarmonyPrefix] private static bool TestCharacterPassedOutPrefix(MushroomZombie __instance) { return !Plugin.IsControlledZombie(__instance); } [HarmonyPatch(typeof(MushroomZombie), "ReadyToDisable")] [HarmonyPrefix] private static bool ReadyToDisablePrefix(MushroomZombie __instance, ref bool __result) { if (!Plugin.IsControlledZombie(__instance)) { return true; } __result = false; return false; } [HarmonyPatch(typeof(MushroomZombie), "DestroyZombie")] [HarmonyPrefix] private static bool DestroyZombiePrefix(MushroomZombie __instance) { return !Plugin.IsControlledZombie(__instance); } [HarmonyPatch(typeof(ZombieManager), "RegisterZombie")] [HarmonyPrefix] private static bool ZombieManagerRegisterZombiePrefix(MushroomZombie zombie) { return !Plugin.ShouldSkipZombieManagerRegistration(zombie); } [HarmonyPatch(typeof(MushroomZombie), "OnBitCharacter")] [HarmonyPrefix] private static bool OnBitCharacterPrefix(MushroomZombie __instance, Character c, ref bool __state) { __state = false; if (!Plugin.IsControlledZombie(__instance)) { return true; } if (Plugin.ShouldRunControlledZombieOriginalBitCharacter(__instance, c)) { Plugin.BeginControlledZombieOriginalBehavior(); __state = true; return true; } Plugin.TryHandleControlledZombieBitCharacter(__instance, c); return false; } [HarmonyPatch(typeof(MushroomZombie), "OnBitCharacter")] [HarmonyPostfix] private static void OnBitCharacterPostfix(bool __state) { if (__state) { Plugin.EndControlledZombieOriginalBehavior(); } } [HarmonyPatch(typeof(MushroomZombieBiteCollider), "OnTriggerEnter")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool MushroomZombieBiteColliderOnTriggerEnterPrefix(MushroomZombieBiteCollider __instance, Collider other) { return !Plugin.ShouldSuppressControlledZombieBiteCollider(__instance, other); } [HarmonyPatch(typeof(MushroomZombie), "RPCA_SetCurrentTarget")] [HarmonyPrefix] private static bool SetCurrentTargetPrefix(MushroomZombie __instance) { return !Plugin.ShouldSuppressControlledZombieNetworkControl(__instance); } [HarmonyPatch(typeof(MushroomZombie), "RPC_SyncState")] [HarmonyPrefix] private static bool SyncStatePrefix(MushroomZombie __instance) { return !Plugin.ShouldSuppressControlledZombieNetworkControl(__instance); } [HarmonyPatch(typeof(MushroomZombie), "PushState")] [HarmonyPrefix] private static bool PushStatePrefix(MushroomZombie __instance) { return !Plugin.ShouldSuppressControlledZombieNetworkControl(__instance); } [HarmonyPatch(typeof(CharacterBackpackHandler), "LateUpdate")] [HarmonyPrefix] private static bool CharacterBackpackHandlerLateUpdatePrefix(CharacterBackpackHandler __instance, Character ___character) { if (!Plugin.ShouldDisableInventoryForCharacter(ResolveCharacter((Component)(object)__instance, ___character))) { return true; } if ((Object)(object)__instance != (Object)null && (Object)(object)__instance.backpack != (Object)null) { __instance.backpack.SetActive(false); } return false; } [HarmonyPatch(typeof(CharacterBackpackHandler), "StashInBackpack")] [HarmonyPrefix] private static bool CharacterBackpackHandlerStashInBackpackPrefix(CharacterBackpackHandler __instance, Character ___character, Character interactor) { if (!Plugin.ShouldDisableInventoryForCharacter(ResolveCharacter((Component)(object)__instance, ___character))) { return !Plugin.ShouldDisableInventoryForCharacter(interactor); } return false; } [HarmonyPatch(typeof(CharacterBackpackHandler), "RPCAddItemToCharacterBackpack")] [HarmonyPrefix] private static bool CharacterBackpackHandlerAddItemPrefix(CharacterBackpackHandler __instance, Character ___character) { return !Plugin.ShouldDisableInventoryForCharacter(ResolveCharacter((Component)(object)__instance, ___character)); } [HarmonyPatch(typeof(CharacterItems), "Update")] [HarmonyPrefix] private static bool CharacterItemsUpdatePrefix(CharacterItems __instance, Character ___character) { Character character = ResolveCharacter((Component)(object)__instance, ___character); if (!Plugin.ShouldDisableInventoryForCharacter(character)) { return true; } Plugin.ResetDisabledInventoryState(__instance, character); return false; } [HarmonyPatch(typeof(CharacterItems), "FixedUpdate")] [HarmonyPrefix] private static bool CharacterItemsFixedUpdatePrefix(CharacterItems __instance, Character ___character) { Character character = ResolveCharacter((Component)(object)__instance, ___character); if (!Plugin.ShouldDisableInventoryForCharacter(character)) { return true; } Plugin.ResetDisabledInventoryState(__instance, character); return false; } [HarmonyPatch(typeof(CharacterItems), "EquipSlot")] [HarmonyPrefix] private static bool CharacterItemsEquipSlotPrefix(CharacterItems __instance, Character ___character) { Character character = ResolveCharacter((Component)(object)__instance, ___character); if (!Plugin.ShouldDisableInventoryForCharacter(character)) { return true; } Plugin.ResetDisabledInventoryState(__instance, character); return false; } [HarmonyPatch(typeof(CharacterItems), "Equip")] [HarmonyPrefix] private static bool CharacterItemsEquipPrefix(CharacterItems __instance, Character ___character, ref Item __result) { Character character = ResolveCharacter((Component)(object)__instance, ___character); if (!Plugin.ShouldDisableInventoryForCharacter(character)) { return true; } Plugin.ResetDisabledInventoryState(__instance, character); __result = null; return false; } [HarmonyPatch(typeof(Item), "Interact")] [HarmonyPrefix] private static bool ItemInteractPrefix(Character interactor) { return !Plugin.ShouldDisableInventoryForCharacter(interactor); } [HarmonyPatch(typeof(Item), "IsInteractible")] [HarmonyPostfix] private static void ItemIsInteractiblePostfix(Character interactor, ref bool __result) { if (Plugin.ShouldDisableInventoryForCharacter(interactor)) { __result = false; } } [HarmonyPatch(typeof(Character), "GetCameraPos")] [HarmonyPostfix] private static void GetCameraPosPostfix(Character __instance, ref Vector3 __result) { Plugin.TryApplyCameraOverride(__instance, ref __result); } [HarmonyPatch(typeof(MainCameraMovement), "LateUpdate")] [HarmonyPostfix] private static void MainCameraMovementLateUpdatePostfix(MainCameraMovement __instance) { Plugin.RefreshCameraAfterGameUpdate(__instance); } [HarmonyPatch(typeof(CharacterMovement), "Update")] [HarmonyPrefix] private static bool CharacterMovementUpdatePrefix(Character ___character) { return !Plugin.ShouldSkipCharacterMovementUpdate(___character); } [HarmonyPatch(typeof(CharacterMovement), "TryToJump")] [HarmonyPrefix] private static bool CharacterMovementTryToJumpPrefix(Character ___character) { return !Plugin.TryHandleControlledZombieJump(___character); } [HarmonyPatch(typeof(CharacterMovement), "JumpRpc")] [HarmonyPrefix] private static bool CharacterMovementJumpRpcPrefix(Character ___character) { return !Plugin.ShouldSuppressControlledZombieJumpRpc(___character); } [HarmonyPatch(typeof(CharacterClimbing), "TryToStartWallClimb")] [HarmonyPrefix] private static bool CharacterClimbingTryToStartWallClimbPrefix(CharacterClimbing __instance, Character ___character, bool forceAttempt, Vector3 overide, bool botGrab, float raycastDistance) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) return !Plugin.TryHandleControlledZombieStartWallClimb(__instance, ___character, forceAttempt, overide, botGrab, raycastDistance); } [HarmonyPatch(typeof(CharacterClimbing), "StopClimbingRpc")] [HarmonyPrefix] private static bool CharacterClimbingStopClimbingRpcPrefix(CharacterClimbing __instance, Character ___character, float setFall) { return !Plugin.TryHandleControlledZombieStopClimb(__instance, ___character, setFall); } [HarmonyPatch(typeof(GUIManager), "UpdateReticle")] [HarmonyPrefix] private static void GUIManagerUpdateReticlePrefix(ref Character ___character) { Plugin.PrepareControlledZombieReticle(); Character controlledZombieCharacter = Plugin.GetControlledZombieCharacter(); if ((Object)(object)controlledZombieCharacter != (Object)null) { ___character = controlledZombieCharacter; } } [HarmonyPatch(typeof(Character), "FixedUpdate")] [HarmonyPrefix] private static bool CharacterFixedUpdatePrefix(Character __instance) { return !Plugin.ShouldSkipCharacterFixedUpdate(__instance); } [HarmonyPatch(typeof(CharacterSyncer), "Update")] [HarmonyPrefix] private static bool CharacterSyncerUpdatePrefix(Character ___m_character) { return !Plugin.ShouldSkipCharacterNetworkInterpolation(___m_character); } [HarmonyPatch(typeof(CharacterSyncer), "FixedUpdate")] [HarmonyPrefix] private static bool CharacterSyncerFixedUpdatePrefix(Character ___m_character) { return !Plugin.ShouldSkipCharacterNetworkInterpolation(___m_character); } [HarmonyPatch(typeof(CharacterMovement), "CheckFallDamage")] [HarmonyPrefix] private static bool CharacterMovementCheckFallDamagePrefix(Character ___character) { return !Plugin.ShouldSuppressControlledCharacterFall(___character); } [HarmonyPatch(typeof(CharacterAfflictions), "AddStatus")] [HarmonyPrefix] private static bool CharacterAfflictionsAddStatusPrefix(CharacterAfflictions __instance, STATUSTYPE statusType) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return !Plugin.ShouldSuppressControlledZombieStatus(__instance, statusType); } [HarmonyPatch(typeof(CharacterAfflictions), "AddAffliction")] [HarmonyPrefix] private static bool CharacterAfflictionsAddAfflictionPrefix(CharacterAfflictions __instance, Affliction affliction) { return !Plugin.ShouldSuppressManagedNoHungerAffliction(__instance, affliction); } [HarmonyPatch(typeof(Character), "Fall", new Type[] { typeof(float), typeof(float) })] [HarmonyPrefix] private static bool CharacterFallPrefix(Character __instance) { return !Plugin.ShouldSuppressControlledCharacterFall(__instance); } [HarmonyPatch(typeof(Character), "RPCA_Fall")] [HarmonyPrefix] private static bool CharacterRpcFallPrefix(Character __instance) { return !Plugin.ShouldSuppressControlledCharacterFall(__instance); } [HarmonyPatch(typeof(Character), "RPCA_FallWithScreenShake")] [HarmonyPrefix] private static bool CharacterRpcFallWithScreenShakePrefix(Character __instance) { return !Plugin.ShouldSuppressControlledCharacterFall(__instance); } [HarmonyPatch(typeof(Character), "RPCA_PassOut")] [HarmonyPrefix] private static bool CharacterRpcPassOutPrefix(Character __instance) { return !Plugin.ShouldSuppressControlledCharacterFall(__instance); } [HarmonyPatch(typeof(Character), "PassOutInstantly")] [HarmonyPrefix] private static bool CharacterPassOutInstantlyPrefix(Character __instance) { return !Plugin.ShouldSuppressControlledCharacterFall(__instance); } [HarmonyPatch(typeof(Character), "get_IsLocal")] [HarmonyPrefix] private static bool CharacterIsLocalPrefix(Character __instance, ref bool __result) { if (Plugin.IsStashedSourceCharacter(__instance)) { __result = false; return false; } if (Plugin.IsLocallyControlledZombieCharacter(__instance)) { __result = true; return false; } return true; } [HarmonyPatch(typeof(Character), "get_IsPlayerControlled")] [HarmonyPrefix] private static bool CharacterIsPlayerControlledPrefix(Character __instance, ref bool __result) { if (Plugin.IsStashedSourceCharacter(__instance)) { __result = false; return false; } if (Plugin.IsLocallyControlledZombieCharacter(__instance)) { __result = true; return false; } return true; } [HarmonyPatch(typeof(Character), "get_IsRegisteredToPlayer")] [HarmonyPrefix] private static bool CharacterIsRegisteredToPlayerPrefix(Character __instance, ref bool __result) { if (Plugin.IsStashedSourceCharacter(__instance)) { __result = false; return false; } if (Plugin.IsLocallyControlledZombieCharacter(__instance)) { __result = true; return false; } return true; } [HarmonyPatch(typeof(Character), "get_player")] [HarmonyPrefix] private static bool CharacterPlayerPrefix(Character __instance, ref Player __result) { if (Plugin.IsStashedSourceCharacter(__instance)) { __result = null; return false; } if (Plugin.IsLocallyControlledZombieCharacter(__instance) && (Object)(object)Player.localPlayer != (Object)null) { __result = Player.localPlayer; return false; } return true; } [HarmonyPatch(typeof(PlayerHandler), "GetPlayer", new Type[] { typeof(Player) })] [HarmonyPrefix] private static bool PlayerHandlerGetPlayerPrefix(Player photonPlayer, ref Player __result) { if (photonPlayer != null) { return true; } __result = null; return false; } [HarmonyPatch(typeof(Player), "get_character")] [HarmonyPostfix] private static void PlayerCharacterPostfix(Player __instance, ref Character __result) { if ((Object)(object)__instance == (Object)(object)Player.localPlayer) { Character controlledZombieCharacter = Plugin.GetControlledZombieCharacter(); if ((Object)(object)controlledZombieCharacter != (Object)null) { __result = controlledZombieCharacter; } } } [HarmonyPatch(typeof(PlayerHandler), "GetPlayerCharacter")] [HarmonyPostfix] private static void PlayerHandlerGetPlayerCharacterPostfix(Player photonPlayer, ref Character __result) { Character character; if (Plugin.TryGetControlledZombieForPhotonPlayer(photonPlayer, out var controlledZombie)) { __result = controlledZombie; } else if ((Object)(object)__result == (Object)null && photonPlayer != null && Plugin.TryGetStableCharacterForActor(photonPlayer.ActorNumber, out character)) { __result = character; } } [HarmonyPatch(typeof(Character), "FinishZombifying")] [HarmonyPrefix] private static bool FinishZombifyingPrefix(Character __instance) { return !Plugin.ShouldSuppressFinishZombifying(__instance); } [HarmonyPatch(typeof(HideTheBody), "SetShowing")] [HarmonyPrefix] private static void HideTheBodySetShowingPrefix(HideTheBody __instance, Character ___character, ref float x) { if (Plugin.ShouldForceShowControlledZombie(__instance, ___character)) { x = 0f; } } [HarmonyPatch(typeof(HideTheBody), "SetShowing")] [HarmonyPostfix] private static void HideTheBodySetShowingPostfix(HideTheBody __instance, Character ___character, Renderer r) { if (Plugin.ShouldForceShowControlledZombie(__instance, ___character)) { Plugin.RefreshHideTheBodyVisuals(__instance); } } [HarmonyPatch(typeof(HideTheBody), "Update")] [HarmonyPostfix] private static void HideTheBodyUpdatePostfix(HideTheBody __instance, Character ___character) { if (Plugin.ShouldForceShowControlledZombie(__instance, ___character)) { Plugin.RefreshHideTheBodyVisuals(__instance); } } } }