Decompiled source of OriginsStaffs v0.1.2

OriginsStaffs.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using OtherLoader;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Rendering;

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace LJIndustries.OriginsStaffs
{
	[BepInPlugin("LJIndustries.OriginsStaffs", "OriginsStaffs", "0.1.2")]
	[BepInProcess("h3vr.exe")]
	[Description("Built with MeatKit")]
	[BepInDependency("h3vr.otherloader", "1.3.0")]
	public class OriginsStaffsPlugin : BaseUnityPlugin
	{
		private static readonly string BasePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

		internal static ManualLogSource Logger;

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			LoadAssets();
		}

		private void LoadAssets()
		{
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "LJIndustries.OriginsStaffs");
			OtherLoader.RegisterDirectLoad(BasePath, "LJIndustries.OriginsStaffs", "", "", "origins_staffs", "");
		}
	}
}
namespace OriginsStaffs
{
	public class OriginsStaff : FVRFireArm
	{
		[Header("Origins Staff")]
		public StaffLever Lever;

		public StaffSupportGrip Support;

		[Tooltip("Below this hand separation (m) two-handed aim blends back to one-handed.")]
		public float MinTwoHandSpan = 0.12f;

		[Header("Blades (upgraded staffs)")]
		[Tooltip("One collider per blade on the upgraded tip; also in MP.StabColliders and MP.HighDamageColliders.")]
		public Collider[] KnifeColliders = (Collider[])(object)new Collider[0];

		[Tooltip("Per blade, a transform whose forward runs along the blade towards its point.")]
		public Transform[] KnifeStabDirections = (Transform[])(object)new Transform[0];

		public int Capacity = 9;

		[Tooltip("Seconds between shots while the trigger is held (BO2 fireTime).")]
		public float RefireDelay = 0.75f;

		public bool FullAuto = true;

		public float StaffTriggerPull = 0.75f;

		public float StaffTriggerReset = 0.35f;

		[Header("Shot")]
		public StaffElement Element = StaffElement.Fire;

		[Tooltip("Fire and lightning: a ball fired from the muzzle.")]
		public StaffProjectile ProjectilePrefab;

		[Tooltip("Ice and wind: BO2's scripted cone shot, carried by icicles or a ball of wind.")]
		public StaffConeShot ConeShotPrefab;

		[Tooltip("Metres per second (BO2 projectileSpeed, e.g. fire 1200 in/s).")]
		public float ProjectileSpeed = 30.48f;

		public float SpreadDegrees = 0.5f;

		[Tooltip("Projectiles per trigger pull, all at once from the muzzle, fanned side to side (fire: 3, base and upgraded). One charge per pull.")]
		public int ProjectilesPerShot = 1;

		[Tooltip("Degrees between neighbouring projectiles in the fan.")]
		public float FanDegrees = 15f;

		public GameObject MuzzleFlashPrefab;

		[Header("Charge shot (upgraded staffs)")]
		[Tooltip("BO2 fireType 'Charge Shot': the shot goes on release; holding charges it up.")]
		public bool ChargeShot;

		[Tooltip("Held this long, the charge begins to show (sound, glow, rumble); a quicker tap is a plain shot.")]
		public float ChargeCueDelay = 0.25f;

		[Tooltip("Seconds held to reach charge level 2, then 3.")]
		public float[] ChargeLevelTimes = new float[2] { 1f, 2f };

		[Tooltip("The charged shots for levels 2 and 3. Each spends one charge per level.")]
		public StaffChargedShot[] ChargedShots = new StaffChargedShot[0];

		public AudioSource ChargeLoop;

		public ParticleSystem ChargeParticles;

		public float ChargeParticleRate = 20f;

		public float ChargeGlowPerLevel = 0.6f;

		public AudioEvent AudEvent_Charge1;

		public AudioEvent AudEvent_Charge2;

		public AudioEvent AudEvent_Charge3;

		[Header("Crystal glow")]
		public Renderer[] GlowRenderers;

		public Light CrystalLight;

		[Tooltip("The crystal held in the tip: glows brighter than the reload crystal, with its own light.")]
		public Renderer[] HeadGlowRenderers = (Renderer[])(object)new Renderer[0];

		public Light HeadLight;

		public float HeadGlowBoost = 1.5f;

		public float HeadLightFull = 1.6f;

		public float GlowFull = 1.6f;

		public float GlowEmpty = 0.06f;

		public float LightFull = 1.2f;

		public float ShotFlash = 1.8f;

		[Header("Audio")]
		public AudioEvent AudEvent_Shot;

		public AudioEvent AudEvent_ShotRear;

		public AudioEvent AudEvent_Flux;

		public AudioEvent AudEvent_DryFire;

		public AudioEvent AudEvent_Recharged;

		public AudioEvent AudEvent_Handle;

		private int m_charges;

		private float m_refire;

		private float m_trigger;

		private int m_triggerFrame = -10;

		private bool m_triggerWasReset = true;

		private bool m_dryFired;

		private float m_flash;

		private MaterialPropertyBlock m_block;

		private bool m_charging;

		private bool m_chargeCued;

		private float m_chargeTime;

		private int m_chargeLevel;

		private float m_chargeBuzz;

		private float m_chargeGlow;

		private bool m_supportCarry;

		private float m_savedPosInterp;

		private float m_savedRotInterp;

		public int Charges => m_charges;

		private bool SupportHeld => (Object)(object)Support != (Object)null && ((FVRInteractiveObject)Support).IsHeld && (Object)(object)((FVRInteractiveObject)Support).m_hand != (Object)null;

		public override void Awake()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			((FVRFireArm)this).Awake();
			m_charges = Capacity;
			m_block = new MaterialPropertyBlock();
			UpdateGlow();
			Debug.Log((object)string.Concat("[OriginsStaffs] ", ((Object)this).name, " ready: ", Capacity, " charges, ", Element, (!((Object)(object)ConeShotPrefab != (Object)null)) ? (" x" + ProjectilesPerShot) : " cone shot", " per pull", (!ChargeShot) ? "" : (", charges up to level " + (1 + ChargedShots.Length))));
		}

		public override void UpdateInteraction(FVRViveHand hand)
		{
			((FVRPhysicalObject)this).UpdateInteraction(hand);
			if (!m_supportCarry)
			{
				m_trigger = hand.Input.TriggerFloat;
				m_triggerFrame = Time.frameCount;
				if ((Object)(object)Lever != (Object)null && ReleasePressed(hand))
				{
					Lever.PressRelease();
				}
			}
		}

