Decompiled source of I am Zombie v1.0.1
plugins/Thanks.I_am_a_Zombie.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Thanks.I_am_a_Zombie")] [assembly: AssemblyDescription("Client-side controllable zombie form for PEAK. Press F to become the game's original mushroom zombie with WASD movement, jump, sprint, crouch, wall climb, and lunge attack.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Thanks")] [assembly: AssemblyProduct("I'm a Zombie")] [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("3a7b9c51-4d2e-4f6a-8b10-9c8d7e6f5a4b")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ImZombie { [BepInPlugin("com.github.Thanks.ImZombie", "I'm a Zombie", "1.0.2")] public sealed class ZombiePlugin : BaseUnityPlugin { public enum ZombieAppearanceOption { Player, Mushroom } public const string Id = "com.github.Thanks.ImZombie"; public const string Name = "I'm a Zombie"; public const string Version = "1.0.2"; private const byte BodyVisibilityEventCode = 199; private const int BodyVisibilityMagic = 1512112921; internal static ManualLogSource Log; internal static ConfigEntry<KeyCode> ToggleKey; internal static ConfigEntry<KeyCode> AttackKey; internal static ConfigEntry<KeyCode> SprintKey; internal static ConfigEntry<KeyCode> JumpKey; internal static ConfigEntry<KeyCode> CrouchKey; internal static ConfigEntry<float> MovementSpeed; internal static ConfigEntry<float> SprintMultiplier; internal static ConfigEntry<float> CrouchMultiplier; internal static ConfigEntry<float> JumpForce; internal static ConfigEntry<float> MaxVelocity; internal static ConfigEntry<float> AttackDuration; internal static ConfigEntry<float> AttackCooldown; internal static ConfigEntry<float> AttackRevertSeconds; internal static ConfigEntry<float> CameraDistance; internal static ConfigEntry<float> CameraHeight; internal static ConfigEntry<float> CameraFov; internal static ConfigEntry<bool> HidePlayerBody; internal static ConfigEntry<bool> ShowZombieName; internal static ConfigEntry<float> HiddenBodyDepth; internal static ConfigEntry<ZombieAppearanceOption> ZombieAppearance; internal static ConfigEntry<bool> VerboseLogging; private readonly Harmony _harmony = new Harmony("com.github.Thanks.ImZombie"); private ZombieController _controller; private bool _switching; private bool _lastTogglePressed; private float _nextPeakStatsRetry; internal static bool Verbose { get { if (VerboseLogging != null) { return VerboseLogging.Value; } return false; } } private void Awake() { Log = ((BaseUnityPlugin)this).Logger; _harmony.PatchAll(typeof(ZombieHarmonyPatches).Assembly); ConfigureOptionalCharacterPatches(); ConfigureOptionalEndgamePatches(); SceneManager.sceneLoaded += OnSceneLoaded; PhotonNetwork.NetworkingClient.EventReceived += OnPhotonEvent; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[I'm a Zombie] Loaded version 1.0.2."); } private void Start() { BindConfig(); } private void BindConfig() { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Expected O, but got Unknown //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Expected O, but got Unknown //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Expected O, but got Unknown //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Expected O, but got Unknown //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Expected O, but got Unknown //IL_03bb: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Expected O, but got Unknown ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ToggleKey", (KeyCode)102, "Press to transform into the game's original zombie (mushroom man). Press again to revert to normal."); AttackKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "AttackKey", (KeyCode)324, "Right-click while in zombie form to lunge forward and bite."); SprintKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "SprintKey", (KeyCode)304, "Hold to sprint (move faster) while in zombie form."); JumpKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "JumpKey", (KeyCode)32, "Press to jump while in zombie form."); CrouchKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "CrouchKey", (KeyCode)306, "Hold to crouch (move slower, lower camera) while in zombie form."); MovementSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Zombie", "MovementSpeed", 12f, new ConfigDescription("How fast the zombie walks with WASD.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>())); SprintMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Zombie", "SprintMultiplier", 2f, new ConfigDescription("Speed multiplier while holding the sprint key.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>())); CrouchMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Zombie", "CrouchMultiplier", 0.5f, new ConfigDescription("Speed multiplier while holding the crouch key.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>())); JumpForce = ((BaseUnityPlugin)this).Config.Bind<float>("Zombie", "JumpForce", 10f, new ConfigDescription("Upward impulse when jumping.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 25f), Array.Empty<object>())); MaxVelocity = ((BaseUnityPlugin)this).Config.Bind<float>("Zombie", "MaxVelocity", 50f, new ConfigDescription("Maximum velocity cap for the zombie ragdoll.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 100f), Array.Empty<object>())); AttackDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "Duration", 1.5f, new ConfigDescription("How long the vanilla-style lunge charge lasts (seconds). Fallback when the zombie prefab's own lungeTime is unavailable.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>())); AttackCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "Cooldown", 1f, new ConfigDescription("Minimum time between attacks (seconds).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>())); AttackRevertSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Attack", "AutoRevertSeconds", 0f, new ConfigDescription("If > 0, auto-revert to normal form this many seconds after attacking. 0 = no auto-revert.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); CameraDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Distance", 2.8f, new ConfigDescription("Third-person zombie camera distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1.5f, 6f), Array.Empty<object>())); CameraHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Height", 0.85f, new ConfigDescription("Third-person camera height offset above the zombie's center.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 1.8f), Array.Empty<object>())); CameraFov = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Fov", 80f, new ConfigDescription("Field of view while in zombie form (game FOV is preserved; this is a fallback only).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(60f, 110f), Array.Empty<object>())); HidePlayerBody = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "HidePlayerBody", true, "Hide the player's original body while in zombie form (synced to all clients)."); ShowZombieName = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "ShowZombieName", false, "Show the player's name on the zombie's nameplate."); HiddenBodyDepth = ((BaseUnityPlugin)this).Config.Bind<float>("Misc", "HiddenBodyDepth", 30f, new ConfigDescription("How far below the player's feet to stash the hidden body while transformed. The body is moved underground and its position keeps being broadcast, so un-modded clients (incl. late joiners) can't see it; lighting stays correct because the local character is swapped to the zombie (on the ground).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 200f), Array.Empty<object>())); ZombieAppearance = ((BaseUnityPlugin)this).Config.Bind<ZombieAppearanceOption>("Misc", "ZombieAppearance", ZombieAppearanceOption.Player, "Zombie appearance: Player = the zombie hides its own lower garments and wears the player's clothes/cosmetics (synced to all clients, incl. un-modded, via PhotonView ownership); Mushroom = pure mushroom-man appearance (un-modded clients will still see it with the player's outfit applied, since they run the vanilla CharacterCustomization"); VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", false, "Enable verbose/diagnostic logging (animator state dumps, NPC prefab animator lists). Off by default to keep the log clean."); } private void ConfigureOptionalCharacterPatches() { TryPatchOptionalMethod(typeof(Character), "RPCA_Die", Type.EmptyTypes, "CharacterRpcDiePrefix", "Character.RPCA_Die()"); TryPatchOptionalMethod(typeof(Character), "RPCA_SetDead", Type.EmptyTypes, "CharacterRpcSetDeadPrefix", "Character.RPCA_SetDead()"); TryPatchOptionalMethod(typeof(Character), "RPCA_PassOut", Type.EmptyTypes, "CharacterRpcPassOutPrefix", "Character.RPCA_PassOut()"); TryPatchOptionalMethod(typeof(Character), "DieInstantly", Type.EmptyTypes, "CharacterDieInstantlyPrefix", "Character.DieInstantly()"); TryPatchOptionalMethod(typeof(Character), "HandleDeath", Type.EmptyTypes, "CharacterHandleDeathPrefix", "Character.HandleDeath()"); TryPatchOptionalMethod(typeof(Character), "WarpPlayer", new Type[2] { typeof(Vector3), typeof(bool) }, "CharacterWarpPlayerPrefix", "Character.WarpPlayer(Vector3,bool)"); TryPatchOptionalMethod(typeof(Character), "Fall", new Type[2] { typeof(float), typeof(float) }, "CharacterFallPrefix", "Character.Fall(float,float)"); TryPatchOptionalMethod(typeof(Character), "RPCA_Fall", new Type[2] { typeof(float), typeof(float) }, "CharacterRpcFallPrefix", "Character.RPCA_Fall(float,float)"); } private void ConfigureOptionalEndgamePatches() { TryPatchOptionalMethod(typeof(GameOverHandler), "BeginAirportLoadRPC", Type.EmptyTypes, "GameOverHandlerBeginAirportLoadRPCPrefix", "GameOverHandler.BeginAirportLoadRPC()"); TryPatchOptionalMethod(typeof(EndScreen), "ReturnToAirport", Type.EmptyTypes, "EndScreenReturnToAirportPrefix", "EndScreen.ReturnToAirport()"); } private void TryPatchOptionalMethod(Type declaringType, string methodName, Type[] parameterTypes, string prefixName, string description) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(declaringType, methodName, parameterTypes, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[I'm a Zombie] Optional " + description + " patch skipped; method not present.")); return; } MethodInfo methodInfo2 = AccessTools.Method(typeof(ZombieHarmonyPatches), prefixName, (Type[])null, (Type[])null); if (methodInfo2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm a Zombie] Optional " + description + " prefix not found.")); } else { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm a Zombie] Optional " + description + " patch failed: " + ex.Message)); } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { try { if (!((Object)(object)_controller == (Object)null) && _controller.Active) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[I'm a Zombie] Scene switched to '" + ((Scene)(ref scene)).name + "' while transformed; force-exiting so the new scene gets a clean player.")); } ForceExit(); } } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[I'm a Zombie] OnSceneLoaded: " + ex.Message)); } } } private void Update() { //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) try { TryInstallPeakStatsGuard(); if ((int)ToggleKey.Value != 0) { bool key = Input.GetKey(ToggleKey.Value); if (key && !_lastTogglePressed) { ToggleZombieForm(); } _lastTogglePressed = key; if ((Object)(object)_controller != (Object)null && _controller.Active && !_controller.IsValid()) { ForceExit(); } } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogError((object)("[I'm a Zombie] Plugin.Update: " + ex)); } } } private void TryInstallPeakStatsGuard() { if (!PeakStatsGuard.IsInstalled && !(Time.unscaledTime < _nextPeakStatsRetry)) { _nextPeakStatsRetry = Time.unscaledTime + 2f; PeakStatsGuard.Install(_harmony); } } private void OnDestroy() { try { SceneManager.sceneLoaded -= OnSceneLoaded; } catch { } try { PhotonNetwork.NetworkingClient.EventReceived -= OnPhotonEvent; } catch { } try { ForceExit(); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm a Zombie] Exit cleanup failed: " + ex.Message)); } } try { _harmony.UnpatchSelf(); } catch (Exception ex2) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[I'm a Zombie] Harmony unpatch failed: " + ex2.Message)); } } } private void OnPhotonEvent(EventData photonEvent) { if (photonEvent.Code != 199) { return; } try { if (photonEvent.CustomData is object[] array && array.Length >= 3 && array[0] is int num && num == 1512112921) { int num2 = (int)array[1]; object obj = array[2]; bool flag = default(bool); int num3; if (obj is bool) { flag = (bool)obj; num3 = 1; } else { num3 = 0; } bool flag2 = (byte)((uint)num3 & (flag ? 1u : 0u)) != 0; PhotonView val = PhotonView.Find(num2); if (!((Object)(object)val == (Object)null)) { SetRenderersVisible(((Component)val).gameObject, !flag2); } } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm a Zombie] Body visibility event failed: " + ex.Message)); } } } internal static void SendBodyVisibility(int viewId, bool hide) { //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_003a: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown try { if (PhotonNetwork.IsConnected) { object[] obj = new object[3] { 1512112921, viewId, hide }; RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)0 }; SendOptions val2 = default(SendOptions); ((SendOptions)(ref val2)).Reliability = true; PhotonNetwork.RaiseEvent((byte)199, (object)obj, val, val2); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm a Zombie] Failed to send body visibility event: " + ex.Message)); } } } internal static void SetRenderersVisible(GameObject root, bool visible) { if ((Object)(object)root == (Object)null) { return; } Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { val.enabled = visible; val.forceRenderingOff = !visible; } } } private void ToggleZombieForm() { if (_switching) { return; } if ((Object)(object)_controller != (Object)null && _controller.Active) { ExitZombie(); return; } Character localCharacter = Character.localCharacter; if (CanTransform(localCharacter)) { _switching = true; ((MonoBehaviour)this).StartCoroutine(EnterZombieRoutine(localCharacter)); } } private static bool CanTransform(Character character) { if ((Object)(object)character == (Object)null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[I'm a Zombie] No local character."); } return false; } if ((Object)(object)character.data == (Object)null || character.refs == null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)"[I'm a Zombie] Character not ready."); } return false; } if (character.data.dead || character.data.passedOut || character.data.fullyPassedOut || character.data.fallSeconds > 0f || character.data.isClimbing || character.data.isRopeClimbing || character.data.isVineClimbing) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)"[I'm a Zombie] Character not in a valid state to transform."); } return false; } if (ZombieController.IsOtherTransformModActive()) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogWarning((object)"[I'm a Zombie] Another transform mod is active (Scoutmaster/Ghost/Tornado…) — exit it first."); } return false; } return true; } private IEnumerator EnterZombieRoutine(Character character) { try { _controller = ((Component)character).gameObject.GetComponent<ZombieController>(); if ((Object)(object)_controller == (Object)null) { _controller = ((Component)character).gameObject.AddComponent<ZombieController>(); } _controller.EnterZombie(character); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogError((object)("[I'm a Zombie] Failed to enter zombie form:\n" + ex)); } _controller = null; } finally { _switching = false; } yield break; } private void ExitZombie() { _switching = true; try { _controller?.ExitZombie(); _controller = null; } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogError((object)("[I'm a Zombie] Failed to exit zombie form:\n" + ex)); } } finally { _switching = false; } } private void ForceExit() { if ((Object)(object)_controller == (Object)null) { return; } try { _controller.ExitZombie(); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[I'm a Zombie] ForceExit: " + ex.Message)); } } _controller = null; } } [DefaultExecutionOrder(-100)] public sealed class ZombieController : MonoBehaviour { private const float ThirdPersonCameraFollowSharpness = 18f; private const float ThirdPersonCameraPositionSharpness = 16f; private const float ThirdPersonCameraRotationSharpness = 22f; private const float ThirdPersonCameraSnapDistance = 8f; private const float ThirdPersonAttackHeightOffset = 0.45f; private const float DefaultCameraDistance = 2.8f; private const float DefaultCameraHeight = 0.85f; private const float DefaultCameraFov = 80f; private const float MaxVelocityConst = 50f; private const float AngularVelocityDamping = 0.92f; private const float MaxAngularVelocity = 10f; private const KeyCode ClimbKey = (KeyCode)323; 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 ClimbStartRayDistance = 1.65f; private const float ClimbAttemptCooldownSeconds = 0.08f; private const float ClimbReleaseFallWindowSeconds = 0.7f; private const float ClimbReleaseFallSeconds = 1.25f; private const float ClimbRepeatedHitDistance = 0.28f; private const float ClimbRepeatedNormalDot = 0.94f; private const float ClimbForwardInputDeadzone = 0.05f; private static readonly MethodInfo ClimbStartClimbRpcMethod = FindClimbStartClimbRpcMethod(); private static readonly FieldInfo ClimbClimbToggledOnField = typeof(CharacterClimbing).GetField("climbToggledOn", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ClimbSinceLastClimbStartedField = typeof(CharacterClimbing).GetField("sinceLastClimbStarted", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ClimbPlayerSlideField = typeof(CharacterClimbing).GetField("playerSlide", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo ClimbCanClimbMethod = typeof(CharacterClimbing).GetMethod("CanClimb", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); private const BindingFlags ClimbReflectFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private float _nextClimbAttemptTime; private float _climbReleaseFallUntil; private bool _hasLastClimbStart; private Vector3 _lastClimbStartPoint; private Vector3 _lastClimbStartNormal = Vector3.forward; private float _nextAnimatorLogTime; private const float DefaultHiddenBodyDepth = 30f; private Character _zombieCharacter; private Character _playerCharacter; private Vector3 _prevCenter; private bool _hasSmoothedCameraPose; private Vector3 _smoothedCameraPosition; private Quaternion _smoothedCameraRotation = Quaternion.identity; private bool _hasSmoothedCameraTarget; private Vector3 _smoothedCameraTarget; private ExitCameraBlend _exitCameraBlend; private const float ExitCameraBlendSeconds = 0.4f; private bool _lastJumpPressed; private bool _lastAttackPressed; private bool _jumpQueued; private bool _attacking; private float _attackStartedAt; private float _lastAttackTime; private GameObject _zombieRoot; private MushroomZombie _mushroomZombie; private PhotonView _zombiePhotonView; private bool _zombieIsNetworked; private bool _playerBodyHidden; private Coroutine _deferredExitRestore; private GameObject _pendingDestroyRoot; private bool _pendingDestroyNetworked; internal static int ExitSfxSuppressedFrame = int.MinValue; private Vector3 _hiddenBodyPos; private bool _hiddenBodyPosSet; private readonly List<MonoBehaviour> _disabledCameraScripts = new List<MonoBehaviour>(); private readonly List<bool> _cameraScriptStates = new List<bool>(); private CharacterMovement _disabledPlayerMovement; private readonly List<Rigidbody> _frozenBodyparts = new List<Rigidbody>(); private readonly List<bool> _frozenKinematic = new List<bool>(); private readonly List<bool> _frozenDetectCollisions = new List<bool>(); private readonly List<bool> _frozenUseGravity = new List<bool>(); private readonly List<Light> _playerLights = new List<Light>(); private readonly List<bool> _playerLightStates = new List<bool>(); private float _nextBodyVisibilityRebroadcast; private const float BodyVisibilityRebroadcastSeconds = 5f; private bool _localCharacterSwapped; private Character _localCharacterSwapTarget; internal const string NetworkVisualMarker = "ImZombie.Visual"; private readonly Dictionary<GameObject, bool> _hiddenHudStates = new Dictionary<GameObject, bool>(); private readonly Dictionary<GameObject, bool> _hiddenHudChildren = new Dictionary<GameObject, bool>(); private bool _hudHidden; private readonly List<Renderer> _playerRenderers = new List<Renderer>(); private readonly List<bool> _playerRendererStates = new List<bool>(); private ZombiePlugin.ZombieAppearanceOption _zombieAppearance; public static Character ActiveZombieCharacter { get; private set; } internal static Character ParkedPlayerCharacter { get; private set; } public bool Active { get; private set; } private static MethodInfo FindClimbStartClimbRpcMethod() { MethodInfo methodInfo = null; MethodInfo[] methods = typeof(CharacterClimbing).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 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[] BuildClimbRpcArguments(MethodInfo method, Vector3 climbPos, Vector3 climbNormal) { //IL_0057: 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 (method == null) { return null; } ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length < 2 || 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; } public bool IsValid() { if (!Active || (Object)(object)_zombieCharacter == (Object)null || (Object)(object)_zombieCharacter.data == (Object)null) { return false; } if (!_zombieCharacter.data.dead) { return !_zombieCharacter.data.fullyPassedOut; } return false; } internal static bool IsOtherTransformModActive() { try { foreach (Character allCharacter in Character.AllCharacters) { if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter.data == (Object)null)) { if (allCharacter.data.isScoutmaster) { return true; } string text = ((Object)allCharacter).name ?? string.Empty; if (text.IndexOf("Scoutmaster", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Ghost", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Tornado", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } } } catch { } return false; } internal static void ForceExitForEndGame() { try { if ((Object)(object)ParkedPlayerCharacter != (Object)null) { ZombieController component = ((Component)ParkedPlayerCharacter).GetComponent<ZombieController>(); if ((Object)(object)component != (Object)null && component.Active) { component.ExitZombie(); return; } } ZombieController[] array = Object.FindObjectsByType<ZombieController>((FindObjectsSortMode)0); foreach (ZombieController zombieController in array) { if ((Object)(object)zombieController != (Object)null && zombieController.Active) { zombieController.ExitZombie(); break; } } } catch (Exception ex) { LogError("ForceExitForEndGame", ex); } } private static void LogInfo(string m) { ZombiePlugin.Log.LogInfo((object)("[ImZombie] " + m)); } private static void LogError(string c, Exception ex) { ZombiePlugin.Log.LogError((object)("[ImZombie] " + c + ": " + ex)); } private static void LogVerbose(string m) { if (ZombiePlugin.Verbose) { ZombiePlugin.Log.LogInfo((object)("[ImZombie][V] " + m)); } } public static bool IsLocalZombieCharacter(Character character) { if ((Object)(object)character == (Object)null || !character.IsLocal) { return false; } ZombieController component = ((Component)character).GetComponent<ZombieController>(); if ((Object)(object)component != (Object)null) { return component.Active; } return false; } public void EnterZombie(Character playerCharacter) { if (Active) { LogInfo("Already in zombie form."); return; } FlushDeferredExitRestore(); StopExitCameraBlend(); _playerCharacter = playerCharacter; FreezePlayerPhysics(); HidePlayerBody(); SendNetworkBodyVisibility(hide: true); GameObject val = SpawnZombiePrefab(playerCharacter); if ((Object)(object)val == (Object)null) { LogInfo("Failed to spawn zombie prefab."); AbortEnterZombie(); return; } _zombieRoot = val; _zombieCharacter = val.GetComponent<Character>(); _mushroomZombie = val.GetComponent<MushroomZombie>(); _zombiePhotonView = val.GetComponent<PhotonView>(); if ((Object)(object)_zombieCharacter == (Object)null) { LogInfo("No Character component on zombie! Aborting."); DestroyZombie(); AbortEnterZombie(); return; } SetupZombieVisuals(); ClearPlayerInput(); InitZombieState(); _attacking = false; _attackStartedAt = 0f; _lastAttackTime = -10f; _lastJumpPressed = false; _lastAttackPressed = false; ResetCameraSmoothing(); Active = true; ActiveZombieCharacter = _zombieCharacter; ParkedPlayerCharacter = _playerCharacter; ((Behaviour)this).enabled = true; try { Character.localCharacter = _zombieCharacter; _localCharacterSwapTarget = _zombieCharacter; _localCharacterSwapped = true; } catch (Exception ex) { LogError("EnterZombie localCharacter swap", ex); } DisableOriginalCameraControl(); HideHud(); WarpPlayerToHiddenPosition(); ((MonoBehaviour)this).StartCoroutine(ReassertOutfitAfterEnter()); ((MonoBehaviour)this).StartCoroutine(PushIdleStateAfterEnter()); _nextBodyVisibilityRebroadcast = Time.unscaledTime + 5f; LogInfo("Entered zombie form."); } private IEnumerator PushIdleStateAfterEnter() { for (int i = 0; i < 4; i++) { yield return (object)new WaitForSeconds(0.2f); if (!Active) { break; } PushZombieStateToRemote(); } } private void PushZombieStateToRemote() { //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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected I4, but got Unknown if ((Object)(object)_zombiePhotonView == (Object)null || !_zombiePhotonView.IsMine || (Object)(object)_zombieCharacter?.data == (Object)null) { return; } try { State val = (State)((!((Object)(object)_mushroomZombie != (Object)null)) ? 2 : ((int)_mushroomZombie.currentState)); _zombiePhotonView.RPC("RPC_SyncState", (RpcTarget)1, new object[4] { (int)val, _zombieCharacter.data.isSprinting, _zombieCharacter.data.fallSeconds, _zombieCharacter.data.passedOut }); } catch (Exception ex) { LogError("PushZombieStateToRemote", ex); } } private IEnumerator ReassertOutfitAfterEnter() { yield return (object)new WaitForSeconds(1.2f); if (!Active || (Object)(object)_mushroomZombie == (Object)null || (Object)(object)_playerCharacter == (Object)null || _zombieAppearance != ZombiePlugin.ZombieAppearanceOption.Mushroom || (Object)(object)_zombiePhotonView == (Object)null || !_zombiePhotonView.IsMine) { yield break; } try { bool playerWearingSkirt = GetPlayerWearingSkirt(); _zombiePhotonView.RPC("RPC_SetOutfit", (RpcTarget)0, new object[1] { playerWearingSkirt }); FieldInfo field = typeof(MushroomZombie).GetField("wearingSkirt", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(_mushroomZombie, playerWearingSkirt); } } catch (Exception ex) { LogError("ReassertOutfitAfterEnter", ex); } } private bool GetPlayerWearingSkirt() { CustomizationRefs val = _playerCharacter?.refs?.customization?.refs; if ((Object)(object)val != (Object)null && (Object)(object)val.skirt != (Object)null && (Object)(object)val.shorts != (Object)null) { if (((Component)val.skirt).gameObject.activeSelf) { return !((Component)val.shorts).gameObject.activeSelf; } return false; } return false; } private void RestoreLocalCharacter() { if (!_localCharacterSwapped) { return; } _localCharacterSwapped = false; try { if ((Object)(object)_playerCharacter != (Object)null && (Object)(object)Character.localCharacter == (Object)(object)_localCharacterSwapTarget) { Character.localCharacter = _playerCharacter; } _localCharacterSwapTarget = null; } catch (Exception ex) { LogError("RestoreLocalCharacter", ex); } } private void AbortEnterZombie() { RestoreLocalCharacter(); RestorePlayerPhysics(); RestorePlayerBody(); SendNetworkBodyVisibility(hide: false); RestoreOriginalCameraControl(); RestoreHud(); _playerCharacter = null; _playerBodyHidden = false; _hiddenBodyPosSet = false; ParkedPlayerCharacter = null; } public void ExitZombie() { //IL_0183: 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_002c: 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_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_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_00d8: 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_00ef: 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_0107: 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_014b: Unknown result type (might be due to invalid IL or missing references) if (!Active && (Object)(object)_zombieRoot == (Object)null) { return; } ExitSfxSuppressedFrame = Time.frameCount; Vector3 val = Vector3.zero; Vector2 lookValues = Vector2.zero; bool flag = false; if ((Object)(object)_zombieCharacter != (Object)null && (Object)(object)_zombieCharacter.data != (Object)null) { val = _zombieCharacter.Center + Vector3.up * 0.25f; lookValues = _zombieCharacter.data.lookValues; flag = true; } Active = false; ActiveZombieCharacter = null; ((Behaviour)this).enabled = false; _hiddenBodyPosSet = false; _attacking = false; _attackStartedAt = 0f; DeactivateZombieForDeferredDestroy(); if (flag && (Object)(object)_playerCharacter != (Object)null) { _playerCharacter.data.lookValues = lookValues; RecalculateLookDirections(_playerCharacter); ResetPlayerState(_playerCharacter, val); SetCharacterPositionImmediate(_playerCharacter, val, ((Component)_playerCharacter).transform.rotation); try { if ((Object)(object)((MonoBehaviourPun)_playerCharacter).photonView != (Object)null && (PhotonNetwork.InRoom || PhotonNetwork.IsConnected)) { ((MonoBehaviourPun)_playerCharacter).photonView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { val, false }); } else { _playerCharacter.WarpPlayerRPC(val, false); } } catch (Exception ex) { LogError("ExitZombie warp", ex); _playerCharacter.WarpPlayerRPC(val, false); } } RestorePlayerPhysics(); RestoreLocalCharacter(); SendNetworkBodyVisibility(hide: false); RestoreOriginalCameraControl(); StartExitCameraBlend(); ParkedPlayerCharacter = null; if (_deferredExitRestore != null) { try { ((MonoBehaviour)this).StopCoroutine(_deferredExitRestore); } catch { } } _deferredExitRestore = ((MonoBehaviour)this).StartCoroutine(DeferredExitRestoreRoutine()); LogInfo("Exited zombie form."); } private IEnumerator DeferredExitRestoreRoutine() { yield return null; _deferredExitRestore = null; DestroyDeactivatedZombie(); RestorePlayerBody(); yield return null; RestoreHud(); } internal void FlushDeferredExitRestore() { if (_deferredExitRestore != null) { try { ((MonoBehaviour)this).StopCoroutine(_deferredExitRestore); } catch { } _deferredExitRestore = null; } DestroyDeactivatedZombie(); RestorePlayerBody(); RestoreHud(); } private void OnDestroy() { FlushDeferredExitRestore(); StopExitCameraBlend(); if (Active) { Active = false; ActiveZombieCharacter = null; _hiddenBodyPosSet = false; DestroyZombie(); RestoreOriginalCameraControl(); RestorePlayerPhysics(); RestorePlayerBody(); RestoreLocalCharacter(); SendNetworkBodyVisibility(hide: false); RestoreHud(); ParkedPlayerCharacter = null; } } private void InitZombieState() { //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) try { _zombieCharacter.data.currentRagdollControll = 1f; _zombieCharacter.data.dead = false; _zombieCharacter.data.passedOut = false; _zombieCharacter.data.fullyPassedOut = false; _zombieCharacter.data.fallSeconds = 0f; _zombieCharacter.data.zombified = false; _zombieCharacter.data.isSprinting = false; _zombieCharacter.data.isCrouching = false; CharacterData data = _zombieCharacter.data; Character playerCharacter = _playerCharacter; float? obj; if (playerCharacter == null) { obj = null; } else { CharacterData data2 = playerCharacter.data; obj = ((data2 != null) ? new float?(data2.currentStamina) : ((float?)null)); } data.currentStamina = obj ?? 1f; _zombieCharacter.data.extraStamina = 0f; try { CharacterMovement component = ((Component)_zombieCharacter).GetComponent<CharacterMovement>(); CharacterMovement val = (((Object)(object)_playerCharacter != (Object)null) ? ((Component)_playerCharacter).GetComponent<CharacterMovement>() : null); if ((Object)(object)component != (Object)null && (Object)(object)val != (Object)null) { component.sprintStaminaUsage = val.sprintStaminaUsage; component.jumpStaminaUsage = val.jumpStaminaUsage; component.jumpStaminaUsageSprinting = val.jumpStaminaUsageSprinting; } } catch (Exception ex) { LogError("InitZombieState stamina rates", ex); } try { _zombieCharacter.InitializeRefs(); if (_zombieCharacter.refs != null && (Object)(object)_zombieCharacter.refs.customization == (Object)null) { _zombieCharacter.refs.customization = ((Component)_zombieCharacter).GetComponentInChildren<CharacterCustomization>(true); } _zombieCharacter.isBot = false; } catch (Exception ex2) { LogError("InitZombieState refs", ex2); } if ((Object)(object)_playerCharacter != (Object)null && (Object)(object)_playerCharacter.data != (Object)null) { _zombieCharacter.data.lookValues = _playerCharacter.data.lookValues; RecalculateLookDirections(_zombieCharacter); } if (_zombieCharacter.refs != null && (Object)(object)_zombieCharacter.refs.ragdoll != (Object)null) { _zombieCharacter.refs.ragdoll.ToggleKinematic(false); CopyPlayerPoseToZombie(); WakeZombieRagdoll(); } } catch (Exception ex3) { LogError("InitZombieState", ex3); } } private void CopyPlayerPoseToZombie() { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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) if (_playerCharacter?.refs?.ragdoll?.partList == null || _zombieCharacter?.refs?.ragdoll?.partList == null) { return; } foreach (Bodypart part in _zombieCharacter.refs.ragdoll.partList) { if (!((Object)(object)part == (Object)null) && !((Object)(object)part.Rig == (Object)null)) { Bodypart val = FindBodypart(_playerCharacter, part.partType); if (!((Object)(object)val == (Object)null) && !((Object)(object)val.Rig == (Object)null)) { part.Rig.MovePosition(val.Rig.position); part.Rig.MoveRotation(val.Rig.rotation); } } } } private static Bodypart FindBodypart(Character character, BodypartType type) { //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) if (character?.refs?.ragdoll?.partList == null) { return null; } foreach (Bodypart part in character.refs.ragdoll.partList) { if ((Object)(object)part != (Object)null && part.partType == type) { return part; } } return null; } private void WakeZombieRagdoll() { if (_zombieCharacter?.refs?.ragdoll?.partList == null) { return; } foreach (Bodypart part in _zombieCharacter.refs.ragdoll.partList) { Rigidbody val = ((part != null) ? part.Rig : null); if (!((Object)(object)val == (Object)null)) { val.isKinematic = false; val.detectCollisions = true; val.useGravity = true; val.WakeUp(); } } } private GameObject SpawnZombiePrefab(Character playerCharacter) { //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_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_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_0182: 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) Vector3 center = playerCharacter.Center; Quaternion rotation = ((Component)playerCharacter).transform.rotation; _zombieAppearance = GetAppearance(); bool flag = _zombieAppearance == ZombiePlugin.ZombieAppearanceOption.Player; string text = (flag ? "MushroomZombie_Player" : "MushroomZombie"); if (PhotonNetwork.InRoom && (Object)(object)((MonoBehaviourPun)playerCharacter).photonView != (Object)null && ((MonoBehaviourPun)playerCharacter).photonView.ViewID > 0) { try { GameObject val = PhotonNetwork.Instantiate(text, center, rotation, (byte)0, new object[3] { "ImZombie.Visual", ((MonoBehaviourPun)playerCharacter).photonView.ViewID, (int)_zombieAppearance }); if ((Object)(object)val != (Object)null) { ((Object)val).name = "ImZombieNetworked"; _zombieIsNetworked = true; LogInfo("Spawned networked zombie (" + text + ")."); return val; } } catch (Exception ex) { LogError("PhotonNetwork.Instantiate " + text, ex); } } try { GameObject val2 = Resources.Load<GameObject>(text); if ((Object)(object)val2 == (Object)null) { val2 = Resources.Load<GameObject>("PhotonPrefabs/" + text); } if ((Object)(object)val2 == (Object)null && !flag) { val2 = Resources.Load<GameObject>("MushroomZombie_Player"); } if ((Object)(object)val2 == (Object)null) { val2 = Resources.Load<GameObject>("PhotonPrefabs/MushroomZombie_Player"); } if ((Object)(object)val2 == (Object)null) { val2 = Resources.Load<GameObject>("MushroomZombie"); } if ((Object)(object)val2 == (Object)null) { LogInfo("Could not find zombie prefab via Resources.Load (" + text + ")."); return null; } GameObject obj = Object.Instantiate<GameObject>(val2, center, rotation); ((Object)obj).name = "ImZombieLocal"; _zombieIsNetworked = false; LogInfo("Spawned local zombie prefab (" + ((Object)val2).name + ")."); return obj; } catch (Exception ex2) { LogError("Resources.Load zombie prefab", ex2); return null; } } private void SetupZombieVisuals() { if ((Object)(object)_mushroomZombie == (Object)null) { return; } try { _mushroomZombie.isNPCZombie = false; _mushroomZombie.initialWakeUpTime = 0f; _mushroomZombie.currentState = (State)2; _mushroomZombie.lifetime = 9999f; MethodInfo method = typeof(MushroomZombie).GetMethod("FadeInRenderers", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { method.Invoke(_mushroomZombie, null); } MethodInfo method2 = typeof(MushroomZombie).GetMethod("SetZombieEyes", BindingFlags.Instance | BindingFlags.NonPublic); if (method2 != null) { method2.Invoke(_mushroomZombie, null); } ApplyZombieAnimator(); ApplyZombieOutfit(); } catch (Exception ex) { LogError("SetupZombieVisuals", ex); } } private void ApplyZombieAnimator() { if ((Object)(object)_zombieCharacter?.refs?.animator == (Object)null) { LogInfo("ApplyZombieAnimator: no zombie animator."); return; } try { GameObject val = null; try { object prefabPool = PhotonNetwork.PrefabPool; if (prefabPool != null) { MethodInfo method = prefabPool.GetType().GetMethod("LoadPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { object? obj = method.Invoke(prefabPool, new object[1] { "MushroomZombie" }); val = (GameObject)((obj is GameObject) ? obj : null); } } } catch (Exception ex) { LogError("ApplyZombieAnimator pool", ex); } if ((Object)(object)val == (Object)null) { val = Resources.Load<GameObject>("MushroomZombie"); } if ((Object)(object)val == (Object)null) { val = Resources.Load<GameObject>("PhotonPrefabs/MushroomZombie"); } if ((Object)(object)val == (Object)null) { LogInfo("ApplyZombieAnimator: NPC prefab not found (pool+resources)."); return; } Animator componentInChildren = val.GetComponentInChildren<Animator>(true); if ((Object)(object)componentInChildren == (Object)null || (Object)(object)componentInChildren.runtimeAnimatorController == (Object)null) { LogInfo("ApplyZombieAnimator: NPC animator/controller missing."); return; } if (ZombiePlugin.Verbose) { try { string text = string.Join(",", Array.ConvertAll(val.GetComponentsInChildren<Animator>(true), (Animator a) => (!((Object)(object)a.runtimeAnimatorController != (Object)null)) ? "null" : ((Object)a.runtimeAnimatorController).name)); LogVerbose("ApplyZombieAnimator: NPC prefab animators=[" + text + "]"); } catch { } } string text2 = (((Object)(object)_zombieCharacter.refs.animator.runtimeAnimatorController != (Object)null) ? ((Object)_zombieCharacter.refs.animator.runtimeAnimatorController).name : "null"); _zombieCharacter.refs.animator.runtimeAnimatorController = componentInChildren.runtimeAnimatorController; LogInfo("ApplyZombieAnimator: switched " + text2 + " -> " + ((Object)componentInChildren.runtimeAnimatorController).name); } catch (Exception ex2) { LogError("ApplyZombieAnimator", ex2); } } private void LogAnimatorDiagnostics() { if (!ZombiePlugin.Verbose || (Object)(object)_zombieCharacter?.refs?.animator == (Object)null || Time.time < _nextAnimatorLogTime) { return; } _nextAnimatorLogTime = Time.time + 2f; try { string text = (((Object)(object)_zombieCharacter.refs.animator.runtimeAnimatorController != (Object)null) ? ((Object)_zombieCharacter.refs.animator.runtimeAnimatorController).name : "null"); LogInfo("AnimatorDiag: ctrl=" + text + " input=" + (((Object)(object)_zombieCharacter.input != (Object)null) ? ((object)Unsafe.As<Vector2, Vector2>(ref _zombieCharacter.input.movementInput)/*cast due to .constrained prefix*/).ToString() : "null") + " sprint=" + _zombieCharacter.data.isSprinting + " vel=" + ((object)Unsafe.As<Vector3, Vector3>(ref _zombieCharacter.data.avarageVelocity)/*cast due to .constrained prefix*/).ToString() + " grounded=" + _zombieCharacter.data.isGrounded + " sinceGrounded=" + _zombieCharacter.data.sinceGrounded + " animators=[" + string.Join(",", Array.ConvertAll(((Component)_zombieCharacter).GetComponentsInChildren<Animator>(true), (Animator a) => (!((Object)(object)a.runtimeAnimatorController != (Object)null)) ? "null" : ((Object)a.runtimeAnimatorController).name)) + "]"); } catch (Exception ex) { LogError("LogAnimatorDiagnostics", ex); } } private void ApplyZombieOutfit() { if ((Object)(object)_mushroomZombie == (Object)null || (Object)(object)_playerCharacter == (Object)null) { return; } try { if (_zombieAppearance == ZombiePlugin.ZombieAppearanceOption.Player) { if ((Object)(object)_zombieCharacter?.refs?.customization != (Object)null) { CharacterCustomization customization = _zombieCharacter.refs.customization; PhotonView photonView = ((MonoBehaviourPun)_playerCharacter).photonView; customization.overridePhotonPlayer = ((photonView != null) ? photonView.Owner : null); _zombieCharacter.refs.customization.ignorePlayerCosmetics = false; } try { if ((Object)(object)_zombieCharacter?.refs?.customization?.refs != (Object)null) { _zombieCharacter.refs.customization.refs.SetMushroomMan(false); } } catch { } HideMushroomParts(); FieldInfo field = typeof(MushroomZombie).GetField("wearingSkirt", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(_mushroomZombie, false); } return; } if ((Object)(object)_zombieCharacter?.refs?.customization != (Object)null) { _zombieCharacter.refs.customization.overridePhotonPlayer = null; _zombieCharacter.refs.customization.ignorePlayerCosmetics = true; } bool playerWearingSkirt = GetPlayerWearingSkirt(); if ((Object)(object)_zombiePhotonView != (Object)null && _zombiePhotonView.IsMine) { try { _zombiePhotonView.RPC("RPC_SetOutfit", (RpcTarget)0, new object[1] { playerWearingSkirt }); } catch { } } if ((Object)(object)_mushroomZombie.skirt != (Object)null) { _mushroomZombie.skirt.SetActive(playerWearingSkirt); } if ((Object)(object)_mushroomZombie.shorts != (Object)null) { _mushroomZombie.shorts.SetActive(!playerWearingSkirt); } FieldInfo field2 = typeof(MushroomZombie).GetField("wearingSkirt", BindingFlags.Instance | BindingFlags.NonPublic); if (field2 != null) { field2.SetValue(_mushroomZombie, playerWearingSkirt); } } catch (Exception ex) { LogError("ApplyZombieOutfit", ex); } } private void HideMushroomParts() { if ((Object)(object)_mushroomZombie == (Object)null) { return; } try { if ((Object)(object)_mushroomZombie.skirt != (Object)null) { _mushroomZombie.skirt.SetActive(false); } if ((Object)(object)_mushroomZombie.shorts != (Object)null) { _mushroomZombie.shorts.SetActive(false); } if (_mushroomZombie.mushroomVisuals != null) { foreach (GameObject mushroomVisual in _mushroomZombie.mushroomVisuals) { if ((Object)(object)mushroomVisual != (Object)null) { mushroomVisual.SetActive(false); } } } CustomizationRefs val = _zombieCharacter?.refs?.customization?.refs; if ((Object)(object)val != (Object)null) { if ((Object)(object)val.skirt != (Object)null) { ((Component)val.skirt).gameObject.SetActive(false); } if ((Object)(object)val.shorts != (Object)null) { ((Component)val.shorts).gameObject.SetActive(false); } if ((Object)(object)val.skirtShadow != (Object)null) { ((Component)val.skirtShadow).gameObject.SetActive(false); } if ((Object)(object)val.shortsShadow != (Object)null) { ((Component)val.shortsShadow).gameObject.SetActive(false); } if ((Object)(object)val.sashRenderer != (Object)null) { val.sashRenderer.enabled = false; } if ((Object)(object)val.accessoryRenderer != (Object)null) { val.accessoryRenderer.enabled = false; } } } catch (Exception ex) { LogError("HideMushroomParts", ex); } } private void FreezePlayerPhysics() { //IL_00d1: 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)_playerCharacter?.refs?.ragdoll == (Object)null) { return; } try { _frozenBodyparts.Clear(); _frozenKinematic.Clear(); _frozenDetectCollisions.Clear(); _frozenUseGravity.Clear(); foreach (Bodypart part in _playerCharacter.refs.ragdoll.partList) { Rigidbody val = ((part != null) ? part.Rig : null); if (!((Object)(object)val == (Object)null)) { _frozenBodyparts.Add(val); _frozenKinematic.Add(val.isKinematic); _frozenDetectCollisions.Add(val.detectCollisions); _frozenUseGravity.Add(val.useGravity); val.linearVelocity = Vector3.zero; val.angularVelocity = Vector3.zero; val.detectCollisions = false; val.useGravity = false; val.isKinematic = true; } } _disabledPlayerMovement = ((Component)_playerCharacter).GetComponent<CharacterMovement>(); if ((Object)(object)_disabledPlayerMovement != (Object)null && ((Behaviour)_disabledPlayerMovement).enabled) { ((Behaviour)_disabledPlayerMovement).enabled = false; } } catch (Exception ex) { LogError("FreezePlayerPhysics", ex); } } private void RestorePlayerPhysics() { //IL_00a8: 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) try { if ((Object)(object)_disabledPlayerMovement != (Object)null) { ((Behaviour)_disabledPlayerMovement).enabled = true; _disabledPlayerMovement = null; } for (int i = 0; i < _frozenBodyparts.Count; i++) { Rigidbody val = _frozenBodyparts[i]; if (!((Object)(object)val == (Object)null)) { val.isKinematic = i < _frozenKinematic.Count && _frozenKinematic[i]; val.detectCollisions = i < _frozenDetectCollisions.Count && _frozenDetectCollisions[i]; val.useGravity = i < _frozenUseGravity.Count && _frozenUseGravity[i]; val.linearVelocity = Vector3.zero; val.angularVelocity = Vector3.zero; } } _frozenBodyparts.Clear(); _frozenKinematic.Clear(); _frozenDetectCollisions.Clear(); _frozenUseGravity.Clear(); } catch (Exception ex) { LogError("RestorePlayerPhysics", ex); } } private void SendNetworkBodyVisibility(bool hide) { Character playerCharacter = _playerCharacter; if (!((Object)(object)((playerCharacter != null) ? ((MonoBehaviourPun)playerCharacter).photonView : null) == (Object)null) && (PhotonNetwork.InRoom || PhotonNetwork.IsConnected)) { ZombiePlugin.SendBodyVisibility(((MonoBehaviourPun)_playerCharacter).photonView.ViewID, hide); } } private void WarpPlayerToHiddenPosition() { //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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_003f: 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_0057: 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) if ((Object)(object)_playerCharacter == (Object)null) { return; } try { Vector3 val = (_hiddenBodyPos = _playerCharacter.Center + Vector3.down * GetHiddenBodyDepth()); _hiddenBodyPosSet = true; ResetPlayerBodyFallState(val); SetCharacterPositionImmediate(_playerCharacter, val, ((Component)_playerCharacter).transform.rotation); LogInfo($"Player body stashed underground ({val.y:F0}m)."); } catch (Exception ex) { LogError("WarpPlayerToHiddenPosition", ex); } } private void ResetPlayerBodyFallState(Vector3 groundPosition) { //IL_007e: 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) if ((Object)(object)_playerCharacter?.data == (Object)null) { return; } try { CharacterData data = _playerCharacter.data; data.dead = false; data.zombified = false; data.passedOut = false; data.fullyPassedOut = false; data.fallSeconds = 0f; data.deathTimer = 0f; data.currentRagdollControll = 1f; data.isGrounded = true; data.isJumping = false; data.sinceGrounded = 0f; data.groundPos = groundPosition; data.sinceJump = 0f; } catch (Exception ex) { LogError("ResetPlayerBodyFallState", ex); } } private static void SetCharacterPositionImmediate(Character character, Vector3 position, Quaternion rotation) { //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_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_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_0033: 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_002a: 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_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_004e: 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_0050: 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_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_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) //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_0155: 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) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0164: 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_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_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: 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_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: 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_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_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_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_0105: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0142: 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; Quaternion rotation2 = transform.rotation; if (!IsFiniteQuaternion(rotation)) { rotation = rotation2; } Vector3 val = character.Center; if (!IsFiniteVector(val)) { val = transform.position; } 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 = part.transform.position; part.transform.position = position + val2 * (position3 - val); part.transform.rotation = val2 * part.transform.rotation; } } } catch (Exception ex) { LogError("SetCharacterPositionImmediate", ex); } } private void HidePlayerBody() { if ((Object)(object)_playerCharacter == (Object)null || _playerCharacter.refs == null || !ZombiePlugin.HidePlayerBody.Value) { return; } _playerRenderers.Clear(); _playerRendererStates.Clear(); try { Renderer[] componentsInChildren = ((Component)_playerCharacter).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { _playerRenderers.Add(val); _playerRendererStates.Add(val.enabled); val.enabled = false; val.forceRenderingOff = true; SetRendererMaterialFloat(val, "_VertexGhost", 1f); SetRendererMaterialFloat(val, "_Opacity", 0f); SetRendererMaterialFloat(val, "_Alpha", 0f); } } _playerLights.Clear(); _playerLightStates.Clear(); Light[] componentsInChildren2 = ((Component)_playerCharacter).GetComponentsInChildren<Light>(true); foreach (Light val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null)) { _playerLights.Add(val2); _playerLightStates.Add(((Behaviour)val2).enabled); ((Behaviour)val2).enabled = false; } } _playerBodyHidden = true; } catch (Exception ex) { LogError("HidePlayerBody", ex); } } private void RestorePlayerBody() { if (_playerBodyHidden) { try { for (int i = 0; i < _playerRenderers.Count && i < _playerRendererStates.Count; i++) { Renderer val = _playerRenderers[i]; if (!((Object)(object)val == (Object)null)) { val.enabled = _playerRendererStates[i]; val.forceRenderingOff = false; if (val.enabled) { SetRendererMaterialFloat(val, "_VertexGhost", 0f); SetRendererMaterialFloat(val, "_Opacity", 1f); SetRendererMaterialFloat(val, "_Alpha", 1f); } } } } catch (Exception ex) { LogError("RestorePlayerBody", ex); } _playerRenderers.Clear(); _playerRendererStates.Clear(); _playerBodyHidden = false; } try { for (int j = 0; j < _playerLights.Count && j < _playerLightStates.Count; j++) { Light val2 = _playerLights[j]; if ((Object)(object)val2 != (Object)null) { ((Behaviour)val2).enabled = _playerLightStates[j]; } } _playerLights.Clear(); _playerLightStates.Clear(); } catch (Exception ex2) { LogError("RestorePlayerBody lights", ex2); } try { if ((Object)(object)_playerCharacter != (Object)null && _playerCharacter.refs != null && (Object)(object)_playerCharacter.refs.customization != (Object)null) { _playerCharacter.refs.customization.ShowAllRenderers(); if ((Object)(object)_playerCharacter.refs.customization.refs != (Object)null) { _playerCharacter.refs.customization.refs.SetMushroomMan(false); } } if ((Object)(object)_playerCharacter != (Object)null && _playerCharacter.refs != null && (Object)(object)_playerCharacter.refs.hideTheBody != (Object)null) { _playerCharacter.refs.hideTheBody.Refresh(); } } catch (Exception ex3) { LogError("RestorePlayerBodyPresentation", ex3); } } private static void SetRendererMaterialFloat(Renderer renderer, string propertyName, float value) { if ((Object)(object)renderer == (Object)null) { return; } try { Material[] materials = renderer.materials; bool flag = false; for (int i = 0; i < materials.Length; i++) { if (!((Object)(object)materials[i] == (Object)null) && materials[i].HasProperty(propertyName)) { materials[i].SetFloat(propertyName, value); flag = true; } } if (flag) { renderer.materials = materials; } } catch { } } internal static bool IsControlledZombieHideTheBody(HideTheBody hideTheBody, Character fallbackCharacter) { if ((Object)(object)hideTheBody == (Object)null) { return false; } Character activeZombieCharacter = ActiveZombieCharacter; if ((Object)(object)activeZombieCharacter != (Object)null) { if ((Object)(object)fallbackCharacter != (Object)null && (Object)(object)fallbackCharacter == (Object)(object)activeZombieCharacter) { return true; } try { Character componentInParent = ((Component)hideTheBody).GetComponentInParent<Character>(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent == (Object)(object)activeZombieCharacter) { return true; } } catch { } } try { Character componentInParent2 = ((Component)hideTheBody).GetComponentInParent<Character>(); if ((Object)(object)componentInParent2 == (Object)null) { return false; } if ((Object)(object)fallbackCharacter != (Object)null && IsNetworkZombieCharacter(fallbackCharacter)) { return true; } return IsNetworkZombieCharacter(componentInParent2); } catch { return false; } } internal static bool IsNetworkZombieCharacter(Character character) { if ((Object)(object)character == (Object)null) { return false; } try { PhotonView componentInParent = ((Component)character).GetComponentInParent<PhotonView>(); object[] array = (((Object)(object)componentInParent != (Object)null) ? componentInParent.InstantiationData : null); return array != null && array.Length != 0 && array[0] is string text && text == "ImZombie.Visual"; } catch { return false; } } internal static void RevealHideTheBody(HideTheBody hideTheBody) { if ((Object)(object)hideTheBody == (Object)null) { return; } try { RevealRenderer((Renderer)(object)hideTheBody.body); RevealRenderer(hideTheBody.headRend); RevealRenderer((Renderer)(object)hideTheBody.sash); if (hideTheBody.costumes != null) { SkinnedMeshRenderer[] costumes = hideTheBody.costumes; for (int i = 0; i < costumes.Length; i++) { RevealRenderer((Renderer)(object)costumes[i]); } } if ((Object)(object)hideTheBody.face != (Object)null) { Renderer[] componentsInChildren = ((Component)hideTheBody.face).GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { RevealRenderer(componentsInChildren[i]); } } if ((Object)(object)hideTheBody.refs != (Object)null && hideTheBody.refs.playerHats != null) { Renderer[] componentsInChildren = hideTheBody.refs.playerHats; for (int i = 0; i < componentsInChildren.Length; i++) { RevealRenderer(componentsInChildren[i]); } } } catch { } } private static void RevealRenderer(Renderer renderer) { if ((Object)(object)renderer == (Object)null) { return; } try { Material sharedMaterial = renderer.sharedMaterial; if ((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_VertexGhost") && sharedMaterial.GetFloat("_VertexGhost") <= 0.01f) { return; } } catch { return; } SetRendererMaterialFloat(renderer, "_VertexGhost", 0f); SetRendererMaterialFloat(renderer, "_Opacity", 1f); SetRendererMaterialFloat(renderer, "_Alpha", 1f); } private static void ResetPlayerState(Character character, Vector3 restorePosition) { //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_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_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)character == (Object)null || (Object)(object)character.data == (Object)null) { return; } try { CharacterData data = character.data; data.dead = false; data.zombified = false; data.passedOut = false; data.fullyPassedOut = false; data.fallSeconds = 0f; data.deathTimer = 0f; data.currentRagdollControll = 1f; data.isSprinting = false; data.isCrouching = false; character.isZombie = false; data.isGrounded = false; data.groundedFor = 0f; data.sinceGrounded = 0f; data.groundPos = restorePosition; data.isJumping = false; data.sinceJump = 0f; data.avarageVelocity = Vector3.zero; data.avarageLastFrameVelocity = Vector3.zero; data.sincePalJump = 10f; data.sinceStandOnPlayer = 10f; data.lastStoodOnPlayer = null; data.launchedByCannon = false; } catch (Exception ex) { LogError("ResetPlayerState", ex); } } private void ClearPlayerInput() { //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_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_playerCharacter == (Object)null) && !((Object)(object)_playerCharacter.input == (Object)null)) { _playerCharacter.input.movementInput = Vector2.zero; _playerCharacter.input.jumpWasPressed = false; _playerCharacter.input.jumpIsPressed = false; _playerCharacter.input.sprintIsPressed = false; _playerCharacter.input.sprintWasPressed = false; _playerCharacter.input.sprintToggleWasPressed = false; _playerCharacter.input.usePrimaryWasPressed = false; _playerCharacter.input.usePrimaryIsPressed = false; _playerCharacter.input.useSecondaryWasPressed = false; _playerCharacter.input.useSecondaryIsPressed = false; _playerCharacter.input.crouchWasPressed = false; _playerCharacter.input.crouchIsPressed = false; _playerCharacter.input.crouchToggleWasPressed = false; _playerCharacter.input.interactWasPressed = false; _playerCharacter.input.interactIsPressed = false; _playerCharacter.input.lookInput = Vector2.zero; } } private void DestroyZombie() { DeactivateZombieForDeferredDestroy(); DestroyDeactivatedZombie(); } private void DeactivateZombieForDeferredDestroy() { if ((Object)(object)_mushroomZombie != (Object)null) { ZombieHarmonyPatches.ClearAttackMouth(_mushroomZombie); } try { AudioSource val = (((Object)(object)_mushroomZombie != (Object)null) ? _mushroomZombie.gruntSource : null); if ((Object)(object)val != (Object)null && val.isPlaying) { val.Stop(); } } catch { } if ((Object)(object)_zombieRoot != (Object)null) { _pendingDestroyRoot = _zombieRoot; _pendingDestroyNetworked = _zombieIsNetworked; try { _zombieRoot.SetActive(false); } catch { } } _zombieRoot = null; _zombieCharacter = null; _mushroomZombie = null; _zombiePhotonView = null; _zombieIsNetworked = false; } private void DestroyDeactivatedZombie() { GameObject pendingDestroyRoot = _pendingDestroyRoot; _pendingDestroyRoot = null; if ((Object)(object)pendingDestroyRoot == (Object)null) { return; } try { if (_pendingDestroyNetworked && PhotonNetwork.InRoom) { PhotonNetwork.Destroy(pendingDestroyRoot); } else { Object.Destroy((Object)(object)pendingDestroyRoot); } } catch (Exception ex) { LogError("DestroyDeactivatedZombie", ex); } } private void Update() { if (!Active || (Object)(object)_zombieCharacter == (Object)null) { return; } try { ClearPlayerInput(); KeepZombieAlive(); PinHiddenBody(); if (Time.unscaledTime >= _nextBodyVisibilityRebroadcast) { _nextBodyVisibilityRebroadcast = Time.unscaledTime + 5f; SendNetworkBodyVisibility(hide: true); } DriveZombieInput(); UpdateAttack(); if (!Active) { return; } if (_localCharacterSwapped && (Object)(object)Character.localCharacter != (Object)(object)_zombieCharacter) { try { Character.localCharacter = _zombieCharacter; } catch { } } if (IsCharacterClimbing()) { StabilizeControlledClimb(); } EnsureClimbSurfaceStillValid(); LogAnimatorDiagnostics(); HideHud(); } catch (Exception ex) { LogError("Update", ex); } } private void FixedUpdate() { if (!Active || (Object)(object)_zombieCharacter == (Object)null || _zombieCharacter.refs == null || (Object)(object)_zombieCharacter.refs.ragdoll == (Object)null) { return; } try { if (IsCharacterClimbing()) { StabilizeControlledClimb(); } if (_jumpQueued && !ViewIsMine()) { _jumpQueued = false; if (_zombieCharacter.data.isGrounded && _zombieCharacter.data.jumpsRemaining > 0) { ApplyJumpImpulse(); } } } catch (Exception ex) { LogError("FixedUpdate", ex); } } private void ApplyJumpImpulse() { //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_005d: Unknown result type (might be due to invalid IL or missing references) float value = ZombiePlugin.JumpForce.Value; foreach (Bodypart part in _zombieCharacter.refs.ragdoll.partList) { Rigidbody val = ((part != null) ? part.Rig : null); if (!((Object)(object)val == (Object)null) && !val.isKinematic) { Vector3 linearVelocity = val.linearVelocity; linearVelocity.y = value; val.linearVelocity = linearVelocity; } } CharacterData data = _zombieCharacter.data; data.jumpsRemaining--; _zombieCharacter.data.sinceJump = 0f; } private void LateUpdate() { if (!Active || (Object)(object)_zombieCharacter == (Object)null) { return; } try { PinHiddenBody(); SyncCharacterData(); if ((Object)(object)_mushroomZombie != (Object)null) { ZombieHarmonyPatches.UpdateControlledMouth(_mushroomZombie); } RefreshCamera(); } catch (Exception ex) { LogError("LateUpdate", ex); } } private void DriveZombieInput() { //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) //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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_00f5: 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_011c: 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) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Invalid comparison between Unknown and I4 if ((Object)(object)_zombieCharacter.input == (Object)null) { return; } _zombieCharacter.input.lookInput = ReadLookDelta(); Vector2 val = GetMovementInput(); bool flag = Input.GetKey(ZombiePlugin.JumpKey.Value); bool sprintIsPressed = Input.GetKey(ZombiePlugin.SprintKey.Value); bool key = Input.GetKey(ZombiePlugin.CrouchKey.Value); bool flag2 = (int)ZombiePlugin.AttackKey.Value != 0 && Input.GetKey(ZombiePlugin.AttackKey.Value); bool num = flag && !_lastJumpPressed; bool flag3 = flag2 && !_lastAttackPressed; _lastJumpPressed = flag; _lastAttackPressed = flag2; bool flag4 = _zombieCharacter.data.fallSeconds > 0f; bool flag5 = IsCharacterClimbing(); if (_attacking) { ((Vector2)(ref val))..ctor(0f, 1.2f); sprintIsPressed = true; flag = false; } else if (flag5) { val.y = Mathf.Max(val.y, 1f); sprintIsPressed = false; flag = false; flag3 = false; } else if (flag4) { val = Vector2.zero; sprintIsPressed = false; flag = false; } if (!_attacking && !flag4 && (Object)(object)_mushroomZombie != (Object)null && (int)_mushroomZombie.currentState == 5) { _mushroomZombie.currentState = (State)2; } _zombieCharacter.input.movementInput = val; _zombieCharacter.input.jumpIsPressed = flag && !_attacking && !flag4; bool flag6 = num && !_attacking && !flag4; if (ViewIsMine()) { _zombieCharacter.input.jumpWasPressed = flag6; _jumpQueued = false; } else { _zombieCharacter.input.jumpWasPressed = false; if (flag6) { _jumpQueued = true; } } _zombieCharacter.input.sprintIsPressed = sprintIsPressed; _zombieCharacter.input.crouchIsPressed = key && !_attacking && !flag4; if (!ViewIsMine()) { _zombieCharacter.data.isSprinting = _zombieCharacter.input.sprintIsPressed; _zombieCharacter.data.isCrouching = _zombieCharacter.input.crouchIsPressed && _zombieCharacter.data.isGrounded; } if (flag3 && !_attacking && !flag4 && Time.unscaledTime - _lastAttackTime >= ZombiePlugin.AttackCooldown.Value) { StartAttack(); } SyncPlayerStamina(); ForwardClimbInput(); } private void SyncPlayerStamina() { if ((Object)(object)_playerCharacter?.data == (Object)null || (Object)(object)_zombieCharacter?.data == (Object)null) { return; } try { _playerCharacter.data.currentStamina = _zombieCharacter.data.currentStamina; } catch (Exception ex) { LogError("SyncPlayerStamina", ex); } } private bool IsCharacterClimbing() { if ((Object)(object)_zombieCharacter?.data != (Object)null) { return _zombieCharacter.data.isClimbing; } return false; } private bool IsInClimbReleaseFall() { return Time.time < _climbReleaseFallUntil; } private bool IsClimbInputHeld() { try { return Input.GetKey((KeyCode)323); } catch { return false; } } private void ForwardClimbInput() { if ((Object)(object)_zombieCharacter?.input == (Object)null || (Object)(object)_zombieCharacter.data == (Object)null || (Object)(object)_zombieCharacter.refs?.climbing == (Object)null) { return; } bool flag = false; bool flag2 = false; bool flag3 = false; try { flag = Input.GetKeyDown((KeyCode)323); flag2 = Input.GetKey((KeyCode)323); flag3 = Input.GetKeyUp((KeyCode)323); } catch { } _zombieCharacter.input.usePrimaryWasPressed = flag; _zombieCharacter.input.usePrimaryIsPressed = flag2 || flag; if (flag2 || flag) { try { if ((Object)(object)_zombieCharacter.data.currentItem == (Object)null) { _zombieCharacter.data.sincePressClimb = 0f; } } catch { } if (!IsCharacterClimbing() && (flag || Time.time >= _nextClimbAttemptTime)) { _nextClimbAttemptTime = Time.time + 0.08f; TryStartLocalClimb(); } } if (flag3) { _zombieCharacter.input.usePrimaryIsPressed = false; _zombieCharacter.input.usePrimaryWasReleased = true; _hasLastClimbStart = false; if (IsCharacterClimbing()) { StopControlledZombieClimb(1.25f); } } else { _zombieCharacter.input.usePrimaryWasReleased = false; } } private bool TryStartLocalClimb() { //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_00bd: 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_00d4: 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_00e9: 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_0108: 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_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) if ((Object)(object)_zombieCharacter == (Object)null || (Object)(object)_zombieCharacter.data == (Object)null || (Object)(object)_zombieCharacter.refs?.climbing == (Object)null) { return false; } if (_zombieCharacter.data.isClimbing || _zombieCharacter.data.isRopeClimbing || _zombieCharacter.data.isVineClimbing) { return true; } if ((Object)(object)_zombieCharacter.data.currentItem != (Object)null) { return false; } CharacterClimbing climbing = _zombieCharacter.refs.climbing; if (!CanControlledZombieClimb(climbing)) { return false; } Vector3 center = _zombieCharacter.Center; Vector3 climbForward = GetClimbForward(); if (((Vector3)(ref climbForward)).sqrMagnitude < 0.0001f) { return false; } if (!TryFindLocalClimbHit(center, climbForward, 1.65f, out var climbHit)) { return false; } if (IsRepeatedClimbStart(((RaycastHit)(ref climbHit)).point, ((RaycastHit)(ref climbHit)).normal)) { return false; } bool num = TryStartControlledZombieClimb(climbing, _zombieCharacter, ((RaycastHit)(ref climbHit)).point, ((RaycastHit)(ref climbHit)).normal); if (num) { RecordClimbStart(((RaycastHit)(ref climbHit)).point, ((RaycastHit)(ref climbHit)).normal); if ((Object)(object)_zombieCharacter.input != (Object)null) { _zombieCharacter.input.jumpWasPressed = false; _zombieCharacter.input.jumpIsPressed = false; } } return num; } private Vector3 GetClimbForward() { //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_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_0049: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_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_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) Vector3 val = Vector3.zero; Camera climbCamera = GetClimbCamera(); if ((Object)(object)climbCamera != (Object)null) { val = ((Component)climbCamera).transform.forward; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)_zombieCharacter != (Object)null) { val = ((Component)_zombieCharacter).transform.forward; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)_zombieCharacter?.data != (Object)null) { val = _zombieCharacter.data.lookDirection; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)_zombieCharacter?.data != (Object)null) { val = _zombieCharacter.data.lookDirection_Flat; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.forward; } return ((Vector3)(ref val)).normalized; } private Camera GetClimbCamera() { try { if ((Object)(object)Camera.main != (Object)null) { return Camera.main; } } catch { } return null; } private bool CanControlledZombieClimb(CharacterClimbing climbing) { if ((Object)(object)climbing == (Object)null) { return false; } try { if (ClimbCanClimbMethod != null) { object obj = ClimbCanClimbMethod.Invoke(climbing, null); if (obj is bool) { return (bool)obj; } } } catch { } return true; } private bool TryStartControlledZombieClimb(CharacterClimbing climbing, Character character, Vector3 climbPos, Vector3 climbNormal) { //IL_0031: 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_006c: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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_012a: 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_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)climbing == (Object)null) { return false; } try { PhotonView val = ((character != null) ? ((MonoBehaviourPun)character).photonView : null); if ((Object)(object)val != (Object)null) { val.RPC("StartClimbRpc", (RpcTarget)0, new object[2] { climbPos, climbNormal }); } else { if (ClimbStartClimbRpcMethod == null) { LogInfo("Climb: StartClimbRpc unavailable."); return false; } object[] array = BuildClimbRpcArguments(ClimbStartClimbRpcMethod, climbPos, climbNormal); if (array == null) { return false; } ClimbStartClimbRpcMethod.Invoke(climbing, array); } ClimbClimbToggledOnField?.SetValue(climbing, false); ClimbPlayerSlideField?.SetValue(climbing, Vector2.zero); ClimbSinceLastClimbStartedField?.SetValue(climbing, 0f); if ((Object)(object)character?.data != (Object)null) { _nextClimbAttemptTime = Time.time + 0.08f; 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 (Exception ex) { LogError("TryStartControlledZombieClimb", ex); return false; } } private void StopControlledZombieClimb(float setFall) { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_zombieCharacter?.data == (Object)null) { return; } try { PhotonView photonView = ((MonoBehaviourPun)_zombieCharacter).photonView; if ((Object)(object)photonView != (Object)null) { photonView.RPC("StopClimbingRpc", (RpcTarget)0, new object[1] { setFall }); } } catch { } _zombieCharacter.data.isClimbing = false; _zombieCharacter.data.isRopeClimbing = false; _zombieCharacter.data.isVineClimbing = false; _zombieCharacter.data.isJumping = false; _zombieCharacter.data.sinceGrounded = setFall; _zombieCharacter.data.sinceClimb = 999f; _zombieCharacter.data.sinceCanClimb = 0f; _zombieCharacter.data.sincePressClimb = 1f; _zombieCharacter.data.climbNormal = Vector3.zero; _climbReleaseFallUntil = Time.time + 0.7f; _nextClimbAttemptTime = Time.time + 0.08f; if ((Object)(object)_zombieCharacter.input != (Object)null) { _zombieCharacter.input.usePrimaryIsPressed = false; _zombieCharacter.input.usePrimaryWasPressed = false; _zombieCharacter.input.usePrimaryWasReleased = true; } try { ClimbPlayerSlideField?.SetValue(_zombieCharacter.refs?.climbing, Vector2.zero); ClimbClimbToggledOnField?.SetValue(_zombieCharacter.refs?.climbing, false); ClimbSinceLastClimbStartedField?.SetValue(_zombieCharacter.refs?.climbing, 999f); } catch { } } private void StabilizeControlledClimb() { //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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_0148: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_zombieCharacter?.data == (Object)null) { return; } try { _zombieCharacter.data.currentRagdollControll = 0.95f; _zombieCharacter.data.fallSeconds = 0f; _zombieCharacter.data.passedOut = false; _zombieCharacter.data.fullyPassedOut = false; _zombieCharacter.data.isGrounded = false; _zombieCharacter.data.sinceGrounded = 0f; _zombieCharacter.data.sinceCanClimb = 0f; _zombieCharacter.data.sincePressClimb = 0f; } catch { } if (_zombieCharacter.refs?.ragdoll?.partList == null) { return; } try { foreach (Bodypart part in _zombieCharacter.refs.ragdoll.partList) { Rigidbody val = ((part != 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 EnsureClimbSurfaceStillValid() { //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_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_0091: 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_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_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_00e2: 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_00f7: 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) if (!IsCharacterClimbing() || (Object)(object)_zombieCharacter?.refs?.climbing == (Object)null || _zombieCharacter.data.isRopeClimbing || _zombieCharacter.data.isVineClimbing) { return; } if (!IsClimbInputHeld()) { StopControlledZombieClimb(1.25f); return; } Vector3 center = _zombieCharacter.Center; Vector3[] array = (Vector3[])(object)new Vector3[4] { -_zombieCharacter.data.climbNormal, _zombieCharacter.data.lookDirection, _zombieCharacter.data.lookDirection_Flat, ((Component)_zombieCharacter).transform.forward }; for (int i = 0; i < array.Length; i++) { Vector3 val = array[i]; if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f) && TryFindLocalClimbHit(center, ((Vector3)(ref val)).normalized, 2.25f, out var _)) { _zombieCharacter.data.sinceCanClimb = 0f; return; } } StopControlledZombieClimb(1.25f); } private bool TryFindLocalClimbHit(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_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_00af: 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) climbHit = default