Decompiled source of Survivors v0.6.5
plugins/MuckSurvivors.dll
Decompiled 9 hours 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.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("MuckSurvivors")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Pick a Risk of Rain 2 survivor in the Muck lobby.")] [assembly: AssemblyFileVersion("0.6.5.0")] [assembly: AssemblyInformationalVersion("0.6.5+1911ecd07d605294f346388086fc942f4c18d4fa")] [assembly: AssemblyProduct("Survivors")] [assembly: AssemblyTitle("MuckSurvivors")] [assembly: AssemblyVersion("0.6.5.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } } namespace MuckSurvivors { internal sealed class AbilityController : MonoBehaviour { private readonly struct MobTarget { public readonly HitableMob Mob; public readonly Collider Collider; public MobTarget(HitableMob mob, Collider collider) { Mob = mob; Collider = collider; } } private readonly struct PhaseTarget { public readonly HitableMob Mob; public readonly Vector3 Point; public PhaseTarget(HitableMob mob, Vector3 point) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Mob = mob; Point = point; } } private readonly struct Strike { public readonly int BaseDamage; public readonly float Strength; public readonly List<MobTarget> Targets; private Strike(int baseDamage, float strength, List<MobTarget> targets) { BaseDamage = baseDamage; Strength = strength; Targets = targets; } public static Strike Take() { return new Strike(KitDamageReader.Read(), PowerupInventory.Instance.GetStrengthMultiplier((int[])null), SnapshotMobs()); } } private const float DashExitSpeed = 6.5f; private const float DoubleTapRadius = 0.15f; private const float MuzzleSpread = 0.18f; private const float CanisterCastRadius = 0.3f; private readonly Cooldown doubleTap = new Cooldown(); private readonly HudRow doubleTapRow = new HudRow(); private bool rightMuzzle; private readonly Cooldown dive = new Cooldown(); private readonly Cooldown phase = new Cooldown(); private readonly Cooldown assault = new Cooldown(); private readonly Cooldown parryCd = new Cooldown(); private readonly ParryWindow parry = new ParryWindow(); private float parryCooldown; private readonly Cooldown transport = new Cooldown(); private readonly Cooldown canister = new Cooldown(); private readonly HitLedger ledger = new HitLedger(); private readonly HitLedger canisterLedger = new HitLedger(); private readonly HudRow diveRow = new HudRow(); private readonly HudRow phaseRow = new HudRow(); private readonly HudRow assaultRow = new HudRow(); private readonly HudRow parryRow = new HudRow(); private readonly HudRow transportRow = new HudRow(); private readonly HudRow canisterRow = new HudRow(); private readonly List<HudRow> hud = new List<HudRow>(); private DashChain chain; private bool busy; private static SurvivorTuning T => SurvivorState.Tuning; private static WeaponTuning W => SurvivorState.Tuning.Weapons; private static SurvivorsConfig Cfg => SurvivorsPlugin.Cfg; private void Awake() { chain = NewChain(); } public void StopAll() { ((MonoBehaviour)this).StopAllCoroutines(); doubleTap.Reset(); dive.Reset(); phase.Reset(); assault.Reset(); parryCd.Reset(); parry.Reset(); parryCooldown = 0f; SurvivorState.ParryActive = false; ParryPose.Clear(); ParryFov.Release(); ParryCue.Reset(); transport.Reset(); canister.Reset(); ledger.Reset(); canisterLedger.Reset(); chain = NewChain(); busy = false; } private static DashChain NewChain() { return new DashChain(T.AssaultMaxDashes, T.AssaultRedashWindow); } private static bool PlayerAlive() { if ((Object)(object)PlayerStatus.Instance != (Object)null && (Object)(object)PlayerMovement.Instance != (Object)null) { return !PlayerStatus.Instance.IsPlayerDead(); } return false; } private void Update() { if (!SurvivorState.Active) { return; } try { float time = Time.time; SurvivorId locked = SurvivorState.Session.Locked; if (locked == SurvivorId.Mercenary && (Object)(object)PlayerStatus.Instance != (Object)null && PlayerStatus.Instance.IsPlayerDead()) { EndParryOnDeath(time); } if (!PlayerAlive()) { return; } if (locked == SurvivorId.Mercenary) { if (chain.Tick(time)) { assault.Start(time, AssaultCooldownNow()); } if (parry.Tick(time)) { FinishParry(time); } } if (!InputBlocked()) { switch (locked) { case SurvivorId.Commando: UpdateCommando(time); break; case SurvivorId.Mercenary: UpdateMercenary(time); break; case SurvivorId.MulT: UpdateMulT(time); break; } } } catch (Exception arg) { SurvivorsPlugin.LogOnce("AbilityController", $"Survivors ability update failed: {arg}"); } } internal static bool InputBlocked() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)GameManager.state == 1) { if ((Object)(object)OtherInput.Instance != (Object)null) { if (!OtherInput.Instance.OtherUiActive()) { return OtherInput.Instance.IsAnyMenuOpen(); } return true; } return false; } return true; } private void UpdateCommando(float now) { //IL_001d: 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) if (Keys.PrimaryHeld(SurvivorId.Commando) && doubleTap.Ready(now)) { FireDoubleTap(now); } if (Keys.Use(SkillKeys.Utility, "Tactical Dive", dive, now, busy)) { dive.Start(now, T.DiveCooldown); SurvivorsPlugin.Verbose("Tactical Dive"); ((MonoBehaviour)this).StartCoroutine(Dash(DashStyle.Dive, T.DiveSpeed, T.DiveDuration, 0f, 0f, null)); } if (Keys.Use(SkillKeys.Secondary, "Phase Round", phase, now)) { phase.Start(now, T.PhaseCooldown); SurvivorsPlugin.Verbose("Phase Round"); FirePhaseRound(); } Keys.LogUnused("Commando", hasSecondary: true); } private void UpdateMercenary(float now) { Keys.LogUnused("Mercenary", hasSecondary: true); TryAssault(now); TryParry(now); } private void TryAssault(float now) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (Keys.Pressed(SkillKeys.Utility)) { DashDecision dashDecision = ((!busy) ? chain.OnKeyPressed(now, assault.Ready(now)) : DashDecision.None); if (dashDecision == DashDecision.None) { SurvivorsPlugin.Verbose(SkillLog.Refusal("Blinding Assault", busy, assault.Remaining(now)) ?? SkillLog.NotCast("Blinding Assault", "the re-dash window has closed or the chain is spent")); return; } float moveMultiplier = MoveSpeed(); float duration = MercenaryMath.DashDuration(T.AssaultDuration, moveMultiplier); string[] obj = new string[9] { "Blinding Assault ", dashDecision.ToString(), " (dash ", chain.DashesUsed.ToString(), ", ", null, null, null, null }; float assaultSpeed = T.AssaultSpeed; obj[5] = assaultSpeed.ToString("0.0", CultureInfo.InvariantCulture); obj[6] = " m/s for "; obj[7] = duration.ToString("0.00", CultureInfo.InvariantCulture); obj[8] = " s)"; SurvivorsPlugin.Verbose(string.Concat(obj)); ((MonoBehaviour)this).StartCoroutine(Dash(DashStyle.Assault, T.AssaultSpeed, duration, T.AssaultDamage, T.AssaultHitRadius, OnAssaultEnded)); } } private void OnAssaultEnded(bool hit) { if (chain.OnDashEnded(hit, Time.time)) { assault.Start(Time.time, AssaultCooldownNow()); } } private static float AssaultCooldownNow() { return MercenaryMath.Cooldown(T.AssaultCooldown, AttackSpeed()); } private void TryParry(float now) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (!Keys.Pressed(SkillKeys.Secondary)) { return; } if (parry.Active) { SurvivorsPlugin.Verbose(SkillLog.NotCast("Parry", "already up")); return; } if (!parryCd.Ready(now)) { SurvivorsPlugin.Verbose(SkillLog.Refusal("Parry", busy: false, parryCd.Remaining(now))); return; } float attackSpeed = AttackSpeed(); float num = MercenaryMath.ParryDuration(T.ParryDuration, attackSpeed); if (!parry.TryStart(now, num)) { SurvivorsPlugin.Verbose(SkillLog.NotCast("Parry", "its duration is not positive")); return; } parryCooldown = MercenaryMath.Cooldown(T.ParryCooldown, attackSpeed); SurvivorState.ParryActive = true; ParryPose.Copy(parry); SurvivorsPlugin.Verbose("Parry"); SurvivorsPlugin.Verbose("Parry: up for " + num.ToString("0.00", CultureInfo.InvariantCulture) + " s"); ParryCue.Cast(); float num2 = MercenaryMath.WireSeconds(num); if (num2 > 0f) { SkillFxNet.Send(SkillFxEvent.Parry(num2)); } } private void EndParryOnDeath(float now) { if (parry.End(now)) { FinishParry(now); } } private void FinishParry(float now) { SurvivorState.ParryActive = false; parryCd.Start(now, parryCooldown); ParryPose.Copy(parry); } private void UpdateMulT(float now) { //IL_0075: 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) Keys.LogUnused("MUL-T", T.BlastCanister.Enabled); if (T.BlastCanister.Enabled && Keys.Use(SkillKeys.Secondary, "Blast Canister", canister, now)) { canister.Start(now, T.BlastCanister.Cooldown); SurvivorsPlugin.Verbose("Blast Canister"); ((MonoBehaviour)this).StartCoroutine(BlastCanister()); } if (Keys.Use(SkillKeys.Utility, "Transport Mode", transport, now, busy)) { SurvivorsPlugin.Verbose("Transport Mode"); ((MonoBehaviour)this).StartCoroutine(Transport()); } } private IEnumerator Dash(DashStyle style, float speed, float duration, float coefficient, float radius, Action<bool> onEnd) { busy = true; SurvivorState.DashActive = true; ledger.Reset(); int hits = 0; Color color = ((style == DashStyle.Dive) ? FxColors.Commando : FxColors.Mercenary); if (TryBeginDash(coefficient, out var dir, out var exitSpeed, out var strike)) { Vector3 start = LocalFx.Feet(); SkillFx.SpeedLines(dir, color, duration); float end = Time.time + duration; while (Time.time < end && DashStep(dir, speed, coefficient, radius, strike, color, ref hits)) { yield return (object)new WaitForFixedUpdate(); } ExitDash(dir, exitSpeed); DashEnded(style, start, dir, hits > 0); } if (style == DashStyle.Assault) { SurvivorsPlugin.Verbose(SkillLog.Outcome($"Blinding Assault dash {chain.DashesUsed}", hits)); } SurvivorState.DashActive = false; busy = false; onEnd?.Invoke(hits > 0); } private static void DashEnded(DashStyle style, Vector3 start, Vector3 dir, bool hit) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) try { Vector3 val = LocalFx.Feet(); LocalFx.Cast(SkillFxEvent.Dash(style, SkillFxPlayer.V(start), SkillFxPlayer.V(val))); if (style == DashStyle.Assault && hit) { SkillFx.Arc(val + Vector3.up, dir, Vector3.Cross(Vector3.up, dir), 2f, 140f, FxColors.Mercenary); } } catch (Exception arg) { SurvivorsPlugin.LogOnce("dash-fx", $"Survivors: drawing the dash failed: {arg}"); } } private static bool TryBeginDash(float coefficient, out Vector3 dir, out float exitSpeed, out Strike strike) { //IL_0001: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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) dir = Vector3.zero; exitSpeed = 6.5f; strike = default(Strike); try { PlayerMovement instance = PlayerMovement.Instance; dir = instance.orientation.forward; dir.y = 0f; if (((Vector3)(ref dir)).sqrMagnitude < 0.0001f) { dir = ((Component)instance).transform.forward; } ((Vector3)(ref dir)).Normalize(); Rigidbody rb = instance.GetRb(); if ((Object)(object)rb != (Object)null) { Vector3 val = new Vector3(rb.velocity.x, 0f, rb.velocity.z); exitSpeed = Mathf.Max(6.5f, ((Vector3)(ref val)).magnitude); } if (coefficient > 0f) { strike = Strike.Take(); } return true; } catch (Exception arg) { SurvivorsPlugin.LogOnce("dash-begin", $"Survivors dash failed to start: {arg}"); return false; } } private bool DashStep(Vector3 dir, float speed, float coefficient, float radius, Strike strike, Color color, ref int hits) { //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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) try { if (!PlayerAlive()) { return false; } Rigidbody rb = PlayerMovement.Instance.GetRb(); if ((Object)(object)rb == (Object)null) { return false; } rb.isKinematic = false; rb.velocity = dir * speed + Vector3.up * rb.velocity.y; if (coefficient > 0f) { hits += SweepHits(strike, ((Component)PlayerMovement.Instance).transform.position, radius, coefficient, color, ledger); } return true; } catch (Exception arg) { SurvivorsPlugin.LogOnce("dash-step", $"Survivors dash step failed: {arg}"); return false; } } private static void ExitDash(Vector3 dir, float exitSpeed) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)PlayerMovement.Instance == (Object)null)) { Rigidbody rb = PlayerMovement.Instance.GetRb(); if (!((Object)(object)rb == (Object)null)) { rb.velocity = dir * exitSpeed + Vector3.up * rb.velocity.y; } } } catch (Exception arg) { SurvivorsPlugin.LogOnce("dash-exit", $"Survivors dash exit failed: {arg}"); } } private IEnumerator Transport() { busy = true; SurvivorState.TransportActive = true; ledger.Reset(); int hits = 0; if (TryBeginTransport(out var strike)) { LocalFx.Cast(SkillFxEvent.Transport(T.TransportDuration)); SkillFx.SpeedLines(PlayerMovement.Instance.orientation.forward, FxColors.MulT, T.TransportDuration); float end = Time.time + T.TransportDuration; while (Time.time < end && TransportStep(strike, ref hits)) { yield return (object)new WaitForFixedUpdate(); } } SurvivorsPlugin.Verbose(SkillLog.Outcome("Transport Mode", hits)); SurvivorState.TransportActive = false; busy = false; transport.Start(Time.time, T.TransportCooldown); } private static bool TryBeginTransport(out Strike strike) { strike = default(Strike); try { strike = Strike.Take(); return true; } catch (Exception arg) { SurvivorsPlugin.LogOnce("transport-begin", $"Survivors Transport Mode failed to start: {arg}"); return false; } } private bool TransportStep(Strike strike, ref int hits) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) try { if (!PlayerAlive()) { return false; } hits += SweepHits(strike, ((Component)PlayerMovement.Instance).transform.position, T.TransportHitRadius, T.TransportDamage, FxColors.MulT, ledger); return true; } catch (Exception arg) { SurvivorsPlugin.LogOnce("transport-step", $"Survivors Transport Mode step failed: {arg}"); return false; } } private IEnumerator BlastCanister() { int hits = 0; if (TryFireCanister(out var strike, out var burst, out var forward, ref hits)) { float start = Time.time; for (int i = 0; i < T.BlastCanister.Bomblets; i++) { float due = start + T.BlastCanister.BombletTime(i); while (Time.time < due) { yield return null; } if (!Bomblet(strike, burst, forward, i, ref hits)) { break; } } } SurvivorsPlugin.Verbose(SkillLog.Outcome("Blast Canister", hits)); } private bool TryFireCanister(out Strike strike, out Vector3 burst, out Vector3 forward, ref int hits) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00c7: 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_0116: 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_012e: 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_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: 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) strike = default(Strike); burst = Vector3.zero; forward = Vector3.forward; try { if (!Hitscan.TryAim(out var origin, out var forward2)) { return false; } strike = Strike.Take(); HitscanShot hitscanShot = Hitscan.Cast(origin, forward2, T.BlastCanister.Range, 0.3f); burst = (hitscanShot.Hit ? hitscanShot.Point : (origin + forward2 * hitscanShot.Stop)); forward = new Vector3(forward2.x, 0f, forward2.z); forward = ((((Vector3)(ref forward)).sqrMagnitude < 0.0001f) ? Vector3.forward : ((Vector3)(ref forward)).normalized); SkillFx.Segment(Tracer.Muzzle(origin, forward2), burst, FxColors.MulT, 0.12f, 0.15f); canisterLedger.Reset(); hits += SweepHits(strike, burst, T.BlastCanister.Radius, T.BlastCanister.Damage, FxColors.MulT, canisterLedger); SkillFx.Flash(burst, FxColors.MulT, 1.2f, 0.12f); SkillFx.Ring(burst, 0.3f, T.BlastCanister.Radius, FxColors.MulT, 0.15f, 0.3f); SkillFx.Puffs(burst, 0.3f, T.BlastCanister.Radius * 0.6f, 5, FxColors.Smoke, 0.6f, 0.6f); return true; } catch (Exception arg) { SurvivorsPlugin.LogOnce("canister", $"Survivors Blast Canister failed: {arg}"); return false; } } private bool Bomblet(Strike strike, Vector3 burst, Vector3 forward, int i, ref int hits) { //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_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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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) //IL_00cf: 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) try { Vec3 vec = T.BlastCanister.BombletOffset(i); Vector3 val = Vector3.Cross(Vector3.up, forward); Vector3 val2 = burst + val * vec.X + forward * vec.Z; RaycastHit val3 = default(RaycastHit); if (Physics.Raycast(val2 + Vector3.up * 2f, Vector3.down, ref val3, 8f, Layers.Walls, (QueryTriggerInteraction)1)) { val2 = ((RaycastHit)(ref val3)).point + Vector3.up * 0.3f; } canisterLedger.Reset(); hits += SweepHits(strike, val2, T.BlastCanister.BombletRadius, T.BlastCanister.BombletDamage, FxColors.MulT, canisterLedger); SkillFx.Flash(val2, FxColors.MulT, 0.6f, 0.1f); SkillFx.Ring(val2, 0.2f, T.BlastCanister.BombletRadius, FxColors.MulT, 0.1f, 0.25f); return true; } catch (Exception arg) { SurvivorsPlugin.LogOnce("canister-bomblet", $"Survivors Blast Canister bomblet failed: {arg}"); return false; } } private static List<MobTarget> SnapshotMobs() { List<MobTarget> list = new List<MobTarget>(); if ((Object)(object)MobManager.Instance == (Object)null || MobManager.Instance.mobs == null) { return list; } foreach (Mob value in MobManager.Instance.mobs.Values) { if (!((Object)(object)value == (Object)null)) { HitableMob component = ((Component)value).GetComponent<HitableMob>(); if (!((Object)(object)component == (Object)null) && ((Hitable)component).hp > 0) { list.Add(new MobTarget(component, ((Component)component).GetComponentInChildren<Collider>())); } } } return list; } private static int SweepHits(Strike strike, Vector3 center, float radius, float coefficient, Color spark, HitLedger claims) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_004e: 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_006c: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) int num = 0; foreach (MobTarget target in strike.Targets) { HitableMob mob = target.Mob; if ((Object)(object)mob == (Object)null || ((Hitable)mob).hp <= 0) { continue; } Vector3 val; if (!((Object)(object)target.Collider != (Object)null)) { val = ((Component)mob).transform.position; } else { Bounds bounds = target.Collider.bounds; val = ((Bounds)(ref bounds)).ClosestPoint(center); } Vector3 val2 = val; Vector3 val3 = val2 - center; if (!(((Vector3)(ref val3)).sqrMagnitude > radius * radius) && claims.TryClaim(((Hitable)mob).GetId())) { int num2 = AbilityDamage.Hit(strike.BaseDamage, coefficient, strike.Strength); if (num2 > 0) { HitMob(mob, num2, val2); SkillFx.Spark(val2, spark); num++; } } } return num; } private static void FirePhaseRound() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: 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_0285: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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) try { PlayerMovement instance = PlayerMovement.Instance; Vector3 position = instance.playerCam.position; Vector3 forward = instance.playerCam.forward; RaycastHit[] array = Physics.SphereCastAll(position, T.PhaseRadius, forward, T.PhaseRange, -1, (QueryTriggerInteraction)1); Transform root = ((Component)instance).transform.root; int mask = LayerMask.GetMask(new string[2] { "Ground", "Object" }); List<PierceCandidate> list = new List<PierceCandidate>(array.Length); Dictionary<int, PhaseTarget> dictionary = new Dictionary<int, PhaseTarget>(); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val = array2[i]; Transform root2 = ((Component)((RaycastHit)(ref val)).collider).transform.root; int instanceID = ((Object)root2).GetInstanceID(); if ((Object)(object)root2 == (Object)(object)root) { list.Add(new PierceCandidate(instanceID, ((RaycastHit)(ref val)).distance, CastKind.Ignore)); continue; } HitableMob component = ((Component)root2).GetComponent<HitableMob>(); if ((Object)(object)component != (Object)null && ((Hitable)component).hp > 0) { if (!dictionary.ContainsKey(instanceID)) { dictionary[instanceID] = new PhaseTarget(component, (((RaycastHit)(ref val)).distance > 0f) ? ((RaycastHit)(ref val)).point : ((Component)component).transform.position); } list.Add(new PierceCandidate(instanceID, ((RaycastHit)(ref val)).distance, CastKind.Mob)); } else { bool flag = (mask & (1 << ((Component)((RaycastHit)(ref val)).collider).gameObject.layer)) != 0; list.Add(new PierceCandidate(instanceID, ((RaycastHit)(ref val)).distance, flag ? CastKind.Blocker : CastKind.Ignore)); } } PiercePlan piercePlan = PierceOrder.Plan(list, T.PhaseMaxTargets, T.PhaseRange); int baseDamage = KitDamageReader.Read(); float strengthMultiplier = PowerupInventory.Instance.GetStrengthMultiplier((int[])null); int num = 0; for (int j = 0; j < piercePlan.Keys.Count; j++) { PhaseTarget phaseTarget = dictionary[piercePlan.Keys[j]]; int num2 = AbilityDamage.Pierce(baseDamage, T.PhaseDamage, T.PhasePierceBonus, j, strengthMultiplier); if (num2 > 0) { HitMob(phaseTarget.Mob, num2, phaseTarget.Point); SkillFx.Spark(phaseTarget.Point, Color.white); num++; } } SurvivorsPlugin.Verbose(SkillLog.Outcome("Phase Round", num)); Vector3 val2 = Tracer.Muzzle(position, forward); Vector3 val3 = Tracer.HeldMuzzle(SurvivorId.Commando, position, forward, val2); Vector3 val4 = position + forward * piercePlan.StopDistance; LocalFx.Cast(SkillFxEvent.Shot(ShotStyle.PhaseRound, SkillFxPlayer.V(val3), SkillFxPlayer.V(val4)), SkillFxEvent.Shot(ShotStyle.PhaseRound, SkillFxPlayer.V(val2), SkillFxPlayer.V(val4))); if (Cfg.LogPhaseRound.Value) { LogPhaseLook(val3, val4); } } catch (Exception arg) { SurvivorsPlugin.LogOnce("phase-round", $"Survivors Phase Round failed: {arg}"); } } private static void LogPhaseLook(Vector3 muzzle, Vector3 end) { //IL_0016: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_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_015a: 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) Camera main = Camera.main; if (!((Object)(object)main == (Object)null)) { Vector3 position = ((Component)main).transform.position; float num = Mathf.Max(2f, Vector3.Distance(position, muzzle)); Vector3 val = muzzle - position; Vector3 val2 = position + ((Vector3)(ref val)).normalized * num; float num2 = Vector3.Distance(position, end); float num3 = Vector3.Distance(val2, end); float fieldOfView = main.fieldOfView; int height = Screen.height; Vector3 val3 = main.WorldToScreenPoint(val2); SurvivorsPlugin.Log.LogInfo((object)string.Format(CultureInfo.InvariantCulture, "Survivors Phase Round fx: flash {0:0.00} m at {1:0.0} m = {2:0} px tall for {3:0.00} s; trail {4:0.00}->{5:0.00} m wide over {6:0.0} m, {7:0} px at its start ({1:0.0} m) and {8:0} px at the end ({9:0.0} m); starts {14:+0;-0} px right and {15:+0;-0} px up of screen centre; bolt flies {10:0.00} s, then the whole trail stays and fades out over {11:0.00} s (screen {12} px, FOV {13:0})", 0.45f, num, PhaseRoundLook.Pixels(0.45f, num, fieldOfView, height), 0.12f, 0.45f, 0.25f, num3, PhaseRoundLook.Pixels(0.45f, num, fieldOfView, height), PhaseRoundLook.Pixels(0.25f, num2, fieldOfView, height), num2, PhaseRoundLook.Travel(num3), 0.25f, height, fieldOfView, val3.x - (float)Screen.width / 2f, val3.y - (float)height / 2f)); } } private void FireDoubleTap(float now) { //IL_003b: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) if (!Hitscan.TryAim(out var origin, out var forward)) { return; } doubleTap.Repeat(now, WeaponTuning.Interval(W.DoubleTapInterval, AttackSpeed()), Time.deltaTime); SurvivorsPlugin.Verbose("Double Tap"); try { HitscanShot hitscanShot = Hitscan.Cast(origin, forward, W.DoubleTapRange, 0.15f); rightMuzzle = !rightMuzzle; Vector3 val = PlayerMovement.Instance.playerCam.right * (rightMuzzle ? 0.18f : (-0.18f)); LocalFx.Cast(SkillFxEvent.Shot(ShotStyle.DoubleTap, SkillFxPlayer.V(Tracer.Muzzle(origin, forward) + val), SkillFxPlayer.V(origin + forward * hitscanShot.Stop))); Recoil(); int num = (hitscanShot.Hit ? AbilityDamage.Hit(KitDamageReader.Read(), W.DoubleTapDamage, PowerupInventory.Instance.GetStrengthMultiplier((int[])null)) : 0); SurvivorsPlugin.Verbose(SkillLog.Outcome("Double Tap", (num > 0) ? 1 : 0)); if (num > 0) { HitMob(hitscanShot.Mob, num, hitscanShot.Point); SkillFx.Spark(hitscanShot.Point, Cfg.TracerColor.Value); } } catch (Exception arg) { SurvivorsPlugin.LogOnce("double-tap", $"Survivors Double Tap failed: {arg}"); } } internal static void Recoil() { try { UseInventory instance = UseInventory.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.animator != (Object)null) { instance.animator.Play("Shoot", -1, 0f); } } catch (Exception arg) { SurvivorsPlugin.LogOnce("recoil", $"Survivors: the gun recoil animation failed: {arg}"); } } internal static float MoveSpeed() { try { return ((Object)(object)PowerupInventory.Instance != (Object)null) ? PowerupInventory.Instance.GetSpeedMultiplier((int[])null) : 1f; } catch (Exception arg) { SurvivorsPlugin.LogOnce("move-speed", $"Survivors: reading move speed failed; the dash uses its base length: {arg}"); return 1f; } } internal static float AttackSpeed() { try { return ((Object)(object)PowerupInventory.Instance != (Object)null) ? PowerupInventory.Instance.GetAttackSpeedMultiplier((int[])null) : 1f; } catch (Exception arg) { SurvivorsPlugin.LogOnce("attack-speed", $"Survivors: reading attack speed failed; primaries fire at their base rate: {arg}"); return 1f; } } private static void HitMob(HitableMob mob, int damage, Vector3 point) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) SurvivorHits.Deal(mob, damage, 0, point, HitSource.Skill); SurvivorsPlugin.Verbose($"Ability hit mob {((Hitable)mob).GetId()} for {damage}"); } private void OnGUI() { DrawParryVignette(); if (!SkillHud.Visible || !PlayerAlive()) { return; } float time = Time.time; int version = SkillKeys.Version; hud.Clear(); switch (SurvivorState.Session.Locked) { default: return; case SurvivorId.Commando: SkillHud.PrimaryRow(doubleTapRow, SurvivorId.Commando, "Double Tap: ", HudClock.Key(doubleTap, time)); hud.Add(doubleTapRow); SkillHud.CooldownRow(diveRow, SkillKeys.UtilityLabel, "Tactical Dive: ", HudClock.Key(dive, time)); SkillHud.CooldownRow(phaseRow, SkillKeys.SecondaryLabel, "Phase Round: ", HudClock.Key(phase, time)); hud.Add(diveRow); hud.Add(phaseRow); break; case SurvivorId.Mercenary: { int num2 = HudClock.Key(assault, time); int num3 = (chain.InChain ? chain.DashesUsed : (-1)); if (assaultRow.Stale(version, num2, num3, T.AssaultMaxDashes)) { string text2 = SkillKeys.UtilityLabel + "Blinding Assault: "; int assaultMaxDashes = T.AssaultMaxDashes; string text3 = "/" + assaultMaxDashes + ")"; HudRow hudRow = assaultRow; string text4 = text2 + HudClock.Status(num2) + ((num3 >= 0) ? (" (dash " + num3 + text3) : ""); assaultMaxDashes = T.AssaultMaxDashes; hudRow.Set(text4, text2 + "88.8s (dash " + assaultMaxDashes + text3); } hud.Add(assaultRow); int num4 = (parry.Active ? (-2) : HudClock.Key(parryCd, time)); if (parryRow.Stale(version, num4)) { string text5 = SkillKeys.SecondaryLabel + "Parry: "; parryRow.Set(text5 + ((num4 == -2) ? "active" : HudClock.Status(num4)), text5 + "88.8s"); } hud.Add(parryRow); break; } case SurvivorId.MulT: { int num = (SurvivorState.TransportActive ? (-2) : HudClock.Key(transport, time)); if (transportRow.Stale(version, num)) { string text = SkillKeys.UtilityLabel + "Transport Mode: "; transportRow.Set(text + ((num == -2) ? "active" : HudClock.Status(num)), text + "88.8s"); } hud.Add(transportRow); if (T.BlastCanister.Enabled) { SkillHud.CooldownRow(canisterRow, SkillKeys.SecondaryLabel, "Blast Canister: ", HudClock.Key(canister, time)); hud.Add(canisterRow); } break; } } SkillHud.Draw(hud); } private static void DrawParryVignette() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 if (Event.current != null && (int)Event.current.type == 7) { SkillHud.ParryVignette(ParryLook.Shown(ParryLook.Vignette(Time.time, ParryPose.StartedAt, ParryPose.EndsAt, ParryPose.Active, ParryPose.Scheduled), ParryScreen.MenuOpen(), ParryScreen.Dead())); } } } [HarmonyPatch(typeof(HitableMob), "Hit", new Type[] { typeof(int), typeof(float), typeof(int), typeof(Vector3), typeof(int) })] internal static class BackstabPatch { internal static readonly CritRoll LastRoll = new CritRoll(); [HarmonyPriority(200)] [HarmonyBefore(new string[] { "evan.muck.crowbar" })] [HarmonyAfter(new string[] { "evan.muck.pennib" })] private static void Prefix(HitableMob __instance, ref int __0, ref int __2, int __4) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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) try { if (!SurvivorState.Active || SurvivorState.Session.Locked != SurvivorId.Bandit || !Backstab.Scales(__0, __4, __2, LastRoll.CritIn(Time.frameCount), SurvivorHits.Dealing) || (Object)(object)__instance == (Object)null || (Object)(object)PlayerMovement.Instance == (Object)null) { return; } Vector3 forward = ((Component)__instance).transform.forward; Vector3 val = ((Component)__instance).transform.position - ((Component)PlayerMovement.Instance).transform.position; if (Backstab.IsBehind(new Vec3(forward.x, forward.y, forward.z), new Vec3(val.x, val.y, val.z))) { int num = __0; __0 = Backstab.CritDamage(__0); if (__2 == 0) { __2 = 1; } SurvivorsPlugin.Verbose($"Backstab {num} -> {__0} on mob {((Hitable)__instance).GetId()}"); } } catch (Exception arg) { SurvivorsPlugin.LogOnce("BackstabPatch", $"Survivors backstab failed: {arg}"); } } } [HarmonyPatch(typeof(PowerupCalculations), "GetDamageMultiplier", new Type[] { typeof(bool), typeof(float) })] internal static class CritRollPatch { private static void Postfix(DamageResult __result) { try { BackstabPatch.LastRoll.Record(__result?.crit ?? false, Time.frameCount); } catch (Exception arg) { SurvivorsPlugin.LogOnce("CritRollPatch", $"Survivors crit roll hook failed: {arg}"); } } } internal sealed class BanditSkills : MonoBehaviour { private struct Strike { public int BaseDamage; public float Strength; public bool Ok; } private struct MobBody { public HitableMob Mob; public Collider Collider; } private const float DashExitSpeed = 6.5f; private readonly Cooldown dagger = new Cooldown(); private readonly Cooldown smokeCd = new Cooldown(); private readonly Cooldown special = new Cooldown(); private readonly SmokeCloak cloak = new SmokeCloak(); private readonly SpreadBloom bloom = new SpreadBloom(); private readonly HemorrhageLedger hemorrhage = new HemorrhageLedger(); private readonly PendingKill pendingKill = new PendingKill(); private readonly List<HemorrhageTick> ticks = new List<HemorrhageTick>(); private readonly Dictionary<int, int> tickTotals = new Dictionary<int, int>(); private readonly List<MobBody> bodies = new List<MobBody>(); private readonly HudRow gunRow = new HudRow(); private readonly HudRow daggerRow = new HudRow(); private readonly HudRow smokeRow = new HudRow(); private readonly HudRow specialRow = new HudRow(); private readonly List<HudRow> hud = new List<HudRow>(); private const float ResetFlash = 0.4f; private static readonly Color BackstabRed = new Color(1f, 0.1f, 0.1f); private BanditMagazine magazine; private int desperado; private bool busy; private Vector3 revolverPoint; private float resetFlashUntil; private bool flashAll; private static BanditSkills active; private static BanditTuning B => SurvivorState.Tuning.Bandit; private static float Shell => WeaponTuning.Interval(B.ReloadShell, AbilityController.AttackSpeed()); private static SurvivorsConfig Cfg => SurvivorsPlugin.Cfg; private static string SecondaryName { get { if (B.Secondary != BanditSecondaryStyle.Shiv) { return "Serrated Dagger"; } return "Serrated Shiv"; } } private void Awake() { magazine = new BanditMagazine(B.MagazineSize); active = this; hud.AddRange(new HudRow[4] { gunRow, daggerRow, smokeRow, specialRow }); } private void OnDestroy() { if ((Object)(object)active == (Object)(object)this) { active = null; } } public void StopAll() { ((MonoBehaviour)this).StopAllCoroutines(); busy = false; if (cloak.Cancel()) { SurvivorState.CloakActive = false; LobbySync.PublishCloak(cloaked: false); } hemorrhage.Clear(); pendingKill.Clear(); bloom.Reset(); dagger.Reset(); smokeCd.Reset(); special.Reset(); desperado = 0; resetFlashUntil = 0f; magazine = new BanditMagazine(B.MagazineSize); } private void Update() { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) if (!SurvivorState.Active || SurvivorState.Session.Locked != SurvivorId.Bandit) { return; } try { float time = Time.time; TickHemorrhage(); if (!Alive()) { DropCloak(); return; } bloom.Tick(time, B.BloomCool); if (!busy) { magazine.Tick(time, Shell, Keys.PrimaryHeld(SurvivorId.Bandit)); } if (cloak.Tick(time)) { EndCloak(blast: true); } if (!AbilityController.InputBlocked()) { if (Keys.Use(SkillKeys.Utility, "Smoke Bomb", smokeCd, time)) { CastSmoke(time); } if (Keys.Use(SkillKeys.Secondary, SecondaryName, dagger, time, busy)) { CastSecondary(time); } if (Keys.Use(SkillKeys.Special, BanditLoadout.SpecialName(B.Special), special, time)) { CastSpecial(time); } if (Keys.PrimaryHeld(SurvivorId.Bandit) && !busy && magazine.CanFire(time)) { CastPrimary(time); } } } catch (Exception arg) { SurvivorsPlugin.LogOnce("BanditSkills", $"Survivors Bandit update failed: {arg}"); } } private void CastSmoke(float now) { if (cloak.Active) { EndCloak(blast: true); } smokeCd.Start(now, B.SmokeCooldown); cloak.Start(now, B.SmokeDuration); SurvivorState.CloakActive = true; LobbySync.PublishCloak(cloaked: true); Hop(); SurvivorsPlugin.Verbose("Smoke Bomb"); SmokeBlast(end: false); } private void CastSecondary(float now) { Strike strike = TakeStrike(); if (strike.Ok) { EndCloak(blast: true); dagger.Start(now, B.DaggerCooldown); magazine.Pause(now, B.ReloadDelay, Shell); SurvivorsPlugin.Verbose(SecondaryName); if (B.Secondary == BanditSecondaryStyle.Shiv) { FireShiv(strike); } else { ((MonoBehaviour)this).StartCoroutine(Lunge(strike)); } } } private void CastSpecial(float now) { Strike strike = TakeStrike(); if (strike.Ok) { EndCloak(blast: true); special.Start(now, B.SpecialCooldown); magazine.Pause(now, B.ReloadDelay, Shell); SurvivorsPlugin.Verbose(BanditLoadout.SpecialName(B.Special)); FireRevolver(strike); } } private void CastPrimary(float now) { //IL_00a9: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (!Hitscan.TryAim(out var origin, out var forward)) { return; } Strike strike = TakeStrike(); if (strike.Ok) { EndCloak(blast: true); magazine.Fire(now, WeaponTuning.Interval(B.ShotInterval, AbilityController.AttackSpeed()), B.ReloadDelay, Shell, emptySkipsDelay: true, Time.deltaTime); if (B.Primary == BanditPrimaryStyle.Blast) { SurvivorsPlugin.Verbose("Blast"); FireBlast(origin, forward, strike); } else { SurvivorsPlugin.Verbose($"Burst {magazine.Stocks}/{magazine.Capacity}"); FireBurst(origin, forward, strike); } bloom.OnShot(); } } private void FireBurst(Vector3 origin, Vector3 forward, Strike strike) { //IL_0017: 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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) float bloomDegrees = B.BurstBloom * bloom.Heat; Vector3 val = Tracer.Muzzle(origin, forward); AbilityController.Recoil(); int num = 0; for (int i = 0; i < B.PelletCount; i++) { BanditMath.Pellet(i, B.PelletCount, B.BurstSpread, bloomDegrees, out var yaw, out var pitch); Vector3 val2 = Aim(forward, yaw, pitch); HitscanShot hitscanShot = Hitscan.Cast(origin, val2, B.ShotRange, B.ShotRadius); if (i == 0) { LocalFx.Cast(SkillFxEvent.Shot(ShotStyle.Burst, SkillFxPlayer.V(val), SkillFxPlayer.V(origin + val2 * hitscanShot.Stop))); } else { SkillFx.Segment(val, origin + val2 * hitscanShot.Stop, Cfg.TracerColor.Value, 0.03f, 0.1f); } if (hitscanShot.Hit) { float falloff = BanditMath.Falloff(hitscanShot.Distance, B.FalloffStart, B.FalloffEnd, B.FalloffFloor); bool flag = Behind(hitscanShot.Mob); float coefficient = BanditMath.Coefficient(B.PelletDamage, flag, 2f, 1f, 1f, falloff); if (Hit(hitscanShot.Mob, AbilityDamage.Hit(strike.BaseDamage, coefficient, strike.Strength), hitscanShot.Point, flag)) { num++; } } } SurvivorsPlugin.Verbose(SkillLog.Outcome("Burst", num)); } private void FireBlast(Vector3 origin, Vector3 forward, Strike strike) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) HitscanShot shot = Hitscan.Cast(origin, forward, B.ShotRange, B.ShotRadius); CastShot(ShotStyle.Blast, origin, forward, shot); AbilityController.Recoil(); bool flag = false; if (shot.Hit) { bool flag2 = Behind(shot.Mob); float coefficient = BanditMath.Coefficient(B.BlastDamage, flag2, 2f, 1f, 1f, 1f); flag = Hit(shot.Mob, AbilityDamage.Hit(strike.BaseDamage, coefficient, strike.Strength), shot.Point, flag2); } SurvivorsPlugin.Verbose(SkillLog.Outcome("Blast", flag ? 1 : 0)); } private static void CastShot(ShotStyle style, Vector3 origin, Vector3 forward, HitscanShot shot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) LocalFx.Cast(SkillFxEvent.Shot(style, SkillFxPlayer.V(Tracer.Muzzle(origin, forward)), SkillFxPlayer.V(origin + forward * shot.Stop))); } private void FireShiv(Strike strike) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_00a2: Unknown result type (might be due to invalid IL or missing references) if (!Hitscan.TryAim(out var origin, out var forward)) { SurvivorsPlugin.Verbose(SkillLog.NotCast("Serrated Shiv", "no camera to aim from")); return; } HitscanShot shot = Hitscan.Cast(origin, forward, B.ShivRange, B.ShotRadius); CastShot(ShotStyle.Shiv, origin, forward, shot); bool flag = false; if (shot.Hit) { bool flag2 = Behind(shot.Mob); float coefficient = BanditMath.Coefficient(B.ShivDamage, flag2, 2f, 1f, 1f, 1f); int damage = AbilityDamage.Hit(strike.BaseDamage, coefficient, strike.Strength); flag = Hit(shot.Mob, damage, shot.Point, flag2); if (flag && flag2) { ApplyHemorrhage(shot.Mob, strike); } } SurvivorsPlugin.Verbose(SkillLog.Outcome("Serrated Shiv", flag ? 1 : 0)); } private void FireRevolver(Strike strike) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) string skill = BanditLoadout.SpecialName(B.Special); if (!Hitscan.TryAim(out var origin, out var forward)) { SurvivorsPlugin.Verbose(SkillLog.NotCast(skill, "no camera to aim from")); return; } HitscanShot shot = Hitscan.Cast(origin, forward, B.SpecialRange, B.ShotRadius); CastShot(ShotStyle.Revolver, origin, forward, shot); AbilityController.Recoil(); if (!shot.Hit) { SurvivorsPlugin.Verbose(SkillLog.Outcome(skill, 0)); return; } revolverPoint = shot.Point; int hp = ((Hitable)shot.Mob).hp; int maxHp = ((Hitable)shot.Mob).maxHp; float slayer = BanditMath.Slayer(hp, maxHp, B.SlayerPerMissing, B.SlayerCap); float bonus = ((B.Special == BanditSpecialStyle.Desperado) ? BanditMath.Desperado(desperado, B.DesperadoPerStack) : 1f); bool behind = Behind(shot.Mob); float coefficient = BanditMath.Coefficient(B.SpecialDamage, behind, 2f, slayer, bonus, 1f); int damage = AbilityDamage.Hit(strike.BaseDamage, coefficient, strike.Strength); HitableMob mob = shot.Mob; bool flag = pendingKill.Shoot(((Hitable)mob).GetId(), Time.time, LocalClient.serverOwner, () => Hit(mob, damage, shot.Point, behind)); SurvivorsPlugin.Verbose(SkillLog.Outcome(skill, flag ? 1 : 0)); } internal static void OnLocalKill(int killType, int mobId) { if (!((Object)(object)active == (Object)null) && killType == -1 && SurvivorState.Active && SurvivorState.Session.Locked == SurvivorId.Bandit) { active.ApplyKill(mobId); } } private void ApplyKill(int mobId) { //IL_0094: 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) SpecialOutcome specialOutcome = BanditMath.OnKill(B.Special, pendingKill.TryConsume(mobId, Time.time)); if (specialOutcome.ResetCooldowns) { BanditMath.ApplyLightsOut(dagger, smokeCd, special, magazine); SurvivorsPlugin.Verbose("Lights Out reset cooldowns"); } if (specialOutcome.AddStack) { desperado = BanditMath.AddDesperadoStack(desperado); SurvivorsPlugin.Verbose($"Desperado x{desperado}"); } if (specialOutcome.ResetCooldowns || specialOutcome.AddStack) { SkillFx.Ring(revolverPoint, 0.3f, 1.5f, FxColors.Gold, 0.12f, 0.3f); resetFlashUntil = Time.time + 0.4f; flashAll = specialOutcome.ResetCooldowns; } } private IEnumerator Lunge(Strike strike) { busy = true; SurvivorState.DashActive = true; HitLedger claimed = new HitLedger(); Vector3 dir = Vector3.zero; float exit = 6.5f; bool num = BeginLunge(out dir, out exit); int hits = 0; if (num) { Vector3 start = LocalFx.Feet(); LungeStarted(dir); float end = Time.time + B.DaggerDuration; while (Time.time < end && LungeStep(dir, strike, claimed, ref hits)) { yield return (object)new WaitForFixedUpdate(); } ExitLunge(dir, exit); LocalFx.Cast(SkillFxEvent.Dash(DashStyle.Dagger, SkillFxPlayer.V(start), SkillFxPlayer.V(LocalFx.Feet()))); } SurvivorsPlugin.Verbose(SkillLog.Outcome("Serrated Dagger", hits)); SurvivorState.DashActive = false; busy = false; } private static bool BeginLunge(out Vector3 dir, out float exit) { //IL_0001: 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_001f: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) dir = Vector3.zero; exit = 6.5f; try { PlayerMovement instance = PlayerMovement.Instance; dir = instance.orientation.forward; dir.y = 0f; if (((Vector3)(ref dir)).sqrMagnitude < 0.0001f) { dir = ((Component)instance).transform.forward; } dir.y = 0f; ((Vector3)(ref dir)).Normalize(); Rigidbody rb = instance.GetRb(); if ((Object)(object)rb != (Object)null) { Vector3 val = new Vector3(rb.velocity.x, 0f, rb.velocity.z); float magnitude = ((Vector3)(ref val)).magnitude; exit = Mathf.Max(6.5f, magnitude); rb.velocity = new Vector3(rb.velocity.x, Mathf.Max(0f, rb.velocity.y), rb.velocity.z); } return true; } catch (Exception arg) { SurvivorsPlugin.LogOnce("dagger-begin", $"Survivors Serrated Dagger failed to start: {arg}"); return false; } } private static void LungeStarted(Vector3 dir) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) try { if (Hitscan.TryAim(out var origin, out var forward)) { SkillFx.Arc(origin, forward, PlayerMovement.Instance.playerCam.right, 1.6f, 120f, FxColors.Bandit); } SkillFx.SpeedLines(dir, FxColors.Bandit, B.DaggerDuration); } catch (Exception arg) { SurvivorsPlugin.LogOnce("dagger-fx", $"Survivors: drawing the Serrated Dagger failed: {arg}"); } } private bool LungeStep(Vector3 dir, Strike strike, HitLedger claimed, ref int hits) { //IL_002b: 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_003b: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) try { if (!Alive()) { return false; } Rigidbody rb = PlayerMovement.Instance.GetRb(); if ((Object)(object)rb == (Object)null) { return false; } rb.isKinematic = false; rb.velocity = dir * B.DaggerSpeed + Vector3.up * rb.velocity.y; hits += Slash(strike, claimed); return true; } catch (Exception arg) { SurvivorsPlugin.LogOnce("dagger-step", $"Survivors Serrated Dagger step failed: {arg}"); return false; } } private static void ExitLunge(Vector3 dir, float exit) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)PlayerMovement.Instance == (Object)null)) { Rigidbody rb = PlayerMovement.Instance.GetRb(); if (!((Object)(object)rb == (Object)null)) { rb.velocity = dir * exit + Vector3.up * rb.velocity.y; } } } catch (Exception arg) { SurvivorsPlugin.LogOnce("dagger-exit", $"Survivors Serrated Dagger exit failed: {arg}"); } } private int Slash(Strike strike, HitLedger claimed) { //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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)PlayerMovement.Instance).transform.position; Snapshot(bodies); float daggerRadius = B.DaggerRadius; int num = 0; for (int i = 0; i < bodies.Count; i++) { MobBody mobBody = bodies[i]; if ((Object)(object)mobBody.Mob == (Object)null || ((Hitable)mobBody.Mob).hp <= 0) { continue; } Vector3 val; if (!((Object)(object)mobBody.Collider != (Object)null)) { val = ((Component)mobBody.Mob).transform.position; } else { Bounds bounds = mobBody.Collider.bounds; val = ((Bounds)(ref bounds)).ClosestPoint(position); } Vector3 val2 = val; Vector3 val3 = val2 - position; if (((Vector3)(ref val3)).sqrMagnitude > daggerRadius * daggerRadius || !claimed.TryClaim(((Hitable)mobBody.Mob).GetId())) { continue; } bool flag = Behind(mobBody.Mob); float coefficient = BanditMath.Coefficient(B.DaggerDamage, flag, 2f, 1f, 1f, 1f); int damage = AbilityDamage.Hit(strike.BaseDamage, coefficient, strike.Strength); if (Hit(mobBody.Mob, damage, val2, flag)) { num++; if (flag) { ApplyHemorrhage(mobBody.Mob, strike); } } } return num; } private void SmokeBlast(bool end) { //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_001f: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: 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_015a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)PlayerMovement.Instance == (Object)null) { return; } Vector3 position = ((Component)PlayerMovement.Instance).transform.position; LocalFx.Cast(SkillFxEvent.Smoke(end, SkillFxPlayer.V(position), B.SmokeRadius)); Strike strike = TakeStrike(); if (!strike.Ok) { return; } Snapshot(bodies); float smokeRadius = B.SmokeRadius; HitLedger hitLedger = new HitLedger(); int num = 0; for (int i = 0; i < bodies.Count; i++) { MobBody mobBody = bodies[i]; if ((Object)(object)mobBody.Mob == (Object)null || ((Hitable)mobBody.Mob).hp <= 0 || !hitLedger.TryClaim(((Hitable)mobBody.Mob).GetId())) { continue; } Vector3 val; if (!((Object)(object)mobBody.Collider != (Object)null)) { val = ((Component)mobBody.Mob).transform.position; } else { Bounds bounds = mobBody.Collider.bounds; val = ((Bounds)(ref bounds)).ClosestPoint(position); } Vector3 val2 = val; Vector3 val3 = val2 - position; if (!(((Vector3)(ref val3)).sqrMagnitude > smokeRadius * smokeRadius)) { bool flag = Behind(mobBody.Mob); float coefficient = BanditMath.Coefficient(B.SmokeDamage, flag, 2f, 1f, 1f, 1f); if (Hit(mobBody.Mob, AbilityDamage.Hit(strike.BaseDamage, coefficient, strike.Strength), val2, flag)) { num++; } } } SurvivorsPlugin.Verbose(SkillLog.Outcome(end ? "Smoke Bomb end blast" : "Smoke Bomb blast", num)); } private static void Hop() { //IL_003f: 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_0064: 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) try { if (!(B.SmokeHop <= 0f) && !((Object)(object)PlayerMovement.Instance == (Object)null)) { Rigidbody rb = PlayerMovement.Instance.GetRb(); if (!((Object)(object)rb == (Object)null)) { rb.isKinematic = false; rb.velocity = new Vector3(rb.velocity.x, Mathf.Max(rb.velocity.y, B.SmokeHop), rb.velocity.z); } } } catch (Exception arg) { SurvivorsPlugin.LogOnce("smoke-hop", $"Survivors Smoke Bomb hop failed: {arg}"); } } private void EndCloak(bool blast) { if (cloak.Cancel() || SurvivorState.CloakActive) { SurvivorState.CloakActive = false; LobbySync.PublishCloak(cloaked: false); if (blast) { SmokeBlast(end: true); } } } private void DropCloak() { if (cloak.Active || SurvivorState.CloakActive) { cloak.Cancel(); SurvivorState.CloakActive = false; LobbySync.PublishCloak(cloaked: false); SkillFxNet.Send(SkillFxEvent.Uncloak()); } } private void TickHemorrhage() { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) ticks.Clear(); hemorrhage.Collect(Time.time, ticks); tickTotals.Clear(); for (int i = 0; i < ticks.Count; i++) { int mobId = ticks[i].MobId; tickTotals.TryGetValue(mobId, out var value); tickTotals[mobId] = value + ticks[i].Damage; } foreach (KeyValuePair<int, int> tickTotal in tickTotals) { HitableMob val = MobLookup.Find(tickTotal.Key); if (!((Object)(object)val == (Object)null) && ((Hitable)val).hp > 0) { Hit(val, tickTotal.Value, ((Component)val).transform.position, crit: false, HitSource.Tick); } } } private void ApplyHemorrhage(HitableMob mob, Strike strike) { int num = BanditMath.HemorrhageTicks(B.HemorrhageDuration, B.HemorrhageTick); float coefficient = BanditMath.HemorrhagePerTick(B.HemorrhageDamage, num); int perTick = AbilityDamage.Hit(strike.BaseDamage, coefficient, strike.Strength); if (hemorrhage.Apply(((Hitable)mob).GetId(), perTick, Time.time, B.HemorrhageDuration, B.HemorrhageTick)) { SurvivorsPlugin.Verbose($"Hemorrhage x{hemorrhage.Stacks(((Hitable)mob).GetId())} on mob {((Hitable)mob).GetId()}"); LocalFx.Cast(SkillFxEvent.Bleed(((Hitable)mob).GetId(), B.HemorrhageDuration)); } } private bool Hit(HitableMob mob, int damage, Vector3 point, bool crit, HitSource source = HitSource.Skill) { //IL_001f: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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) if ((Object)(object)mob == (Object)null || damage <= 0) { return false; } int hitEffect = (crit ? 1 : 0); int id = ((Hitable)mob).GetId(); SurvivorHits.Deal(mob, damage, hitEffect, point, source); SurvivorsPlugin.Verbose($"Bandit hit mob {id} for {damage}"); if (source == HitSource.Skill) { SkillFx.Spark(point, crit ? BackstabRed : FxColors.Bandit); if (crit) { SkillFx.Spark(point, Color.white); } } return true; } private static bool Behind(HitableMob mob) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mob == (Object)null || (Object)(object)PlayerMovement.Instance == (Object)null) { return false; } Vector3 forward = ((Component)mob).transform.forward; Vector3 val = ((Component)mob).transform.position - ((Component)PlayerMovement.Instance).transform.position; return Backstab.IsBehind(new Vec3(forward.x, forward.y, forward.z), new Vec3(val.x, val.y, val.z)); } private static Vector3 Aim(Vector3 forward, float yawDeg, float pitchDeg) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_000b: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.Cross(Vector3.up, forward); if (((Vector3)(ref val)).sqrMagnitude < 1E-06f) { val = Vector3.right; } ((Vector3)(ref val)).Normalize(); Vector3 val2 = Vector3.Cross(forward, val); Vector3 normalized = ((Vector3)(ref val2)).normalized; val2 = forward + val * Mathf.Tan(yawDeg * (MathF.PI / 180f)) + normalized * Mathf.Tan(pitchDeg * (MathF.PI / 180f)); return ((Vector3)(ref val2)).normalized; } private static Strike TakeStrike() { try { return new Strike { BaseDamage = KitDamageReader.Read(), Strength = PowerupInventory.Instance.GetStrengthMultiplier((int[])null), Ok = true }; } catch (Exception arg) { SurvivorsPlugin.LogOnce("bandit-strike", $"Survivors Bandit failed to read damage: {arg}"); return default(Strike); } } private static void Snapshot(List<MobBody> into) { into.Clear(); if ((Object)(object)MobManager.Instance == (Object)null || MobManager.Instance.mobs == null) { return; } foreach (Mob value in MobManager.Instance.mobs.Values) { if (!((Object)(object)value == (Object)null)) { HitableMob component = ((Component)value).GetComponent<HitableMob>(); if (!((Object)(object)component == (Object)null) && ((Hitable)component).hp > 0) { into.Add(new MobBody { Mob = component, Collider = ((Component)component).GetComponentInChildren<Collider>() }); } } } } private static bool Alive() { if ((Object)(object)PlayerStatus.Instance != (Object)null && (Object)(object)PlayerMovement.Instance != (Object)null) { return !PlayerStatus.Instance.IsPlayerDead(); } return false; } private void OnGUI() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 if (SurvivorState.Session.Locked != SurvivorId.Bandit || !SurvivorState.Active || !Alive()) { return; } if (cloak.Active && (int)Event.current.type == 7) { SkillHud.CloakVignette(); } if (SkillHud.Visible) { float time = Time.time; int version = SkillKeys.Version; bool flag = time < resetFlashUntil; gunRow.Highlight = flag && flashAll; daggerRow.Highlight = flag && flashAll; smokeRow.Highlight = flag && flashAll; specialRow.Highlight = flag; bool flag2 = magazine.Stocks <= 0 || magazine.Reloading; int num = (flag2 ? HudClock.Tenths(magazine.ReloadRemaining(time, Shell)) : (magazine.CanFire(time) ? (-1) : HudClock.Tenths(magazine.ShotRemaining(time)))); bool flag3 = SkillHud.HoldingPrimary(SurvivorId.Bandit); int shownStocks = magazine.ShownStocks; if (gunRow.Stale(version, shownStocks, flag2 ? (-2 - num) : num, flag3 ? magazine.Capacity : (-magazine.Capacity))) { string text = SkillKeys.PrimaryLabel + BanditLoadout.PrimaryName(B.Primary) + " " + shownStocks + "/" + magazine.Capacity + ": "; string text2 = SkillHud.HoldHint(SurvivorId.Bandit); gunRow.Set(text + (flag2 ? ("reload " + HudClock.Seconds(num)) : HudClock.Status(num)) + (flag3 ? "" : text2), text + "reload 88.8s" + text2); } int num2 = HudClock.Key(dagger, time); if (daggerRow.Stale(version, num2)) { string text3 = SkillKeys.SecondaryLabel + BanditLoadout.SecondaryName(B.Secondary) + ": "; daggerRow.Set(text3 + HudClock.Status(num2), text3 + "88.8s"); } int num3 = HudClock.Key(smokeCd, time); int num4 = (cloak.Active ? HudClock.Tenths(cloak.Remaining(time)) : (-1)); if (smokeRow.Stale(version, num3, num4)) { string text4 = SkillKeys.UtilityLabel + "Smoke Bomb: "; smokeRow.Set(text4 + HudClock.Status(num3) + (cloak.Active ? (" cloak " + HudClock.Seconds(num4)) : ""), text4 + "88.8s cloak 88.8s"); } int num5 = HudClock.Key(special, time); int num6 = ((B.Special == BanditSpecialStyle.Desperado) ? desperado : 0); if (specialRow.Stale(version, num5, num6)) { string text5 = SkillKeys.SpecialLabel + BanditLoadout.SpecialName(B.Special) + ": "; string text6 = ((num6 > 0) ? (" x" + num6.ToString(CultureInfo.InvariantCulture)) : ""); specialRow.Set(text5 + HudClock.Status(num5) + text6, text5 + "88.8s" + text6); } SkillHud.Draw(hud); } } } internal sealed class BodyDirector : MonoBehaviour { private const float Interval = 0.5f; private static readonly FieldInfo SteamToLobbyId = AccessTools.Field(typeof(LobbyVisuals), "steamToLobbyId"); private float next; public static SurvivorId OwnPick { get { SurvivorsConfig cfg = SurvivorsPlugin.Cfg; if (!cfg.Enabled.Value) { return SurvivorId.None; } return cfg.SelectedSurvivor.Value; } } public static SurvivorId PickFor(int muckId) { int myId = (((Object)(object)LocalClient.instance != (Object)null) ? LocalClient.instance.myId : (-1)); return BodyPicks.ForPlayer(muckId, myId, OwnPick, LobbySync.Members); } public static void ApplyPlayer(GameObject rig, int muckId) { SurvivorBody.Apply(rig, PickFor(muckId)); int myId = (((Object)(object)LocalClient.instance != (Object)null) ? LocalClient.instance.myId : (-1)); SurvivorBody.SetCloaked(rig, BodyPicks.Cloaked(muckId, myId, SurvivorState.CloakActive, LobbySync.Members, RemoteFx.Cloaks, Time.unscaledTime)); } private void Update() { if (!(Time.unscaledTime < next)) { next = Time.unscaledTime + 0.5f; Reconcile(); } } public static void Reconcile() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) try { Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name == "GameAfterLobby") { ReconcilePlayers(); } else { ReconcileLobbyFigures(); } } catch (Exception arg) { SurvivorsPlugin.LogOnce("BodyDirector", $"Survivors: updating survivor bodies failed: {arg}"); } } private static void ReconcilePlayers() { if (GameManager.players == null) { return; } foreach (PlayerManager value in GameManager.players.Values) { if (!((Object)(object)value == (Object)null) && !((Object)(object)value.onlinePlayer == (Object)null)) { ApplyPlayer(((Component)value.onlinePlayer).gameObject, value.id); } } } private static void ReconcileLobbyFigures() { LobbyVisuals instance = LobbyVisuals.Instance; if ((Object)(object)instance == (Object)null || instance.lobbyPlayers == null) { return; } Dictionary<int, ulong> dictionary = new Dictionary<int, ulong>(); if (SteamToLobbyId?.GetValue(instance) is Dictionary<ulong, int> dictionary2) { foreach (KeyValuePair<ulong, int> item in dictionary2) { dictionary[item.Value] = item.Key; } } for (int i = 0; i < instance.lobbyPlayers.Length; i++) { ulong value; SurvivorId pick = (dictionary.TryGetValue(i, out value) ? BodyPicks.ForSteamId(value, LobbySync.Rows) : SurvivorId.None); SurvivorBody.Apply(instance.lobbyPlayers[i], pick); } } } [HarmonyPatch(typeof(GameManager), "SpawnPlayer")] internal static class SpawnPlayerPatch { private static void Postfix(int __0) { try { if (GameManager.players.TryGetValue(__0, out var value) && (Object)(object)value != (Object)null && (Object)(object)value.onlinePlayer != (Object)null) { BodyDirector.ApplyPlayer(((Component)value.onlinePlayer).gameObject, __0); } } catch (Exception arg) { SurvivorsPlugin.LogOnce("SpawnPlayerPatch", $"Survivors: applying a survivor body on spawn failed: {arg}"); } } } [HarmonyPatch(typeof(PlayerRagdoll), "SetRagdoll")] internal static class RagdollPatch { private static void Prefix(PlayerRagdoll __instance, out Rig<Transform> __state) { __state = default(Rig<Transform>); try { if ((Object)(object)__instance.ragdoll != (Object)null) { __state = SurvivorBody.FindRig(((Component)__instance.ragdoll).transform); } } catch (Exception arg) { SurvivorsPlugin.LogOnce("RagdollPatch.Prefix", $"Survivors: finding the ragdoll rig failed: {arg}"); } } private static void Postfix(PlayerRagdoll __instance, int __0, Rig<Transform> __state) { try { SurvivorBody.Apply(__state, BodyDirector.PickFor(__0), ((Object)__instance).name); } catch (Exception arg) { SurvivorsPlugin.LogOnce("RagdollPatch", $"Survivors: applying a survivor body to a ragdoll failed: {arg}"); } } } internal static class EngineerFx { public static readonly Color Glow = new Color(0.35f, 0.95f, 1f); private static readonly Color Blast = new Color(1f, 0.75f, 0.3f); private const float ShieldAlpha = 0.35f; public static readonly Vector3 Muzzle = new Vector3(0f, 1.08f, 0.9f); public static GameObject Play(EngStyle style, Vector3 at, float size, float seconds) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_00a6: 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) //IL_0111: Unknown result type (might be due to invalid IL or missing references) switch (style) { case EngStyle.Blast: SkillFx.Flash(at, Blast, size * 0.5f, 0.12f); SkillFx.Ring(at, 0.3f, size, Blast, 0.2f, 0.25f); SkillFx.Puffs(at, 0.2f, size * 0.6f, 4, FxColors.Smoke, 0.8f, 0.6f); return null; case EngStyle.Mine: return Prop("EngineerMine", FxAssets.Mine, at, 0f, 1f, Color.white); case EngStyle.Turret: return Prop("EngineerTurret", FxAssets.Turret, at, size, 1f, Color.white); case EngStyle.Shield: { GameObject val = Prop("EngineerShield", FxAssets.Shield, at, 0f, size, new Color(1f, 1f, 1f, 0.35f)); if ((Object)(object)val == (Object)null) { return null; } val.AddComponent<BubbleBlocker>().Begin(size); Object.Destroy((Object)(object)val, (seconds > 0f) ? seconds : 0.1f); SkillFx.Ring(at, size, size, Glow, 0.15f, (seconds > 0f) ? seconds : 0.1f); return val; } default: return null; } } public static GameObject GrenadeBody(Vector3 at, float life) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0011: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("SurvivorsEngineerGrenade"); val.transform.position = at; Mesh val2 = FxAssets.Grenade ?? FxAssets.Icosahedron; FxAssets.AddMesh(val, val2, ((Object)(object)val2 == (Object)(object)FxAssets.Grenade) ? Color.white : Glow); if ((Object)(object)val2 != (Object)(object)FxAssets.Grenade) { val.transform.localScale = Vector3.one * 0.3f; } Object.Destroy((Object)(object)val, life); return val; } private static GameObject Prop(string name, Mesh mesh, Vector3 at, float yaw, float scale, Color tint) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0017: 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_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_005a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Survivors" + name); val.transform.position = at; val.transform.rotation = Quaternion.Euler(0f, yaw, 0f); val.transform.localScale = Vector3.one * scale; if ((Object)(object)mesh != (Object)null) { FxAssets.AddMesh(val, mesh, tint); } return val; } } internal sealed class EngineerSkills : MonoBehaviour { private readonly GrenadeCharge charge = new GrenadeCharge(); private readonly Cooldown mineCd = new Cooldown(); private readonly Cooldown shieldCd = new Cooldown(); private readonly Cooldown turretCd = new Cooldown(); private readonly MineField mines = new MineField(); private readonly TurretRoster turrets = new TurretRoster(); private readonly Dictionary<int, GameObject> mineObjects = new Dictionary<int, GameObject>(); private readonly Dictionary<int, EngineerTurret> turretObjects = new Dictionary<int, EngineerTurret>(); private readonly List<Vector3> mobPositions = new List<Vector3>(); private readonly List<HitableMob> mobs = new List<HitableMob>(); private readonly List<int> blown = new List<int>(); private readonly HashSet<HitableMob> struck = new HashSet<HitableMob>(); private readonly HudRow grenadeRow = new HudRow(); private readonly HudRow mineRow = new HudRow(); private readonly HudRow shieldRow = new HudRow(); private readonly HudRow turretRow = new HudRow(); private readonly List<HudRow> hud = new List<HudRow>(); private int volleyLeft; private float nextVolleyShot; private static EngineerTuning E => SurvivorState.Tuning.Engineer; private void Awake() { hud.AddRange(new HudRow[4] { grenadeRow, mineRow, shieldRow, turretRow }); } public void StopAll() { charge.Cancel(); volleyLeft = 0; mineCd.Reset(); shieldCd.Reset(); turretCd.Reset(); foreach (int item in new List<int>(mineObjects.Keys)) { DropMine(item); } mines.Clear(); foreach (int item2 in new List<int>(turretObjects.Keys)) { DropTurret(item2); } turrets.Clear(); } private void Update() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) if (!SurvivorState.Active || SurvivorState.Session.Locked != SurvivorId.Engineer) { return; } try { float time = Time.time; SyncWorld(); if (!Alive()) { charge.Cancel(); volleyLeft = 0; return; } TickMines(time); TickVolley(time); if (!AbilityController.InputBlocked()) { if (Keys.Use(SkillKeys.Secondary, "Pressure Mines", mineCd, time)) { LayMine(time); } if (Keys.Use(SkillKeys.Utility, "Bubble Shield", shieldCd, time)) { CastShield(time); } if (Keys.Use(SkillKeys.Special, "TR12 Gauss Auto-Turret", turretCd, time)) { PlaceTurret(time); } bool flag = Keys.PrimaryHeld(SurvivorId.Engineer); if (flag && volleyLeft == 0) { charge.Press(time); } else if (!flag && charge.Charging) { StartVolley(time, charge.Release(time, E.GrenadeChargePer, E.GrenadeMax)); } } } catch (Exception arg) { SurvivorsPlugin.LogOnce("EngineerSkills", $"Survivors Engineer update failed: {arg}"); } } private void SyncWorld() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); string worldKey = ((Scene)(ref activeScene)).handle + "/" + GameManager.GetSeed(); List<int> list = turrets.Sync(worldKey); if (list.Count == 0) { return; } foreach (int item in list) { DropTurret(item); } foreach (int item2 in new List<int>(mineObjects.Keys)) { DropMine(item2); } mines.Clear(); } private void StartVolley(float now, int count) { if (count > 0) { SurvivorsPlugin.Verbose(EngineerLog.Volley(count)); volleyLeft = count; nextVolleyShot = now; } } private void TickVolley(float now) { while (volleyLeft > 0 && now >= nextVolleyShot) { volleyLeft--; nextVolleyShot += E.GrenadeVolleyGap; FireGrenade(); } } private void FireGrenade() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_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_005b: Unknown result type (might be due to invalid IL or missing references) if (Hitscan.TryAim(out var origin, out var forward)) { Vector3 at = Tracer.HeldMuzzle(SurvivorId.Engineer, origin, forward, Tracer.Muzzle(origin, forward)); Vector3 val = Random.insideUnitSphere * 0.04f; Vector3 val2 = forward + Vector3.up * 0.12f + val; Vector3 normalized = ((Vector3)(ref val2)).normalized; EngineerGrenade.Launch(at, normalized * E.GrenadeSpeed, E.GrenadeFuse, Blast); } } private int Blast(Vector3 center, float radius, float coefficient, string skill) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) int num = 0; int num2 = Damage(coefficient); if (num2 > 0)