Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Jak v0.1.1
BepInEx/plugins/Kulfs-Jak/JakSurvivor.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.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 System.Text; using System.Threading; using BepInEx; using BepInEx.Logging; using EntityStates; using JakSurvivor.States; using KinematicCharacterController; using R2API; using R2API.Utils; using RoR2; using RoR2.ConVar; 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 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 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 JakArcAudio { private struct Biquad { private double b0; private double b1; private double b2; private double a1; private double a2; private double z1; private double z2; private Biquad(double b0, double b1, double b2, double a0, double a1, double a2) { this.b0 = b0 / a0; this.b1 = b1 / a0; this.b2 = b2 / a0; this.a1 = a1 / a0; this.a2 = a2 / a0; z1 = (z2 = 0.0); } internal double Process(double input) { double num = b0 * input + z1; z1 = b1 * input - a1 * num + z2; z2 = b2 * input - a2 * num; return num; } internal static Biquad LowPass(double hz) { double num = Math.PI * 2.0 * hz / 48000.0; double num2 = Math.Cos(num); double num3 = Math.Sin(num) / Math.Sqrt(2.0); return new Biquad((1.0 - num2) * 0.5, 1.0 - num2, (1.0 - num2) * 0.5, 1.0 + num3, -2.0 * num2, 1.0 - num3); } internal static Biquad Peaking(double hz, double q, double db) { double num = Math.PI * 2.0 * hz / 48000.0; double num2 = Math.Cos(num); double num3 = Math.Sin(num) / (2.0 * q); double num4 = Math.Pow(10.0, db / 40.0); return new Biquad(1.0 + num3 * num4, -2.0 * num2, 1.0 - num3 * num4, 1.0 + num3 / num4, -2.0 * num2, 1.0 - num3 / num4); } internal static Biquad HighShelf(double hz, double db) { double num = Math.PI * 2.0 * hz / 48000.0; double num2 = Math.Cos(num); double num3 = Math.Pow(10.0, db / 40.0); double num4 = Math.Sin(num) * Math.Sqrt(2.0 * num3); return new Biquad(num3 * (num3 + 1.0 + (num3 - 1.0) * num2 + num4), -2.0 * num3 * (num3 - 1.0 + (num3 + 1.0) * num2), num3 * (num3 + 1.0 + (num3 - 1.0) * num2 - num4), num3 + 1.0 - (num3 - 1.0) * num2 + num4, 2.0 * (num3 - 1.0 - (num3 + 1.0) * num2), num3 + 1.0 - (num3 - 1.0) * num2 - num4); } } private Biquad tone; private Biquad edge; private Biquad hiss; private readonly float authoredGain; private readonly float level; private readonly float detectorScale; private readonly bool beam; private readonly float[] delay; private int delayAt; private double reduction; private static readonly double Attack = Math.Exp(-1.0 / 288.0); private static readonly double Release = Math.Exp(-0.0002314814814814815); private const double Threshold = -32.0; private const double Knee = 12.0; private const double Ratio = 1.18; private const double Slope = 0.15254237288135586; private const float OutputGain = 2f; private static readonly double MakeupTrim = Math.Pow(10.0, (0.0 - Compression(0.0) + -4.8813559322033875) * 0.6 / 20.0); internal static Func<float, float> Create(string key, float gameplayGain) { return key switch { "arc-loop" => new JakArcAudio(8300.0, 0.65f, 0.7f, gameplayGain, beam: true).Process, "arc-spin" => new JakArcAudio(3000.0, 0.20799999f, 0.76f, gameplayGain, beam: false).Process, "blue-gun-whine" => new JakArcAudio(1300.0, 0.097500004f, 1f, gameplayGain, beam: false).Process, _ => null, }; } private JakArcAudio(double cutoff, float authoredGain, float level, float gameplayGain, bool beam) { this.authoredGain = authoredGain; this.level = level * 2f; this.beam = beam; tone = Biquad.LowPass(cutoff); if (beam) { edge = Biquad.Peaking(3000.0, 0.85, -4.5); hiss = Biquad.HighShelf(5000.0, -3.5); delay = new float[288]; detectorScale = Math.Max(1E-06f, gameplayGain * 0.75f * 0.7f); } } private float Process(float sample) { double num = tone.Process(sample * authoredGain); if (!beam) { return (float)num * level; } num = hiss.Process(edge.Process(num)); double num2 = Compression(20.0 * Math.Log10(Math.Max(1E-12, Math.Abs(num) * (double)detectorScale))); double num3 = ((num2 < reduction) ? Attack : Release); reduction = num2 + num3 * (reduction - num2); float num4 = delay[delayAt]; delay[delayAt] = (float)num; if (++delayAt == delay.Length) { delayAt = 0; } return (float)((double)num4 * Math.Pow(10.0, reduction / 20.0) * MakeupTrim) * level; } private static double Compression(double db) { double num = db - -32.0; if (num <= 0.0) { return 0.0; } if (!(num < 12.0)) { return -0.15254237288135586 * (num - 6.0); } return -0.15254237288135586 * num * num / 24.0; } } 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, null, loop: true, 0.8f, menu: false, (num2 < 1f) ? (1524f * Mathf.Lerp(-0.5f, 0f, num2)) : 0f, 768f); } else if (num2 < 1f) { loop = JakAudio.Play("arc-loop", ((Component)muzzle).gameObject, null, loop: true, 0.8f, menu: false, 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, null, loop: true, 0.8f, menu: false, 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 sealed class JakAudio : MonoBehaviour { internal readonly struct Clip { public readonly float[] Samples; public readonly float Peak; public Clip(float[] samples) { Samples = samples; Peak = JakSoundLevels.Peak(samples); } } internal sealed class Voice { public NativeAudio.Voice Playback; public string Key; public GameObject Owner; public float Gain; public bool Menu; public bool HasPoint; public bool Fading; public Vector3 Point; public void SetPlaybackParameters(float pitchMod, float volume1024) { Playback.Rate = (float)Math.Pow(2.0, (double)pitchMod / 1536.0); Playback.Gain = Mathf.Max(0f, volume1024 / 1024f); } } 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 Dictionary<string, Clip> Clips = new Dictionary<string, Clip>(); private static JakAudio instance; private readonly List<Voice> voices = new List<Voice>(); private NativeAudio mixer; private BaseConVar masterVolume; private BaseConVar sfxVolume; private BaseConVar focusedOnly; private float volume = 1f; private float settingsAt; 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; } } private void Awake() { instance = this; } public static void LoadClips() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if (Application.isBatchMode || (int)SystemInfo.graphicsDeviceType == 4) { return; } string[] keys = Keys; foreach (string text in keys) { if (!Clips.ContainsKey(text)) { try { Clips.Add(text, new Clip(ReadClip(JakAssets.Bundle, text))); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not load Jak sound " + text + ": " + ex.Message)); } } } if (Clips.Count > 0 && Object.op_Implicit((Object)(object)instance) && instance.mixer == null) { try { instance.mixer = new NativeAudio(); } catch (Exception ex2) { Clips.Clear(); Plugin.Log.LogWarning((object)("Jak audio unavailable; using native fallback: " + ex2.Message)); } } Plugin.Log.LogInfo((object)("Loaded " + Clips.Count + " original Jak 3 sound effects.")); } internal static float[] ReadClip(AssetBundle bundle, string key) { TextAsset obj = bundle.LoadAsset<TextAsset>("jak3-sfx-" + key + ".bytes"); if (!Object.op_Implicit((Object)(object)obj)) { throw new InvalidDataException("Missing raw PCM audio payload for " + key); } int channels; int sampleRate; float[] result = PcmWave.Decode(obj.bytes, out channels, out sampleRate); if (channels != 1 || sampleRate != 48000) { throw new InvalidDataException("Expected 48kHz mono PCM."); } return result; } internal static float Duration(string key) { if (!Clips.TryGetValue(key, out var value)) { return 0f; } return (float)value.Samples.Length / 48000f; } public static Voice Play(string key, GameObject owner, string fallback = null, bool loop = false, float gain = 0.8f, bool menu = false, float pitchMod = 0f, float volume1024 = 1024f) { if (!Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)instance) || instance.mixer == null || !Clips.TryGetValue(key, out var value)) { if (Object.op_Implicit((Object)(object)owner) && !string.IsNullOrEmpty(fallback)) { Util.PlaySound(fallback, owner); } return null; } instance.voices.RemoveAll((Voice v) => v.Playback.Stopped); if (loop) { foreach (Voice voice2 in instance.voices) { if ((Object)(object)voice2.Owner == (Object)(object)owner && voice2.Key == key && voice2.Playback.Loop) { voice2.SetPlaybackParameters(pitchMod, volume1024); return voice2; } } } float num = (menu ? gain : JakSoundLevels.GameplayGain(gain, value.Peak)); Voice voice = new Voice { Key = key, Owner = owner, Gain = num, Menu = menu, Playback = instance.mixer.Play(value.Samples, loop, menu ? null : JakArcAudio.Create(key, num)) }; if (voice.Playback.Stopped) { return null; } voice.SetPlaybackParameters(pitchMod, volume1024); voice.Playback.Paused = Time.timeScale <= 0f && !menu; instance.voices.Add(voice); instance.Position(voice, instance.ListenerTransform()); return voice; } public static Voice PlayAt(string key, Vector3 point, GameObject owner, float gain = 0.8f) { //IL_0023: 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) Voice voice = Play(key, owner, null, loop: false, gain); if (voice == null) { return null; } voice.HasPoint = true; voice.Point = point; instance.Position(voice, instance.ListenerTransform()); return voice; } public static void Fade(Voice voice, float seconds) { //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) if (voice != null && !voice.Fading && !voice.Playback.Stopped) { if (!voice.HasPoint && Object.op_Implicit((Object)(object)voice.Owner)) { voice.Point = voice.Owner.transform.position; voice.HasPoint = true; } voice.Fading = true; voice.Playback.FadeOut((int)(seconds * 48000f)); } } public static void Stop(Voice voice) { if (voice != null) { voice.Playback.Stopped = true; if (Object.op_Implicit((Object)(object)instance)) { instance.voices.Remove(voice); } } } private void Update() { if (mixer == null) { return; } if (mixer.Failure != null) { Plugin.Log.LogWarning((object)("Jak audio output stopped (" + mixer.Failure + "); using native fallback sounds.")); Shutdown(); return; } if (Time.unscaledTime >= settingsAt) { settingsAt = Time.unscaledTime + 0.2f; Console val = Console.instance; if (Object.op_Implicit((Object)(object)val)) { masterVolume = masterVolume ?? val.FindConVar("volume_master"); sfxVolume = sfxVolume ?? val.FindConVar("volume_sfx"); focusedOnly = focusedOnly ?? val.FindConVar("audio_focused_only"); } volume = Mathf.Clamp01(Read(masterVolume, 100f) / 100f) * Mathf.Clamp01(Read(sfxVolume, 100f) / 100f); } mixer.Paused = !Application.isFocused && Read(focusedOnly, 1f) != 0f; Transform listener = ListenerTransform(); for (int num = voices.Count - 1; num >= 0; num--) { Voice voice = voices[num]; if ((!voice.Fading && (!Object.op_Implicit((Object)(object)voice.Owner) || !voice.Owner.activeInHierarchy)) || voice.Playback.Stopped) { voice.Playback.Stopped = true; voices.RemoveAt(num); } else { voice.Playback.Paused = Time.timeScale <= 0f && !voice.Menu; Position(voice, listener); } } } private void Position(Voice voice, Transform listener) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) float left = 0f; float right = 0f; if (voice.Menu) { left = (right = volume * voice.Gain * Mathf.Sqrt(0.5f)); } else if (Object.op_Implicit((Object)(object)listener) && (voice.HasPoint || Object.op_Implicit((Object)(object)voice.Owner))) { Vector3 val = (voice.HasPoint ? voice.Point : voice.Owner.transform.position) - listener.position; float magnitude = ((Vector3)(ref val)).magnitude; float num = ((magnitude >= 65f) ? 0f : Mathf.Min(1f, 8f / Mathf.Max(magnitude, 0.01f))); float num2 = Mathf.Clamp((magnitude > 0.01f) ? Vector3.Dot(listener.right, val / magnitude) : 0f, -1f, 1f); float num3 = volume * voice.Gain * num; left = num3 * Mathf.Sqrt((1f - num2) * 0.5f); right = num3 * Mathf.Sqrt((1f + num2) * 0.5f); } voice.Playback.Left = left; voice.Playback.Right = right; } private Transform ListenerTransform() { foreach (CameraRigController readOnlyInstances in CameraRigController.readOnlyInstancesList) { if (Object.op_Implicit((Object)(object)readOnlyInstances) && ((Behaviour)readOnlyInstances).isActiveAndEnabled && readOnlyInstances.localUserViewer != null && Object.op_Implicit((Object)(object)readOnlyInstances.sceneCam) && ((Behaviour)readOnlyInstances.sceneCam).isActiveAndEnabled) { return ((Component)readOnlyInstances.sceneCam).transform; } } Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { return null; } return ((Component)main).transform; } private static float Read(BaseConVar convar, float fallback) { if (convar == null || !float.TryParse(convar.GetString(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return fallback; } return result; } private void Shutdown() { foreach (Voice voice in voices) { voice.Playback.Stopped = true; } voices.Clear(); mixer?.Dispose(); mixer = null; } private void OnDestroy() { Shutdown(); Clips.Clear(); if ((Object)(object)instance == (Object)(object)this) { instance = null; } } } 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_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0182: 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, null, loop: true); 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: Unkno