Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ZombieTransportation v0.1.2
ZombieTransportation.dll
Decompiled 7 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using REPOLib.Modules; using UnityEngine; using UnityEngine.AI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("GoodGoodZhao")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: AssemblyInformationalVersion("0.1.2+5c752d9c681dddfb6f6e3b9acab25c0701f8993a")] [assembly: AssemblyProduct("ZombieTransportation")] [assembly: AssemblyTitle("ZombieTransportation")] [assembly: AssemblyVersion("0.1.2.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 ZombieTransportation { [HarmonyPatch] internal static class CompanionBellRegistration { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Valuables), "RegisterValuableWithGame", new Type[1] { typeof(PrefabRef) }, (Type[])null) ?? throw new MissingMethodException("REPOLib.Valuables.RegisterValuableWithGame(PrefabRef) changed; companion-only protection could not be installed."); } private static bool Prefix(PrefabRef __0) { if (__0 == null || !NetworkPrefabs.Prefabs.TryGetValue(((PrefabRef<GameObject>)(object)__0).ResourcePath, out var value) || !Object.op_Implicit((Object)(object)value) || !Object.op_Implicit((Object)(object)value.GetComponent<SoulBell>())) { return true; } Debug.Log((object)("[Zombie Transportation] Companion-only bell: excluded from all random valuable presets; network prefab retained: " + ((PrefabRef<GameObject>)(object)__0).ResourcePath)); return false; } } [BepInPlugin("GoodGoodZhao.ZombieTransportation", "Zombie Transportation", "0.1.2")] [BepInDependency("REPOLib", "4.2.0")] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "GoodGoodZhao.ZombieTransportation"; private static ConfigEntry<float> guidanceGrace; internal static float GuidanceGraceSeconds { get { if (guidanceGrace != null) { return guidanceGrace.Value; } return 0.15f; } } private void Awake() { //IL_0005: 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_0061: Expected O, but got Unknown new Harmony("GoodGoodZhao.ZombieTransportation.CompanionOnly").PatchAll(typeof(CompanionBellRegistration)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Zombie Transportation 0.1.2 companion-only spawn protection installed."); guidanceGrace = ((BaseUnityPlugin)this).Config.Bind<float>("Soul Bell", "Guidance Grace Seconds", 0.15f, new ConfigDescription("Host only. Extra follow time after each pulse, in seconds. Applies on the next ring; releasing all grabs still stops guidance immediately.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.4f), Array.Empty<object>())); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Zombie Transportation loaded. Swing a held Soul Bell left and right to guide zombies. All players must use the same DLL and bundle."); } } [RequireComponent(typeof(PhysGrabObject), typeof(PhotonView))] public sealed class SoulBell : MonoBehaviour, IPunObservable { internal static readonly List<SoulBell> Active = new List<SoulBell>(); [SerializeField] private AudioSource ringAudio; [SerializeField] private Transform bellVisual; [SerializeField] private AudioClip[] ringClips; [SerializeField] private AudioClip commandClip; [SerializeField] [Min(0.02f)] private float swingThreshold = 0.1f; [SerializeField] [Min(0.05f)] private float minimumSwingSpeed = 0.55f; [SerializeField] [Min(0.05f)] private float swingCooldown = 0.14f; [SerializeField] [Min(0.1f)] private float ringDuration = 0.65f; [SerializeField] [Min(1f)] private float hearingRange = 16f; private PhysGrabObject grab; private PhotonView view; private readonly SwingDetector swingDetector = new SwingDetector(); private Quaternion visualRotation; private int activeHolderId; private int localHolderId; private double ringUntil; private int stateSequence; private int lastAudioSequence; private readonly BellPulseGate pulseGate = new BellPulseGate(); private float ringStrength; private int rhythmPattern = -1; private int rhythmStep = 3; private int rhythmA; private int rhythmB; private int rhythmC; private int lastCleanClipIndex = -1; private int authorityActor = int.MinValue; private readonly PulseStateOrder stateOrder = new PulseStateOrder(); private Vector3 soundPosition; private const int CommandClipIndex = -1; private const int FallbackClipIndex = -2; private static readonly int[,] CleanPatterns = new int[4, 3] { { 0, 0, 1 }, { 0, 1, 0 }, { 0, 1, 1 }, { 0, 1, 2 } }; private static readonly int[] PatternBag = new int[6] { 0, 0, 1, 1, 2, 3 }; private static double Clock { get { if (!GameManager.Multiplayer()) { return Time.unscaledTimeAsDouble; } return PhotonNetwork.Time; } } private float ringTimer => (float)Math.Max(0.0, ringUntil - Clock); public bool IsRinging { get { if (ringTimer > 0f && Object.op_Implicit((Object)(object)grab) && !grab.dead) { return grab.playerGrabbing.Count > 0; } return false; } } public Transform Holder { get; private set; } public Vector3 SoundPosition => soundPosition; public int PulseSequence { get; private set; } public float HearingRange => hearingRange; internal string CompanionKey { get { object[] array = (Object.op_Implicit((Object)(object)view) ? view.InstantiationData : null); if (array == null || array.Length != 2 || !(array[0] is string text) || !(text == "ZT.Pair.v1") || !(array[1] is string result)) { return null; } return result; } } private void Awake() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) grab = ((Component)this).GetComponent<PhysGrabObject>(); view = ((Component)this).GetComponent<PhotonView>(); if (!Object.op_Implicit((Object)(object)grab) || !Object.op_Implicit((Object)(object)view)) { Debug.LogError((object)"[Zombie Transportation] Bell requires grab and PhotonView components."); ((Behaviour)this).enabled = false; return; } soundPosition = ((Component)this).transform.position; if (Object.op_Implicit((Object)(object)bellVisual)) { visualRotation = bellVisual.localRotation; } } private void OnEnable() { if (!Active.Contains(this)) { Active.Add(this); } } private void OnDisable() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) Active.Remove(this); ZombieValuable.ForgetBell(this); activeHolderId = (localHolderId = 0); ringUntil = 0.0; ringStrength = 0f; pulseGate.Clear(); ResetRhythm(); Holder = null; swingDetector.Reset(0f); if (Object.op_Implicit((Object)(object)ringAudio)) { ringAudio.Stop(); } if (Object.op_Implicit((Object)(object)bellVisual)) { bellVisual.localRotation = visualRotation; } } private void Update() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) float deltaTime = Mathf.Max(Time.unscaledDeltaTime, 0.0001f); bool flag = SemiFunc.IsMasterClientOrSingleplayer(); RefreshAuthority(); PhysGrabber val = FindLocalHolder(); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.playerAvatar)) { int num = PlayerId(((Component)val.playerAvatar).GetComponent<PhotonView>()); float x = ((Component)val.playerAvatar).transform.InverseTransformPoint(((Component)this).transform.position).x; if (num != localHolderId) { localHolderId = num; swingDetector.Reset(x); } if (swingDetector.TryPulse(x, deltaTime, Time.unscaledTimeAsDouble, swingThreshold, minimumSwingSpeed, swingCooldown, out var strength)) { if (flag) { AuthorizePulse(num, strength, Clock); } else if (Object.op_Implicit((Object)(object)view) && view.ViewID != 0) { view.RPC("RequestSwing", (RpcTarget)2, new object[3] { num, strength, Clock }); } } } else { localHolderId = 0; } if (flag && (!Object.op_Implicit((Object)(object)grab) || grab.dead || grab.playerGrabbing.Count == 0)) { activeHolderId = 0; ringUntil = 0.0; ringStrength = 0f; } Holder = FindAnyHolder(); if (ringTimer <= 0f) { ringStrength = 0f; } if (Object.op_Implicit((Object)(object)bellVisual)) { float num2 = (IsRinging ? (Mathf.Sin((float)(Clock * 22.0 % (Math.PI * 2.0))) * (8f + ringStrength * 16f)) : 0f); bellVisual.localRotation = visualRotation * Quaternion.Euler(0f, 0f, num2); } } private void RefreshAuthority() { int num = ((!GameManager.Multiplayer()) ? (-1) : ((PhotonNetwork.MasterClient != null) ? PhotonNetwork.MasterClient.ActorNumber : 0)); if (num != authorityActor) { authorityActor = num; activeHolderId = (localHolderId = 0); ringUntil = 0.0; ringStrength = 0f; PulseSequence = (stateSequence = (lastAudioSequence = 0)); pulseGate.Clear(); stateOrder.Clear(); ResetRhythm(); } } private PhysGrabber FindLocalHolder() { foreach (PhysGrabber item in grab.playerGrabbing) { if (Object.op_Implicit((Object)(object)item) && item.isLocal && Object.op_Implicit((Object)(object)item.playerAvatar)) { return item; } } return null; } private Transform FindHolder(int holderId) { if (holderId == 0) { return null; } foreach (PhysGrabber item in grab.playerGrabbing) { if (Object.op_Implicit((Object)(object)item) && Object.op_Implicit((Object)(object)item.playerAvatar) && PlayerId(((Component)item.playerAvatar).GetComponent<PhotonView>()) == holderId) { return ((Component)item.playerAvatar).transform; } } return null; } private bool IsHolderGrabbing(int holderId) { return (Object)(object)FindHolder(holderId) != (Object)null; } private static int PlayerId(PhotonView playerView) { if (!GameManager.Multiplayer()) { return 1; } if (!Object.op_Implicit((Object)(object)playerView)) { return 0; } return playerView.ViewID; } private void AuthorizePulse(int holderId, float strength, double requestTime) { //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) RefreshAuthority(); if (!IsFinite(strength) || !Object.op_Implicit((Object)(object)grab) || grab.dead || !IsHolderGrabbing(holderId)) { return; } double clock = Clock; if (pulseGate.TryAccept(holderId, requestTime, clock, Mathf.Max(swingCooldown, 0.05f))) { int num = SelectRingClip(ringTimer <= 0f); activeHolderId = holderId; ringUntil = clock + (double)ringDuration + (double)Plugin.GuidanceGraceSeconds; ringStrength = Mathf.Clamp01(strength); if (GameManager.Multiplayer()) { view.RPC("RingPulseRPC", (RpcTarget)0, new object[5] { ringStrength, num, ((Component)this).transform.position, ringUntil, ++stateSequence }); } else { RingPulseLogic(ringStrength, num, ((Component)this).transform.position, ringUntil, ++stateSequence, playSound: true, Clock); } } } [PunRPC] private void RequestSwing(int holderId, float strength, double requestTime, PhotonMessageInfo info) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMasterClientOrSingleplayer() || info.Sender == null || holderId <= 0 || !IsFinite(strength) || strength < 0f || strength > 1f) { return; } foreach (PhysGrabber item in grab.playerGrabbing) { if (Object.op_Implicit((Object)(object)item) && Object.op_Implicit((Object)(object)item.playerAvatar)) { PhotonView component = ((Component)item.playerAvatar).GetComponent<PhotonView>(); if (Object.op_Implicit((Object)(object)component) && component.ViewID == holderId && component.Owner == info.Sender) { AuthorizePulse(holderId, strength, requestTime); break; } } } } [PunRPC] private void RingPulseRPC(float strength, int clipIndex, Vector3 position, double until, int sequence, PhotonMessageInfo info) { //IL_0007: 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_0010: Unknown result type (might be due to invalid IL or missing references) if ((!GameManager.Multiplayer() || (info.Sender != null && info.Sender.IsMasterClient)) && IsFinite(strength)) { RefreshAuthority(); RingPulseLogic(strength, clipIndex, position, until, sequence, playSound: true, ((PhotonMessageInfo)(ref info)).SentServerTime); } } private static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } private int SelectRingClip(bool command) { if (command && Object.op_Implicit((Object)(object)commandClip)) { rhythmStep = 3; return -1; } AudioClip[] array = ringClips; int num = ((array != null) ? array.Length : 0); if (num == 0) { return -2; } if (rhythmStep >= 3) { BeginRhythmPhrase(num); } return lastCleanClipIndex = CleanPatterns[rhythmPattern, rhythmStep++] switch { 1 => rhythmB, 0 => rhythmA, _ => rhythmC, }; } private void BeginRhythmPhrase(int clipCount) { int num = PatternBag[Random.Range(0, PatternBag.Length)]; if (PatternBag.Length > 1 && num == rhythmPattern) { num = PatternBag[(Random.Range(0, PatternBag.Length - 1) + 1) % PatternBag.Length]; } rhythmPattern = num; rhythmStep = 0; rhythmA = Random.Range(0, clipCount); if (clipCount > 1 && rhythmA == lastCleanClipIndex) { rhythmA = (rhythmA + Random.Range(1, clipCount)) % clipCount; } rhythmB = ((clipCount > 1) ? RandomDifferent(clipCount, rhythmA) : rhythmA); rhythmC = ((clipCount > 2) ? RandomDifferent(clipCount, rhythmA, rhythmB) : rhythmA); } private static int RandomDifferent(int count, int first, int second = -1) { int num = count - 1 - ((second >= 0 && second != first) ? 1 : 0); if (num <= 0) { return first; } int num2 = Random.Range(0, num); for (int i = 0; i < count; i++) { if (i != first && i != second && num2-- == 0) { return i; } } return first; } private void ResetRhythm() { rhythmPattern = -1; rhythmStep = 3; lastCleanClipIndex = -1; } private AudioClip ResolveRingClip(int clipIndex) { if (clipIndex == -1 && Object.op_Implicit((Object)(object)commandClip)) { return commandClip; } if (clipIndex >= 0 && ringClips != null && clipIndex < ringClips.Length && Object.op_Implicit((Object)(object)ringClips[clipIndex])) { return ringClips[clipIndex]; } if (!Object.op_Implicit((Object)(object)ringAudio)) { return null; } return ringAudio.clip; } private void RingPulseLogic(float strength, int clipIndex, Vector3 position, double until, int sequence, bool playSound, double sentTime) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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) if (!NetworkRules.IsFinite(until) || !IsFinite(position.x) || !IsFinite(position.y) || !IsFinite(position.z) || !stateOrder.TryApply(sequence, sentTime)) { return; } bool flag = sequence > lastAudioSequence; soundPosition = position; PulseSequence = sequence; stateSequence = Math.Max(stateSequence, sequence); ringUntil = until; ringStrength = Mathf.Clamp01(strength); AudioClip val = ResolveRingClip(clipIndex); if (playSound && flag && until > Clock && Object.op_Implicit((Object)(object)ringAudio) && Object.op_Implicit((Object)(object)val)) { lastAudioSequence = sequence; ringAudio.loop = false; ringAudio.pitch = Mathf.Lerp(0.98f, 1.02f, ringStrength); float num = Mathf.Lerp(0.72f, 1f, ringStrength); if (clipIndex == -1) { num *= 1.05f; } ringAudio.PlayOneShot(val, num); } } private Transform FindAnyHolder() { foreach (PhysGrabber item in grab.playerGrabbing) { if (Object.op_Implicit((Object)(object)item) && Object.op_Implicit((Object)(object)item.playerAvatar)) { return ((Component)item.playerAvatar).transform; } } return null; } public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) { //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_00a1: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if (stream.IsWriting) { RefreshAuthority(); stream.SendNext((object)activeHolderId); stream.SendNext((object)ringUntil); stream.SendNext((object)soundPosition); stream.SendNext((object)PulseSequence); stream.SendNext((object)ringStrength); return; } int num = (int)stream.ReceiveNext(); double until = (double)stream.ReceiveNext(); Vector3 position = (Vector3)stream.ReceiveNext(); int sequence = (int)stream.ReceiveNext(); float num2 = (float)stream.ReceiveNext(); if (info.Sender != null && info.Sender.IsMasterClient && IsFinite(num2)) { RefreshAuthority(); activeHolderId = num; RingPulseLogic(num2, -2, position, until, sequence, playSound: false, ((PhotonMessageInfo)(ref info)).SentServerTime); } } } public sealed class RingLease { private double expires; private int holder; public void Renew(int holderId, double now) { if (holderId != 0 && (holder == 0 || holder == holderId || !(now < expires))) { holder = holderId; expires = now + 0.45; } } public void Release(int holderId) { if (holder == holderId) { Clear(); } } public void Clear() { holder = 0; expires = 0.0; } public bool IsActive(int holderId, double now) { if (holderId != 0 && holder == holderId) { return now < expires; } return false; } } public sealed class SwingDetector { private bool initialized; private float previousPosition; private int side; private double lastPulse; public void Reset(float lateralPosition) { initialized = true; previousPosition = lateralPosition; side = 0; lastPulse = double.NegativeInfinity; } public bool TryPulse(float lateralPosition, float deltaTime, double now, float threshold, float minimumSpeed, float cooldown, out float strength) { strength = 0f; if (!initialized) { Reset(lateralPosition); return false; } float value = (lateralPosition - previousPosition) / Math.Max(deltaTime, 0.0001f); previousPosition = lateralPosition; int num = ((lateralPosition >= threshold) ? 1 : ((lateralPosition <= 0f - threshold) ? (-1) : 0)); if (num == 0 || num == side) { return false; } bool num2 = side != 0 && num != side; side = num; if (!num2 || Math.Abs(value) < minimumSpeed || now - lastPulse < (double)cooldown) { return false; } lastPulse = now; strength = (float)Math.Max(0.0, Math.Min(1.0, (Math.Abs(value) - minimumSpeed) / Math.Max(minimumSpeed * 2f, 0.01f))); return true; } } public static class HopPose { public static float Height(float phase) { phase -= (float)Math.Floor(phase); if (!(phase < 0.2f)) { return (float)Math.Sin((double)((phase - 0.2f) / 0.8f) * Math.PI); } return 0f; } public static float Waist(float phase) { phase -= (float)Math.Floor(phase); if (!(phase < 0.2f)) { return 9f * (1f - (phase - 0.2f) / 0.8f) - Height(phase) * 12f; } return phase / 0.2f * 9f; } } public static class NetworkRules { public static bool IsFinite(double value) { if (!double.IsNaN(value)) { return !double.IsInfinity(value); } return false; } public static bool IsFresh(double sent, double now) { if (IsFinite(sent) && IsFinite(now) && sent <= now + 0.1) { return now - sent <= 0.75; } return false; } } public sealed class BellPulseGate { private readonly Dictionary<int, double> lastRequests = new Dictionary<int, double>(); private double nextPulse; public void Clear() { lastRequests.Clear(); nextPulse = 0.0; } public bool TryAccept(int holderId, double sent, double now, double cooldown) { if (holderId <= 0 || !NetworkRules.IsFresh(sent, now) || !NetworkRules.IsFinite(cooldown) || cooldown < 0.0) { return false; } if (lastRequests.TryGetValue(holderId, out var value) && sent <= value) { return false; } lastRequests[holderId] = sent; if (now < nextPulse) { return false; } nextPulse = now + cooldown; return true; } } public sealed class PulseStateOrder { private int sequence; private double timestamp = double.NegativeInfinity; public void Clear() { sequence = 0; timestamp = double.NegativeInfinity; } public bool TryApply(int nextSequence, double sentTime) { if (!NetworkRules.IsFinite(sentTime) || nextSequence < sequence || nextSequence < 0 || (nextSequence == sequence && sentTime < timestamp)) { return false; } sequence = nextSequence; timestamp = sentTime; return true; } } [RequireComponent(typeof(PhysGrabObject), typeof(Rigidbody))] public sealed class ZombieValuable : MonoBehaviour, IPunInstantiateMagicCallback { private sealed class QueueState { internal int sequence; internal readonly List<ZombieValuable> members = new List<ZombieValuable>(); } private static readonly List<ZombieValuable> Active = new List<ZombieValuable>(); private static readonly Dictionary<SoulBell, QueueState> Queues = new Dictionary<SoulBell, QueueState>(); [SerializeField] private Transform visualRoot; [SerializeField] private Transform sizeRoot; [SerializeField] private Transform waist; [SerializeField] private Transform talisman; [SerializeField] [Min(0.1f)] private float followSpeed = 1.6f; [SerializeField] [Min(0.5f)] private float hearingRange = 16f; [SerializeField] [Min(0.5f)] private float stopDistance = 1.7f; [SerializeField] [Min(0.1f)] private float hopDuration = 0.62f; [SerializeField] [Range(0f, 0.3f)] private float hopHeight = 0.12f; [SerializeField] private GameObject pairedBell; private const float ResponseTurnSpeed = 360f; private const float ResponseReadyAngle = 8f; private const float QueueSpacing = 1.25f; private string companionKey; private string identityKey; private bool pairedSpawned; private int pairAttempts; private double nextPairAttempt; private bool pairWarningLogged; private bool respondingToBell; private PhysGrabObject grab; private Rigidbody body; private PhotonView view; private SoulBell target; private NavMeshPath path; private Vector3[] corners; private int corner; private float nextPath; private Vector3 visualOrigin; private Vector3 sizeOriginScale; private Quaternion waistOrigin; private Quaternion paperOrigin; private Vector3 previousPosition; private float phase; private float blend; private bool variationApplied; private int observedPulseSequence; private int predecessorId = int.MinValue; private float responseDelay; public void OnPhotonInstantiate(PhotonMessageInfo info) { //IL_0006: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown identityKey = "ZT.Identity.v1." + info.photonView.ViewID; if (PhotonNetwork.IsMasterClient && info.Sender == PhotonNetwork.LocalPlayer && PhotonNetwork.CurrentRoom != null) { companionKey = "ZT.Pair.v1." + Guid.NewGuid().ToString("N"); PhotonNetwork.CurrentRoom.SetCustomProperties(new Hashtable { [(object)identityKey] = companionKey }, (Hashtable)null, (WebFlags)null); } } internal static void ForgetBell(SoulBell bell) { Queues.Remove(bell); } private void OnDestroy() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown if (GameManager.Multiplayer() && PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom != null && companionKey != null) { Hashtable val = new Hashtable { [(object)companionKey] = null }; if (identityKey != null && ((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)identityKey, out object value) && value as string == companionKey) { val[(object)identityKey] = null; } PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } private void Awake() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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) grab = ((Component)this).GetComponent<PhysGrabObject>(); body = ((Component)this).GetComponent<Rigidbody>(); view = ((Component)this).GetComponent<PhotonView>(); path = new NavMeshPath(); if (!Object.op_Implicit((Object)(object)grab) || !Object.op_Implicit((Object)(object)body)) { Debug.LogError((object)"[Zombie Transportation] Zombie requires grab and Rigidbody components."); ((Behaviour)this).enabled = false; return; } if (Object.op_Implicit((Object)(object)visualRoot)) { visualOrigin = visualRoot.localPosition; } if (!Object.op_Implicit((Object)(object)sizeRoot)) { sizeRoot = visualRoot; } if (Object.op_Implicit((Object)(object)sizeRoot)) { sizeOriginScale = sizeRoot.localScale; } if (Object.op_Implicit((Object)(object)waist)) { waistOrigin = waist.localRotation; } if (Object.op_Implicit((Object)(object)talisman)) { paperOrigin = talisman.localRotation; } previousPosition = ((Component)this).transform.position; } private void OnEnable() { if (!Active.Contains(this)) { Active.Add(this); } } private void FixedUpdate() { //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: 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_0177: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMasterClientOrSingleplayer() || !grab.spawned || grab.dead || grab.grabbed) { ClearRoute(); return; } EnsurePairedBell(); if (!Valid(target)) { target = null; observedPulseSequence = 0; predecessorId = int.MinValue; respondingToBell = false; responseDelay = 0f; target = ChooseBell(); corners = null; nextPath = 0f; } if (!Object.op_Implicit((Object)(object)target)) { ClearRoute(); return; } QueueState queue = GetQueue(target); ZombieValuable zombieValuable = FindPredecessor(queue); int num = (Object.op_Implicit((Object)(object)zombieValuable) ? zombieValuable.QueueId() : 0); bool num2 = observedPulseSequence == 0 || num != predecessorId; observedPulseSequence = queue.sequence; predecessorId = num; if (num2) { respondingToBell = true; responseDelay = 0.06f; corners = null; } if (responseDelay > 0f) { responseDelay -= Time.fixedDeltaTime; return; } Vector3 soundPosition = target.SoundPosition; Vector3 destination = (Object.op_Implicit((Object)(object)zombieValuable) ? zombieValuable.body.position : soundPosition); if (respondingToBell) { if (Object.op_Implicit((Object)(object)zombieValuable) && zombieValuable.respondingToBell) { corners = null; return; } if (!StandAndFace(destination)) { corners = null; return; } respondingToBell = false; } Vector3 val = (Object.op_Implicit((Object)(object)zombieValuable) ? zombieValuable.body.position : soundPosition); float num3 = (Object.op_Implicit((Object)(object)zombieValuable) ? 1.25f : stopDistance); if (Vector3.Distance(body.position, val) <= num3) { corners = null; return; } if (Time.time >= nextPath) { nextPath = Time.time + 0.3f; corners = null; NavMeshHit val2 = default(NavMeshHit); NavMeshHit val3 = default(NavMeshHit); if (NavMesh.SamplePosition(body.position, ref val2, 1.5f, -1) && NavMesh.SamplePosition(val, ref val3, 1.5f, -1) && NavMesh.CalculatePath(((NavMeshHit)(ref val2)).position, ((NavMeshHit)(ref val3)).position, -1, path) && (int)path.status == 0) { corners = path.corners; corner = 1; } } if (corners != null && corner < corners.Length) { while (corner < corners.Length - 1 && Vector3.Distance(body.position, corners[corner]) < 0.2f) { corner++; } Vector3 val4 = Vector3.MoveTowards(body.position, corners[corner], followSpeed * Time.fixedDeltaTime); Vector3 val5 = val4 - body.position; val5.y = 0f; grab.OverrideKinematic(0.1f); grab.OverrideIndestructible(0.15f); body.MovePosition(val4); if (((Vector3)(ref val5)).sqrMagnitude > 1E-05f) { body.MoveRotation(Quaternion.RotateTowards(body.rotation, Quaternion.LookRotation(val5), 300f * Time.fixedDeltaTime)); } } } private bool StandAndFace(Vector3 destination) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) Vector3 val = destination - body.position; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude <= 1E-05f) { return true; } Quaternion val2 = Quaternion.LookRotation(val, Vector3.up); float num = Quaternion.Angle(body.rotation, val2); grab.OverrideKinematic(0.1f); grab.OverrideIndestructible(0.15f); body.MoveRotation(Quaternion.RotateTowards(body.rotation, val2, 360f * Time.fixedDeltaTime)); return num <= 8f; } private QueueState GetQueue(SoulBell bell) { if (!Queues.TryGetValue(bell, out var value)) { value = new QueueState(); Queues.Add(bell, value); } if (value.sequence != bell.PulseSequence || !value.members.Contains(this)) { RebuildQueue(value, bell); } return value; } private static void RebuildQueue(QueueState state, SoulBell bell) { //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) state.sequence = bell.PulseSequence; state.members.Clear(); foreach (ZombieValuable item in Active) { if (Object.op_Implicit((Object)(object)item) && item.WouldChoose(bell)) { state.members.Add(item); } } Vector3 sound = bell.SoundPosition; state.members.Sort(delegate(ZombieValuable left, ZombieValuable right) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) Vector3 val = left.body.position - sound; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; val = right.body.position - sound; float sqrMagnitude2 = ((Vector3)(ref val)).sqrMagnitude; int num = sqrMagnitude.CompareTo(sqrMagnitude2); return (num == 0) ? left.QueueId().CompareTo(right.QueueId()) : num; }); } private ZombieValuable FindPredecessor(QueueState state) { for (int num = state.members.IndexOf(this) - 1; num >= 0; num--) { ZombieValuable zombieValuable = state.members[num]; if (Object.op_Implicit((Object)(object)zombieValuable) && zombieValuable.WouldChoose(target)) { return zombieValuable; } } return null; } private bool WouldChoose(SoulBell bell) { if (Object.op_Implicit((Object)(object)grab) && grab.spawned && !grab.dead && !grab.grabbed) { return (Object)(object)ChooseBell() == (Object)(object)bell; } return false; } private SoulBell ChooseBell() { //IL_0050: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (Valid(target)) { return target; } SoulBell result = null; float num = hearingRange * hearingRange; int num2 = int.MaxValue; foreach (SoulBell item in SoulBell.Active) { if (Valid(item)) { Vector3 val = item.SoundPosition - body.position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; PhotonView component = ((Component)item).GetComponent<PhotonView>(); int num3 = ((Object.op_Implicit((Object)(object)component) && component.ViewID != 0) ? component.ViewID : ((Object)item).GetInstanceID()); if (sqrMagnitude < num || (Mathf.Abs(sqrMagnitude - num) < 0.0001f && num3 < num2)) { result = item; num = sqrMagnitude; num2 = num3; } } } return result; } private int QueueId() { if (!Object.op_Implicit((Object)(object)view) || view.ViewID == 0) { return ((Object)this).GetInstanceID(); } return view.ViewID; } private void ApplyBodyVariation() { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) if (variationApplied || !Object.op_Implicit((Object)(object)sizeRoot)) { return; } int num; if (GameManager.Multiplayer()) { if (!Object.op_Implicit((Object)(object)view) || view.ViewID == 0) { return; } num = view.ViewID; } else { num = Mathf.Abs(((Object)this).GetInstanceID()); } float num2 = Mathf.Repeat(Mathf.Sin((float)num * 12.9898f) * 43758.547f, 1f); float num3 = Mathf.Lerp(0.93f, 1.08f, num2); float num4 = Mathf.Lerp(1.06f, 0.92f, num2); sizeRoot.localScale = Vector3.Scale(sizeOriginScale, new Vector3(num4, num3, num4)); variationApplied = true; } private void EnsurePairedBell() { //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Expected O, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Expected O, but got Unknown if (pairedSpawned || !Object.op_Implicit((Object)(object)pairedBell) || !Object.op_Implicit((Object)(object)LevelGenerator.Instance) || !LevelGenerator.Instance.Generated) { return; } double unscaledTimeAsDouble = Time.unscaledTimeAsDouble; if (unscaledTimeAsDouble < nextPairAttempt || pairAttempts >= 3) { return; } bool flag = GameManager.Multiplayer(); string text = null; Room currentRoom = PhotonNetwork.CurrentRoom; if (flag) { if (!Object.op_Implicit((Object)(object)view) || view.ViewID == 0 || currentRoom == null || !PhotonNetwork.IsMasterClient) { return; } if (string.IsNullOrEmpty(companionKey)) { if (identityKey != null && ((Dictionary<object, object>)(object)((RoomInfo)currentRoom).CustomProperties).TryGetValue((object)identityKey, out object value)) { companionKey = value as string; } if (string.IsNullOrEmpty(companionKey)) { return; } } text = companionKey; foreach (SoulBell item in SoulBell.Active) { if (Object.op_Implicit((Object)(object)item) && !(item.CompanionKey != text)) { pairedSpawned = true; currentRoom.SetCustomProperties(new Hashtable { [(object)text] = ((Component)item).GetComponent<PhotonView>().ViewID }, (Hashtable)null, (WebFlags)null); return; } } if (((Dictionary<object, object>)(object)((RoomInfo)currentRoom).CustomProperties).TryGetValue((object)text, out object value2) && value2 is int num && num != 0) { if (num > 0) { pairedSpawned = true; return; } if (num != -PhotonNetwork.LocalPlayer.ActorNumber) { if (!pairWarningLogged) { pairWarningLogged = true; Debug.LogWarning((object)("[Zombie Transportation] Unresolved companion reservation after host change; duplicate spawn prevented for " + view.ViewID)); } return; } } if (!currentRoom.SetCustomProperties(new Hashtable { [(object)text] = -PhotonNetwork.LocalPlayer.ActorNumber }, (Hashtable)null, (WebFlags)null)) { nextPairAttempt = unscaledTimeAsDouble + 1.0; return; } } pairAttempts++; nextPairAttempt = unscaledTimeAsDouble + 1.0; Vector3 val = body.position + ((Component)this).transform.right * 0.85f + Vector3.up * 0.3f; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.down, ref val2, 2f, LayerMask.GetMask(new string[1] { "Default" }))) { val = ((RaycastHit)(ref val2)).point + Vector3.up * 0.25f; } GameObject val3; try { val3 = (flag ? PhotonNetwork.InstantiateRoomObject("Valuables/" + ((Object)pairedBell).name, val, Quaternion.identity, (byte)0, new object[2] { "ZT.Pair.v1", text }) : Object.Instantiate<GameObject>(pairedBell, val, Quaternion.identity)); } catch (Exception ex) { pairAttempts = 3; Debug.LogError((object)("[Zombie Transportation] Companion spawn outcome uncertain; automatic retry stopped. " + ex)); return; } if (!Object.op_Implicit((Object)(object)val3)) { Debug.LogWarning((object)("[Zombie Transportation] Companion spawn returned null (attempt " + pairAttempts + "/3).")); return; } pairedSpawned = true; if (flag) { currentRoom.SetCustomProperties(new Hashtable { [(object)text] = val3.GetComponent<PhotonView>().ViewID }, (Hashtable)null, (WebFlags)null); } } private bool Valid(SoulBell bell) { //IL_0019: 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) if (Object.op_Implicit((Object)(object)bell) && ((Behaviour)bell).isActiveAndEnabled && bell.IsRinging) { Vector3 val = bell.SoundPosition - body.position; return ((Vector3)(ref val)).sqrMagnitude <= hearingRange * hearingRange; } return false; } private void ClearRoute() { target = null; corners = null; respondingToBell = false; observedPulseSequence = 0; predecessorId = int.MinValue; responseDelay = 0f; } private void LateUpdate() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) ApplyBodyVariation(); float num = Mathf.Max(Time.deltaTime, 0.0001f); Vector3 val = ((Component)this).transform.position - previousPosition; previousPosition = ((Component)this).transform.position; val.y = 0f; bool flag = !grab.grabbed && !grab.dead && ((Vector3)(ref val)).magnitude / num > 0.12f && ((Vector3)(ref val)).magnitude < 1f; if (flag) { double num2 = (GameManager.Multiplayer() ? PhotonNetwork.Time : Time.timeAsDouble); phase = (float)(num2 / (double)Mathf.Max(hopDuration, 0.01f) % 1.0); } else if (blend > 0.01f) { phase = Mathf.Repeat(phase + num / hopDuration, 1f); } blend = Mathf.MoveTowards(blend, flag ? 1f : 0f, num * 5f); if (Object.op_Implicit((Object)(object)visualRoot)) { visualRoot.localPosition = visualOrigin + Vector3.up * (HopPose.Height(phase) * hopHeight * blend); } if (Object.op_Implicit((Object)(object)waist)) { waist.localRotation = waistOrigin * Quaternion.Euler(HopPose.Waist(phase) * blend, 0f, 0f); } if (Object.op_Implicit((Object)(object)talisman)) { talisman.localRotation = paperOrigin * Quaternion.Euler(Mathf.Sin(phase * MathF.PI * 2f) * 12f * blend, 0f, 0f); } } private void OnDisable() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) Active.Remove(this); if (Active.Count == 0) { Queues.Clear(); } ClearRoute(); blend = (phase = 0f); if (Object.op_Implicit((Object)(object)visualRoot)) { visualRoot.localPosition = visualOrigin; } if (Object.op_Implicit((Object)(object)waist)) { waist.localRotation = waistOrigin; } if (Object.op_Implicit((Object)(object)talisman)) { talisman.localRotation = paperOrigin; } } } }