		private static bool ReleasePressed(FVRViveHand hand)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (hand.IsInStreamlinedMode)
			{
				return hand.Input.AXButtonDown;
			}
			Vector2 touchpadAxes = hand.Input.TouchpadAxes;
			return hand.Input.TouchpadDown && ((Vector2)(ref touchpadAxes)).magnitude > 0.2f && Vector2.Angle(touchpadAxes, Vector2.up) <= 45f;
		}

		public override Quaternion GetRotTarget()
		{
			//IL_0002: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			Quaternion rotTarget = ((FVRPhysicalObject)this).GetRotTarget();
			if (!((FVRInteractiveObject)this).IsHeld || (Object)(object)((FVRInteractiveObject)this).m_hand == (Object)null || (Object)(object)((FVRPhysicalObject)this).QuickbeltSlot != (Object)null || !SupportHeld || m_supportCarry)
			{
				return rotTarget;
			}
			Vector3 val = ((HandInput)(ref ((FVRInteractiveObject)this).m_hand.Input)).Pos - ((HandInput)(ref ((FVRInteractiveObject)Support).m_hand.Input)).Pos;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.001f)
			{
				return rotTarget;
			}
			Vector3 val2 = val / magnitude;
			Vector3 val3 = Vector3.ProjectOnPlane(rotTarget * Vector3.up, val2);
			if (((Vector3)(ref val3)).sqrMagnitude < 1E-06f)
			{
				val3 = Vector3.ProjectOnPlane(rotTarget * Vector3.forward, val2);
			}
			Quaternion val4 = Quaternion.LookRotation(val2, val3) * ((FVRInteractiveObject)this).PoseOverride.localRotation;
			return Quaternion.Slerp(rotTarget, val4, Mathf.InverseLerp(MinTwoHandSpan * 0.5f, MinTwoHandSpan, magnitude));
		}

		public override bool IsForegripStabilized()
		{
			return SupportHeld;
		}

		public override bool IsTwoHandStabilized()
		{
			return SupportHeld;
		}

		public override void BeginInteraction(FVRViveHand hand)
		{
			FVRViveHand val = ((!m_supportCarry || !((Object)(object)((FVRInteractiveObject)this).m_hand != (Object)(object)hand)) ? null : ((FVRInteractiveObject)this).m_hand);
			if (m_supportCarry && (Object)(object)((FVRInteractiveObject)this).m_hand != (Object)(object)hand)
			{
				EndSupportCarry();
			}
			((FVRFireArm)this).BeginInteraction(hand);
			if ((Object)(object)val != (Object)null && (Object)(object)Support != (Object)null)
			{
				val.ForceSetInteractable((FVRInteractiveObject)(object)Support);
				((FVRInteractiveObject)Support).BeginInteraction(val);
			}
		}

		public override void EndInteraction(FVRViveHand hand)
		{
			FVRViveHand val = ((!SupportHeld || m_supportCarry) ? null : ((FVRInteractiveObject)Support).m_hand);
			((FVRFireArm)this).EndInteraction(hand);
			if ((Object)(object)Lever != (Object)null)
			{
				Lever.OnTriggerHandReleased();
			}
			if (m_supportCarry)
			{
				EndSupportCarry();
			}
			if ((Object)(object)val != (Object)null && (Object)(object)((FVRPhysicalObject)this).QuickbeltSlot == (Object)null)
			{
				m_savedPosInterp = ((FVRInteractiveObject)this).PositionInterpSpeed;
				m_savedRotInterp = ((FVRInteractiveObject)this).RotationInterpSpeed;
				((FVRInteractiveObject)this).PositionInterpSpeed = 0f;
				((FVRInteractiveObject)this).RotationInterpSpeed = 0f;
				val.ForceSetInteractable((FVRInteractiveObject)(object)this);
				((FVRInteractiveObject)this).BeginInteraction(val);
				m_supportCarry = true;
			}
		}

		private void EndSupportCarry()
		{
			m_supportCarry = false;
			((FVRInteractiveObject)this).PositionInterpSpeed = m_savedPosInterp;
			((FVRInteractiveObject)this).RotationInterpSpeed = m_savedRotInterp;
		}

		public override void OnCollisionEnter(Collision col)
		{
			if (((FVRPhysicalObject)this).MP != null && ((FVRPhysicalObject)this).MP.IsMeleeWeapon && KnifeColliders.Length > 0 && col.contacts.Length > 0)
			{
				int num = Array.IndexOf(KnifeColliders, ((ContactPoint)(ref col.contacts[0])).thisCollider);
				if (num >= 0 && num < KnifeStabDirections.Length)
				{
					((FVRPhysicalObject)this).MP.StabDirection = KnifeStabDirections[num];
				}
			}
			((FVRPhysicalObject)this).OnCollisionEnter(col);
		}

		public override void EndInteractionIntoInventorySlot(FVRViveHand hand, FVRQuickBeltSlot slot)
		{
			if (SupportHeld)
			{
				FVRViveHand hand2 = ((FVRInteractiveObject)Support).m_hand;
				hand2.EndInteractionIfHeld((FVRInteractiveObject)(object)Support);
				((FVRInteractiveObject)Support).EndInteraction(hand2);
			}
			((FVRFireArm)this).EndInteractionIntoInventorySlot(hand, slot);
		}

		public void BuzzTriggerHand(bool strong)
		{
			if (!((Object)(object)((FVRInteractiveObject)this).m_hand == (Object)null))
			{
				((FVRInteractiveObject)this).m_hand.Buzz((!strong) ? ((FVRInteractiveObject)this).m_hand.Buzzer.Buzz_OnHoverInteractive : ((FVRInteractiveObject)this).m_hand.Buzzer.Buzz_BeginInteraction);
			}
		}

		public void PlayHandleSound(Vector3 pos)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			PlaySoundAt(AudEvent_Handle, (FVRPooledAudioType)4, pos);
		}

		public void Recharge()
		{
			Debug.Log((object)("[OriginsStaffs] " + ((Object)this).name + " recharged: " + m_charges + " -> " + Capacity));
			m_charges = Capacity;
			m_flash = 1f;
			PlaySound(AudEvent_Recharged, (FVRPooledAudioType)3);
		}

		public override void FVRUpdate()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			((FVRFireArm)this).FVRUpdate();
			if (Time.frameCount - m_triggerFrame > 1)
			{
				m_trigger = 0f;
			}
			if ((Object)(object)Lever != (Object)null)
			{
				bool flag = ((FVRInteractiveObject)this).IsHeld && (Object)(object)((FVRInteractiveObject)this).m_hand != (Object)null && (Object)(object)((FVRPhysicalObject)this).QuickbeltSlot == (Object)null && SupportHeld;
				float gap = ((!flag) ? 0f : Vector3.Dot(((HandInput)(ref ((FVRInteractiveObject)this).m_hand.Input)).Pos - ((HandInput)(ref ((FVRInteractiveObject)Support).m_hand.Input)).Pos, ((Component)this).transform.forward));
				Lever.Tick(flag, gap, Time.deltaTime);
			}
			if (m_refire > 0f)
			{
				m_refire -= Time.deltaTime;
			}
			if (m_trigger <= StaffTriggerReset)
			{
				m_triggerWasReset = true;
				m_dryFired = false;
			}
			bool flag2 = m_trigger >= StaffTriggerPull;
			bool flag3 = (Object)(object)Lever == (Object)null || Lever.IsClosed;
			if (ChargeShot)
			{
				UpdateCharge(flag2, flag3);
			}
			else if (flag2 && m_refire <= 0f && (m_triggerWasReset || FullAuto))
			{
				if (m_charges > 0 && flag3)
				{
					FireStaff();
					m_refire = RefireDelay;
					m_triggerWasReset = false;
				}
				else if (m_charges == 0 && !m_dryFired)
				{
					PlaySound(AudEvent_DryFire, (FVRPooledAudioType)3);
					m_dryFired = true;
					m_triggerWasReset = false;
				}
			}
			m_flash = Mathf.MoveTowards(m_flash, 0f, Time.deltaTime * 5f);
			UpdateGlow();
		}

		private void FireStaff()
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			m_charges--;
			Transform muzzle = ((FVRFireArm)this).GetMuzzle();
			if ((Object)(object)ProjectilePrefab != (Object)null)
			{
				int playerIFF = GM.CurrentPlayerBody.GetPlayerIFF();
				int num = Mathf.Max(1, ProjectilesPerShot);
				for (int i = 0; i < num; i++)
				{
					float num2 = ((float)i - (float)(num - 1) * 0.5f) * FanDegrees;
					Vector2 val = Random.insideUnitCircle * SpreadDegrees;
					LaunchProjectile(muzzle.position, muzzle.rotation * Quaternion.Euler(val.x, num2 + val.y, 0f) * Vector3.forward, playerIFF);
				}
			}
			if ((Object)(object)ConeShotPrefab != (Object)null)
			{
				GameObject val2 = Object.Instantiate<GameObject>(((Component)ConeShotPrefab).gameObject, muzzle.position, muzzle.rotation);
				val2.GetComponent<StaffConeShot>().Fire(GM.CurrentPlayerBody.GetPlayerIFF());
			}
			ShotEffects();
		}

		private void LaunchProjectile(Vector3 from, Vector3 dir, int iff)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = Quaternion.LookRotation(dir);
			GameObject val2 = Object.Instantiate<GameObject>(((Component)ProjectilePrefab).gameObject, from, val);
			val2.GetComponent<StaffProjectile>().Launch(val * Vector3.forward * ProjectileSpeed, iff, ((FVRPhysicalObject)this).RootRigidbody);
		}

		private void UpdateCharge(bool pulled, bool mechanismClosed)
		{
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			float deltaTime = Time.deltaTime;
			if (!m_charging)
			{
				m_chargeGlow = Mathf.MoveTowards(m_chargeGlow, 0f, deltaTime * 4f);
				if (pulled && m_triggerWasReset && m_refire <= 0f)
				{
					m_triggerWasReset = false;
					if (m_charges > 0 && mechanismClosed)
					{
						m_charging = true;
						m_chargeCued = false;
						m_chargeTime = 0f;
						m_chargeLevel = 1;
					}
					else if (m_charges == 0 && !m_dryFired)
					{
						PlaySound(AudEvent_DryFire, (FVRPooledAudioType)3);
						m_dryFired = true;
					}
				}
				return;
			}
			if (!((FVRInteractiveObject)this).IsHeld || (Object)(object)((FVRInteractiveObject)this).m_hand == (Object)null || (Object)(object)((FVRPhysicalObject)this).QuickbeltSlot != (Object)null || m_supportCarry || !mechanismClosed)
			{
				EndCharge();
				return;
			}
			m_chargeTime += deltaTime;
			if (!m_chargeCued && m_chargeTime >= ChargeCueDelay)
			{
				m_chargeCued = true;
				PlaySound(AudEvent_Charge1, (FVRPooledAudioType)3);
				if ((Object)(object)ChargeLoop != (Object)null)
				{
					ChargeLoop.Play();
				}
				if ((Object)(object)ChargeParticles != (Object)null)
				{
					ChargeParticles.Play();
				}
			}
			int num = 1;
			for (int i = 0; i < ChargeLevelTimes.Length; i++)
			{
				if (m_chargeTime >= ChargeLevelTimes[i])
				{
					num = i + 2;
				}
			}
			num = Mathf.Min(new int[3]
			{
				num,
				m_charges,
				1 + ChargedShots.Length
			});
			if (num > m_chargeLevel)
			{
				m_chargeLevel = num;
				PlaySound((num != 2) ? AudEvent_Charge3 : AudEvent_Charge2, (FVRPooledAudioType)3);
				if ((Object)(object)((FVRInteractiveObject)this).m_hand != (Object)null)
				{
					((FVRInteractiveObject)this).m_hand.Buzz(((FVRInteractiveObject)this).m_hand.Buzzer.Buzz_GunShot);
				}
			}
			if (m_chargeCued)
			{
				m_chargeBuzz -= deltaTime;
				if (m_chargeBuzz <= 0f && (Object)(object)((FVRInteractiveObject)this).m_hand != (Object)null)
				{
					m_chargeBuzz = 0.15f;
					((FVRInteractiveObject)this).m_hand.Buzz((m_chargeLevel < 3) ? ((FVRInteractiveObject)this).m_hand.Buzzer.Buzz_OnHoverInteractive : ((FVRInteractiveObject)this).m_hand.Buzzer.Buzz_BeginInteraction);
				}
				if ((Object)(object)ChargeParticles != (Object)null)
				{
					EmissionModule emission = ChargeParticles.emission;
					((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(ChargeParticleRate * (float)m_chargeLevel);
				}
				m_chargeGlow = Mathf.MoveTowards(m_chargeGlow, ChargeGlowPerLevel * (float)m_chargeLevel, deltaTime * 3f);
			}
			if (m_trigger <= StaffTriggerReset)
			{
				int chargeLevel = m_chargeLevel;
				EndCharge();
				m_triggerWasReset = true;
				if (chargeLevel >= 2)
				{
					FireCharged(chargeLevel);
				}
				else
				{
					FireStaff();
				}
				m_refire = RefireDelay;
			}
		}

		private void EndCharge()
		{
			m_charging = false;
			m_chargeCued = false;
			m_chargeTime = 0f;
			m_chargeLevel = 0;
			if ((Object)(object)ChargeLoop != (Object)null)
			{
				ChargeLoop.Stop();
			}
			if ((Object)(object)ChargeParticles != (Object)null)
			{
				ChargeParticles.Stop(true, (ParticleSystemStopBehavior)1);
			}
		}

		private void FireCharged(int level)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			StaffChargedShot staffChargedShot = ((level - 2 >= ChargedShots.Length) ? null : ChargedShots[level - 2]);
			if ((Object)(object)staffChargedShot == (Object)null)
			{
				FireStaff();
				return;
			}
			m_charges = Mathf.Max(0, m_charges - level);
			Transform muzzle = ((FVRFireArm)this).GetMuzzle();
			GameObject val = Object.Instantiate<GameObject>(((Component)staffChargedShot).gameObject, muzzle.position, muzzle.rotation);
			val.GetComponent<StaffChargedShot>().Fire(this);
			Debug.Log((object)("[OriginsStaffs] " + ((Object)this).name + ": charged shot, level " + level + " (" + m_charges + " charges left)"));
			ShotEffects();
		}

		public void ExtraShotEffects()
		{
			ShotEffects();
		}

		private void ShotEffects()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			Transform muzzle = ((FVRFireArm)this).GetMuzzle();
			if ((Object)(object)MuzzleFlashPrefab != (Object)null)
			{
				Object.Instantiate<GameObject>(MuzzleFlashPrefab, muzzle.position, muzzle.rotation);
			}
			((FVRFireArm)this).Recoil(((FVRFireArm)this).IsTwoHandStabilized(), ((FVRFireArm)this).IsForegripStabilized(), ((FVRFireArm)this).IsShoulderStabilized(), (FVRFireArmRecoilProfile)null, 1f);
			if ((Object)(object)((FVRInteractiveObject)this).m_hand != (Object)null)
			{
				((FVRInteractiveObject)this).m_hand.Buzz(((FVRInteractiveObject)this).m_hand.Buzzer.Buzz_GunShot);
			}
			if (SupportHeld)
			{
				((FVRInteractiveObject)Support).m_hand.Buzz(((FVRInteractiveObject)Support).m_hand.Buzzer.Buzz_GunShot);
			}
			GM.CurrentSceneSettings.OnShotFired((FVRFireArm)(object)this);
			GM.CurrentPlayerBody.VisibleEvent(2f);
			PlaySound(AudEvent_Shot, (FVRPooledAudioType)1);
			PlaySound(AudEvent_ShotRear, (FVRPooledAudioType)1);
			PlaySound(AudEvent_Flux, (FVRPooledAudioType)3);
			m_flash = 1f;
		}

		private void UpdateGlow()
		{
			float num = ((Capacity <= 0) ? 0f : ((float)m_charges / (float)Capacity));
			float num2 = Mathf.Lerp(GlowEmpty, GlowFull, num);
			if (m_charges == 0)
			{
				num2 *= 0.5f + 0.5f * Mathf.PerlinNoise(Time.time * 6f, 0.5f);
			}
			num2 += m_flash * ShotFlash;
			num2 += m_chargeGlow * (0.85f + 0.15f * Mathf.Sin(Time.time * 18f));
			if ((Object)(object)Lever != (Object)null)
			{
				num2 *= Lever.GlowMultiplier;
			}
			SetEmission(GlowRenderers, num2);
			SetEmission(HeadGlowRenderers, num2 * HeadGlowBoost);
			SetLight(CrystalLight, LightFull * num2 / GlowFull);
			SetLight(HeadLight, HeadLightFull * num2 / GlowFull);
		}

		private void SetEmission(Renderer[] renderers, float level)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if (renderers == null)
			{
				return;
			}
			Color val = Color.white * level;
			foreach (Renderer val2 in renderers)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					val2.GetPropertyBlock(m_block);
					m_block.SetColor("_EmissionColor", val);
					val2.SetPropertyBlock(m_block);
				}
			}
		}

		private static void SetLight(Light light, float intensity)
		{
			if (!((Object)(object)light == (Object)null))
			{
				light.intensity = intensity;
				((Behaviour)light).enabled = intensity > 0.02f;
			}
		}

		public void PlaySound(AudioEvent ev, FVRPooledAudioType type)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			PlaySoundAt(ev, type, ((FVRFireArm)this).GetMuzzle().position);
		}

		public void PlaySoundAt(AudioEvent ev, FVRPooledAudioType type, Vector3 pos)
		{
			//IL_0027: 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_003f: Expected I4, but got Unknown
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if (ev == null || ev.Clips == null || ev.Clips.Count == 0)
			{
				return;
			}
			switch (type - 1)
			{
			case 0:
				if (base.m_pool_shot != null)
				{
					base.m_pool_shot.PlayClip(ev, pos, (AudioMixerGroup)null);
				}
				break;
			case 2:
				if (base.m_pool_mechanics != null)
				{
					base.m_pool_mechanics.PlayClip(ev, pos, (AudioMixerGroup)null);
				}
				break;
			case 3:
				if (base.m_pool_handling != null)
				{
					base.m_pool_handling.PlayClip(ev, pos, (AudioMixerGroup)null);
				}
				break;
			default:
				SM.PlayCoreSound(type, ev, pos);
				break;
			}
		}
	}
	public class StaffBlizzard : MonoBehaviour
	{
		[Tooltip("Metres (BO2: 175 in).")]
		public float Radius = 4.445f;

		[Tooltip("Seconds of storm (BO2: 6, level 3: 9).")]
		public float Duration = 6f;

		public float StartDelay = 1f;

		public float Tick = 0.1f;

		[Tooltip("BO2 raises the storm 33 in above the impact.")]
		public float Rise = 0.84f;

		public float Bo2Damage = 3300f;

		[Header("Effects")]
		public GameObject IciclePrefab;

		public GameObject FrostPrefab;

		public GameObject ShatterPrefab;

		public AudioSource Loop;

		public Light StormLight;

		public ParticleSystem[] StopOnEnd;

		private static StaffBlizzard s_active;

		private bool m_ended;

		private IEnumerator Start()
		{
			if ((Object)(object)s_active != (Object)null)
			{
				s_active.End();
			}
			s_active = this;
			Transform transform = ((Component)this).transform;
			transform.position += Vector3.up * Rise;
			((Component)this).transform.rotation = Quaternion.identity;
			int iff = GM.CurrentPlayerBody.GetPlayerIFF();
			yield return (object)new WaitForSeconds(StartDelay);
			for (float t = 0f; t < Duration; t += Tick)
			{
				if (m_ended)
				{
					break;
				}
				foreach (KeyValuePair<Sosig, SosigLink> item in StaffDamage.SosigsNear(((Component)this).transform.position, Radius))
				{
					if (!StaffFreeze.IsOnIce(item.Key))
					{
						StaffFreeze.Apply(item.Key, Bo2Damage, iff, ((Component)this).transform.position, IciclePrefab, FrostPrefab, ShatterPrefab, new Vector2(0.5f, 0.7f), alwaysKill: true);
					}
				}
				yield return (object)new WaitForSeconds(Tick);
			}
			End();
		}

		private void End()
		{
			if (!m_ended)
			{
				m_ended = true;
				if ((Object)(object)s_active == (Object)(object)this)
				{
					s_active = null;
				}
				((MonoBehaviour)this).StartCoroutine(FadeOut());
			}
		}

		private IEnumerator FadeOut()
		{
			if (StopOnEnd != null)
			{
				for (int i = 0; i < StopOnEnd.Length; i++)
				{
					if ((Object)(object)StopOnEnd[i] != (Object)null)
					{
						StopOnEnd[i].Stop(true, (ParticleSystemStopBehavior)1);
					}
				}
			}
			float volume = ((!((Object)(object)Loop != (Object)null)) ? 0f : Loop.volume);
			float light = ((!((Object)(object)StormLight != (Object)null)) ? 0f : StormLight.intensity);
			for (float t = 0f; t < 1.5f; t += Time.deltaTime)
			{
				float k = 1f - t / 1.5f;
				if ((Object)(object)Loop != (Object)null)
				{
					Loop.volume = volume * k;
				}
				if ((Object)(object)StormLight != (Object)null)
				{
					StormLight.intensity = light * k;
				}
				yield return null;
			}
			Object.Destroy((Object)(object)((Component)this).gameObject, 1f);
		}
	}
	public class StaffBolt : MonoBehaviour
	{
		public float Lifetime = 0.3f;

		public float CastRadius = 0.03f;

		public LayerMask BlockerMask;

		[Tooltip("Spawned where the bolt hits the level or a sosig.")]
		public GameObject ImpactPrefab;

		[Tooltip("Spawned where the bolt runs out of life or reaches its target.")]
		public GameObject EndPrefab;

		[Tooltip("Particle systems that keep fading out after the bolt is gone (trails).")]
		public ParticleSystem[] DetachOnEnd;

		[Tooltip("Spins the bolt about its flight direction (degrees per second; an ice shard tumbling, the wind ball turning).")]
		public float Spin = 0f;

		[Tooltip("Living sosigs within this many metres of the bolt as it flies, with nothing solid in between, are reported to OnSosigNear (the wind ball's gust). 0: off.")]
		public float NearRadius = 0f;

		public Action<SosigLink> OnSosigHit;

		public Action<SosigLink> OnSosigNear;

		private Vector3 m_velocity;

		private float m_age;

		private float m_maxDistance = float.MaxValue;

		private float m_travelled;

		private bool m_done;

		public void Launch(Vector3 velocity)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			m_velocity = velocity;
			((Component)this).transform.rotation = Quaternion.LookRotation(velocity);
		}

		public void LaunchAt(Vector3 target, float speed)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = target - ((Component)this).transform.position;
			m_maxDistance = ((Vector3)(ref val)).magnitude;
			Launch((!(m_maxDistance > 0.001f)) ? (((Component)this).transform.forward * speed) : (val / m_maxDistance * speed));
		}

		private void Update()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: 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_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: 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_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Invalid comparison between Unknown and I4
			//IL_028a: 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_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: 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_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			if (m_done)
			{
				return;
			}
			float deltaTime = Time.deltaTime;
			m_age += deltaTime;
			Vector3 val = m_velocity * deltaTime;
			float num = ((Vector3)(ref val)).magnitude;
			if (m_age >= Lifetime || num <= 0f)
			{
				End(EndPrefab, ((Component)this).transform.position, Quaternion.LookRotation(-m_velocity));
				return;
			}
			if (m_travelled + num >= m_maxDistance)
			{
				num = m_maxDistance - m_travelled;
				val = ((Vector3)(ref val)).normalized * num;
			}
			if (NearRadius > 0f && OnSosigNear != null)
			{
				Sweep(((Component)this).transform.position, ((Component)this).transform.position + val);
			}
			int num2 = LayerMask.op_Implicit(BlockerMask) | ((OnSosigHit != null) ? StaffDamage.AgentBodyMask : 0);
			RaycastHit[] array = Physics.SphereCastAll(((Component)this).transform.position, CastRadius, val / num, num, num2, (QueryTriggerInteraction)1);
			RaycastHit val2 = default(RaycastHit);
			SosigLink val3 = null;
			bool flag = false;
			for (int i = 0; i < array.Length; i++)
			{
				if (flag && ((RaycastHit)(ref array[i])).distance >= ((RaycastHit)(ref val2)).distance)
				{
					continue;
				}
				SosigLink val4 = null;
				if (((1 << ((Component)((RaycastHit)(ref array[i])).collider).gameObject.layer) & LayerMask.op_Implicit(BlockerMask)) == 0)
				{
					val4 = StaffDamage.FindLink(((RaycastHit)(ref array[i])).collider);
					if ((Object)(object)val4 == (Object)null || (Object)(object)val4.S == (Object)null || (int)val4.S.BodyState == 3)
					{
						continue;
					}
				}
				val2 = array[i];
				val3 = val4;
				flag = true;
			}
			if (flag)
			{
				Vector3 val5 = ((!(((RaycastHit)(ref val2)).point == Vector3.zero)) ? ((RaycastHit)(ref val2)).point : (((Component)this).transform.position + val / num * ((RaycastHit)(ref val2)).distance));
				if ((Object)(object)val3 != (Object)null)
				{
					OnSosigHit(val3);
				}
				End(ImpactPrefab, val5 + ((RaycastHit)(ref val2)).normal * 0.03f, Quaternion.LookRotation((!(((RaycastHit)(ref val2)).normal == Vector3.zero)) ? ((RaycastHit)(ref val2)).normal : (-m_velocity)));
				return;
			}
			Transform transform = ((Component)this).transform;
			transform.position += val;
			m_travelled += num;
			((Component)this).transform.rotation = Quaternion.LookRotation(m_velocity) * Quaternion.Euler(0f, 0f, Spin * m_age);
			if (m_travelled >= m_maxDistance - 0.001f)
			{
				End(EndPrefab, ((Component)this).transform.position, Quaternion.LookRotation(-m_velocity));
			}
		}

		private void Sweep(Vector3 from, Vector3 to)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Invalid comparison between Unknown and I4
			//IL_0059: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			Collider[] array = Physics.OverlapCapsule(from, to, NearRadius, StaffDamage.AgentBodyMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				SosigLink val = StaffDamage.FindLink(array[i]);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.S == (Object)null) && (int)val.S.BodyState != 3 && !StaffDamage.Blocked(from, ((Component)val).transform.position, LayerMask.op_Implicit(BlockerMask)))
				{
					OnSosigNear(val);
				}
			}
		}

		private void End(GameObject prefab, Vector3 point, Quaternion rotation)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			m_done = true;
			if ((Object)(object)prefab != (Object)null)
			{
				Object.Instantiate<GameObject>(prefab, point, rotation);
			}
			if (DetachOnEnd != null)
			{
				for (int i = 0; i < DetachOnEnd.Length; i++)
				{
					ParticleSystem val = DetachOnEnd[i];
					if (!((Object)(object)val == (Object)null))
					{
						((Component)val).transform.SetParent((Transform)null, true);
						val.Stop(true, (ParticleSystemStopBehavior)1);
						Object.Destroy((Object)(object)((Component)val).gameObject, 2f);
					}
				}
			}
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}
	public class StaffBurn : MonoBehaviour
	{
		public static void Apply(Sosig s, float bo2PerSecond, float duration, int iff, GameObject flames)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			if (!((Object)(object)s == (Object)null) && (int)s.BodyState != 3 && !((Object)(object)((Component)s).GetComponent<StaffBurn>() != (Object)null))
			{
				StaffBurn staffBurn = ((Component)s).gameObject.AddComponent<StaffBurn>();
				((MonoBehaviour)staffBurn).StartCoroutine(staffBurn.Run(s, bo2PerSecond, duration, iff, flames));
			}
		}

		private IEnumerator Run(Sosig s, float bo2PerSecond, float duration, int iff, GameObject flames)
		{
			SosigLink torso = StaffDamage.Torso(s);
			GameObject fx = ((!((Object)(object)torso != (Object)null)) ? null : StaffDamage.SpawnOn(flames, ((Component)torso).transform, ((Component)torso).transform.position));
			yield return (object)new WaitForSeconds(0.5f);
			for (float t = 0f; t < duration; t += 1f)
			{
				if ((Object)(object)s == (Object)null)
				{
					break;
				}
				if ((int)s.BodyState == 3)
				{
					break;
				}
				if (StaffDamage.WouldKill(s, bo2PerSecond))
				{
					StaffDamage.Kill(s, iff);
					break;
				}
				StaffDamage.Hurt(s, bo2PerSecond, Vector3.down, iff, ((Component)s).transform.position);
				yield return (object)new WaitForSeconds(1f);
			}
			if ((Object)(object)fx != (Object)null)
			{
				Object.Destroy((Object)(object)fx, 1f);
			}
			Object.Destroy((Object)(object)this);
		}
	}
	public class StaffChargedShot : MonoBehaviour
	{
		public StaffElement Element = StaffElement.Fire;

		[Tooltip("BO2 charge level: 2 or 3.")]
		public int Level = 2;

		public LayerMask BlockerMask;

		[Header("Ice and wind")]
		public StaffBolt BoltPrefab;

		[Tooltip("Metres per second (BO2 projectileSpeed: ice 2000 in/s, wind 1500 in/s).")]
		public float BoltSpeed = 38.1f;

		[Header("Fire")]
		public StaffFireGrenade GrenadePrefab;

		[Tooltip("BO2 projectileSpeed / projectileSpeedUp: 1300 in/s forward, 200 in/s up.")]
		public float GrenadeSpeed = 33.02f;

		public float GrenadeLift = 5.08f;

		[Tooltip("BO2 fire_additional_shots: 1 more at level 2, 2 more at level 3.")]
		public int ExtraGrenades = 1;

		public float ExtraDelay = 0.35f;

		[Header("Lightning")]
		public StaffLightningOrb OrbPrefab;

		[Tooltip("BO2 spawns the ball 100 in in front of the muzzle...")]
		public float OrbStartDistance = 2.54f;

		[Tooltip("...and sends it 800 in (level 3: 1200 in) along the aim, stopping at walls.")]
		public float OrbRange = 20.32f;

		[Tooltip("BO2: the full range takes 8 s.")]
		public float OrbTravelTime = 8f;

		public void Fire(OriginsStaff staff)
		{
			//IL_002c: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: 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_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)this).transform;
			switch (Element)
			{
			case StaffElement.Fire:
				Lob(transform.position, transform.rotation);
				if (ExtraGrenades > 0)
				{
					((MonoBehaviour)this).StartCoroutine(ExtraShots(staff));
				}
				break;
			case StaffElement.Ice:
			case StaffElement.Wind:
				if ((Object)(object)BoltPrefab != (Object)null)
				{
					GameObject val4 = Object.Instantiate<GameObject>(((Component)BoltPrefab).gameObject, transform.position, transform.rotation);
					StaffBolt component = val4.GetComponent<StaffBolt>();
					component.OnSosigHit = delegate
					{
					};
					component.Launch(transform.forward * BoltSpeed);
				}
				break;
			case StaffElement.Lightning:
				if ((Object)(object)OrbPrefab != (Object)null)
				{
					Vector3 val = transform.position + transform.forward * OrbStartDistance;
					Vector3 target = transform.position + transform.forward * OrbRange;
					RaycastHit val2 = default(RaycastHit);
					if (Physics.Raycast(transform.position, transform.forward, ref val2, OrbRange, LayerMask.op_Implicit(BlockerMask), (QueryTriggerInteraction)1))
					{
						target = ((RaycastHit)(ref val2)).point - transform.forward * 0.3f;
					}
					GameObject val3 = Object.Instantiate<GameObject>(((Component)OrbPrefab).gameObject, val, transform.rotation);
					val3.GetComponent<StaffLightningOrb>().Launch(target, OrbRange / OrbTravelTime);
				}
				break;
			}
		}

		private void Lob(Vector3 from, Quaternion aim)
		{
			//IL_0022: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)GrenadePrefab == (Object)null))
			{
				GameObject val = Object.Instantiate<GameObject>(((Component)GrenadePrefab).gameObject, from, aim);
				val.GetComponent<StaffFireGrenade>().Launch(aim * Vector3.forward * GrenadeSpeed + Vector3.up * GrenadeLift);
			}
		}

		private IEnumerator ExtraShots(OriginsStaff staff)
		{
			for (int i = 1; i <= ExtraGrenades; i++)
			{
				yield return (object)new WaitForSeconds(ExtraDelay);
				if ((Object)(object)staff == (Object)null || !((FVRInteractiveObject)staff).IsHeld)
				{
					break;
				}
				Transform muzzle = ((FVRFireArm)staff).GetMuzzle();
				Lob(muzzle.position, muzzle.rotation * Quaternion.Euler(5f * (float)i, Random.Range(-15f, 15f), 0f));
				staff.ExtraShotEffects();
			}
		}
	}
	public class StaffConeShot : MonoBehaviour
	{
		public StaffElement Element = StaffElement.Ice;

		[Header("BO2 targeting")]
		[Tooltip("Metres (ice 600 in, wind 400 in).")]
		public float Range = 15.24f;

		[Tooltip("Degrees either side of the aim (ice 25, wind 45, upgraded wind 60).")]
		public float HalfAngle = 25f;

		[Tooltip("Ice: sosigs frozen per shot (BO2: 3 searches). Wind: closest sosigs considered (BO2: 12).")]
		public int MaxTargets = 3;

		[Tooltip("BO2 damage per target (2050 base, 3300 upgraded).")]
		public float Bo2Damage = 2050f;

		public bool NeedsLineOfSight = true;

		public LayerMask BlockerMask;

		[Tooltip("Off: no target search, only what the bolts touch is hit.")]
		public bool UsesCone = true;

		[Header("Bolts")]
		public StaffBolt BoltPrefab;

		[Tooltip("Metres per second (BO2 projectileSpeed: ice 2000 in/s, wind 1500 in/s).")]
		public float BoltSpeed = 50.8f;

		[Tooltip("Ice: shards in the spray, aimed ones included.")]
		public int SprayCount = 1;

		public float SprayDegrees = 0f;

		[Header("Ice")]
		public GameObject IciclePrefab;

		public GameObject FrostPrefab;

		public GameObject ShatterPrefab;

		[Header("Wind")]
		[Tooltip("BO2 launches killed zombies at 300 in/s away from the player, lifted 5-35% of that.")]
		public float LaunchSpeed = 7.62f;

		public Vector2 LaunchLift = new Vector2(0.05f, 0.35f);

		[Tooltip("Survivors play BO2's electric stun (zm_electric_stun) for about this long.")]
		public float StunTime = 1.5f;

		[Tooltip("Sosigs the ball of wind blows on but does not kill are knocked down and pushed away this fast (not BO2).")]
		public float SurvivorPush = 4.5f;

		public GameObject GustPrefab;

		private readonly HashSet<Sosig> m_hit = new HashSet<Sosig>();

		private Vector3 m_origin;

		private Vector3 m_forward;

		private string m_name;

		private int m_iff;

		public void Fire(int iff)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			m_origin = ((Component)this).transform.position;
			m_forward = ((Component)this).transform.forward;
			m_name = ((Object)this).name;
			m_iff = iff;
			Vector3 forward = m_forward;
			List<KeyValuePair<Sosig, SosigLink>> list = ((!UsesCone) ? new List<KeyValuePair<Sosig, SosigLink>>() : StaffDamage.SosigsNear(m_origin, Range).OrderBy(delegate(KeyValuePair<Sosig, SosigLink> p)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = ((Component)p.Value).transform.position - m_origin;
				return ((Vector3)(ref val)).sqrMagnitude;
			}).ToList());
			int num = ((Element != StaffElement.Ice) ? FireWind(forward, list) : FireIce(forward, list));
			if (UsesCone)
			{
				Debug.Log((object)("[OriginsStaffs] " + m_name + ": " + list.Count + " sosig(s) within " + Range.ToString("0.0") + " m, " + num + " in the cone"));
			}
		}

		private bool InCone(Vector3 forward, Vector3 point)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = point - m_origin;
			return ((Vector3)(ref val)).sqrMagnitude < 0.0001f || Vector3.Angle(forward, val) <= HalfAngle;
		}

		private int FireIce(Vector3 forward, List<KeyValuePair<Sosig, SosigLink>> near)
		{
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: 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_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			for (int i = 0; i < MaxTargets; i++)
			{
				foreach (KeyValuePair<Sosig, SosigLink> item in near)
				{
					Sosig key = item.Key;
					if (m_hit.Contains(key) || StaffFreeze.IsOnIce(key))
					{
						continue;
					}
					SosigLink val = StaffDamage.Torso(key) ?? item.Value;
					if (InCone(forward, ((Component)val).transform.position))
					{
						SosigLink val2 = key.Links[Random.Range(0, key.Links.Count)];
						if ((Object)(object)val2 == (Object)null)
						{
							val2 = val;
						}
						if (!NeedsLineOfSight || !StaffDamage.Blocked(m_origin, ((Component)val2).transform.position, LayerMask.op_Implicit(BlockerMask)))
						{
							m_hit.Add(key);
							num++;
							Vector3 position = ((Component)val).transform.position;
							SpawnBolt(position - m_origin, position);
							((MonoBehaviour)this).StartCoroutine(FreezeOnArrival(key, Vector3.Distance(m_origin, position) / BoltSpeed));
							break;
						}
					}
				}
			}
			for (int j = num; j < SprayCount; j++)
			{
				Vector2 val3 = Random.insideUnitCircle * SprayDegrees;
				SpawnBolt(Quaternion.LookRotation(forward) * Quaternion.Euler(val3.x, val3.y, 0f) * Vector3.forward, null);
			}
			return num;
		}

		private IEnumerator FreezeOnArrival(Sosig s, float delay)
		{
			yield return (object)new WaitForSeconds(delay);
			Freeze(s);
		}

		private void Freeze(Sosig s)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s != (Object)null)
			{
				StaffFreeze.Apply(s, Bo2Damage, m_iff, m_origin, IciclePrefab, FrostPrefab, ShatterPrefab);
			}
		}

		private void OnShardHit(SosigLink link)
		{
			Sosig s = link.S;
			if (m_hit.Contains(s))
			{
				Freeze(s);
			}
			else if (m_hit.Count < MaxTargets && !StaffFreeze.IsOnIce(s))
			{
				m_hit.Add(s);
				Freeze(s);
			}
		}

		private int FireWind(Vector3 forward, List<KeyValuePair<Sosig, SosigLink>> near)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			SpawnBolt(forward, null);
			int num = 0;
			foreach (KeyValuePair<Sosig, SosigLink> item in near.Take(MaxTargets))
			{
				SosigLink val = StaffDamage.Torso(item.Key) ?? item.Value;
				Vector3 position = ((Component)val).transform.position;
				if (InCone(forward, position) && (!NeedsLineOfSight || !StaffDamage.Blocked(m_origin, position, LayerMask.op_Implicit(BlockerMask))))
				{
					num++;
					((MonoBehaviour)this).StartCoroutine(GustOnArrival(item.Key, Vector3.Distance(m_origin, position) / BoltSpeed));
				}
			}
			return num;
		}

		private IEnumerator GustOnArrival(Sosig s, float delay)
		{
			yield return (object)new WaitForSeconds(delay);
			Gust(s, fromBall: false);
		}

		private void OnBall(SosigLink link)
		{
			Gust(link.S, fromBall: true);
		}

		private void Gust(Sosig s, bool fromBall)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s == (Object)null || (int)s.BodyState == 3 || !m_hit.Add(s))
			{
				return;
			}
			SosigLink val = StaffDamage.Torso(s);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)val).transform.position;
			StaffDamage.SpawnOn(GustPrefab, null, position);
			Vector3 val2 = position - m_origin;
			val2.y = 0f;
			val2 = ((!(((Vector3)(ref val2)).sqrMagnitude > 0.0001f)) ? m_forward : ((Vector3)(ref val2)).normalized);
			bool flag = StaffDamage.WouldKill(s, Bo2Damage);
			if (flag)
			{
				StaffDamage.Kill(s, m_iff);
				StaffDamage.Launch(s, (val2 + Vector3.up * Random.Range(LaunchLift.x, LaunchLift.y)) * LaunchSpeed);
			}
			else
			{
				StaffDamage.Hurt(s, Bo2Damage, val2, m_iff, m_origin);
				if (fromBall)
				{
					s.Shudder(1f);
					StaffDamage.Launch(s, (val2 + Vector3.up * 0.3f) * SurvivorPush);
				}
				s.Stun(StunTime);
			}
			Debug.Log((object)("[OriginsStaffs] " + m_name + ": " + ((!flag) ? "stunned " : "killed and flung ") + ((Object)s).name + " at " + Vector3.Distance(m_origin, position).ToString("0.0") + " m"));
		}

		private void SpawnBolt(Vector3 dir, Vector3? target)
		{
			//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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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 (!((Object)(object)BoltPrefab == (Object)null) && !(((Vector3)(ref dir)).sqrMagnitude < 0.0001f))
			{
				GameObject val = Object.Instantiate<GameObject>(((Component)BoltPrefab).gameObject, m_origin, Quaternion.LookRotation(dir));
				StaffBolt component = val.GetComponent<StaffBolt>();
				if (Element == StaffElement.Ice)
				{
					component.OnSosigHit = OnShardHit;
				}
				else
				{
					component.OnSosigHit = OnBall;
					component.OnSosigNear = OnBall;
				}
				if (target.HasValue)
				{
					component.LaunchAt(target.Value, BoltSpeed);
				}
				else
				{
					component.Launch(((Vector3)(ref dir)).normalized * BoltSpeed);
				}
			}
		}
	}
	public enum StaffElement
	{
		Fire,
		Ice,
		Lightning,
		Wind
	}
	public static class StaffDamage
	{
		public const float Bo2ToBlunt = 1.6f;

		private static int s_agentMask;

		public static int AgentMask
		{
			get
			{
				if (s_agentMask == 0)
				{
					int num = LayerMask.NameToLayer("AgentBody");
					s_agentMask = ((num < 0) ? 1048576 : (1 << num)) | 1;
				}
				return s_agentMask;
			}
		}

		public static int AgentBodyMask => AgentMask & -2;

		public static IFVRDamageable FindDamageable(Collider col)
		{
			Component component = ((Component)col).gameObject.GetComponent(typeof(IFVRDamageable));
			IFVRDamageable val = (IFVRDamageable)(object)((component is IFVRDamageable) ? component : null);
			if (val == null && (Object)(object)col.attachedRigidbody != (Object)null)
			{
				Component component2 = ((Component)col.attachedRigidbody).gameObject.GetComponent(typeof(IFVRDamageable));
				val = (IFVRDamageable)(object)((component2 is IFVRDamageable) ? component2 : null);
			}
			return val;
		}

		public static SosigLink FindLink(Collider col)
		{
			SosigLink component = ((Component)col).GetComponent<SosigLink>();
			if ((Object)(object)component == (Object)null && (Object)(object)col.attachedRigidbody != (Object)null)
			{
				component = ((Component)col.attachedRigidbody).GetComponent<SosigLink>();
			}
			return component;
		}

		public static Dictionary<Sosig, SosigLink> SosigsNear(Vector3 centre, float range)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Invalid comparison between Unknown and I4
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<Sosig, SosigLink> dictionary = new Dictionary<Sosig, SosigLink>();
			Dictionary<Sosig, float> dictionary2 = new Dictionary<Sosig, float>();
			Collider[] array = Physics.OverlapSphere(centre, range, AgentMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				SosigLink val = FindLink(array[i]);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.S == (Object)null) && (int)val.S.BodyState != 3)
				{
					Vector3 val2 = ((Component)val).transform.position - centre;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (!dictionary2.TryGetValue(val.S, out var value) || sqrMagnitude < value)
					{
						dictionary2[val.S] = sqrMagnitude;
						dictionary[val.S] = val;
					}
				}
			}
			return dictionary;
		}

		public static SosigLink Torso(Sosig s)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Invalid comparison between Unknown and I4
			SosigLink val = null;
			for (int i = 0; i < s.Links.Count; i++)
			{
				SosigLink val2 = s.Links[i];
				if (!((Object)(object)val2 == (Object)null))
				{
					if ((int)val2.BodyPart == 1)
					{
						return val2;
					}
					if ((Object)(object)val == (Object)null)
					{
						val = val2;
					}
				}
			}
			return val;
		}

		public static bool WouldKill(Sosig s, float bo2Damage)
		{
			if (s.IsInvuln)
			{
				return false;
			}
			SosigLink val = Torso(s);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			float num = bo2Damage * 1.6f * s.DamMult_Projectile;
			if (s.AppliesDamageResistToIntegrityLoss)
			{
				num *= s.DamMult_Blunt;
			}
			float num2 = Mathf.Clamp(num * 0.032f * val.DamMult, 0f, 100f);
			return num2 >= val.GetIntegrityRatio() * 100f;
		}

		public static void Kill(Sosig s, int iff)
		{
			s.SetLastIFFDamageSource(iff);
			s.KillSosig();
		}

		public static void Hurt(Sosig s, float bo2Damage, Vector3 dir, int iff, Vector3 source)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			SosigLink val = Torso(s);
			if (!((Object)(object)val == (Object)null))
			{
				Damage val2 = Make((DamageClass)1, ((Component)val).transform.position, dir, iff, source);
				val2.Dam_Blunt = bo2Damage * 1.6f;
				Totals(val2);
				val.Damage(val2);
			}
		}

		public static void Gib(Sosig s, int iff, DamageClass cls)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			Kill(s, iff);
			for (int i = 0; i < s.Links.Count; i++)
			{
				if ((Object)(object)s.Links[i] != (Object)null)
				{
					s.Links[i].LinkExplodes(cls);
				}
			}
		}

		public static List<KeyValuePair<Sosig, SosigLink>> SosigsNearSorted(Vector3 centre, float range)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			List<KeyValuePair<Sosig, SosigLink>> list = new List<KeyValuePair<Sosig, SosigLink>>(SosigsNear(centre, range));
			list.Sort(delegate(KeyValuePair<Sosig, SosigLink> a, KeyValuePair<Sosig, SosigLink> b)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = ((Component)a.Value).transform.position - centre;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				Vector3 val2 = ((Component)b.Value).transform.position - centre;
				return sqrMagnitude.CompareTo(((Vector3)(ref val2)).sqrMagnitude);
			});
			return list;
		}

		public static Vector3 Away(Vector3 from, Vector3 at, Vector3 fallback)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = at - from;
			val.y = 0f;
			return (!(((Vector3)(ref val)).sqrMagnitude > 0.0001f)) ? fallback : ((Vector3)(ref val)).normalized;
		}

		public static void Launch(Sosig s, Vector3 velocity)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < s.Links.Count; i++)
			{
				SosigLink val = s.Links[i];
				if ((Object)(object)val != (Object)null && (Object)(object)val.R != (Object)null)
				{
					val.R.AddForce(velocity, (ForceMode)2);
				}
			}
		}

		public static bool Blocked(Vector3 from, Vector3 to, int blockerMask)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = to - from;
			float magnitude = ((Vector3)(ref val)).magnitude;
			return magnitude > 0.01f && Physics.Raycast(from, val / magnitude, magnitude, blockerMask, (QueryTriggerInteraction)1);
		}

		public static Damage Make(DamageClass cls, Vector3 point, Vector3 dir, int iff, Vector3 source)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			Damage val = new Damage();
			val.Class = cls;
			val.point = point;
			val.hitNormal = -dir;
			val.strikeDir = dir;
			val.damageSize = 0.1f;
			val.Source_IFF = iff;
			val.Source_Point = source;
			return val;
		}

		public static void Totals(Damage d)
		{
			d.Dam_TotalKinetic = d.Dam_Blunt + d.Dam_Piercing + d.Dam_Cutting;
			d.Dam_TotalEnergetic = d.Dam_Thermal + d.Dam_Chilling + d.Dam_EMP;
		}

		public static GameObject SpawnOn(GameObject prefab, Transform target, Vector3 point)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(prefab, point, (!((Object)(object)target != (Object)null)) ? Quaternion.identity : target.rotation);
			if ((Object)(object)target != (Object)null)
			{
				val.transform.SetParent(target, true);
			}
			return val;
		}
	}
	public class StaffFireGrenade : MonoBehaviour
	{
		[Tooltip("BO2 g_gravity: 800 in/s^2.")]
		public float Gravity = 20.32f;

		public float ArmTime = 0.5f;

		public float Fuse = 10f;

		public float CastRadius = 0.08f;

		public LayerMask BlockerMask;

		public GameObject ExplosionPrefab;

		public StaffFirePool PoolPrefab;

		public ParticleSystem[] DetachOnEnd;

		private Vector3 m_velocity;

		private float m_age;

		private bool m_stuck;

		private Vector3 m_normal = Vector3.up;

		private bool m_done;

		public void Launch(Vector3 velocity)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			m_velocity = velocity;
		}

		private void Update()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: 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_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Invalid comparison between Unknown and I4
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: 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_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: 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_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: 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_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			if (m_done)
			{
				return;
			}
			float deltaTime = Time.deltaTime;
			m_age += deltaTime;
			if ((m_stuck && m_age >= ArmTime) || m_age >= Fuse)
			{
				Explode();
			}
			else
			{
				if (m_stuck)
				{
					return;
				}
				m_velocity += Vector3.down * Gravity * deltaTime;
				Vector3 val = m_velocity * deltaTime;
				float magnitude = ((Vector3)(ref val)).magnitude;
				if (magnitude <= 0f)
				{
					return;
				}
				int num = LayerMask.op_Implicit(BlockerMask) | StaffDamage.AgentBodyMask;
				RaycastHit[] array = Physics.SphereCastAll(((Component)this).transform.position, CastRadius, val / magnitude, magnitude, num, (QueryTriggerInteraction)1);
				RaycastHit val2 = default(RaycastHit);
				bool flag = false;
				bool flag2 = false;
				for (int i = 0; i < array.Length; i++)
				{
					if (flag && ((RaycastHit)(ref array[i])).distance >= ((RaycastHit)(ref val2)).distance)
					{
						continue;
					}
					bool flag3 = ((1 << ((Component)((RaycastHit)(ref array[i])).collider).gameObject.layer) & LayerMask.op_Implicit(BlockerMask)) != 0;
					if (!flag3)
					{
						SosigLink val3 = StaffDamage.FindLink(((RaycastHit)(ref array[i])).collider);
						if ((Object)(object)val3 == (Object)null || (Object)(object)val3.S == (Object)null || (int)val3.S.BodyState == 3)
						{
							continue;
						}
					}
					val2 = array[i];
					flag = true;
					flag2 = !flag3;
				}
				if (!flag)
				{
					Transform transform = ((Component)this).transform;
					transform.position += val;
					if (((Vector3)(ref m_velocity)).sqrMagnitude > 0.01f)
					{
						((Component)this).transform.rotation = Quaternion.LookRotation(m_velocity);
					}
					return;
				}
				Vector3 val4 = ((!(((RaycastHit)(ref val2)).point == Vector3.zero)) ? ((RaycastHit)(ref val2)).point : (((Component)this).transform.position + val / magnitude * ((RaycastHit)(ref val2)).distance));
				Vector3 val5 = ((!(((RaycastHit)(ref val2)).normal == Vector3.zero)) ? ((RaycastHit)(ref val2)).normal : (-val / magnitude));
				if (flag2)
				{
					((Component)this).transform.position = val4 + val5 * (CastRadius + 0.02f);
					m_velocity = Vector3.Reflect(m_velocity, val5) * 0.3f;
					return;
				}
				((Component)this).transform.position = val4 + val5 * 0.05f;
				m_normal = val5;
				m_stuck = true;
				m_velocity = Vector3.zero;
			}
		}

		private void Explode()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			m_done = true;
			Vector3 position = ((Component)this).transform.position;
			Quaternion val = Quaternion.LookRotation(m_normal);
			if ((Object)(object)ExplosionPrefab != (Object)null)
			{
				Object.Instantiate<GameObject>(ExplosionPrefab, position, val);
			}
			if ((Object)(object)PoolPrefab != (Object)null)
			{
				Object.Instantiate<GameObject>(((Component)PoolPrefab).gameObject, position, Quaternion.identity);
			}
			GM.CurrentSceneSettings.PingReceivers(position);
			if (DetachOnEnd != null)
			{
				for (int i = 0; i < DetachOnEnd.Length; i++)
				{
					ParticleSystem val2 = DetachOnEnd[i];
					if (!((Object)(object)val2 == (Object)null))
					{
						((Component)val2).transform.SetParent((Transform)null, true);
						val2.Stop(true, (ParticleSystemStopBehavior)1);
						Object.Destroy((Object)(object)((Component)val2).gameObject, 2f);
					}
				}
			}
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}
	public class StaffFirePool : MonoBehaviour
	{
		[Tooltip("Metres (BO2: 80 in, level 3: 100 in).")]
		public float Radius = 2.03f;

		public float Duration = 5f;

		public float Step = 0.2f;

		[Tooltip("BO2 get_impact_damage: 11500 (level 3: 20000).")]
		public float Bo2Damage = 11500f;

		[Tooltip("BO2 get_damage_per_second: 300 (level 3: 450), for 8 s.")]
		public float Bo2BurnPerSecond = 300f;

		public float BurnTime = 8f;

		public LayerMask BlockerMask;

		[Header("Effects")]
		public GameObject BodyFlamesPrefab;

		public GameObject FinalBurstPrefab;

		public Light PoolLight;

		public AudioSource Loop;

		public ParticleSystem[] StopOnEnd;

		private float m_lightBase;

		private IEnumerator Start()
		{
			int iff = GM.CurrentPlayerBody.GetPlayerIFF();
			if ((Object)(object)PoolLight != (Object)null)
			{
				m_lightBase = PoolLight.intensity;
			}
			Vector3 centre = ((Component)this).transform.position;
			float left = Duration;
			while (left > 0f)
			{
				float radius = ((!(left - Step <= 0f)) ? Radius : (Radius * 2f));
				List<KeyValuePair<Sosig, SosigLink>> near = StaffDamage.SosigsNearSorted(centre, radius);
				yield return (object)new WaitForSeconds(Step);
				left -= Step;
				foreach (KeyValuePair<Sosig, SosigLink> item in near)
				{
					Sosig key = item.Key;
					if (!((Object)(object)key == (Object)null) && (int)key.BodyState != 3 && !StaffDamage.Blocked(centre + Vector3.up * 0.3f, ((Component)item.Value).transform.position, LayerMask.op_Implicit(BlockerMask)))
					{
						Flame(key, centre, iff);
					}
				}
			}
			if ((Object)(object)FinalBurstPrefab != (Object)null)
			{
				Object.Instantiate<GameObject>(FinalBurstPrefab, centre, Quaternion.identity);
			}
			if ((Object)(object)Loop != (Object)null)
			{
				Loop.Stop();
			}
			if (StopOnEnd != null)
			{
				for (int i = 0; i < StopOnEnd.Length; i++)
				{
					if ((Object)(object)StopOnEnd[i] != (Object)null)
					{
						StopOnEnd[i].Stop(true, (ParticleSystemStopBehavior)1);
					}
				}
			}
			if ((Object)(object)PoolLight != (Object)null)
			{
				((Behaviour)PoolLight).enabled = false;
			}
			Object.Destroy((Object)(object)((Component)this).gameObject, 2.5f);
		}

		private void Update()
		{
			if ((Object)(object)PoolLight != (Object)null && ((Behaviour)PoolLight).enabled)
			{
				PoolLight.intensity = m_lightBase * (0.75f + 0.5f * Mathf.PerlinNoise(Time.time * 7f, 0.3f));
			}
		}

		private void Flame(Sosig s, Vector3 centre, int iff)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			SosigLink val = StaffDamage.Torso(s);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (StaffDamage.WouldKill(s, Bo2Damage))
			{
				if (Random.value < 0.5f)
				{
					StaffDamage.Gib(s, iff, (DamageClass)2);
					return;
				}
				StaffDamage.SpawnOn(BodyFlamesPrefab, ((Component)val).transform, ((Component)val).transform.position);
				StaffDamage.Kill(s, iff);
			}
			else
			{
				StaffBurn.Apply(s, Bo2BurnPerSecond, BurnTime, iff, BodyFlamesPrefab);
				StaffDamage.Hurt(s, Bo2Damage, StaffDamage.Away(centre, ((Component)val).transform.position, Vector3.forward), iff, centre);
			}
		}
	}
	public class StaffFreeze : MonoBehaviour
	{
		public static bool IsOnIce(Sosig s)
		{
			return (Object)(object)((Component)s).GetComponent<StaffFreeze>() != (Object)null;
		}

		public static void Apply(Sosig s, float bo2Damage, int iff, Vector3 source, GameObject icicle, GameObject frost, GameObject shatter)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			Apply(s, bo2Damage, iff, source, icicle, frost, shatter, new Vector2(1.8f, 2.3f), alwaysKill: false);
		}

		public static void Apply(Sosig s, float bo2Damage, int iff, Vector3 source, GameObject icicle, GameObject frost, GameObject shatter, Vector2 delay, bool alwaysKill)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)s == (Object)null) && !IsOnIce(s) && (int)s.BodyState != 3)
			{
				StaffFreeze staffFreeze = ((Component)s).gameObject.AddComponent<StaffFreeze>();
				((MonoBehaviour)staffFreeze).StartCoroutine(staffFreeze.Run(s, bo2Damage, iff, source, icicle, frost, shatter, delay, alwaysKill));
			}
		}

		private IEnumerator Run(Sosig s, float bo2Damage, int iff, Vector3 source, GameObject icicle, GameObject frost, GameObject shatter, Vector2 delay, bool alwaysKill)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			SosigLink torso = StaffDamage.Torso(s);
			Vector3 val2;
			if ((Object)(object)torso != (Object)null)
			{
				Vector3 val = ((Component)torso).transform.position - source;
				val2 = ((Vector3)(ref val)).normalized;
			}
			else
			{
				val2 = Vector3.forward;
			}
			Vector3 dir = val2;
			GameObject stuck = null;
			if ((Object)(object)torso != (Object)null)
			{
				stuck = StaffDamage.SpawnOn(icicle, ((Component)torso).transform, ((Component)torso).transform.position - dir * 0.08f);
				if ((Object)(object)stuck != (Object)null)
				{
					stuck.transform.rotation = Quaternion.LookRotation(dir);
				}
				StaffDamage.SpawnOn(frost, ((Component)torso).transform, ((Component)torso).transform.position);
			}
			Debug.Log((object)("[OriginsStaffs] Ice: froze " + ((Object)s).name));
			s.ActivatePower((PowerupType)15, (PowerUpIntensity)0, (PowerUpDuration)2, false, true);
			yield return (object)new WaitForSeconds(Random.Range(delay.x, delay.y));
			if ((Object)(object)s == (Object)null || (int)s.BodyState == 3)
			{
				Finish(stuck);
				yield break;
			}
			if (alwaysKill || StaffDamage.WouldKill(s, bo2Damage))
			{
				Vector3 point = ((!((Object)(object)torso != (Object)null)) ? ((Component)s).transform.position : ((Component)torso).transform.position);
				StaffDamage.SpawnOn(shatter, null, point);
				Debug.Log((object)("[OriginsStaffs] Ice: shattered " + ((Object)s).name));
				StaffDamage.Gib(s, iff, (DamageClass)1);
				Finish(stuck);
				yield break;
			}
			s.ActivatePower((PowerupType)15, (PowerUpIntensity)0, (PowerUpDuration)2, false, false);
			StaffDamage.Hurt(s, bo2Damage, dir, iff, source);
			Debug.Log((object)("[OriginsStaffs] Ice: " + ((Object)s).name + " too tough to shatter, took the hit and thawed"));
			if ((Object)(object)stuck != (Object)null)
			{
				Object.Destroy((Object)(object)stuck);
			}
			yield return (object)new WaitForSeconds(0.5f);
			Finish(null);
		}

		private void Finish(GameObject stuck)
		{
			if ((Object)(object)stuck != (Object)null)
			{
				Object.Destroy((Object)(object)stuck, 1f);
			}
			Object.Destroy((Object)(object)this);
		}
	}
	[RequireComponent(typeof(AudioSource))]
	public class StaffImpactSound : MonoBehaviour
	{
		public AudioClip[] Clips;

		public Vector2 VolumeRange = new Vector2(0.9f, 0.9f);

		public Vector2 PitchRange = new Vector2(1f, 1f);

		private void Start()
		{
			if (Clips != null && Clips.Length != 0)
			{
				AudioSource component = ((Component)this).GetComponent<AudioSource>();
				component.clip = Clips[Random.Range(0, Clips.Length)];
				component.volume = Random.Range(VolumeRange.x, VolumeRange.y);
				component.pitch = Random.Range(PitchRange.x, PitchRange.y);
				component.Play();
			}
		}
	}
	public class StaffLever : MonoBehaviour
	{
		public enum Phase
		{
			Closed,
			Unlocked,
			Pulling,
			Cycling,
			Out,
			Seating
		}

		public OriginsStaff Staff;

		public StaffReloadRig Rig;

		[Tooltip("Full pump stroke (m).")]
		public float Travel = 0.08f;

		[Tooltip("Fraction of the stroke after which the pull completes itself.")]
		[Range(0.2f, 1f)]
		public float PullSnap = 0.6f;

		[Tooltip("Fraction of the stroke back towards home after which the push completes itself.")]
		[Range(0.2f, 1f)]
		public float PushSnap = 0.5f;

		[Tooltip("Speed (m/s) the lever springs to the stop or home once a pull or push snaps.")]
		public float SnapSpeed = 2.5f;

		[Tooltip("Speed (m/s) the lever springs home when the handle hand lets go mid-pull.")]
		public float ReturnSpeed = 1.5f;

		[Tooltip("How fast (m/s) the resting hand gap may shrink without counting as a pull, so slow drift is ignored.")]
		public float RestDrift = 0.05f;

		[Tooltip("Playback speed of BO2's automatic reload segments (1 = BO2's 30 fps).")]
		public float AnimSpeed = 1f;

		[Tooltip("Playback speed of the rest of the spin when the lever is pushed home early.")]
		public float RushSpeed = 4f;

		[Tooltip("A haptic tick every this many metres of pull.")]
		public float TickSpacing = 0.015f;

		[Tooltip("Unlock the lever by itself when the crystal runs dry. Off: play-testing wanted the release press every time.")]
		public bool AutoUnlockWhenEmpty = false;

		[Header("BO2 reload frames (30 fps)")]
		public float FrameUnlocked = 12.6f;

		public float FramePullStart = 12f;

		public float FrameTubeBack = 16f;

		public float FrameSpinEnd = 45f;

		public float FrameSeated = 50f;

		public float FrameHome = 57f;

		public float FrameCue1 = 14f;

		public float FrameCue2 = 29f;

		public float FrameCue3 = 43f;

		[Header("Audio")]
		public AudioEvent AudEvent_Unlock;

		public AudioEvent AudEvent_Lock;

		public AudioEvent AudEvent_Cue1;

		public AudioEvent AudEvent_Cue2;

		public AudioEvent AudEvent_Cue3;

		public AudioEvent AudEvent_Cue4;

		private Phase m_phase = Phase.Closed;

		private float m_homeZ;

		private float m_offset;

		private float m_frame;

		private float m_restGap;

		private bool m_hasRest;

		private float m_pushBase;

		private float m_lastTick;

		private bool m_cue1;

		private bool m_cue2;

		private bool m_cue3;

		private bool m_recharged;

		private bool m_pushQueued;

		private bool m_atStop;

		private bool m_autoUnlocked;

		public Phase CurrentPhase => m_phase;

		public bool IsClosed => m_phase == Phase.Closed;

		public float GlowMultiplier
		{
			get
			{
				if (m_phase == Phase.Cycling)
				{
					return 1.6f + 0.4f * Mathf.Sin(Time.time * 25f);
				}
				if (m_phase == Phase.Out)
				{
					return 1.3f;
				}
				return 1f;
			}
		}

		private void Awake()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			m_homeZ = ((Component)this).transform.localPosition.z;
		}

		public void PressRelease()
		{
			if (m_phase == Phase.Closed)
			{
				Unlock();
			}
			else if (m_phase == Phase.Unlocked)
			{
				Lock(audible: true);
			}
		}

		public void OnTriggerHandReleased()
		{
			if (m_phase == Phase.Unlocked && Staff.Charges > 0)
			{
				Lock(audible: false);
			}
		}

		public void Tick(bool pumping, float gap, float dt)
		{
			//IL_04e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0502: Unknown result type (might be due to invalid IL or missing references)
			float num = ((!((Object)(object)Rig != (Object)null)) ? 30f : Rig.FramesPerSecond);
			if (Staff.Charges > 0)
			{
				m_autoUnlocked = false;
			}
			switch (m_phase)
			{
			case Phase.Closed:
				m_offset = 0f;
				m_frame = 0f;
				m_hasRest = false;
				if (AutoUnlockWhenEmpty && Staff.Charges == 0 && !m_autoUnlocked)
				{
					m_autoUnlocked = true;
					Unlock();
				}
				break;
			case Phase.Unlocked:
				m_frame = FrameUnlocked;
				FollowPull(pumping, gap, dt);
				if (m_offset > 0.003f)
				{
					m_phase = Phase.Pulling;
					m_cue1 = (m_cue2 = (m_cue3 = (m_recharged = (m_pushQueued = (m_atStop = false)))));
					m_lastTick = m_offset;
				}
				break;
			case Phase.Pulling:
			{
				FollowPull(pumping, gap, dt);
				float num3 = Mathf.Clamp01(m_offset / (Travel * PullSnap));
				m_frame = Mathf.Lerp(FramePullStart, FrameTubeBack, num3);
				CueAt(ref m_cue1, FrameCue1, AudEvent_Cue1, strong: true);
				if (Mathf.Abs(m_offset - m_lastTick) >= TickSpacing)
				{
					m_lastTick = m_offset;
					Staff.BuzzTriggerHand(strong: false);
				}
				if (num3 >= 1f)
				{
					m_phase = Phase.Cycling;
					m_frame = FrameTubeBack;
					m_atStop = false;
					CueAt(ref m_cue1, 0f, AudEvent_Cue1, strong: true);
					Staff.BuzzTriggerHand(strong: true);
				}
				else if (m_offset <= 0.0015f)
				{
					m_phase = Phase.Unlocked;
					m_offset = 0f;
				}
				break;
			}
			case Phase.Cycling:
			case Phase.Out:
				if (m_pushQueued || !pumping)
				{
					m_pushQueued = true;
					m_offset = Mathf.MoveTowards(m_offset, 0f, SnapSpeed * dt);
				}
				else if (!m_atStop)
				{
					m_offset = Mathf.MoveTowards(m_offset, Travel, SnapSpeed * dt);
					if (m_offset >= Travel)
					{
						m_atStop = true;
						m_pushBase = gap;
					}
				}
				else
				{
					m_pushBase = Mathf.Min(m_pushBase, gap);
					float num2 = Mathf.Clamp(Travel - (gap - m_pushBase), 0f, Travel);
					m_offset = Mathf.MoveTowards(m_offset, num2, 6f * dt);
					if (m_offset <= Travel * (1f - PushSnap))
					{
						m_pushQueued = true;
						Staff.BuzzTriggerHand(strong: true);
					}
				}
				if (m_phase == Phase.Cycling)
				{
					m_frame += dt * num * ((!m_pushQueued) ? AnimSpeed : RushSpeed);
					CueAt(ref m_cue2, FrameCue2, AudEvent_Cue2, strong: false);
					CueAt(ref m_cue3, FrameCue3, AudEvent_Cue3, strong: false);
					if (m_frame >= FrameSpinEnd)
					{
						m_frame = FrameSpinEnd;
						m_phase = ((!m_pushQueued) ? Phase.Out : Phase.Seating);
						if (!m_pushQueued)
						{
							Staff.BuzzTriggerHand(strong: false);
						}
					}
				}
				else if (m_pushQueued)
				{
					m_phase = Phase.Seating;
				}
				break;
			case Phase.Seating:
				m_offset = Mathf.MoveTowards(m_offset, 0f, SnapSpeed * dt);
				m_frame += dt * num * AnimSpeed;
				if (!m_recharged && m_frame >= FrameSeated)
				{
					m_recharged = true;
					Play(AudEvent_Cue4);
					Staff.BuzzTriggerHand(strong: true);
					Staff.Recharge();
				}
				if (m_frame >= FrameHome && m_offset <= 0f)
				{
					m_phase = Phase.Closed;
					m_frame = 0f;
				}
				break;
			}
			Vector3 localPosition = ((Component)this).transform.localPosition;
			localPosition.z = m_homeZ - m_offset;
			((Component)this).transform.localPosition = localPosition;
			if ((Object)(object)Rig != (Object)null)
			{
				Rig.Sample(Mathf.Min(m_frame, FrameHome));
			}
		}

		private void FollowPull(bool pumping, float gap, float dt)
		{
			if (!pumping)
			{
				m_hasRest = false;
				m_offset = Mathf.MoveTowards(m_offset, 0f, ReturnSpeed * dt);
				return;
			}
			if (!m_hasRest)
			{
				m_restGap = gap;
				m_hasRest = true;
			}
			m_restGap = Mathf.Max(gap, m_restGap - RestDrift * dt);
			float num = Mathf.Clamp(m_restGap - gap, 0f, Travel);
			m_offset = Mathf.MoveTowards(m_offset, num, 6f * dt);
		}

		private void Unlock()
		{
			m_phase = Phase.Unlocked;
			m_hasRest = false;
			Play(AudEvent_Unlock);
			Staff.BuzzTriggerHand(strong: false);
		}

		private void Lock(bool audible)
		{
			m_phase = Phase.Closed;
			m_offset = 0f;
			m_frame = 0f;
			if (audible)
			{
				Play(AudEvent_Lock);
				Staff.