BepInEx/plugins/Kulfs-Jak/JakSurvivor.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Logging;
using EntityStates;
using JakSurvivor.States;
using KinematicCharacterController;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.Audio;
using RoR2.ContentManagement;
using RoR2.Projectile;
using RoR2.Skills;
using RoR2.SurvivorMannequins;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.ResourceManagement.AsyncOperations;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("JakSurvivor.DevTools")]
[assembly: InternalsVisibleTo("JakSurvivor.Editor")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace JakSurvivor
{
	public sealed class ArcWielderSkillDef : SkillDef
	{
		public override bool CanExecute(GenericSkill slot)
		{
			if (!((SkillDef)this).IsAlreadyInState(slot) && JakWeaponCombat.CanUseWeapons(slot.characterBody))
			{
				return ((SkillDef)this).CanExecute(slot);
			}
			return false;
		}
	}
	public static class Balance
	{
		public readonly struct ClawStep
		{
			public readonly string Clip;

			public readonly float Duration;

			public readonly float HitStart;

			public readonly float HitEnd;

			public readonly float Damage;

			public readonly bool Finisher;

			public readonly Vector3 SlashPosition;

			public readonly Vector3 SlashRotation;

			public readonly Vector3 SlashScale;

			public ClawStep(string clip, float duration, float hitStart, float hitEnd, float damage, bool finisher, Vector3 slashPosition, Vector3 slashRotation, float slashScale)
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//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)
				//IL_0045: 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)
				Clip = clip;
				Duration = duration;
				HitStart = hitStart;
				HitEnd = hitEnd;
				Damage = damage;
				Finisher = finisher;
				SlashPosition = slashPosition;
				SlashRotation = slashRotation;
				SlashScale = Vector3.one * slashScale;
			}
		}

		public const float BlasterDamage = 2.4f;

		public const float BlasterDuration = 0.3f;

		public const float ScatterCooldown = 5f;

		public const float ArcDamage = 1.6f;

		public const float ArcInterval = 0.4f;

		public const float ArcDamageRetention = 0.75f;

		public const float ArcProc = 0.5f;

		public const int WaveStocks = 2;

		public const float WaveCooldown = 5f;

		public const float WaveMinimumCharge = 0.1f;

		public const float WaveFullCharge = 1f;

		public const float WaveAutoReleaseDelay = 9.95f;

		public const float WaveBaseRadius = 3f;

		public const float WaveRadiusGain = 15f;

		public const float WaveMinimumDamage = 2f;

		public const float WaveFullDamage = 10f;

		public const float WaveOuterRetention = 0.5f;

		public const float WaveProc = 1f;

		public const float WaveExpansionDuration = 0.7f;

		public const float WaveRecoveryDuration = 0.3f;

		public const float WaveForce = 500f;

		public const float SpinDamage = 3.5f;

		public const float SpinProc = 0.5f;

		public const float SpinCooldown = 3f;

		public const float SpinForce = 800f;

		public const float SpinRadius = 4f;

		public const float DarkBlastDamage = 8f;

		public const float DarkBlastProc = 1f;

		public const float DarkBlastCooldown = 3f;

		public const float RollCooldown = 4f;

		public const float BoardDuration = 4f;

		public const float BoardSpeed = 2.64f;

		public const float BoardMinimumRide = 1f;

		public const float BoardCooldown = 6f;

		public const float DarkDuration = 10f;

		public const float DarkCooldown = 24f;

		public const float DarkArmor = 30f;

		public const float DarkMoveBonus = 0.2f;

		public static readonly Vector3 ClawHitBoxCenter = new Vector3(0f, 1.2f, 2.5f);

		public static readonly Vector3 ClawHitBoxSize = new Vector3(4f, 3f, 6f);

		public static readonly ClawStep[] ClawCombo = new ClawStep[3]
		{
			new ClawStep("jakb-darkjak-attack-combo1", 0.333333f, 0.62f, 0.82f, 1.6f, finisher: false, new Vector3(0f, 1.2f, 0.2f), new Vector3(55f, 90f, 90f), 0.405429f),
			new ClawStep("jakb-darkjak-attack-combo2", 0.466666f, 0.76f, 0.92f, 1.9f, finisher: false, new Vector3(0f, 1.2f, 0.2f), new Vector3(20f, 90f, 90f), 0.405429f),
			new ClawStep("jakb-darkjak-attack-combo3c", 0.666664f, 0.7f, 0.82f, 3f, finisher: true, new Vector3(0f, 1.7f, 1f), new Vector3(0f, 90f, 0f), 0.282857f)
		};

		public const float ClawStepGrace = 0.4f;

		public const float DarkBombDamage = 8f;

		public const float DarkBombRadius = 14f;
	}
	public sealed class DarkBlastSkillDef : SkillDef
	{
		private sealed class Instance : BaseSkillInstanceData
		{
			public EntityStateMachine Weapon;
		}

		public override BaseSkillInstanceData OnAssigned(GenericSkill slot)
		{
			return (BaseSkillInstanceData)(object)new Instance
			{
				Weapon = EntityStateMachine.FindByCustomName(((Component)slot).gameObject, "Weapon")
			};
		}

		public override bool CanExecute(GenericSkill slot)
		{
			if (((SkillDef)this).CanExecute(slot) && slot.skillInstanceData is Instance instance && Object.op_Implicit((Object)(object)instance.Weapon))
			{
				return instance.Weapon.CanInterruptState((InterruptPriority)1);
			}
			return false;
		}
	}
	public sealed class DarkBombSkillDef : SkillDef
	{
		public override int GetMaxStock(GenericSkill slot)
		{
			return slot.baseSkill.GetMaxStock(slot);
		}

		public override int GetRechargeStock(GenericSkill slot)
		{
			return slot.baseSkill.GetRechargeStock(slot);
		}

		public override float GetRechargeInterval(GenericSkill slot)
		{
			return slot.baseSkill.GetRechargeInterval(slot);
		}

		public override float GetRechargeRate(GenericSkill slot)
		{
			return slot.baseSkill.GetRechargeRate(slot);
		}
	}
	public sealed class DarkJakSkillDef : SkillDef
	{
		public override bool IsReady(GenericSkill slot)
		{
			if (((SkillDef)this).IsReady(slot))
			{
				return !slot.characterBody.HasBuff(JakContent.DarkBuff);
			}
			return false;
		}
	}
	internal static class Icons
	{
		public static Sprite Blaster => JakAssets.Get<Sprite>("blaster");

		public static Sprite Scatter => JakAssets.Get<Sprite>("scatter");

		public static Sprite ArcWielder => JakAssets.Get<Sprite>("arc_wielder");

		public static Sprite WaveConcussor => JakAssets.Get<Sprite>("wave_concussor");

		public static Sprite Spin => JakAssets.Get<Sprite>("spin");

		public static Sprite Roll => JakAssets.Get<Sprite>("roll");

		public static Sprite Board => JakAssets.Get<Sprite>("board");

		public static Sprite Dark => JakAssets.Get<Sprite>("jak3-icon-dark");

		public static Sprite Claws => JakAssets.Get<Sprite>("jak3-icon-claws");

		public static Sprite DarkBlast => JakAssets.Get<Sprite>("jak3-icon-blast");

		public static Sprite Bomb => JakAssets.Get<Sprite>("jak3-icon-bomb");

		public static Sprite Passive => JakAssets.Get<Sprite>("passive");

		public static Sprite DarkBuff => JakAssets.Get<Sprite>("buff_dark");

		public static Sprite Skin => JakAssets.Get<Sprite>("skin_default");

		public static Sprite Portrait => JakAssets.Get<Sprite>("jak3-portrait");
	}
	internal readonly struct JakShot
	{
		public readonly Ray Ray;

		public readonly bool Spinning;

		public JakShot(Ray ray, bool spinning)
		{
			//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)
			Ray = ray;
			Spinning = spinning;
		}

		public float Interval(float normal)
		{
			if (!Spinning)
			{
				return normal;
			}
			return 0.1f;
		}
	}
	internal static class JakAim
	{
		public static JakShot Shot(EntityStateMachine body, Ray aim)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)body) || !(body.state is SpinAttack spinAttack) || !spinAttack.TryAim(aim, out var shot))
			{
				return new JakShot(aim, spinning: false);
			}
			return new JakShot(shot, spinning: true);
		}

		public static bool SpinOwnsGun(EntityStateMachine body)
		{
			if (Object.op_Implicit((Object)(object)body) && body.state is SpinAttack { Timeline: var timeline } spinAttack)
			{
				return timeline.OwnsGun(spinAttack.Age);
			}
			return false;
		}
	}
	public enum JakWeaponMode
	{
		Blaster,
		ArcWielder,
		WaveConcussor
	}
	internal static class JakAnimator
	{
		public static class Layers
		{
			public const string Body = "Body";

			public const string FullBody = "FullBody, Override";

			public const string Gesture = "Gesture, Override";

			public const string Transformation = "Transformation, Override";

			public const string AimPitch = "AimPitch";

			public const string AimYaw = "AimYaw";

			public const string BodyAction = "BodyAction";

			public const string Gun = "Gun";

			public const string Board = "Board";
		}

		public static class States
		{
			public const string Empty = "Empty";

			public const string Idle = "Idle";

			public const string Run = "Run";

			public const string Jump = "Jump";

			public const string Roll = "Roll";

			public const string RollLeap = "RollLeap";

			public const string BonusJump = "BonusJump";

			public const string AscendDescend = "AscendDescend";

			public const string Land = "Land";

			public const string Death = "Death";

			public static readonly string[] ClawCombo = new string[3] { "ClawCombo1", "ClawCombo2", "ClawCombo3" };

			public const string Bomb = "Bomb";

			public const string DarkEnter = "DarkEnter";

			public const string DarkExit = "DarkExit";

			public const string DarkExitEnd = "DarkExitEnd";

			public const string DarkExitBomb = "DarkExitBomb";

			public const string BoardOn = "BoardOn";

			public const string BoardOff = "BoardOff";

			public const string FireBlaster = "FireBlaster";

			public const string BlasterHold = "BlasterHold";

			public const string FireScatter = "FireScatter";

			public const string ArcStart = "ArcStart";

			public const string ArcLoop = "ArcLoop";

			public const string WaveCharge = "WaveCharge";

			public const string WaveChargeLoop = "WaveChargeLoop";

			public const string WaveRelease = "WaveRelease";

			public const string PitchControl = "PitchControl";

			public const string YawControl = "YawControl";

			public const string BoardOpen = "Open";

			public const string BoardClose = "Close";
		}

		public static class Parameters
		{
			public const string Form = "form";

			public const string MoveForward = "moveForward";

			public const string MoveRight = "moveRight";

			public const string WeaponMode = "weaponMode";

			public const string ArcRate = "Arc.playbackRate";

			public const string WaveRate = "Wave.playbackRate";

			public const string BlasterRate = "Blaster.playbackRate";

			public const string ScatterRate = "Scatter.playbackRate";

			public const string ClawRate = "Claw.playbackRate";

			public const string BombRate = "Bomb.playbackRate";

			public const string TransformRate = "Transform.playbackRate";

			public const string BoardRate = "Board.playbackRate";

			public const string SpinRate = "Spin.playbackRate";

			public const string RollRate = "Roll.playbackRate";

			public const string JumpRate = "Jump.playbackRate";

			public const string ClawHitBoxActive = "Claw.hitBoxActive";
		}

		public static class Spin
		{
			public const string DataAsset = "Jak3Spin";

			public const string HitBoxGroup = "JakSpin";

			public static readonly string[] EndStates = (from i in Enumerable.Range(0, JakSpinRecipe.Count)
				select (JakSpinVariant)i into v
				where JakSpinRecipe.Get(v).EndOverlay != null
				select v).Select(EndState).ToArray();

			public static string State(JakSpinVariant variant)
			{
				return "Spin" + variant;
			}

			public static string EndState(JakSpinVariant variant)
			{
				return "SpinEnd" + JakSpinRecipe.Get(variant).Form;
			}
		}

		public static class Blast
		{
			public const string Charge = "BlastCharge";

			public const string Release = "BlastRelease";

			public const string Recovery = "BlastRecovery";

			public const string Rate = "Blast.playbackRate";

			public static readonly string[] States = new string[3] { "BlastCharge", "BlastRelease", "BlastRecovery" };
		}

		public static class Bomb
		{
			public const float Duration = 0.9f;

			public const float ImpactFraction = 0.5f;

			public const float ImpactSourceTime = 1f / 30f;

			public const float LandingBlend = 0.05f;

			public const float FallTime = 0.36666664f;

			public const string Clip = "jakb-darkjak-bomb@sequence";

			public static void Sample(float time, float windupLength, float landingLength, out float windupTime, out float landingTime, out float landingWeight)
			{
				windupTime = Mathf.Clamp01(time / 0.36666664f) * windupLength;
				landingTime = ((time <= 0.45f) ? Mathf.Max(0f, time - 5f / 12f) : Mathf.Lerp(1f / 30f, landingLength, (time - 0.45f) / 0.45f));
				landingWeight = Mathf.Clamp01((time - 0.36666664f) / 0.05f);
			}
		}

		public static class Weapon
		{
			public const int ArcFrames = 7;

			public const int WaveFrames = 21;

			public const float WaveLoopStartFrame = 5f;

			public const float WaveLoopEndFrame = 8.5f;

			public const float WaveReleaseFrame = 10f;

			public const string ArcBody = "jakb-gun-blue-fire-2";

			public const string ArcGun = "gun-gun-blue-fire-2";

			public const string ArcStance = "jakb-gun-blue-stance-2";

			public const string ArcIdle = "jakb-gun-stance-blue";

			public const string WaveBody = "jakb-gun-red-fire-2";

			public const string WaveGun = "gun-gun-red-fire-2";

			public const string ChargeStart = "@charge-start";

			public const string ChargeLoop = "@charge-loop";

			public const string Release = "@release";

			public static readonly string[] RequiredBodyClips = new string[4] { "jakb-gun-stance-blue", "jakb-gun-blue-stance-2", "jakb-gun-blue-fire-2", "jakb-gun-red-fire-2" };

			public static readonly string[] RequiredGunClips = new string[4] { "gun-idle-blue2", "gun-gun-blue-fire-2", "gun-idle-red2", "gun-gun-red-fire-2" };

			public static readonly string[] ArcLocomotion = new string[7] { "jakb-gun-front-run", "jakb-jump@armed", "jakb-jump-forward@armed", "jakb-jump-double@armed", "jakb-jump-forward-double@armed", "jakb-jump-fall@armed", "jakb-gun-jump-land" };

			public static readonly string[] ActionStates = new string[5] { "ArcStart", "ArcLoop", "WaveCharge", "WaveChargeLoop", "WaveRelease" }.Concat(Spin.EndStates).ToArray();

			public static float FrameTime(float duration, int frames, float frame)
			{
				return duration * frame / (float)(frames - 1);
			}

			public static string ArcClip(string locomotion)
			{
				return locomotion.Replace("@armed", "") + "@arc";
			}
		}

		public static readonly string[] ControllerLayers = new string[9] { "Body", "FullBody, Override", "Transformation, Override", "Gesture, Override", "AimPitch", "AimYaw", "BodyAction", "Gun", "Board" };

		public static readonly string[] PoseLayers = new string[5] { "BodyAction", "Gesture, Override", "Transformation, Override", "FullBody, Override", "Body" };

		public const float JumpAirTime = 1f / 3f;

		public const float BoardAirTime = 0.25f;

		public const float BlasterHoldTime = 0.1f;

		public const float Armed = 0f;

		public const float Dark = 1f;

		public const float Board = 2f;

		public const string BodyController = "animJak";

		public const string DisplayController = "animJakDisplay";

		public const string ModelPrefab = "mdlJak";

		public const string DisplayPrefab = "JakDisplay";

		public const string DrawOffset = "Jak3DrawOffset";

		public const string ClawHitBoxGroup = "JakClaws";

		public static readonly string[] ClawSlashChildren = new string[3] { "ClawSlash0", "ClawSlash1", "ClawSlash2" };

		public static void ArcStart(Animator animator, float sampledRate)
		{
			PlayWeaponAction(animator, "ArcStart", "Arc.playbackRate", sampledRate);
		}

		public static void ArcLoop(Animator animator, float sampledRate)
		{
			PlayWeaponAction(animator, "ArcLoop", "Arc.playbackRate", sampledRate);
		}

		public static void WaveCharge(Animator animator, float sampledRate, float normalizedTime = 0f)
		{
			if (Object.op_Implicit((Object)(object)animator))
			{
				float num = ClipLength(animator, "jakb-gun-red-fire-2@charge-start");
				float num2 = ClipLength(animator, "jakb-gun-red-fire-2@charge-loop");
				float num3 = Mathf.Clamp01(normalizedTime) * 1f;
				bool flag = num3 >= num;
				float normalizedTime2 = (flag ? (Mathf.Repeat(num3 - num, num2) / num2) : (num3 / num));
				PlayWeaponAction(animator, flag ? "WaveChargeLoop" : "WaveCharge", "Wave.playbackRate", sampledRate, normalizedTime2);
			}
		}

		public static void WaveRelease(Animator animator, float sampledRate)
		{
			PlayWeaponAction(animator, "WaveRelease", "Wave.playbackRate", sampledRate);
		}

		public static void StopWeaponAction(Animator animator)
		{
			if (Object.op_Implicit((Object)(object)animator))
			{
				int layerIndex = animator.GetLayerIndex("Gesture, Override");
				int layerIndex2 = animator.GetLayerIndex("Gun");
				if (layerIndex >= 0 && layerIndex2 >= 0)
				{
					animator.SetFloat("Arc.playbackRate", 1f);
					animator.SetFloat("Wave.playbackRate", 1f);
					animator.Play("Empty", layerIndex, 0f);
					animator.Play("Idle", layerIndex2, 0f);
				}
			}
		}

		public static bool HasWeaponAction(Animator animator)
		{
			//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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)animator))
			{
				return false;
			}
			int layerIndex = animator.GetLayerIndex("Gesture, Override");
			if (layerIndex < 0)
			{
				return false;
			}
			string[] actionStates = Weapon.ActionStates;
			foreach (string text in actionStates)
			{
				AnimatorStateInfo val = animator.GetCurrentAnimatorStateInfo(layerIndex);
				if (!((AnimatorStateInfo)(ref val)).IsName(text))
				{
					if (!animator.IsInTransition(layerIndex))
					{
						continue;
					}
					val = animator.GetNextAnimatorStateInfo(layerIndex);
					if (!((AnimatorStateInfo)(ref val)).IsName(text))
					{
						continue;
					}
				}
				return true;
			}
			return false;
		}

		private static void PlayWeaponAction(Animator animator, string state, string rate, float sampledRate, float normalizedTime = 0f)
		{
			if (Object.op_Implicit((Object)(object)animator))
			{
				animator.SetFloat(rate, Mathf.Max(0.01f, sampledRate));
				animator.Play(state, animator.GetLayerIndex("Gesture, Override"), normalizedTime);
				animator.Play(state, animator.GetLayerIndex("Gun"), normalizedTime);
			}
		}

		private static float ClipLength(Animator animator, string name)
		{
			AnimationClip[] animationClips = animator.runtimeAnimatorController.animationClips;
			foreach (AnimationClip val in animationClips)
			{
				if (((Object)val).name == name)
				{
					return val.length;
				}
			}
			throw new InvalidOperationException("Required Morph Gun animation is missing: " + name);
		}
	}
	internal sealed class JakArcRope
	{
		internal struct V
		{
			internal float x;

			internal float y;

			internal float z;

			internal float Length => (float)Math.Sqrt(Dot(this, this));

			internal V Unit
			{
				get
				{
					float length = Length;
					if (!(length > 0f))
					{
						return default(V);
					}
					return this / length;
				}
			}

			internal V(float x, float y, float z)
			{
				this.x = x;
				this.y = y;
				this.z = z;
			}

			public static V operator +(V a, V b)
			{
				return new V(a.x + b.x, a.y + b.y, a.z + b.z);
			}

			public static V operator -(V a, V b)
			{
				return new V(a.x - b.x, a.y - b.y, a.z - b.z);
			}

			public static V operator *(V a, float b)
			{
				return new V(a.x * b, a.y * b, a.z * b);
			}

			public static V operator /(V a, float b)
			{
				return a * (1f / b);
			}

			internal static float Dot(V a, V b)
			{
				return a.x * b.x + a.y * b.y + a.z * b.z;
			}

			internal static V Cross(V a, V b)
			{
				return new V(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
			}

			internal static V Lerp(V a, V b, float t)
			{
				return a + (b - a) * t;
			}

			internal static V Rotate(V v, V axis, float radians)
			{
				float num = (float)Math.Cos(radians);
				return v * num + Cross(axis, v) * (float)Math.Sin(radians) + axis * (Dot(axis, v) * (1f - num));
			}

			internal static void Frame(V forward, V up, out V right, out V vertical)
			{
				right = Cross(up, forward).Unit;
				if (right.Length == 0f)
				{
					right = Cross(new V(1f, 0f, 0f), forward).Unit;
				}
				vertical = Cross(forward, right).Unit;
			}
		}

		internal interface IWorld
		{
			int Targets { get; }

			float Probe(V start, V end, float radius);

			int Target(int index, V point, out V centre, out float distance);

			bool Visible(V from, V to);
		}

		internal struct Knot
		{
			internal V Point;

			internal V Direction;

			internal float Length;
		}

		internal readonly struct Span
		{
			internal readonly V Start;

			internal readonly V End;

			internal readonly int StartId;

			internal Span(V start, V end, int startId)
			{
				Start = start;
				End = end;
				StartId = startId;
			}
		}

		internal sealed class ArcPath
		{
			internal readonly V[] Points = new V[12];

			internal readonly int[] TargetIds = new int[12];

			internal readonly Span[] Spans = new Span[12];

			internal int Count;

			internal int SpanCount;

			internal bool Terminal;

			internal float RepeatDistance => Math.Min(64f, (Points[Count - 1] - Points[0]).Length + 4f);
		}

		internal const int Knots = 12;

		internal const float KnotLength = 6f;

		internal const float TargetRadius = 4f;

		internal const float TargetDot = 0.6f;

		internal const float KeepRadius = 8f;

		internal const float SweepRadius = 1f;

		internal const float MaxTurnDegreesPerSecond = 720f;

		internal const float CarryDegreesPerSecond = 360f;

		internal const float FullReach = 66f;

		internal static float FollowSeconds = 0.025f;

		internal static float AimSeconds = 0.07f;

		internal static float GrabSeconds = 0.08f;

		internal static float ReachSpeed = 250f;

		internal readonly Knot[] Constraints = new Knot[12];

		internal readonly ArcPath Path = new ArcPath();

		private readonly int[] found = new int[12];

		private readonly int[] held = new int[12];

		private readonly int[] grabbed = new int[12];

		private readonly int[] keep = new int[1];

		private int[] occluded = new int[12];

		private readonly float[] weights = new float[12];

		private readonly V[] centres = new V[12];

		private readonly V[] offsets = new V[12];

		private V previousBody;

		private V aim;

		private V requested;

		internal float Reach { get; private set; }

		internal float RevolveAngle { get; private set; }

		internal float SwayAngle { get; private set; }

		internal void Enter(V fire, V direction, V body)
		{
			previousBody = body;
			direction = direction.Unit;
			aim = (requested = direction);
			Reach = 0f;
			Array.Clear(held, 0, 12);
			Array.Clear(grabbed, 0, 12);
			Array.Clear(weights, 0, 12);
			for (int i = 0; i < 12; i++)
			{
				Constraints[i] = new Knot
				{
					Point = fire + direction * (6f * (float)i),
					Direction = direction,
					Length = 6f
				};
			}
		}

		internal static V Follow(V from, V to, float delta, float seconds)
		{
			float num = V.Dot(from, to);
			V v = V.Cross(from, to);
			float length = v.Length;
			if (length == 0f)
			{
				if (!(num < 0f))
				{
					return from;
				}
				return to;
			}
			return V.Rotate(from, v / length, (float)Math.Atan2(length, num) * (1f - (float)Math.Exp((0f - delta) / seconds))).Unit;
		}

		internal void Constrain(float delta)
		{
			for (int i = 0; i < 11; i++)
			{
				V v = Constraints[i + 1].Point - Constraints[i].Point;
				float length = v.Length;
				v = v.Unit;
				V unit = Constraints[i].Direction.Unit;
				float num = V.Dot(v, unit);
				V v2 = V.Cross(v, unit);
				float length2 = v2.Length;
				if (length2 > 0f && held[i + 1] == 0)
				{
					float radians = Math.Min((float)Math.Atan2(length2, num) * (1f - (float)Math.Exp((0f - delta) / FollowSeconds)), 720f * delta * MathF.PI / 180f);
					v = V.Rotate(v, v2 / length2, radians).Unit;
					Constraints[i + 1].Direction = v;
					Constraints[i + 1].Point = Constraints[i].Point + v * length;
				}
			}
			for (int j = 0; j < 11; j++)
			{
				Constraints[j + 1].Point = Constraints[j].Point + (Constraints[j + 1].Point - Constraints[j].Point).Unit * Constraints[j].Length;
			}
		}

		internal void Update(V fire, V direction, V body, float delta, bool active, IWorld world, float age = -1f)
		{
			if (active)
			{
				RevolveAngle += 65536f * delta;
				SwayAngle += 65536f * delta;
			}
			V v = body - previousBody;
			previousBody = body;
			for (int i = 0; i < 12; i++)
			{
				Constraints[i].Point += v;
			}
			direction = direction.Unit;
			V v2 = V.Cross(requested, direction);
			float length = v2.Length;
			float num = (float)Math.Atan2(length, V.Dot(requested, direction));
			if (length > 0f && num <= 360f * delta * MathF.PI / 180f)
			{
				aim = V.Rotate(aim, v2 / length, num).Unit;
			}
			requested = direction;
			aim = Follow(aim, direction, delta, AimSeconds);
			direction = aim;
			Constraints[0].Point = fire;
			Constraints[0].Direction = direction;
			Reach = Math.Min(66f, (age >= 0f) ? (ReachSpeed * age) : (Reach + ReachSpeed * delta));
			Constrain(delta);
			int num2 = 11;
			while (num2 > 0 && (float)num2 * 6f > Reach)
			{
				Constraints[num2].Direction = direction;
				Constraints[num2].Point = fire + direction * ((float)num2 * 6f);
				num2--;
			}
			Array.Clear(Path.TargetIds, 0, 12);
			Path.Count = 1;
			Path.SpanCount = 0;
			Path.Terminal = false;
			for (int j = 0; j < 12; j++)
			{
				Path.Points[j] = Constraints[j].Point;
			}
			V v3 = fire - direction * 1.8f;
			V v4 = v3 + direction * 2.16f;
			float num3 = world.Probe(v3, v4, 0.1f);
			float num4 = delta / GrabSeconds;
			if (num3 >= 0f)
			{
				Path.Points[0] = V.Lerp(v3, v4, num3);
				Path.Terminal = true;
				Release(1, num4);
				Array.Clear(held, 0, 12);
				return;
			}
			Path.Spans[Path.SpanCount++] = new Span(v3, v4, 0);
			int count = 0;
			int num5 = -1;
			int num6 = 1;
			float num7 = 1f;
			for (int k = 1; k < 12; k++)
			{
				float num8 = Clamp((Reach - (float)(k - 1) * 6f) / 6f);
				if (num8 <= 0f)
				{
					break;
				}
				num6 = k + 1;
				num7 = num8;
				V v5 = Path.Points[k];
				V centre = default(V);
				keep[0] = held[k];
				bool flag = keep[0] != 0;
				V v6 = (flag ? Constraints[k - 1].Direction : Constraints[k].Direction);
				V point = (flag ? (Constraints[k - 1].Point + v6 * (6f * num7)) : V.Lerp(Constraints[k - 1].Point, v5, num7));
				int num9 = FindTarget(world, Path.Points[k - 1], Constraints[k - 1].Point, point, v6, fire, direction, count, keep, flag ? 1 : 0, out centre);
				if (num9 != 0)
				{
					found[count++] = num9;
					Path.TargetIds[k] = num9;
					num5 = k;
					V v7 = Follow(Constraints[k].Direction.Unit, (centre - Constraints[k - 1].Point).Unit, delta, GrabSeconds);
					Constraints[k].Direction = v7;
					Constraints[k].Point = Constraints[k - 1].Point + v7 * Constraints[k - 1].Length;
				}
				else
				{
					Constraints[k].Direction = (Constraints[k].Point - Constraints[k - 1].Point).Unit;
				}
				if (num9 != 0 && (weights[k] == 0f || grabbed[k] == num9))
				{
					grabbed[k] = num9;
					centres[k] = centre;
					weights[k] = Math.Min(1f, weights[k] + num4);
				}
				else
				{
					Release(k, k + 1, num4);
				}
				v5 = V.Lerp(v5, centres[k], weights[k]);
				V v8 = Path.Points[k - 1];
				if (num7 < 1f)
				{
					v5 = V.Lerp(v8, v5, num7);
				}
				num3 = world.Probe(v8, v5, 0.21f);
				if (num3 >= 0f)
				{
					v5 = V.Lerp(v8, v5, num3);
					Path.Terminal = true;
				}
				Path.Points[k] = v5;
				Path.Count++;
				Path.Spans[Path.SpanCount++] = new Span(v8, v5, (weights[k - 1] >= 1f) ? grabbed[k - 1] : 0);
				if (num3 >= 0f || num7 < 1f)
				{
					break;
				}
			}
			Release(num6, num4);
			Array.Copy(Path.TargetIds, held, 12);
			if (num5 == Path.Count - 2)
			{
				Path.Terminal = false;
			}
			for (int l = 1; l < Path.Count; l++)
			{
				V.Frame(Constraints[l].Direction, new V(0f, 1f, 0f), out var _, out var vertical);
				short num10 = (short)(int)(RevolveAngle + 6144f * (float)l);
				offsets[l] = V.Rotate(vertical, Constraints[l].Direction, (float)num10 * 9.58738E-05f).Unit * (0.5f * (1f - weights[l]));
			}
			for (int m = 1; m < Path.Count; m++)
			{
				Path.Points[m] += ((m < Path.Count - 1 || num7 >= 1f) ? offsets[m] : V.Lerp((m > 1) ? offsets[m - 1] : default(V), offsets[m], num7));
			}
		}

		private void Release(int from, float grab)
		{
			Release(from, 12, grab);
		}

		private void Release(int from, int to, float grab)
		{
			for (int i = from; i < to; i++)
			{
				weights[i] = Math.Max(0f, weights[i] - grab);
				if (weights[i] == 0f)
				{
					grabbed[i] = 0;
				}
			}
		}

		private int FindTarget(IWorld world, V from, V previous, V point, V direction, V fire, V aim, int count, int[] held, int heldCount, out V centre)
		{
			int num = 0;
			int num2;
			while (true)
			{
				num2 = 0;
				float nearest = 8f;
				centre = default(V);
				int i = 0;
				for (int targets = world.Targets; i < targets; i++)
				{
					V centre2;
					float distance;
					int num3 = world.Target(i, point, out centre2, out distance);
					if (heldCount > 0 && num3 == held[0] && !Has(found, count, num3) && OnAim(fire, aim, centre2))
					{
						distance = 0f;
					}
					else if (!Candidate(previous, direction, centre2, distance, num3, found, count, held, heldCount, nearest))
					{
						continue;
					}
					if (!Has(occluded, num, num3))
					{
						nearest = distance;
						num2 = num3;
						centre = centre2;
					}
				}
				if (num2 == 0 || world.Visible(from, centre))
				{
					break;
				}
				if (num == occluded.Length)
				{
					Array.Resize(ref occluded, num * 2);
				}
				occluded[num++] = num2;
			}
			return num2;
		}

		internal static bool Candidate(V previous, V direction, V centre, float distance, int id, int[] excluded, int count, int[] held, int heldCount, float nearest)
		{
			if (id == 0 || distance >= nearest || Has(excluded, count, id))
			{
				return false;
			}
			bool num = Has(held, heldCount, id);
			float num2 = V.Dot((centre - previous).Unit, direction);
			if (!num)
			{
				if (distance < 4f)
				{
					return num2 > 0.6f;
				}
				return false;
			}
			if (distance < 8f)
			{
				return num2 > 0f;
			}
			return false;
		}

		private static bool Has(int[] ids, int count, int id)
		{
			for (int i = 0; i < count; i++)
			{
				if (ids[i] == id)
				{
					return true;
				}
			}
			return false;
		}

		private static bool OnAim(V fire, V aim, V centre)
		{
			V v = centre - fire;
			float num = V.Dot(v, aim);
			if (num > 0f)
			{
				return (v - aim * num).Length < 1f;
			}
			return false;
		}

		internal static float Clamp(float value)
		{
			return Math.Max(0f, Math.Min(1f, value));
		}
	}
	internal struct ArcCandidate
	{
		internal readonly int Health;

		internal readonly int Box;

		internal readonly Vector3 Point;

		internal readonly float Radius;

		internal float Distance;

		internal float Score;

		internal byte Flags;

		internal ArcCandidate(int health, int box, Vector3 point, float radius = 0f)
		{
			Health = health;
			Box = box;
			Point = point;
			Radius = Math.Max(0f, radius);
			Distance = (Score = 0f);
			Flags = 0;
		}
	}
	internal struct ArcFocus
	{
		internal int Health;

		internal int Box;
	}
	internal interface IArcWorld
	{
		bool Visible(Vector3 from, int candidate);
	}
	internal static class JakArcTargeting
	{
		private const byte Eligible = 1;

		private const byte Occluded = 2;

		internal const float Reach = 88f;

		internal const float ConeDegrees = 30f;

		internal const float AirReach = 30f;

		private static readonly float ConeTangent = (float)Math.Tan(Math.PI / 6.0);

		internal static int Select(Vector3 origin, Vector3 direction, ArcCandidate[] candidates, int count, IArcWorld world, ArcFocus focus, bool airborne = false)
		{
			float num = direction.Length();
			if (num <= 0f)
			{
				return -1;
			}
			direction /= num;
			for (int i = 0; i < count; i++)
			{
				ref ArcCandidate reference = ref candidates[i];
				reference.Flags = 0;
				reference.Distance = 0f;
				Vector3 vector = reference.Point - origin;
				float num2 = vector.LengthSquared();
				if (reference.Health == 0 || reference.Box == 0 || num2 <= 0f)
				{
					continue;
				}
				reference.Distance = (float)Math.Sqrt(num2);
				float num3 = Vector3.Dot(vector, direction);
				float num4 = Math.Max(-1f, Math.Min(1f, num3 / reference.Distance));
				float num5 = reference.Distance - reference.Radius;
				reference.Score = (airborne ? num5 : (num5 * Math.Max(0.01f, 1f - num4)));
				if (num5 >= (airborne ? 30f : 88f))
				{
					continue;
				}
				if (airborne)
				{
					if (num3 < 0f)
					{
						continue;
					}
				}
				else if ((float)Math.Sqrt(Math.Max(0f, num2 - num3 * num3)) - reference.Radius > num3 * ConeTangent)
				{
					continue;
				}
				reference.Flags = 1;
			}
			while (true)
			{
				int num6 = -1;
				for (int j = 0; j < count; j++)
				{
					if ((candidates[j].Flags & 3) == 1 && (num6 < 0 || Ranked(in candidates[j], in candidates[num6])))
					{
						num6 = j;
					}
				}
				if (num6 < 0)
				{
					break;
				}
				if (world.Visible(origin, num6))
				{
					return num6;
				}
				candidates[num6].Flags |= 2;
			}
			for (int k = 0; k < count; k++)
			{
				ref ArcCandidate reference2 = ref candidates[k];
				if (focus.Health == 0 || reference2.Health != focus.Health || reference2.Box != focus.Box || (reference2.Flags & 2) != 0 || reference2.Distance <= 0f)
				{
					continue;
				}
				float num7 = Vector3.Dot(reference2.Point - origin, direction) / reference2.Distance;
				if (airborne)
				{
					if (reference2.Distance > 25f && num7 < 0.5f)
					{
						return -1;
					}
				}
				else
				{
					Vector3 vector2 = reference2.Point - origin;
					float num8 = (float)Math.Sqrt((vector2.X * vector2.X + vector2.Z * vector2.Z) * (direction.X * direction.X + direction.Z * direction.Z));
					if (num8 > 0f && (vector2.X * direction.X + vector2.Z * direction.Z) / num8 < -0.5f)
					{
						return -1;
					}
				}
				if (!world.Visible(origin, k))
				{
					return -1;
				}
				return k;
			}
			return -1;
		}

		private static bool Ranked(in ArcCandidate a, in ArcCandidate b)
		{
			if (a.Score != b.Score)
			{
				return a.Score < b.Score;
			}
			if (a.Health == b.Health)
			{
				return a.Box < b.Box;
			}
			return a.Health < b.Health;
		}
	}
	[DisallowMultipleComponent]
	[DefaultExecutionOrder(10010)]
	internal sealed class JakArcTracker : MonoBehaviour
	{
		internal enum Phase
		{
			Active,
			Inactive,
			Dead
		}

		internal bool CaptureHidden;

		private readonly JakLightningBolt.TickClock clock = new JakLightningBolt.TickClock();

		private readonly HashSet<int> victims = new HashSet<int>();

		private JakWeaponRules.PulseGate gate;

		private CharacterBody body;

		private JakWeaponPresentation presentation;

		private JakWeaponCombat combat;

		private JakArcWorld world;

		private Transform muzzle;

		private Transform model;

		private Random random;

		private Mesh[] meshes;

		private Material[] materials;

		private JakLightningBolt.Vertex[][] strips;

		private JakEffectPlayer effect;

		private uint effectLease;

		private JakAudio.Voice loop;

		private JakAudio.Voice spin;

		private Vector3[] positions;

		private Vector2[] uvs;

		private Vector2[] ends;

		private Color32[] colors;

		private JakShockSpec explodeSpec;

		private JakShockSpec terminalSpec;

		private float spinIntensity;

		private int lastSpark;

		private int sparkInterval;

		private int stateTick;

		private int sampledFrame;

		private bool requested;

		private uint actionId;

		internal Phase State { get; private set; } = Phase.Dead;

		internal JakArcRope Rope { get; private set; }

		internal JakLightningBolt[] Bolts { get; private set; }

		internal int CosmeticHitCount { get; private set; }

		internal int ResourceCount
		{
			get
			{
				if (meshes != null)
				{
					return meshes.Length;
				}
				return 0;
			}
		}

		internal Transform Muzzle => muzzle;

		private int Layer
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)muzzle))
				{
					return ((Component)this).gameObject.layer;
				}
				return ((Component)muzzle).gameObject.layer;
			}
		}

		internal void Drive(uint id, Transform follow)
		{
			//IL_0109: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			SampleClock();
			requested = id != 0 && Object.op_Implicit((Object)(object)follow);
			if (!requested)
			{
				return;
			}
			body = ((Component)this).GetComponent<CharacterBody>();
			presentation = ((Component)this).GetComponent<JakWeaponPresentation>();
			combat = ((Component)this).GetComponent<JakWeaponCombat>();
			if (!Object.op_Implicit((Object)(object)body))
			{
				return;
			}
			Transform val = (Object.op_Implicit((Object)(object)body.modelLocator) ? body.modelLocator.modelTransform : null);
			if ((Object)(object)model != (Object)(object)val || (Object)(object)muzzle != (Object)(object)follow)
			{
				Kill();
			}
			model = val;
			muzzle = follow;
			requested = true;
			if (State == Phase.Active && (!Object.op_Implicit((Object)(object)effect) || !effect.IsLease(effectLease)))
			{
				Release();
			}
			if (State == Phase.Active)
			{
				actionId = id;
				return;
			}
			if (Rope == null)
			{
				Initialize(id);
			}
			Rope.Enter(JakArcWorld.ToV(muzzle.position), JakArcWorld.ToV(Aim()), JakArcWorld.ToV(((Component)body).transform.position));
			JakLightningBolt[] bolts = Bolts;
			for (int i = 0; i < bolts.Length; i++)
			{
				bolts[i].Fade(0, clock.Now);
			}
			State = Phase.Active;
			actionId = id;
			effect = JakEffectPlayer.Spawn("arc-muzzle", muzzle.position, Quaternion.identity, muzzle);
			effectLease = effect.LeaseId;
			((Component)effect).gameObject.layer = Layer;
			effect.Driven = true;
			stateTick = clock.Now;
		}

		private void Initialize(uint id)
		{
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Expected O, but got Unknown
			lastSpark = (sparkInterval = 0);
			random = new Random((int)id);
			Rope = new JakArcRope();
			world = new JakArcWorld(body);
			explodeSpec = JakEffects.ShockSpec("lightning-blue-shot-attack-explode");
			terminalSpec = JakEffects.ShockSpec("lightning-blue-shot-terminal");
			Bolts = new JakLightningBolt[6];
			meshes = (Mesh[])(object)new Mesh[12];
			materials = (Material[])(object)new Material[2];
			strips = new JakLightningBolt.Vertex[12][];
			for (int i = 0; i < 6; i++)
			{
				Bolts[i] = new JakLightningBolt(random, i >= 4);
				for (int j = 0; j < 2; j++)
				{
					int num = i * 2 + j;
					int capacity = Bolts[i].Capacity;
					strips[num] = new JakLightningBolt.Vertex[capacity];
					meshes[num] = new Mesh
					{
						name = "JakNativeArcStrip"
					};
					meshes[num].MarkDynamic();
					meshes[num].vertices = (Vector3[])(object)new Vector3[capacity];
					meshes[num].triangles = Triangles(capacity);
				}
			}
			int capacity2 = Bolts[0].Capacity;
			positions = (Vector3[])(object)new Vector3[capacity2];
			uvs = (Vector2[])(object)new Vector2[capacity2];
			ends = (Vector2[])(object)new Vector2[capacity2];
			colors = (Color32[])(object)new Color32[capacity2];
			materials[0] = CreateMaterial("jak3-vfx-lightning-tile.png");
			materials[1] = CreateMaterial("jak3-vfx-pal-lightning.png");
		}

		internal static Material CreateMaterial(string texture)
		{
			//IL_000a: 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_002c: Expected O, but got Unknown
			Material val = new Material(JakEffects.Assets.lightningShader);
			val.SetTexture("_MainTex", JakEffects.Material(texture).GetTexture("_MainTex"));
			return val;
		}

		internal void Release()
		{
			SampleClock();
			requested = false;
			if (State == Phase.Active)
			{
				if (Object.op_Implicit((Object)(object)effect))
				{
					effect.Release(effectLease);
				}
				effect = null;
				JakLightningBolt[] bolts = Bolts;
				for (int i = 0; i < bolts.Length; i++)
				{
					bolts[i].Fade(2, clock.Now);
				}
				stateTick = clock.Now;
				State = Phase.Inactive;
			}
		}

		private void Awake()
		{
			clock.Reset(Time.time);
			sampledFrame = Time.frameCount;
		}

		private void SampleClock()
		{
			if (sampledFrame != Time.frameCount)
			{
				sampledFrame = Time.frameCount;
				clock.Advance(Time.deltaTime);
			}
		}

		private void OnEnable()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(Draw));
		}

		private void LateUpdate()
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			SampleClock();
			if (State == Phase.Dead)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.healthComponent) || !body.healthComponent.alive || !Object.op_Implicit((Object)(object)muzzle) || !((Component)muzzle).gameObject.activeInHierarchy || !Object.op_Implicit((Object)(object)body.modelLocator) || (Object)(object)model != (Object)(object)body.modelLocator.modelTransform)
			{
				Kill();
				return;
			}
			if (!requested)
			{
				Release();
			}
			Sound();
			if (State == Phase.Active || Bolts[0].FadeMode != 3)
			{
				Rope.Update(JakArcWorld.ToV(muzzle.position), JakArcWorld.ToV(Aim()), JakArcWorld.ToV(((Component)body).transform.position), Time.deltaTime, State == Phase.Active, world, (State == Phase.Active && combat.ActionKind == JakWeaponCombat.Kind.Arc) ? combat.ActionAge : (-1f));
				JakLightningBolt[] bolts = Bolts;
				foreach (JakLightningBolt obj in bolts)
				{
					obj.Setup(Rope.Path);
					obj.Update(clock.Now, clock.Previous);
				}
				if (Rope.Path.Terminal && clock.Now - lastSpark >= sparkInterval)
				{
					lastSpark = clock.Now;
					sparkInterval = 5 * JakLightningBolt.IntRange(random, 3, 5);
					int num = JakLightningBolt.IntRange(random, 3, 5);
					for (int j = 0; j < num; j++)
					{
						JakShock.ProbeReplace(((Component)this).gameObject, terminalSpec, 168, JakArcWorld.ToVector(Rope.Path.Points[Rope.Path.Count - 1]), null, Layer);
					}
				}
				if (State == Phase.Active)
				{
					CosmeticSweep();
				}
			}
			if (State == Phase.Inactive)
			{
				JakLightningBolt[] bolts = Bolts;
				for (int i = 0; i < bolts.Length; i++)
				{
					bolts[i].Update(clock.Now, clock.Previous);
				}
				if (clock.Now - stateTick >= 2400)
				{
					Kill();
				}
			}
		}

		private void Sound()
		{
			float num = (Object.op_Implicit((Object)(object)presentation) ? presentation.GunSpinSpeed : 0f);
			float num2 = (float)(clock.Now - stateTick) / 60f;
			bool flag = State == Phase.Active;
			float num3 = (flag ? (1f - Square(1f - JakArcRope.Clamp(num / 109226.664f))) : JakArcRope.Clamp(num / 218453.33f));
			float num4 = 2f * Time.deltaTime;
			spinIntensity = ((spinIntensity < num3) ? Mathf.Min(num3, spinIntensity + num4) : Mathf.Max(num3, spinIntensity - num4));
			if (flag)
			{
				loop = JakAudio.Play("arc-loop", ((Component)muzzle).gameObject, 0.8f, (num2 < 1f) ? (1524f * Mathf.Lerp(-0.5f, 0f, num2)) : 0f, 768f);
			}
			else if (num2 < 1f)
			{
				loop = JakAudio.Play("arc-loop", ((Component)muzzle).gameObject, 0.8f, 1524f * Mathf.Lerp(0f, -0.5f, num2), 768f);
			}
			else
			{
				JakAudio.Stop(loop);
				loop = null;
			}
			if (spinIntensity > (flag ? 0.1f : 0.001f))
			{
				spin = JakAudio.Play("arc-spin", ((Component)muzzle).gameObject, 0.8f, volume1024: 1024f * Mathf.Lerp(flag ? 0.75f : 0.3f, 1f, spinIntensity), pitchMod: 1524f * Mathf.Lerp(-0.5f, 0f, spinIntensity));
			}
			else if (!flag)
			{
				JakAudio.Stop(spin);
				spin = null;
			}
		}

		private static float Square(float value)
		{
			return value * value;
		}

		private Vector3 Aim()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			world.Focus = combat.ArcFocus;
			world.BeginUpdate();
			return world.Direction(muzzle.position, combat.ArcShot());
		}

		private void CosmeticSweep()
		{
			if (gate.TryPulse((double)clock.Now / 300.0, combat.SampledAttackSpeed))
			{
				victims.Clear();
			}
			for (int i = 0; i < Rope.Path.SpanCount; i++)
			{
				Vector3 point;
				HurtBox val = world.Sweep(Rope.Path.Spans[i], victims, out point);
				if (Object.op_Implicit((Object)(object)val))
				{
					victims.Add(((Object)val.healthComponent).GetInstanceID());
					CosmeticHitCount++;
					if (JakLightningBolt.IntRange(random, 0, 10) < 2)
					{
						JakShock.Probe(((Component)this).gameObject, explodeSpec, 664, JakShock.VictimJoint(val), ((Component)val.healthComponent).gameObject, Layer);
					}
				}
			}
		}

		private void Draw(Camera camera)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (!CaptureHidden && State != Phase.Dead && Object.op_Implicit((Object)(object)camera) && meshes != null && (camera.cullingMask & (1 << Layer)) != 0)
			{
				for (int i = 0; i < 6; i++)
				{
					Bolts[i].Emit(JakArcWorld.ToV(((Component)camera).transform.up), strips[i * 2], strips[i * 2 + 1], out var count, out var count2);
					DrawStrip(camera, i * 2, count, Bolts[i].Width, materials[(i >= 4) ? 1u : 0u]);
					DrawStrip(camera, i * 2 + 1, count2, Bolts[i].Width, materials[(i >= 4) ? 1u : 0u]);
				}
			}
		}

		internal static int[] Triangles(int count)
		{
			int[] array = new int[Math.Max(0, count - 2) * 3];
			for (int i = 0; i < count - 2; i++)
			{
				array[i * 3] = i;
				array[i * 3 + 1] = i + ((i % 2 == 0) ? 1 : 2);
				array[i * 3 + 2] = i + ((i % 2 != 0) ? 1 : 2);
			}
			return array;
		}

		internal static Vector2 EndFade(JakLightningBolt.Vertex vertex, float length, float width)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2(vertex.Distance / width, (length - vertex.Distance) / width);
		}

		private void DrawStrip(Camera camera, int index, int count, float width, Material material)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			if (count >= 3)
			{
				Mesh val = meshes[index];
				int num = strips[index].Length;
				float distance = strips[index][count - 1].Distance;
				for (int i = 0; i < num; i++)
				{
					JakLightningBolt.Vertex vertex = strips[index][Math.Min(i, count - 1)];
					positions[i] = JakArcWorld.ToVector(vertex.Position);
					uvs[i] = new Vector2(vertex.U, vertex.V);
					ends[i] = EndFade(vertex, distance, width);
					colors[i] = new Color32((byte)128, (byte)128, (byte)128, vertex.Alpha);
				}
				val.SetVertices(positions, 0, num);
				val.SetUVs(0, uvs, 0, num);
				val.SetUVs(1, ends, 0, num);
				val.SetColors(colors, 0, num);
				val.RecalculateBounds();
				Graphics.DrawMesh(val, Matrix4x4.identity, material, Layer, camera, 0, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false);
			}
		}

		internal void Kill()
		{
			Release();
			JakShock.Clear(((Component)this).gameObject);
			JakAudio.Stop(loop);
			JakAudio.Stop(spin);
			loop = (spin = null);
			spinIntensity = 0f;
			if (meshes != null)
			{
				Mesh[] array = meshes;
				foreach (Mesh val in array)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						Object.Destroy((Object)(object)val);
					}
				}
			}
			if (materials != null)
			{
				Material[] array2 = materials;
				foreach (Material val2 in array2)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						Object.Destroy((Object)(object)val2);
					}
				}
			}
			meshes = null;
			materials = null;
			strips = null;
			Bolts = null;
			Rope = null;
			State = Phase.Dead;
			muzzle = (model = null);
		}

		private void OnDisable()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(Draw));
			Kill();
		}

		private void OnDestroy()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(Draw));
			Kill();
		}
	}
	internal sealed class JakArcWorld : JakArcRope.IWorld
	{
		private struct TargetSnapshot
		{
			internal int Id;

			internal Bounds Bounds;
		}

		private readonly CharacterBody owner;

		private readonly List<TargetSnapshot> targets = new List<TargetSnapshot>(128);

		private RaycastHit[] hits = (RaycastHit[])(object)new RaycastHit[32];

		internal HurtBox Focus;

		private TeamMask Enemies => TeamMask.GetEnemyTeams(owner.teamComponent.teamIndex);

		public int Targets => targets.Count;

		internal JakArcWorld(CharacterBody owner)
		{
			this.owner = owner;
		}

		internal static JakArcRope.V ToV(Vector3 p)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return new JakArcRope.V(p.x, p.y, p.z);
		}

		internal static Vector3 ToVector(JakArcRope.V p)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(p.x, p.y, p.z);
		}

		public float Probe(JakArcRope.V start, JakArcRope.V end, float radius)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ToVector(end - start);
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude == 0f)
			{
				return -1f;
			}
			Vector3 val2 = ToVector(start);
			Vector3 val3 = val / magnitude;
			LayerIndex world = LayerIndex.world;
			RaycastHit val4 = default(RaycastHit);
			if (!Physics.SphereCast(val2, radius, val3, ref val4, magnitude, LayerMask.op_Implicit(((LayerIndex)(ref world)).mask), (QueryTriggerInteraction)1))
			{
				return -1f;
			}
			return ((RaycastHit)(ref val4)).distance / magnitude;
		}

		internal void BeginUpdate()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			targets.Clear();
			TeamMask enemies = Enemies;
			ReadOnlyCollection<CharacterBody> readOnlyInstancesList = CharacterBody.readOnlyInstancesList;
			bool flag = JakWeaponTargets.Eligible(Focus, enemies);
			for (int i = 0; i < readOnlyInstancesList.Count; i++)
			{
				CharacterBody val = readOnlyInstancesList[i];
				HurtBox val2 = (Object.op_Implicit((Object)(object)val) ? val.mainHurtBox : null);
				if (Object.op_Implicit((Object)(object)val2) && flag && (Object)(object)Focus.healthComponent == (Object)(object)val2.healthComponent)
				{
					val2 = Focus;
				}
				if (JakWeaponTargets.Eligible(val2, enemies))
				{
					targets.Add(new TargetSnapshot
					{
						Id = ((Object)val2.healthComponent).GetInstanceID(),
						Bounds = val2.collider.bounds
					});
				}
			}
		}

		public int Target(int index, JakArcRope.V point, out JakArcRope.V centre, out float distance)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			TargetSnapshot targetSnapshot = targets[index];
			centre = ToV(((Bounds)(ref targetSnapshot.Bounds)).center);
			distance = (ToV(((Bounds)(ref targetSnapshot.Bounds)).ClosestPoint(ToVector(point))) - point).Length;
			return targetSnapshot.Id;
		}

		public bool Visible(JakArcRope.V from, JakArcRope.V to)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return JakWeaponTargets.Visible(ToVector(from), ToVector(to));
		}

		internal HurtBox Sweep(JakArcRope.Span span, HashSet<int> victims, out Vector3 point)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			point = default(Vector3);
			Vector3 val = ToVector(span.Start);
			Vector3 val2 = ToVector(span.End - span.Start);
			float num = ((Vector3)(ref val2)).magnitude;
			if (num == 0f)
			{
				return null;
			}
			Vector3 val3 = val2 / num;
			float num2 = num;
			LayerIndex val4 = LayerIndex.world;
			RaycastHit val5 = default(RaycastHit);
			if (Physics.SphereCast(val, 0.2f, val3, ref val5, num2, LayerMask.op_Implicit(((LayerIndex)(ref val4)).mask), (QueryTriggerInteraction)1))
			{
				num = ((RaycastHit)(ref val5)).distance;
			}
			int num4;
			while (true)
			{
				RaycastHit[] array = hits;
				float num3 = num;
				val4 = LayerIndex.entityPrecise;
				if ((num4 = Physics.SphereCastNonAlloc(val, 1f, val3, array, num3, LayerMask.op_Implicit(((LayerIndex)(ref val4)).mask), (QueryTriggerInteraction)2)) != hits.Length)
				{
					break;
				}
				hits = (RaycastHit[])(object)new RaycastHit[hits.Length * 2];
			}
			TeamMask enemies = Enemies;
			HurtBox val6;
			while (true)
			{
				val6 = null;
				int num5 = -1;
				for (int i = 0; i < num4; i++)
				{
					if (((RaycastHit)(ref hits[i])).distance < 0f || (num5 >= 0 && ((RaycastHit)(ref hits[i])).distance >= ((RaycastHit)(ref hits[num5])).distance))
					{
						continue;
					}
					Collider collider = ((RaycastHit)(ref hits[i])).collider;
					HurtBox val7 = (Object.op_Implicit((Object)(object)collider) ? ((Component)collider).GetComponent<HurtBox>() : null);
					if (JakWeaponTargets.Eligible(val7, enemies))
					{
						int instanceID = ((Object)val7.healthComponent).GetInstanceID();
						if (instanceID != span.StartId && !victims.Contains(instanceID))
						{
							num5 = i;
							val6 = val7;
						}
					}
				}
				if (!Object.op_Implicit((Object)(object)val6))
				{
					point = default(Vector3);
					return null;
				}
				RaycastHit val8 = hits[num5];
				Vector3 val10;
				if (!(((RaycastHit)(ref val8)).distance > 0f))
				{
					Collider collider2 = ((RaycastHit)(ref val8)).collider;
					MeshCollider val9 = (MeshCollider)(object)((collider2 is MeshCollider) ? collider2 : null);
					if (val9 == null || val9.convex)
					{
						val10 = ((RaycastHit)(ref val8)).collider.ClosestPoint(val);
					}
					else
					{
						Bounds bounds = ((RaycastHit)(ref val8)).collider.bounds;
						val10 = ((Bounds)(ref bounds)).center;
					}
				}
				else
				{
					val10 = ((RaycastHit)(ref val8)).point;
				}
				point = val10;
				if (JakWeaponTargets.Visible(val, point))
				{
					break;
				}
				((RaycastHit)(ref hits[num5])).distance = -1f;
			}
			return val6;
		}

		internal Vector3 Direction(Vector3 fire, in JakShot shot)
		{
			//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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_00d6: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			Ray ray;
			Vector3 val;
			if (shot.Spinning)
			{
				ray = shot.Ray;
				val = ((Ray)(ref ray)).direction;
				return ((Vector3)(ref val)).normalized;
			}
			TeamMask enemies = Enemies;
			if (JakWeaponTargets.Eligible(Focus, enemies))
			{
				Bounds bounds = Focus.collider.bounds;
				val = ((Bounds)(ref bounds)).center - fire;
				return ((Vector3)(ref val)).normalized;
			}
			ray = shot.Ray;
			Vector3 point = ((Ray)(ref ray)).GetPoint(1000f);
			float num = 1000f;
			Ray ray2 = shot.Ray;
			LayerIndex val2 = LayerIndex.world;
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(ray2, ref val3, 1000f, LayerMask.op_Implicit(((LayerIndex)(ref val2)).mask), (QueryTriggerInteraction)1))
			{
				point = ((RaycastHit)(ref val3)).point;
				num = ((RaycastHit)(ref val3)).distance;
			}
			int num3;
			while (true)
			{
				Ray ray3 = shot.Ray;
				RaycastHit[] array = hits;
				float num2 = num;
				val2 = LayerIndex.entityPrecise;
				if ((num3 = Physics.RaycastNonAlloc(ray3, array, num2, LayerMask.op_Implicit(((LayerIndex)(ref val2)).mask), (QueryTriggerInteraction)2)) != hits.Length)
				{
					break;
				}
				hits = (RaycastHit[])(object)new RaycastHit[hits.Length * 2];
			}
			for (int i = 0; i < num3; i++)
			{
				HurtBox box = (Object.op_Implicit((Object)(object)((RaycastHit)(ref hits[i])).collider) ? ((Component)((RaycastHit)(ref hits[i])).collider).GetComponent<HurtBox>() : null);
				if (((RaycastHit)(ref hits[i])).distance < num && JakWeaponTargets.Eligible(box, enemies))
				{
					point = ((RaycastHit)(ref hits[i])).point;
					num = ((RaycastHit)(ref hits[i])).distance;
				}
			}
			val = point - fire;
			return ((Vector3)(ref val)).normalized;
		}
	}
	internal static class JakAssets
	{
		public const string BundleName = "jaksurvivor";

		public static string PluginDirectory => Path.GetDirectoryName(typeof(Plugin).Assembly.Location);

		public static AssetBundle Bundle { get; private set; }

		internal static float ScatterRecovery { get; private set; }

		public static AssetBundleCreateRequest BeginLoad()
		{
			string text = Path.Combine(PluginDirectory, "jaksurvivor");
			if (!File.Exists(text))
			{
				throw new FileNotFoundException("Jak's AssetBundle is missing. Stage the plugin with scripts/Build-Unity.ps1.", text);
			}
			return AssetBundle.LoadFromFileAsync(text);
		}

		public static void EndLoad(AssetBundleCreateRequest request)
		{
			Bundle = request.assetBundle;
			if (!Object.op_Implicit((Object)(object)Bundle))
			{
				throw new InvalidDataException("Jak's AssetBundle could not be loaded.");
			}
			ScatterRecovery = JakAssets.Get<RuntimeAnimatorController>("animJak").animationClips.Single((AnimationClip c) => ((Object)c).name == "jakb-gun-red-fire-fast").length;
		}

		public static T Get<T>(string name) where T : Object
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			return Bundle.LoadAsset<T>(name) ?? throw new MissingReferenceException("Jak's AssetBundle has no " + typeof(T).Name + " named " + name + ".");
		}
	}
	internal static class JakAudio
	{
		internal sealed class Voice
		{
			public readonly uint PlayingId;

			public readonly string Key;

			public readonly GameObject Owner;

			public readonly bool Menu;

			public bool Ended { get; internal set; }

			internal Voice(uint playingId, string key, GameObject owner, bool menu)
			{
				PlayingId = playingId;
				Key = key;
				Owner = owner;
				Menu = menu;
			}
		}

		internal const string BankFile = "Jak.bnk";

		internal static readonly string[] Keys = new string[39]
		{
			"blast-charge", "blast-swing", "blast-flight", "blast-hit", "blast-wall", "spin-kick", "blue-whoosh", "gun-spin-hit", "jump", "jump-double",
			"blaster", "scatter", "board-start", "board-loop", "board-jump", "board-q-jump", "board-bounce", "dark-enter", "dark-exit", "claws",
			"bomb-charge", "bomb-impact", "gun-draw", "gun-twirl", "arc-loop", "arc-spin", "blue-gun-whine", "wave-charge", "wave-shot", "roll-stn",
			"roll-drt", "roll-grs", "roll-san", "roll-wod", "roll-mtl", "roll-wtr", "roll-flip", "transform-zap", "stretched-zap"
		};

		private static readonly List<Voice> voices = new List<Voice>();

		private static uint pitchParameter;

		private static uint volumeParameter;

		internal static bool Loaded { get; private set; }

		internal static IReadOnlyList<Voice> Playing => voices;

		internal static bool IsLoop(string key)
		{
			switch (key)
			{
			default:
				return key == "wave-charge";
			case "blast-charge":
			case "blast-flight":
			case "board-loop":
			case "arc-loop":
			case "arc-spin":
			case "blue-gun-whine":
				return true;
			}
		}

		internal static string EventName(string key, bool menu = false)
		{
			return (menu ? "Play_JakMenu_" : "Play_Jak_") + key.Replace('-', '_');
		}

		public unsafe static void LoadBank()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Invalid comparison between Unknown and I4
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Invalid comparison between Unknown and I4
			if (Loaded)
			{
				return;
			}
			if (!AkSoundEngine.IsInitialized())
			{
				Plugin.Log.LogWarning((object)"Wwise is not running; Jak plays without sound.");
				return;
			}
			byte[] array = File.ReadAllBytes(Path.Combine(JakAssets.PluginDirectory, "Jak.bnk"));
			GCHandle gCHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
			AKRESULT val;
			try
			{
				uint num = default(uint);
				val = AkSoundEngine.LoadBankMemoryCopy(gCHandle.AddrOfPinnedObject(), (uint)array.Length, ref num);
			}
			finally
			{
				gCHandle.Free();
			}
			if ((int)val != 1 && (int)val != 69)
			{
				throw new InvalidDataException("Wwise rejected Jak.bnk: " + ((object)(*(AKRESULT*)(&val))/*cast due to .constrained prefix*/).ToString());
			}
			pitchParameter = AkSoundEngine.GetIDFromString("Jak_Pitch");
			volumeParameter = AkSoundEngine.GetIDFromString("Jak_Volume");
			Loaded = true;
			Plugin.Log.LogInfo((object)("Loaded Jak.bnk with " + Keys.Length + " original Jak 3 sound effects."));
		}

		public static Voice Play(string key, GameObject owner, float gain = 0.8f, float pitchMod = 0f, float volume1024 = 1024f)
		{
			if (!Object.op_Implicit((Object)(object)owner) || !Loaded)
			{
				return null;
			}
			Voice voice = (IsLoop(key) ? voices.Find((Voice v) => (Object)(object)v.Owner == (Object)(object)owner && v.Key == key) : null);
			voice = voice ?? Post(key, owner, menu: false);
			if (voice == null)
			{
				return null;
			}
			SetParameters(voice.PlayingId, gain / 0.8f * volume1024 / 1024f, pitchMod * 1200f / 1536f);
			return voice;
		}

		public static Voice PlayMenu(string key, GameObject owner, float gain)
		{
			if (!Object.op_Implicit((Object)(object)owner) || !Loaded)
			{
				return null;
			}
			Voice voice = Post(key, owner, menu: true);
			if (voice != null)
			{
				SetParameters(voice.PlayingId, gain, 0f);
			}
			return voice;
		}

		public static Voice PlayAt(string key, Vector3 point)
		{
			//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)
			if (!Loaded)
			{
				return null;
			}
			uint num = PointSoundManager.EmitSoundLocal(AkEventIdArg.op_Implicit(AkSoundEngine.GetIDFromString(EventName(key))), point);
			if (num != 0)
			{
				return new Voice(num, key, null, menu: false);
			}
			return null;
		}

		public static void Fade(Voice voice, float seconds)
		{
			if (voice != null)
			{
				AkSoundEngine.StopPlayingID(voice.PlayingId, (int)(seconds * 1000f), (AkCurveInterpolation)4);
				End(voice);
			}
		}

		public static void Stop(Voice voice)
		{
			if (voice != null)
			{
				AkSoundEngine.StopPlayingID(voice.PlayingId);
				End(voice);
			}
		}

		private static void End(Voice voice)
		{
			voice.Ended = true;
			voices.Remove(voice);
		}

		private static Voice Post(string key, GameObject owner, bool menu)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			voices.RemoveAll((Voice v) => !Object.op_Implicit((Object)(object)v.Owner));
			uint num = AkSoundEngine.PostEvent(EventName(key, menu), owner, 1u, new EventCallback(OnEnd), (object)null);
			if (num == 0)
			{
				Plugin.Log.LogWarning((object)("Wwise could not post " + EventName(key, menu) + "."));
				return null;
			}
			Voice voice = new Voice(num, key, owner, menu);
			voices.Add(voice);
			return voice;
		}

		private static void SetParameters(uint playingId, float gain, float cents)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			AkSoundEngine.SetRTPCValueByPlayingID(volumeParameter, Mathf.Clamp(20f * Mathf.Log10(Mathf.Max(gain, 1E-05f)), -96f, 24f), playingId);
			AkSoundEngine.SetRTPCValueByPlayingID(pitchParameter, Mathf.Clamp(cents, -2400f, 2400f), playingId);
		}

		private static void OnEnd(object cookie, AkCallbackType type, AkCallbackInfo info)
		{
			AkEventCallbackInfo end = (AkEventCallbackInfo)(object)((info is AkEventCallbackInfo) ? info : null);
			if (end != null)
			{
				Voice voice = voices.Find((Voice v) => v.PlayingId == end.playingID);
				if (voice != null)
				{
					End(voice);
				}
			}
		}
	}
	internal static class JakBlast
	{
		internal sealed class Stall
		{
			private readonly float[] history = new float[16]
			{
				999999f, 999999f, 999999f, 999999f, 999999f, 999999f, 999999f, 999999f, 999999f, 999999f,
				999999f, 999999f, 999999f, 999999f, 999999f, 999999f
			};

			private const float Seed = 999999f;

			private int next;

			internal bool Record(float distance, bool touchingWall)
			{
				history[next] = 0.0625f * distance;
				next = (next + 1) & 0xF;
				float num = 0f;
				float[] array = history;
				foreach (float num2 in array)
				{
					num += num2;
				}
				if (!touchingWall || !(num < 0.5f))
				{
					return num < 0.05f;
				}
				return true;
			}
		}

		internal const float SampleSeconds = 0.066666536f;

		internal const float LaunchTime = 0.46666574f;

		internal const float ReleaseTime = 0.7333319f;

		internal const float RecoveryTime = 0.59999883f;

		internal const float Speed = 60f;

		internal const float Lifetime = 4f;

		internal const float InitialRadius = 2f;

		internal const float MaxRadius = 6f;

		internal const float Growth = 6f;

		internal const float TrailStep = 1f / 60f;

		internal static float Radius(float age)
		{
			return Math.Min(6f, 2f + 6f * Math.Max(0f, age));
		}

		internal static float Flatten(float velocity, float dt)
		{
			return (float)Math.Sign(velocity) * Math.Max(0f, Math.Abs(velocity) - 20f * dt);
		}

		internal static float Lift(float height, float ground, float radius, float dt)
		{
			return Math.Min(Math.Max(0f, ground + radius * 0.5f - height), 10f * dt);
		}

		internal static float SegmentFraction(float px, float py, float pz, float dx, float dy, float dz)
		{
			float num = dx * dx + dy * dy + dz * dz;
			if (!(num <= 1E-08f))
			{
				return Math.Max(0f, Math.Min(1f, (px * dx + py * dy + pz * dz) / num));
			}
			return 0f;
		}

		internal static bool CrossesLaunch(float age, float rate)
		{
			return age * rate >= 0.46666574f;
		}

		internal static bool Slide(ref float vx, ref float vy, ref float vz, float nx, float ny, float nz)
		{
			float num = (float)Math.Sqrt(vx * vx + vy * vy + vz * vz);
			if (num <= 1E-08f)
			{
				return false;
			}
			float num2 = vx * nx + vy * ny + vz * nz;
			bool result = num2 / num < -0.3f;
			float num3 = vx - nx * 1.2f * num2;
			float num4 = vy - ny * 1.2f * num2;
			float num5 = vz - nz * 1.2f * num2;
			float num6 = (float)Math.Sqrt(num3 * num3 + num4 * num4 + num5 * num5);
			float num7 = Math.Min(0.4f, (num6 <= 1E-08f) ? 0f : (num4 / num6)) / 4096f;
			float num8 = num / (float)Math.Sqrt(vx * vx + num7 * num7 + vz * vz);
			if (float.IsInfinity(num8) || float.IsNaN(num8))
			{
				vx = (vz = 0f);
				vy = num;
				return result;
			}
			vx *= num8;
			vy = num7 * num8;
			vz *= num8;
			return result;
		}

		internal static bool Impacts(bool flagged, float height, float fireHeight, float speed)
		{
			if (flagged)
			{
				if (Math.Abs(height - fireHeight) < 1.5f)
				{
					return !(speed > 4f);
				}
				return true;
			}
			return false;
		}

		internal static float TrailFraction(float carried, float delta, int index)
		{
			if (!(delta <= 0f))
			{
				return Math.Max(0f, Math.Min(1f, ((float)(index + 1) * (1f / 60f) - carried) / delta));
			}
			return 1f;
		}
	}
	[DefaultExecutionOrder(10010)]
	internal sealed class JakBlastPresentation : MonoBehaviour
	{
		private JakBlastProjectile shot;

		private JakBlastAppearance style;

		private readonly JakEffectPlayer[] lobes = new JakEffectPlayer[2];

		private readonly uint[] lobeLeases = new uint[2];

		private readonly Mesh[] strips = (Mesh[])(object)new Mesh[6];

		private readonly Vector3[][] points = new Vector3[3][]
		{
			(Vector3[])(object)new Vector3[17],
			(Vector3[])(object)new Vector3[17],
			(Vector3[])(object)new Vector3[17]
		};

		private readonly Vector3[][] current = new Vector3[3][]
		{
			(Vector3[])(object)new Vector3[17],
			(Vector3[])(object)new Vector3[17],
			(Vector3[])(object)new Vector3[17]
		};

		private readonly Vector3[][] desired = new Vector3[3][]
		{
			(Vector3[])(object)new Vector3[17],
			(Vector3[])(object)new Vector3[17],
			(Vector3[])(object)new Vector3[17]
		};

		private readonly Vector3[] vertices = (Vector3[])(object)new Vector3[34];

		private readonly Vector2[] uv = (Vector2[])(object)new Vector2[34];

		private readonly Color32[] colors = (Color32[])(object)new Color32[34];

		private readonly int[] triangles = new int[96];

		private JakEffectPlayer trail;

		private JakAudio.Voice loop;

		private float retired = -1f;

		private float nextBolt;

		private float generated;

		private float emission;

		private float elapsed;

		private bool sampled;

		private bool trailed;

		private Vector3 trailFrom;

		internal void Begin(JakBlastProjectile projectile)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_013f: Expected O, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Expected O, but got Unknown
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			shot = projectile;
			style = JakEffects.Assets.blast;
			((Component)this).transform.position = ((Component)projectile).transform.position;
			for (int i = 0; i < lobes.Length; i++)
			{
				lobes[i] = JakEffectPlayer.Spawn("blast-core", ((Component)this).transform);
				lobeLeases[i] = lobes[i].LeaseId;
				lobes[i].Driven = true;
			}
			trail = JakEffectPlayer.CreateLauncher(((Component)this).gameObject.layer);
			loop = JakAudio.Play("blast-flight", ((Component)this).gameObject);
			for (int j = 0; j < 16; j++)
			{
				int num = j * 6;
				int num2 = j * 2;
				triangles[num] = num2;
				triangles[num + 1] = num2 + 1;
				triangles[num + 2] = num2 + 2;
				triangles[num + 3] = num2 + 1;
				triangles[num + 4] = num2 + 3;
				triangles[num + 5] = num2 + 2;
			}
			for (int k = 0; k < strips.Length; k++)
			{
				strips[k] = new Mesh
				{
					name = "DarkBlastNativeBolt" + k
				};
				strips[k].MarkDynamic();
			}
			Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(Draw));
		}

		private void Midpoint(Vector3[] offsets, int first, int last, float scale)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (last - first > 1)
			{
				int num = (first + last) / 2;
				offsets[num] = (offsets[first] + offsets[last]) * 0.5f + Random.insideUnitSphere * scale;
				Midpoint(offsets, first, num, scale * style.reduction);
				Midpoint(offsets, num, last, scale * style.reduction);
			}
		}

		private void LateUpdate()
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_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_0100: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: 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_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03de: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: 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_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_040a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: 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_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_0463: Unknown result type (might be due to invalid IL or missing references)
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			//IL_049a: Unknown result type (might be due to invalid IL or missing references)
			//IL_049c: Unknown result type (might be due to invalid IL or missing references)
			if (retired >= 0f)
			{
				if (Time.time - retired >= style.fade)
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
				return;
			}
			if (!Object.op_Implicit((Object)(object)shot))
			{
				Retire();
				return;
			}
			for (int i = 0; i < lobes.Length; i++)
			{
				if (!Object.op_Implicit((Object)(object)lobes[i]) || !lobes[i].IsLease(lobeLeases[i]))
				{
					Retire();
					return;
				}
			}
			((Component)this).transform.position = ((Component)shot).transform.position;
			float num = FixedTimeStamp.now.t * 8.377581f;
			Vector3 val = new Vector3(Mathf.Cos(num), 0f, 0f - Mathf.Sin(num)) * (0.75f * shot.Radius);
			((Component)lobes[0]).transform.position = ((Component)this).transform.position + val;
			((Component)lobes[1]).transform.position = ((Component)this).transform.position - val;
			float num2 = elapsed;
			elapsed += Time.deltaTime;
			if (!sampled || elapsed >= nextBolt)
			{
				generated = num2;
				nextBolt = elapsed + Random.Range(style.regenerateMin, style.regenerateMax);
				for (int j = 0; j < 3; j++)
				{
					Array.Copy(current[j], desired[j], 17);
					desired[j][0] = Random.insideUnitSphere * style.endpointOffset;
					desired[j][15] = Random.insideUnitSphere * style.endpointOffset;
					Midpoint(desired[j], 0, 15, style.innerOffset);
					desired[j][16] = Vector3.zero;
				}
			}
			float num3 = Mathf.Clamp01((num2 - generated) / style.travel);
			float num4 = Mathf.Clamp01((elapsed - generated) / style.travel);
			float num5 = ((num3 < 1f) ? ((num4 - num3) / (1f - num3)) : 0f);
			for (int k = 0; k < 3; k++)
			{
				for (int l = 0; l < 17; l++)
				{
					current[k][l] = ((!sampled) ? desired[k][l] : Vector3.Lerp(current[k][l], desired[k][l], num5));
					points[k][l] = Vector3.Lerp(((Component)lobes[0]).transform.position, ((Component)lobes[1]).transform.position, (float)Mathf.Min(l, 15) / 15f) + current[k][l];
				}
			}
			sampled = true;
			Vector3 position = ((Component)this).transform.position;
			Vector3 val2 = position;
			Vector3 down = Vector3.down;
			LayerIndex world = LayerIndex.world;
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(val2, down, ref val3, 30f, LayerMask.op_Implicit(((LayerIndex)(ref world)).mask), (QueryTriggerInteraction)1))
			{
				position.y = ((RaycastHit)(ref val3)).point.y + 0.4f;
			}
			Vector3 val4 = Vector3.ProjectOnPlane(((Component)shot).transform.forward, Vector3.up);
			Vector3 normalized = ((Vector3)(ref val4)).normalized;
			Quaternion rotation = ((((Vector3)(ref normalized)).sqrMagnitude > 0f) ? Quaternion.LookRotation(normalized) : Quaternion.identity);
			if (!trailed)
			{
				trailFrom = position;
				trailed = true;
			}
			float carried = emission;
			emission += Time.deltaTime;
			int num6 = 0;
			while (emission >= 1f / 60f)
			{
				trail.Launch(628, Vector3.Lerp(trailFrom, position, JakBlast.TrailFraction(carried, Time.deltaTime, num6)), rotation);
				num6++;
				emission -= 1f / 60f;
			}
			trailFrom = position;
		}

		private void Draw(Camera camera)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00fc: 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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: 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_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: 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_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			if (!sampled || !Object.op_Implicit((Object)(object)camera) || (camera.cullingMask & (1 << ((Component)this).gameObject.layer)) == 0)
			{
				return;
			}
			float num = ((retired < 0f) ? 1f : Mathf.Clamp01(1f - (Time.time - retired) / style.fade));
			Color32 val5 = default(Color32);
			for (int i = 0; i < 3; i++)
			{
				for (int j = 0; j < 2; j++)
				{
					float num2 = 0f;
					for (int k = 0; k < 17; k++)
					{
						Vector3 val = points[i][k];
						if (k > 0)
						{
							num2 += Vector3.Distance(val, points[i][k - 1]);
						}
						Vector3 val2 = points[i][Mathf.Min(16, k + 1)] - points[i][Mathf.Max(0, k - 1)];
						if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
						{
							val2 = Vector3.right;
						}
						Vector3 val3 = Vector3.Cross(((Vector3)(ref val2)).normalized, ((Component)camera).transform.forward);
						Vector3 val4 = ((Vector3)(ref val3)).normalized;
						if (((Vector3)(ref val4)).sqrMagnitude < 0.0001f)
						{
							val4 = ((Component)camera).transform.up;
						}
						if (j != 0)
						{
							val3 = Vector3.Cross(((Vector3)(ref val2)).normalized, val4);
							val4 = ((Vector3)(ref val3)).normalized;
						}
						val4 *= style.width * 0.5f;
						vertices[k * 2] = val - val4;
						vertices[k * 2 + 1] = val + val4;
						float num3 = num2 / style.uvRepeat + Time.time / style.uvSpeed;
						uv[k * 2] = new Vector2(0f, num3);
						uv[k * 2 + 1] = new Vector2(1f, num3);
						int num4 = i * 4;
						((Color32)(ref val5))..ctor((byte)style.colors[num4], (byte)style.colors[num4 + 1], (byte)style.colors[num4 + 2], (byte)((float)style.colors[num4 + 3] * num * Mathf.Clamp01(1f - num2 / 64f)));
						colors[k * 2] = (colors[k * 2 + 1] = val5);
					}
					Mesh obj = strips[i * 2 + j];
					obj.vertices = vertices;
					obj.uv = uv;
					obj.colors32 = colors;
					obj.triangles = triangles;
					obj.RecalculateBounds();
					Graphics.DrawMesh(obj, Matrix4x4.identity, JakShock.Material(style.texture), ((Component)this).gameObject.layer, camera, 0, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false);
				}
			}
		}

		internal void Retire()
		{
			if (!(retired >= 0f))
			{
				retired = Time.time;
				shot = null;
				ReleaseLobes();
				JakAudio.Stop(loop);
				loop = null;
				if (Object.op_Implicit((Object)(object)trail))
				{
					trail.Retire(4.1f);
					trail = null;
				}
			}
		}

		private void OnDestroy()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(Draw));
			JakAudio.Stop(loop);
			ReleaseLobes();
			Mesh[] array = strips;
			foreach (Mesh val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					Object.Destroy((Object)(object)val);
				}
			}
			if (Object.op_Implicit((Object)(object)trail))
			{
				trail.Release();
			}
		}

		private void ReleaseLobes()
		{
			for (int i = 0; i < lobes.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)lobes[i]))
				{
					lobes[i].Release(lobeLeases[i]);
				}
				lobes[i] = null;
			}
		}
	}
	public sealed class JakBlastProjectile : NetworkBehaviour
	{
		private ProjectileController controller;

		private ProjectileDamage damage;

		private TeamFilter team;

		private FixedTimeStamp bornAt;

		private const float Skin = 0.01f;

		private Vector3 velocity;

		private Vector3 normal;

		private float fireHeight;

		private bool impact;

		private readonly JakBlast.Stall stall = new JakBlast.Stall();

		private Collider[] overlaps = (Collider[])(object)new Collider[64];

		private readonly HashSet<HealthComponent> victims = new HashSet<HealthComponent>();

		private JakBlastPresentation presentation;

		internal static GameObject Prefab { get; private set; }

		internal float Age => ((FixedTimeStamp)(ref bornAt)).timeSinceClamped;

		internal float Radius => JakBlast.Radius(Age);

		internal int HitCount => victims.Count;

		internal static GameObject BuildPrefab()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0024: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_0084: Expected O, but got Unknown
			GameObject val = new GameObject("JakDarkBlastProjectile");
			val.SetActive(false);
			val.AddComponent<NetworkIdentity>().localPlayerAuthority = false;
			val.AddComponent<TeamFilter>();
			ProjectileController obj = val.AddComponent<ProjectileController>();
			obj.allowPrediction = false;
			obj.authorityHandlesCollisionEvents = false;
			obj.doNotPerformImpactOnCollision = true;
			obj.procCoefficient = 1f;
			obj.startSound = "";
			val.AddComponent<ProjectileDamage>();
			val.AddComponent<ProjectileNetworkTransform>().checkForLocalPlayerAuthority = false;
			val.AddComponent<JakBlastProjectile>();
			Prefab = PrefabAPI.InstantiateClone(val, "JakDarkBlastProjectile", true);
			Object.Destroy((Object)val);
			Prefab.SetActive(true);
			return Prefab;
		}

		private void Awake()
		{
			controller = ((Component)this).GetComponent<ProjectileController>();
			damage = ((Component)this).GetComponent<ProjectileDamage>();
			team = ((Component)this).GetComponent<TeamFilter>();
			controller.onInitialized += Initialized;
		}

		private void Initialized(ProjectileController shot)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active)
			{
				bornAt = FixedTimeStamp.now;
				velocity = ((Component)this).transform.forward * 60f;
				fireHeight = ((Component)this).transform.position.y;
				normal = -((Component)this).transform.forward;
			}
		}

		private void Start()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if ((int)SystemInfo.graphicsDeviceType != 4)
			{
				presentation = new GameObject("DarkBlastFlight").AddComponent<JakBlastPresentation>();
				presentation.Begin(this);
			}
		}

		private void FixedUpdate()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing