Decompiled source of ZombieTransportation v0.1.2

ZombieTransportation.dll

Decompiled 7 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using 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;
			}
		}
	}
}