using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Pigeon.Math; using Pigeon.Movement; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("AntiMaterialRifle")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("AntiMaterialRifle")] [assembly: AssemblyTitle("AntiMaterialRifle")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public sealed class BallisticSniperBehaviour : MonoBehaviour { [Serializable] public struct Data { public bool singleRoundReload; public float shellDamageMult; public float fullHpDamageMult; public int bonusBounces; public float postBounceHoming; public bool overpressure; public float overpressureChargeDuration; public float overpressureDamageMult; public float overpressureMoveMult; public int overpressureMagPenalty; public int extraBulletsPerShot; public float twinLinkFenceDamage; public float twinLinkFenceRadius; public float exhaustionCooldown; public float exhaustionSlowDuration; public float exhaustionSlowStrength; public float longwatchAimSeconds; public float longwatchRangeBonus; public float longwatchGravityMult; public float longwatchSpeedMult; public float scouterInterval; public float scouterRadius; public int pierceTargets; public float pierceFalloff; public float spotterRadius; public float spotterDuration; public float deadboltDuration; public bool deathMark; public float deathMarkFuse; public float deathMarkRadius; public float deathMarkDamageScale; public float deathMarkHeadshotFuseMult; public float deathMarkStackScale; public bool autoTrigger; public float autoTriggerFireInterval; public float autoTriggerDamageMult; public int autoTriggerMagBonus; public float autoTriggerAdsSpread; public bool highExplosive; public float c4Damage; public float c4Radius; public float c4ThrowForce; public float c4ArmTime; public bool clipped; public float clippedReloadMult; public bool anchor; public float anchorSpeedThreshold; public bool oneInTheChamber; public float disruptDuration; public float heavyGrainDamageMult; public float reserveAmmoMult; public float rotAmount; public float rotSplashRadius; public float waterAmount; public float repositionMoveBonus; public float repositionAdsMoveMult; public float echoDelay; public float echoDamageScale; public float echoShockAmount; public float transferRelayScale; public float syncWindow; public float syncDamageMult; public bool overkill; } public struct DeathMarkEntry { public ITarget target; public float detonateAt; public float stacks; public Vector3 lastPos; public bool fromHeadshot; } public struct PendingEcho { public float fireAt; public Vector3 position; public Quaternion rotation; public float damage; public float speed; public float gravity; } [SerializeField] private Data data = CreateDefaultData(); private Data prefabSnapshot = CreateDefaultData(); private string description = "Anti-Material Rifle"; public readonly List DeathMarks = new List(8); public readonly List PendingEchoes = new List(4); public readonly List TwinShotHits = new List(4); private Gun boundGun; private bool hooksBound; private bool moveHookBound; private GameObject c4Visual; private readonly List activeHighlights = new List(16); private float highlightClearAt = -999f; private BulletData lastFiredBullet; private bool hasLastFiredBullet; private bool hasPendingOverkill; private float pendingOverkill; private ITarget pendingOverkillParent; private Vector3 pendingOverkillPos; private Gun pendingOverkillGun; private EffectType pendingOverkillEffect; private float pendingOverkillEffectAmt; public bool IsTubeReloading { get; set; } public float AimHoldTime { get; private set; } public float LastKillTime { get; set; } = -999f; public float ExhaustionReadyAt { get; set; } public bool ExhaustionShotArmed { get; set; } public float LastScouterPulse { get; set; } = -999f; public bool ChamberBonusReady { get; set; } public bool LastReloadWasFullTopOff { get; set; } public bool BlockAutoReloadForChamber { get; set; } public bool C4Deployed { get; set; } public Vector3 C4Position { get; set; } public float C4DeployedAt { get; set; } public float ReloadHoldTime { get; set; } public bool ReloadHeld { get; set; } public ref Data WeaponData => ref data; public string Description => description; public bool SingleRoundReload { get { if (data.singleRoundReload) { return !data.clipped; } return false; } } public Data GetPrefabSnapshot() { return prefabSnapshot; } public static Data CreateDefaultData() { return new Data { singleRoundReload = true, shellDamageMult = 1f, fullHpDamageMult = 1f, bonusBounces = 0, postBounceHoming = 0f, overpressure = false, overpressureChargeDuration = 0f, overpressureDamageMult = 1f, overpressureMoveMult = 1f, overpressureMagPenalty = 0, extraBulletsPerShot = 0, twinLinkFenceDamage = 0f, twinLinkFenceRadius = 0f, exhaustionCooldown = 0f, exhaustionSlowDuration = 0f, exhaustionSlowStrength = 0f, longwatchAimSeconds = 0f, longwatchRangeBonus = 0f, longwatchGravityMult = 1f, longwatchSpeedMult = 1f, scouterInterval = 0f, scouterRadius = 0f, pierceTargets = 0, pierceFalloff = 0f, spotterRadius = 0f, spotterDuration = 0f, deadboltDuration = 0f, deathMark = false, deathMarkFuse = 2f, deathMarkRadius = 4f, deathMarkDamageScale = 1.2f, deathMarkHeadshotFuseMult = 0.6f, deathMarkStackScale = 0.35f, autoTrigger = false, autoTriggerFireInterval = 0.35f, autoTriggerDamageMult = 0.5f, autoTriggerMagBonus = 5, autoTriggerAdsSpread = 0.8f, highExplosive = false, c4Damage = 220f, c4Radius = 8f, c4ThrowForce = 18f, c4ArmTime = 0.45f, clipped = false, clippedReloadMult = 1f, anchor = false, anchorSpeedThreshold = 0.15f, oneInTheChamber = false, disruptDuration = 0f, heavyGrainDamageMult = 1f, reserveAmmoMult = 1f, rotAmount = 0f, rotSplashRadius = 0f, waterAmount = 0f, repositionMoveBonus = 0f, repositionAdsMoveMult = 1f, echoDelay = 0f, echoDamageScale = 0f, echoShockAmount = 0f, transferRelayScale = 0f, syncWindow = 0f, syncDamageMult = 1f, overkill = false }; } public void InitializeAsPrefab(string desc) { description = desc ?? "Anti-Material Rifle"; data = CreateDefaultData(); prefabSnapshot = data; ResetRuntime(); } public void RestoreFromPrefab() { data = prefabSnapshot; } public void CapturePrefabSnapshot() { prefabSnapshot = data; } public void CopyFrom(BallisticSniperBehaviour template) { if (!((Object)(object)template == (Object)null)) { description = template.description; prefabSnapshot = template.prefabSnapshot; data = prefabSnapshot; ResetRuntime(); } } public void ResetRuntime() { IsTubeReloading = false; AimHoldTime = 0f; LastKillTime = -999f; ExhaustionReadyAt = 0f; ExhaustionShotArmed = false; LastScouterPulse = -999f; ChamberBonusReady = false; LastReloadWasFullTopOff = false; BlockAutoReloadForChamber = false; C4Deployed = false; ReloadHoldTime = 0f; ReloadHeld = false; DeathMarks.Clear(); PendingEchoes.Clear(); TwinShotHits.Clear(); hasLastFiredBullet = false; hasPendingOverkill = false; pendingOverkill = 0f; pendingOverkillParent = null; pendingOverkillGun = null; ClearHighlights(); DestroyC4Visual(); } public void InterruptTubeReload(Gun gun) { IsTubeReloading = false; if ((Object)(object)gun == (Object)null) { return; } try { if (gun.Reloading) { gun.CancelReload(); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] CancelReload: " + ex.Message)); } } } public void OnUpgradesApplied(Gun gun) { boundGun = gun; BindHooks(gun, bind: true); ApplyGunDataMutations(gun); WeaponRegistration.EnsureProjectileBullet(gun); } public void OnUpgradesCleared(Gun gun) { BindHooks(gun, bind: false); data = prefabSnapshot; ResetRuntime(); } private void BindHooks(Gun gun, bool bind) { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_00a4: 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_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)gun == (Object)null || (bind && hooksBound) || (!bind && !hooksBound)) { return; } try { if (bind) { gun.OnDamageTarget = (DamageCallback)Delegate.Combine((Delegate?)(object)gun.OnDamageTarget, (Delegate?)new DamageCallback(OnDamageTarget)); gun.OnBeforeDamage = (MutableDamageCallback)Delegate.Combine((Delegate?)(object)gun.OnBeforeDamage, (Delegate?)new MutableDamageCallback(OnBeforeDamage)); gun.OnKillTarget = (KillCallback)Delegate.Combine((Delegate?)(object)gun.OnKillTarget, (Delegate?)new KillCallback(OnKillTarget)); if ((Object)(object)gun.Player != (Object)null) { Player player = gun.Player; player.OnSetMovementSpeed += (RefAction)HandleSetMoveSpeed; moveHookBound = true; } hooksBound = true; } else { gun.OnDamageTarget = (DamageCallback)Delegate.Remove((Delegate?)(object)gun.OnDamageTarget, (Delegate?)new DamageCallback(OnDamageTarget)); gun.OnBeforeDamage = (MutableDamageCallback)Delegate.Remove((Delegate?)(object)gun.OnBeforeDamage, (Delegate?)new MutableDamageCallback(OnBeforeDamage)); gun.OnKillTarget = (KillCallback)Delegate.Remove((Delegate?)(object)gun.OnKillTarget, (Delegate?)new KillCallback(OnKillTarget)); if ((Object)(object)gun.Player != (Object)null && moveHookBound) { Player player2 = gun.Player; player2.OnSetMovementSpeed -= (RefAction)HandleSetMoveSpeed; moveHookBound = false; } hooksBound = false; } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)$"[BallisticSniper] BindHooks({bind}): {ex.Message}"); } } } private void HandleSetMoveSpeed(ref float speed) { if (data.repositionMoveBonus > 0f) { speed *= 1f + data.repositionMoveBonus; } bool flag = false; try { flag = (Object)(object)boundGun != (Object)null && boundGun.IsAiming; } catch { } if (flag && data.repositionAdsMoveMult < 0.99f) { speed *= data.repositionAdsMoveMult; } if (!data.overpressure || !((Object)(object)boundGun != (Object)null)) { return; } try { if (boundGun.GunData.chargeData.duration > 0.01f && boundGun.GunData.chargeData.time > 0.01f) { speed *= data.overpressureMoveMult; } } catch { } } public void ApplyGunDataMutations(Gun gun) { //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)gun == (Object)null)) { ref GunData gunData = ref gun.GunData; if (data.heavyGrainDamageMult > 1f) { gunData.damage *= data.heavyGrainDamageMult; } if (data.reserveAmmoMult > 1f) { gunData.ammoCapacity = Mathf.Max(1, Mathf.RoundToInt((float)gunData.ammoCapacity * data.reserveAmmoMult)); } if (data.bonusBounces > 0) { gunData.maxBounces = Mathf.Max(gunData.maxBounces, data.bonusBounces); } if (data.extraBulletsPerShot > 0) { gunData.bulletsPerShot = Mathf.Max(1, gunData.bulletsPerShot + data.extraBulletsPerShot); } if (data.clipped) { gunData.refillAmmoOnReload = true; gunData.reloadDuration = Mathf.Max(0.25f, gunData.reloadDuration * data.clippedReloadMult); data.singleRoundReload = false; } if (data.autoTrigger) { gunData.automatic = 1; gunData.fireInterval = data.autoTriggerFireInterval; gunData.damage *= data.autoTriggerDamageMult; gunData.magazineSize += data.autoTriggerMagBonus; } if (data.overpressure) { gunData.chargeData.duration = data.overpressureChargeDuration; gunData.chargeData.fireWhenFullyCharged = true; gunData.chargeData.fireOnRelease = false; gunData.chargeData.canFireWhileCharging = false; gunData.chargeData.coolDownSpeed = 2.5f; gunData.damage *= data.overpressureDamageMult; gunData.magazineSize = Mathf.Max(1, gunData.magazineSize - data.overpressureMagPenalty); } if (data.rotAmount > 0f) { gunData.damageEffect = (EffectType)7; gunData.damageEffectAmount = Mathf.Max(gunData.damageEffectAmount, data.rotAmount); } else if (data.waterAmount > 0f) { gunData.damageEffect = (EffectType)9; gunData.damageEffectAmount = Mathf.Max(gunData.damageEffectAmount, data.waterAmount); } } } public void Tick(float dt, Gun gun) { if (!((Object)(object)gun == (Object)null) && ((NetworkBehaviour)gun).IsOwner) { if (gun.IsAiming) { AimHoldTime += dt; } else { AimHoldTime = 0f; } if (data.exhaustionCooldown > 0f && Time.time >= ExhaustionReadyAt) { ExhaustionShotArmed = true; } if (data.oneInTheChamber && ChamberBonusReady && gun.RemainingAmmoCount <= 0) { OnMagazineEmptied(gun); } TickDeathMarks(gun); TickEchoes(gun); TickScouter(gun); } } private void TickDeathMarks(Gun gun) { //IL_011e: 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_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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) if (!data.deathMark || DeathMarks.Count == 0) { return; } for (int num = DeathMarks.Count - 1; num >= 0; num--) { DeathMarkEntry value = DeathMarks[num]; if (value.target != null && ((ISelectable)value.target).Exists() && value.target.IsAlive) { value.lastPos = ((IFollowable)value.target).GetHealthbarPosition(); } DeathMarks[num] = value; if (!(Time.time < value.detonateAt)) { float num2 = gun.GunData.damage * data.deathMarkDamageScale * (1f + (value.stacks - 1f) * data.deathMarkStackScale); float num3 = data.deathMarkRadius * (1f + (value.stacks - 1f) * 0.15f); try { GameManager.Instance.SpawnExplosionObserverSeeThrough((IDamageSource)(object)gun, value.lastPos, num3, (TargetType)5, new DamageData(num2, (EffectType)0, 0f, (DamageFlags)16), ((NetworkBehaviour)gun).OwnerClientId, 12f); } catch { try { GameManager.Instance.SpawnExplosionFirstPerson((IDamageSource)(object)gun, value.lastPos, num3, (TargetType)5, new DamageData(num2, (EffectType)0, 0f, (DamageFlags)16), 2f); } catch { } } DeathMarks.RemoveAt(num); } } } private void TickEchoes(Gun gun) { if (data.echoDelay <= 0f || PendingEchoes.Count == 0) { return; } for (int num = PendingEchoes.Count - 1; num >= 0; num--) { if (!(Time.time < PendingEchoes[num].fireAt)) { PendingEcho echo = PendingEchoes[num]; PendingEchoes.RemoveAt(num); FireEchoBullet(gun, echo); } } } private void FireEchoBullet(Gun gun, PendingEcho echo) { //IL_0043: 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_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_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_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) try { BulletData bulletData; if (hasLastFiredBullet) { bulletData = lastFiredBullet; bulletData.position = echo.position; bulletData.rotation = echo.rotation; bulletData.direction = echo.rotation * Vector3.forward; } else { Vector3 position = echo.position; Quaternion rotation = echo.rotation; bulletData = ((GunData)(ref gun.GunData)).GetBulletData(ref position, ref rotation); } bulletData.damage = echo.damage; bulletData.speed = echo.speed; bulletData.gravity = echo.gravity; bulletData.damageEffect = (EffectType)2; bulletData.damageEffectAmount = Mathf.Max(data.echoShockAmount, 10f); IBullet bullet = gun.GetBullet(); if (bullet != null) { Action action = ResolveBulletRelease(gun); gun.ModifyBulletData(ref bulletData, (BulletFlags)11); bullet.Initialize(bulletData, (IDamageSource)(object)gun, action, (BulletFlags)11); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] Echo fire failed: " + ex.Message)); } } } private static Action ResolveBulletRelease(Gun gun) { try { FieldInfo fieldInfo = AccessTools.Field(typeof(Gun), "releaseBulletToPool"); if (fieldInfo != null && fieldInfo.GetValue(gun) is Action result) { return result; } } catch { } return delegate { }; } private void TickScouter(Gun gun) { //IL_00fb: 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_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: 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_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) if (highlightClearAt > 0f && Time.time >= highlightClearAt) { ClearHighlights(); } if (data.scouterInterval <= 0f || !gun.IsAiming || Time.time - LastScouterPulse < data.scouterInterval) { return; } LastScouterPulse = Time.time; try { Player player = gun.Player; if ((Object)(object)player == (Object)null) { return; } float num = ((data.scouterRadius > 0f) ? data.scouterRadius : 50f); Vector3 val = ((Component)player).transform.position + Vector3.up * 1.4f; Vector3 forward = ((Component)player).transform.forward; try { if ((Object)(object)gun.playerLook != (Object)null) { val = ((Component)gun.playerLook).transform.position; forward = ((Component)gun.playerLook).transform.forward; } } catch { } Vector3 val2 = val + forward * (num * 0.5f); int num2 = -1; try { RaycastHit val3 = default(RaycastHit); if (Physics.Raycast(val + forward * 0.35f, forward, ref val3, num * 2f, num2, (QueryTriggerInteraction)1)) { bool flag = false; try { if ((Object)(object)((RaycastHit)(ref val3)).collider != (Object)null && ((Component)((RaycastHit)(ref val3)).collider).transform.IsChildOf(((Component)player).transform)) { flag = true; } } catch { } if (!flag) { val2 = ((RaycastHit)(ref val3)).point; } } } catch { } Collider[] array = Physics.OverlapSphere(val2, num, -1, (QueryTriggerInteraction)1); int num3 = 0; float num4 = 0.15f; for (int i = 0; i < array.Length && num3 < 32; i++) { ITarget target = IDamageSource.GetTarget((Component)(object)array[i]); if (target == null || !target.IsAlive) { continue; } try { Vector3 val4 = ((IFollowable)target).GetHealthbarPosition() - val; if (((Vector3)(ref val4)).sqrMagnitude > 0.01f && Vector3.Dot(((Vector3)(ref val4)).normalized, forward) < num4) { continue; } } catch { } ISelectable val5 = (ISelectable)(object)target; if (val5 != null) { HighlightTarget(val5, 2.5f); num3++; } } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] Scouter: " + ex.Message)); } } } private void HighlightTarget(ISelectable selectable, float duration) { if (selectable == null) { return; } try { Highlighter.RegisterObjectForHighlight(selectable); if (!activeHighlights.Contains(selectable)) { activeHighlights.Add(selectable); } highlightClearAt = Mathf.Max(highlightClearAt, Time.time + duration); } catch { } } private void ClearHighlights() { for (int i = 0; i < activeHighlights.Count; i++) { try { Highlighter.RemoveObjectFromHighlighting(activeHighlights[i]); } catch { } } activeHighlights.Clear(); highlightClearAt = -999f; } private void DestroyC4Visual() { if ((Object)(object)c4Visual != (Object)null) { try { Object.Destroy((Object)(object)c4Visual); } catch { } c4Visual = null; } } public void ModifyBulletData(ref BulletData bullet, Gun gun) { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) if (data.longwatchAimSeconds > 0f && AimHoldTime >= data.longwatchAimSeconds) { bullet.speed *= data.longwatchSpeedMult; bullet.gravity *= data.longwatchGravityMult; bullet.range.falloffStartDistance += data.longwatchRangeBonus; bullet.range.falloffEndDistance += data.longwatchRangeBonus; bullet.range.maxDamageRange += data.longwatchRangeBonus; } if (data.bonusBounces > 0) { bullet.maxBounces = Mathf.Max(bullet.maxBounces, data.bonusBounces); } if (data.rotAmount > 0f) { bullet.damageEffect = (EffectType)7; bullet.damageEffectAmount = Mathf.Max(bullet.damageEffectAmount, data.rotAmount); } else if (data.waterAmount > 0f) { bullet.damageEffect = (EffectType)9; bullet.damageEffectAmount = Mathf.Max(bullet.damageEffectAmount, data.waterAmount); } } public void OnBulletFired(IBullet bullet, ref BulletData bulletData) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) lastFiredBullet = bulletData; hasLastFiredBullet = true; if (data.pierceTargets > 0 && bullet != null) { SniperProjectilePierceHook.ResetBullet(bullet); } } public void OnShotFired(Gun gun) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0130: 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_00d5: Unknown result type (might be due to invalid IL or missing references) TwinShotHits.Clear(); if (BlockAutoReloadForChamber) { BlockAutoReloadForChamber = false; try { IUpgradable prefab = gun.Prefab; IWeapon val = (IWeapon)(object)((prefab is IWeapon) ? prefab : null); if (val != null) { gun.GunData.autoReloadWhenEmpty = val.GunData.autoReloadWhenEmpty; } else { gun.GunData.autoReloadWhenEmpty = true; } } catch { } } if (data.echoDelay > 0f && (Object)(object)gun != (Object)null) { try { Vector3 position = (hasLastFiredBullet ? lastFiredBullet.position : (((Object)(object)gun.GunData.firePoint != (Object)null) ? gun.GunData.firePoint.position : ((Component)gun).transform.position)); Quaternion rotation = (hasLastFiredBullet ? lastFiredBullet.rotation : (((Object)(object)gun.Player != (Object)null) ? ((Component)gun.Player.playerLook).transform.rotation : ((Component)gun).transform.rotation)); PendingEchoes.Add(new PendingEcho { fireAt = Time.time + data.echoDelay, position = position, rotation = rotation, damage = gun.GunData.damage * ((data.echoDamageScale > 0f) ? data.echoDamageScale : 0.85f), speed = (hasLastFiredBullet ? lastFiredBullet.speed : gun.GunData.bulletSpeed), gravity = (hasLastFiredBullet ? lastFiredBullet.gravity : gun.GunData.bulletGravity) }); } catch { } } } public void OnMagazineEmptied(Gun gun) { if (!data.oneInTheChamber || !ChamberBonusReady || (Object)(object)gun == (Object)null) { return; } gun.RemainingAmmo = 1f; ChamberBonusReady = false; BlockAutoReloadForChamber = true; try { gun.GunData.autoReloadWhenEmpty = false; } catch { } } public void OnFullReloadCompleted(Gun gun) { if (data.oneInTheChamber) { LastReloadWasFullTopOff = true; ChamberBonusReady = true; BlockAutoReloadForChamber = false; } } private void OnBeforeDamage(ref DamageCallbackData callback) { //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) IDamageSource source = callback.source; object obj = ((source is Gun) ? source : null); if (obj == null) { IDamageSource source2 = callback.source; IDamageSource obj2 = ((source2 != null) ? source2.ParentSource : null); obj = ((obj2 is Gun) ? obj2 : null); } Gun val = (Gun)obj; if ((Object)(object)val == (Object)null || !IsOurGear((IGear)(object)val)) { return; } ITarget target = callback.target; if (target == null) { return; } if (data.shellDamageMult > 1.01f && IsShellTarget(target)) { callback.damageData.damage *= data.shellDamageMult; } if (data.fullHpDamageMult > 1.01f && GetHealthFraction(target) >= 0.98f) { callback.damageData.damage *= data.fullHpDamageMult; } if (data.syncWindow > 0f && data.syncDamageMult > 1.01f && SniperAllyDamageTracker.WasDamagedByAlly(target, val, data.syncWindow)) { callback.damageData.damage *= data.syncDamageMult; } if (data.overkill && IsShellTarget(target)) { EnemyPart val2 = (EnemyPart)(object)((target is EnemyPart) ? target : null); if (val2 != null) { try { float health = val2.Health; float damage = callback.damageData.damage; if (health > 0f && damage > health + 0.01f) { pendingOverkill = damage - health; ref ITarget reference = ref pendingOverkillParent; IEnemyComponent parent = val2.Parent; reference = (ITarget)(object)((parent is ITarget) ? parent : null); pendingOverkillPos = callback.position; pendingOverkillGun = val; pendingOverkillEffect = callback.damageData.effect; pendingOverkillEffectAmt = callback.damageData.effectAmount; hasPendingOverkill = true; } } catch { } } } if (!(data.transferRelayScale > 0f) || !(callback.damageData.damage <= 0.01f)) { return; } try { float num = val.GunData.damage * data.transferRelayScale; IDamageSource.DamageTarget((IDamageSource)(object)val, target, new DamageData(num, (EffectType)(-1), 0f, (DamageFlags)0), callback.position, (Collider)null); } catch { } } private void ApplyPendingOverkill() { //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_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_0076: 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) if (!hasPendingOverkill) { return; } float num = pendingOverkill; ITarget val = pendingOverkillParent; Vector3 val2 = pendingOverkillPos; Gun val3 = pendingOverkillGun; EffectType val4 = pendingOverkillEffect; float num2 = pendingOverkillEffectAmt; hasPendingOverkill = false; pendingOverkill = 0f; pendingOverkillParent = null; pendingOverkillGun = null; if (num <= 0.01f || val == null || !val.IsAlive || (Object)(object)val3 == (Object)null) { return; } try { IDamageSource.DamageTarget((IDamageSource)(object)val3, val, new DamageData(num, val4, num2 * 0.5f, (DamageFlags)0), val2, (Collider)null); } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] Overkill carry: " + ex.Message)); } } } private static bool IsShellTarget(ITarget target) { //IL_000b: 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_0019: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 try { EnemyPart val = (EnemyPart)(object)((target is EnemyPart) ? target : null); if (val != null) { if ((val.ComponentType & 4) != 0) { return true; } if ((val.ComponentType & 2) == 0 && (int)val.ComponentType != 1) { return true; } } } catch { } return (((object)((target is Component) ? target : null))?.GetType().Name ?? ((object)target).GetType().Name).IndexOf("Shell", StringComparison.OrdinalIgnoreCase) >= 0; } private static float GetHealthFraction(ITarget target) { try { EnemyPart val = (EnemyPart)(object)((target is EnemyPart) ? target : null); if (val != null) { return val.NormalizedHealth; } } catch { } try { float maxHealth = target.MaxHealth; if (maxHealth > 0f) { EnemyPart val2 = (EnemyPart)(object)((target is EnemyPart) ? target : null); if (val2 != null) { return val2.Health / maxHealth; } } } catch { } return 0.5f; } private void OnDamageTarget(in DamageCallbackData callback) { //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_024e: 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_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: 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_00d5: Unknown result type (might be due to invalid IL or missing references) if (callback.source == null) { return; } IDamageSource source = callback.source; Gun val = (Gun)(((object)((source is Gun) ? source : null)) ?? ((object)/*isinst with value type is only supported in some contexts*/)); if ((Object)(object)val == (Object)null || !IsOurGear((IGear)(object)val) || callback.damageData.damage <= 0f) { return; } ITarget target = callback.target; if (target == null) { return; } if (BlockAutoReloadForChamber && val.RemainingAmmoCount <= 0) { BlockAutoReloadForChamber = false; } if (data.deathMark) { ApplyDeathMark(target, callback.position, headshot: false); } if (data.spotterRadius > 0f) { float duration = ((data.spotterDuration > 0f) ? data.spotterDuration : 6f); ISelectable val2 = (ISelectable)(object)target; if (val2 != null) { HighlightTarget(val2, duration); } try { Collider[] array = Physics.OverlapSphere(callback.position, data.spotterRadius, -1, (QueryTriggerInteraction)1); for (int i = 0; i < array.Length && i < 32; i++) { ITarget target2 = IDamageSource.GetTarget((Component)(object)array[i]); if (target2 != null && target2.IsAlive && target2 != target) { ISelectable val3 = (ISelectable)(object)target2; if (val3 != null) { HighlightTarget(val3, duration); } } } } catch { } } if (data.rotSplashRadius > 0f && data.rotAmount > 0f) { try { GameManager.Instance.SpawnExplosionFirstPerson((IDamageSource)(object)val, callback.position, data.rotSplashRadius, (TargetType)5, new DamageData(0f, (EffectType)7, data.rotAmount, (DamageFlags)16), 1.5f); } catch { } } if (data.twinLinkFenceDamage > 0f && !TwinShotHits.Contains(target)) { TwinShotHits.Add(target); if (TwinShotHits.Count >= 2) { TryTwinFence(val); } } if (ExhaustionShotArmed && data.exhaustionSlowDuration > 0f) { ExhaustionShotArmed = false; ExhaustionReadyAt = Time.time + data.exhaustionCooldown; try { target.SlowTargetThisTick(Mathf.Clamp01(1f - data.exhaustionSlowStrength * 0.05f)); IDamageSource.DamageTarget((IDamageSource)(object)val, target, new DamageData(0f, (EffectType)10, data.exhaustionSlowStrength, (DamageFlags)0), callback.position, (Collider)null); } catch { } } if (!(data.disruptDuration > 0f)) { return; } try { string text = ((object)((target is Component) ? target : null))?.GetType().Name ?? ""; if (text.IndexOf("Shield", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Bubble", StringComparison.OrdinalIgnoreCase) >= 0) { IDamageSource.DamageTarget((IDamageSource)(object)val, target, new DamageData(val.GunData.damage * 3.5f, (EffectType)(-1), 0f, (DamageFlags)0), callback.position, (Collider)null); } } catch { } } private void ApplyDeathMark(ITarget target, Vector3 pos, bool headshot) { //IL_00ca: 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_0072: 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) float num = data.deathMarkFuse * (headshot ? data.deathMarkHeadshotFuseMult : 1f); for (int i = 0; i < DeathMarks.Count; i++) { if (DeathMarks[i].target == target) { DeathMarkEntry value = DeathMarks[i]; value.stacks += 1f; value.detonateAt = Mathf.Min(value.detonateAt, Time.time + num); value.lastPos = pos; DeathMarks[i] = value; return; } } DeathMarks.Add(new DeathMarkEntry { target = target, detonateAt = Time.time + num, stacks = 1f, lastPos = pos, fromHeadshot = headshot }); } private void TryTwinFence(Gun gun) { //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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_0161: Unknown result type (might be due to invalid IL or missing references) if (TwinShotHits.Count < 2) { return; } try { ITarget val = TwinShotHits[0]; ITarget val2 = TwinShotHits[1]; Vector3 healthbarPosition = ((IFollowable)val).GetHealthbarPosition(); Vector3 healthbarPosition2 = ((IFollowable)val2).GetHealthbarPosition(); if (Vector3.Distance(healthbarPosition, healthbarPosition2) < 0.05f) { TwinShotHits.Clear(); return; } float num = Mathf.Max(14f, data.twinLinkFenceDamage * 0.15f); float twinLinkFenceDamage = data.twinLinkFenceDamage; try { IDamageSource.DamageTarget((IDamageSource)(object)gun, val, new DamageData(twinLinkFenceDamage * 0.5f, (EffectType)2, num, (DamageFlags)0), healthbarPosition, (Collider)null); IDamageSource.DamageTarget((IDamageSource)(object)gun, val2, new DamageData(twinLinkFenceDamage * 0.5f, (EffectType)2, num, (DamageFlags)0), healthbarPosition2, (Collider)null); } catch { } Vector3 val3 = (healthbarPosition + healthbarPosition2) * 0.5f; try { GameManager.Instance.SpawnExplosionFirstPerson((IDamageSource)(object)gun, val3, Mathf.Max(1.2f, data.twinLinkFenceRadius * 0.5f), (TargetType)5, new DamageData(twinLinkFenceDamage * 0.35f, (EffectType)2, num, (DamageFlags)16), 1.2f); } catch { } for (int i = 0; i < 2; i++) { ITarget obj3 = TwinShotHits[i]; EnemyPart val4 = (EnemyPart)(object)((obj3 is EnemyPart) ? obj3 : null); if (val4 == null) { continue; } IEnemyComponent parent = val4.Parent; ITarget val5 = (ITarget)(object)((parent is ITarget) ? parent : null); if (val5 != null && val5.IsAlive) { try { IDamageSource.DamageTarget((IDamageSource)(object)gun, val5, new DamageData(twinLinkFenceDamage * 0.4f, (EffectType)2, num, (DamageFlags)0), ((IFollowable)val5).GetHealthbarPosition(), (Collider)null); } catch { } } } } catch { } TwinShotHits.Clear(); } private void OnKillTarget(in KillCallbackData callback) { if (callback.source == null) { return; } IDamageSource source = callback.source; Gun val = (Gun)(((object)((source is Gun) ? source : null)) ?? ((object)/*isinst with value type is only supported in some contexts*/)); if (!((Object)(object)val == (Object)null) && IsOurGear((IGear)(object)val)) { LastKillTime = Time.time; if (data.overkill) { ApplyPendingOverkill(); } } } public bool IsDeadboltActive() { if (data.deadboltDuration > 0f) { return Time.time - LastKillTime <= data.deadboltDuration; } return false; } public bool IsLongwatchActive() { if (data.longwatchAimSeconds > 0f) { return AimHoldTime >= data.longwatchAimSeconds; } return false; } public bool IsAnchored(Gun gun) { //IL_002a: 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) if (!data.anchor || (Object)(object)((gun != null) ? gun.Player : null) == (Object)null) { return false; } try { Vector3 velocity = gun.Player.Velocity; velocity.y = 0f; return ((Vector3)(ref velocity)).sqrMagnitude <= data.anchorSpeedThreshold * data.anchorSpeedThreshold && !gun.Player.IsSprinting && !gun.Player.Sliding; } catch { return false; } } public void TryThrowOrDetonateC4(Gun gun) { //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: 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_0092: 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_0055: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) if (!data.highExplosive || (Object)(object)gun == (Object)null || !((NetworkBehaviour)gun).IsOwner) { return; } if (C4Deployed) { try { GameManager.Instance.SpawnExplosionFirstPerson((IDamageSource)(object)gun, C4Position, data.c4Radius, (TargetType)5, new DamageData(data.c4Damage, (EffectType)0, 0f, (DamageFlags)16), 3f); } catch { try { GameManager.Instance.SpawnExplosionObserverSeeThrough((IDamageSource)(object)gun, C4Position, data.c4Radius, (TargetType)5, new DamageData(data.c4Damage, (EffectType)0, 0f, (DamageFlags)16), ((NetworkBehaviour)gun).OwnerClientId, 12f); } catch { } } DestroyC4Visual(); C4Deployed = false; return; } try { PlayerLook val = gun.Player?.playerLook; Vector3 val2 = (((Object)(object)val != (Object)null) ? ((Component)val).transform.position : ((Component)gun).transform.position); Vector3 val3 = (((Object)(object)val != (Object)null) ? ((Component)val).transform.forward : ((Component)gun).transform.forward); C4Position = val2 + val3 * data.c4ThrowForce * 0.65f + Vector3.up * 0.5f; RaycastHit val4 = default(RaycastHit); if (Physics.Raycast(C4Position + Vector3.up * 2f, Vector3.down, ref val4, 40f)) { C4Position = ((RaycastHit)(ref val4)).point + Vector3.up * 0.15f; } C4Deployed = true; C4DeployedAt = Time.time; SpawnC4Visual(C4Position); } catch { C4Position = ((Component)gun).transform.position + ((Component)gun).transform.forward * 10f; C4Deployed = true; C4DeployedAt = Time.time; SpawnC4Visual(C4Position); } } private void SpawnC4Visual(Vector3 pos) { //IL_002d: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) DestroyC4Visual(); try { c4Visual = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)c4Visual).name = "BallisticSniper_C4"; c4Visual.transform.position = pos; c4Visual.transform.localScale = Vector3.one * 0.35f; Collider component = c4Visual.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Renderer component2 = c4Visual.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.material.color = new Color(0.15f, 0.15f, 0.15f, 1f); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] C4 visual: " + ex.Message)); } } } private void OnDestroy() { if ((Object)(object)boundGun != (Object)null) { BindHooks(boundGun, bind: false); } ClearHighlights(); DestroyC4Visual(); } public static bool TryGet(IGear gear, out BallisticSniperBehaviour behaviour) { behaviour = null; if ((Object)(object)((gear != null) ? gear.gameObject : null) == (Object)null) { return false; } behaviour = gear.gameObject.GetComponent(); if ((Object)(object)behaviour != (Object)null) { return true; } bool num = (Object)(object)((IUpgradable)gear).Info != (Object)null && (((IUpgradable)gear).Info.APIName == "ballistic_sniper" || ((IUpgradable)gear).Info.ID == 87421); BallisticSniperBehaviour ballisticSniperBehaviour = null; IUpgradable prefab = ((IUpgradable)gear).Prefab; Component val = (Component)(object)((prefab is Component) ? prefab : null); if (val != null) { ballisticSniperBehaviour = val.GetComponent(); } if (!num && (Object)(object)ballisticSniperBehaviour == (Object)null) { return false; } string desc = (((Object)(object)ballisticSniperBehaviour != (Object)null) ? ballisticSniperBehaviour.Description : "Heavy kinetic bolt-action rifle. High single-shot damage, low capacity, and a deliberate single-round reload. Built for long-range elimination."); behaviour = gear.gameObject.AddComponent(); behaviour.InitializeAsPrefab(desc); if ((Object)(object)ballisticSniperBehaviour != (Object)null) { behaviour.CopyFrom(ballisticSniperBehaviour); } return true; } public static bool IsOurGear(IGear gear) { if ((Object)(object)((gear != null) ? ((IUpgradable)gear).Info : null) == (Object)null) { return false; } if (!(((IUpgradable)gear).Info.APIName == "ballistic_sniper")) { return ((IUpgradable)gear).Info.ID == 87421; } return true; } public static bool IsOurGear(IUpgradable gear) { if ((Object)(object)((gear != null) ? gear.Info : null) == (Object)null) { return false; } if (!(gear.Info.APIName == "ballistic_sniper")) { return gear.Info.ID == 87421; } return true; } } internal static class BallisticSniperCombatHooks { public static void Apply(Harmony harmony) { TryPatch(harmony, typeof(SniperGunUpdateHook)); TryPatch(harmony, typeof(SniperModifyBulletHook)); TryPatch(harmony, typeof(SniperCartridgeModifyBulletHook)); TryPatch(harmony, typeof(SniperOnFireHook)); TryPatch(harmony, typeof(SniperCartridgeOnFireHook)); TryPatch(harmony, typeof(SniperOnFiredBulletHook)); TryPatch(harmony, typeof(SniperRecoilHook)); TryPatch(harmony, typeof(SniperUpgradesEnabledHook)); TryPatch(harmony, typeof(SniperUpgradesDisabledHook)); TryPatch(harmony, typeof(SniperReloadHoldC4Hook)); TryPatch(harmony, typeof(SniperCanReloadHook)); TryPatch(harmony, typeof(SniperProjectileBounceHomingHook)); TryPatch(harmony, typeof(SniperProjectilePierceHook)); TryPatch(harmony, typeof(SniperAllyDamageTracker)); } private static void TryPatch(Harmony harmony, Type patchClass) { try { harmony.PatchAll(patchClass); } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogWarning((object)("[BallisticSniper] Skipped patch " + patchClass.Name + ": " + ex.Message)); } } } } [HarmonyPatch(typeof(Gun), "Update")] internal static class SniperGunUpdateHook { [HarmonyPostfix] private static void Postfix(Gun __instance) { try { if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour)) { behaviour.Tick(Time.deltaTime, __instance); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] Update: " + ex.Message)); } } } } [HarmonyPatch(typeof(Gun), "ModifyBulletData")] internal static class SniperModifyBulletHook { [HarmonyPostfix] private static void Postfix(Gun __instance, ref BulletData data) { try { if (!((Object)(object)__instance == (Object)null) && !(__instance is CartridgeSMG) && BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour)) { behaviour.ModifyBulletData(ref data, __instance); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] ModifyBullet: " + ex.Message)); } } } } [HarmonyPatch(typeof(CartridgeSMG), "ModifyBulletData")] internal static class SniperCartridgeModifyBulletHook { [HarmonyPostfix] private static void Postfix(CartridgeSMG __instance, ref BulletData data, BulletFlags flags) { try { if (!((Object)(object)__instance == (Object)null) && BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour)) { behaviour.ModifyBulletData(ref data, (Gun)(object)__instance); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] SMG ModifyBullet: " + ex.Message)); } } } } [HarmonyPatch(typeof(Gun), "OnFire")] internal static class SniperOnFireHook { [HarmonyPostfix] private static void Postfix(Gun __instance) { try { if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour)) { behaviour.OnShotFired(__instance); } } catch { } } } [HarmonyPatch(typeof(CartridgeSMG), "OnFire")] internal static class SniperCartridgeOnFireHook { [HarmonyPostfix] private static void Postfix(CartridgeSMG __instance, int numBullets) { try { if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour)) { behaviour.OnShotFired((Gun)(object)__instance); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] Cartridge OnFire: " + ex.Message)); } } } } [HarmonyPatch(typeof(Gun), "OnFiredBullet")] internal static class SniperOnFiredBulletHook { [HarmonyPostfix] private static void Postfix(Gun __instance, IBullet bullet, BulletFlags flags, int shotIndex, ref BulletData bulletData) { try { if (!((Object)(object)__instance == (Object)null) && bullet != null && BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour)) { behaviour.OnBulletFired(bullet, ref bulletData); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] OnFiredBullet: " + ex.Message)); } } } } [HarmonyPatch(typeof(Gun), "AddRecoil")] internal static class SniperRecoilHook { [HarmonyPrefix] private static void Prefix(Gun __instance, ref float multiplier) { try { if (!((Object)(object)__instance == (Object)null) && BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour) && behaviour.IsAnchored(__instance)) { multiplier = 0f; } } catch { } } } [HarmonyPatch(typeof(Gun), "OnUpgradesEnabled")] internal static class SniperUpgradesEnabledHook { [HarmonyPostfix] private static void Postfix(Gun __instance) { try { if (!((Object)(object)__instance == (Object)null) && BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour)) { behaviour.OnUpgradesApplied(__instance); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] OnUpgradesEnabled: " + ex.Message)); } } } } [HarmonyPatch(typeof(Gun), "OnUpgradesDisabled")] internal static class SniperUpgradesDisabledHook { [HarmonyPrefix] private static void Prefix(Gun __instance) { try { if (!((Object)(object)__instance == (Object)null) && BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour)) { behaviour.OnUpgradesCleared(__instance); } } catch { } } } [HarmonyPatch(typeof(Gun), "OnReloadPerformed")] internal static class SniperReloadHoldC4Hook { [HarmonyPrefix] private static bool Prefix(Gun __instance) { try { if ((Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsOwner) { return true; } if (!BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour)) { return true; } if (!behaviour.WeaponData.highExplosive) { return true; } if (behaviour.C4Deployed) { behaviour.TryThrowOrDetonateC4(__instance); return false; } if (__instance.RemainingAmmoCount >= __instance.GunData.magazineSize) { behaviour.TryThrowOrDetonateC4(__instance); return false; } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] C4 reload: " + ex.Message)); } } return true; } } [HarmonyPatch(typeof(Gun), "CanReload")] internal static class SniperCanReloadHook { [HarmonyPrefix] private static bool Prefix(Gun __instance, ref bool __result) { try { if ((Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsOwner) { return true; } if (!BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour)) { return true; } if (!behaviour.WeaponData.oneInTheChamber) { return true; } if (behaviour.BlockAutoReloadForChamber && __instance.RemainingAmmoCount > 0) { __result = false; return false; } } catch { } return true; } } [HarmonyPatch(typeof(SimpleProjectileBullet), "Bounce")] internal static class SniperProjectileBounceHomingHook { [HarmonyPostfix] private static void Postfix(SimpleProjectileBullet __instance, ref RaycastHit hit) { //IL_00a2: 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_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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_016c: 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_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null) { return; } IDamageSource parentSource = __instance.ParentSource; Gun val = (Gun)(object)((parentSource is Gun) ? parentSource : null); if (val == null || !BallisticSniperBehaviour.TryGet((IGear)(object)val, out var behaviour) || (behaviour.WeaponData.postBounceHoming <= 0f && behaviour.WeaponData.bonusBounces <= 0)) { return; } FieldInfo fieldInfo = AccessTools.Field(typeof(SimpleProjectileBullet), "data"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(SimpleProjectileBullet), "velocity"); if (fieldInfo == null || !(fieldInfo.GetValue(__instance) is BulletData val2)) { return; } Vector3 point = ((RaycastHit)(ref hit)).point; float num = Mathf.Max(25f, behaviour.WeaponData.postBounceHoming * 8f); ITarget val3 = null; float num2 = float.MaxValue; int num3 = val2.targetCollisionMask; if (num3 == 0) { num3 = -1; } Collider[] array = Physics.OverlapSphere(point, num, num3, (QueryTriggerInteraction)1); ITarget target = IDamageSource.GetTarget((Component)(object)((RaycastHit)(ref hit)).collider); Vector3 val4; for (int i = 0; i < array.Length; i++) { ITarget target2 = IDamageSource.GetTarget((Component)(object)array[i]); if (target2 != null && target2.IsAlive && target2 != target) { val4 = ((IFollowable)target2).GetHealthbarPosition() - point; float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude; if (sqrMagnitude < num2) { num2 = sqrMagnitude; val3 = target2; } } } if (val3 == null) { return; } val4 = ((IFollowable)val3).GetHealthbarPosition() - point; Vector3 normalized = ((Vector3)(ref val4)).normalized; float num4 = Mathf.Clamp01(behaviour.WeaponData.postBounceHoming / 8f); num4 = Mathf.Max(num4, 0.75f); val4 = Vector3.Slerp(val2.direction, normalized, num4); val2.direction = ((Vector3)(ref val4)).normalized; fieldInfo.SetValue(__instance, val2); if (fieldInfo2 != null) { val4 = (Vector3)fieldInfo2.GetValue(__instance); float num5 = ((Vector3)(ref val4)).magnitude; if (num5 < 1f) { num5 = ((val2.speed > 0f) ? val2.speed : 220f); } fieldInfo2.SetValue(__instance, val2.direction * num5); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] Projectile bounce homing: " + ex.Message)); } } } } [HarmonyPatch(typeof(SimpleProjectileBullet), "OnHit")] internal static class SniperProjectilePierceHook { private static readonly Dictionary HitCounts = new Dictionary(32); private static readonly FieldInfo BouncesField = AccessTools.Field(typeof(SimpleProjectileBullet), "bounces"); private static readonly FieldInfo DataField = AccessTools.Field(typeof(SimpleProjectileBullet), "data"); private static readonly FieldInfo IsAliveField = AccessTools.Field(typeof(SimpleProjectileBullet), "isAlive"); private static readonly FieldInfo VelocityField = AccessTools.Field(typeof(SimpleProjectileBullet), "velocity"); private static readonly FieldInfo PositionNextField = AccessTools.Field(typeof(SimpleProjectileBullet), "positionNext"); public static void ResetBullet(IBullet bullet) { if (bullet != null) { HitCounts[((object)bullet).GetHashCode()] = 0; } } [HarmonyPrefix] private static bool Prefix(SimpleProjectileBullet __instance, ref RaycastHit hit, ref Vector3 direction, ITarget target) { //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0119: 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_0125: 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_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null) { return true; } IDamageSource parentSource = __instance.ParentSource; Gun val = (Gun)(object)((parentSource is Gun) ? parentSource : null); if (val == null) { return true; } if (!BallisticSniperBehaviour.TryGet((IGear)(object)val, out var behaviour)) { return true; } if (behaviour.WeaponData.pierceTargets <= 0) { return true; } if (target == null || !IBullet.CanDamageTarget(target, (IBullet)(object)__instance)) { return true; } int hashCode = ((object)__instance).GetHashCode(); HitCounts.TryGetValue(hashCode, out var value); int pierceTargets = behaviour.WeaponData.pierceTargets; if (value >= pierceTargets) { return true; } float num = ((behaviour.WeaponData.pierceFalloff > 0f) ? behaviour.WeaponData.pierceFalloff : 0.25f); float num2 = ((value == 0) ? 1f : Mathf.Pow(Mathf.Clamp01(1f - num), (float)value)); if (BulletFlagsExtensions.IsOwner(__instance.Flags)) { BulletData val2 = (BulletData)((DataField != null && DataField.GetValue(__instance) is BulletData val3) ? val3 : default(BulletData)); float num3 = 1f; try { ref RangeData range = ref val2.range; Vector3 val4 = ((RaycastHit)(ref hit)).point - val2.position; num3 = ((RangeData)(ref range)).GetDamageMultiplier(((Vector3)(ref val4)).magnitude); } catch { } float num4 = val2.damage * num3 * num2; float num5 = val2.damageEffectAmount * num3 * num2; IDamageSource.DamageTarget((IDamageSource)(object)__instance, target, new DamageData(num4, val2.damageEffect, num5, val2.damageFlags), ((RaycastHit)(ref hit)).point, ((RaycastHit)(ref hit)).collider); } HitCounts[hashCode] = value + 1; Vector3 val5 = ((((Vector3)(ref direction)).sqrMagnitude > 0.001f) ? ((Vector3)(ref direction)).normalized : ((Component)__instance).transform.forward); Vector3 val6 = ((RaycastHit)(ref hit)).point + val5 * 0.35f; if (PositionNextField != null) { PositionNextField.SetValue(__instance, val6); } if (DataField != null && DataField.GetValue(__instance) is BulletData val7) { val7.position = val6; DataField.SetValue(__instance, val7); } if (IsAliveField != null) { IsAliveField.SetValue(__instance, true); } return false; } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] Projectile pierce: " + ex.Message)); } return true; } } } [HarmonyPatch(typeof(EnemyPart), "Damage")] internal static class SniperAllyDamageTracker { private struct HitRecord { public ulong ownerId; public float time; } private static readonly Dictionary> Recent = new Dictionary>(64); [HarmonyPostfix] private static void Postfix(EnemyPart __instance, DamageData data, IDamageSource source, Vector3 position) { try { if ((Object)(object)__instance == (Object)null || source == null) { return; } ulong num = ResolveOwnerId(source); if (num == ulong.MaxValue) { return; } int instanceID = ((Object)__instance).GetInstanceID(); if (!Recent.TryGetValue(instanceID, out var value)) { value = new List(4); Recent[instanceID] = value; } float time = Time.time; for (int num2 = value.Count - 1; num2 >= 0; num2--) { if (time - value[num2].time > 6f) { value.RemoveAt(num2); } } value.Add(new HitRecord { ownerId = num, time = time }); if (value.Count > 8) { value.RemoveAt(0); } } catch { } } public static bool WasDamagedByAlly(ITarget target, Gun selfGun, float windowSeconds) { if (target == null || (Object)(object)selfGun == (Object)null || windowSeconds <= 0f) { return false; } try { EnemyPart val = (EnemyPart)(object)((target is EnemyPart) ? target : null); int instanceID; if (val != null) { instanceID = ((Object)val).GetInstanceID(); } else { Component val2 = (Component)(object)((target is Component) ? target : null); if (val2 == null) { return false; } instanceID = ((Object)val2).GetInstanceID(); } if (!Recent.TryGetValue(instanceID, out var value) || value.Count == 0) { return false; } ulong ownerClientId = ((NetworkBehaviour)selfGun).OwnerClientId; float time = Time.time; for (int num = value.Count - 1; num >= 0; num--) { if (!(time - value[num].time > windowSeconds) && value[num].ownerId != ownerClientId && value[num].ownerId != ulong.MaxValue) { return true; } } } catch { } return false; } private static ulong ResolveOwnerId(IDamageSource source) { try { IDamageSource val = source.GetBase(); Gun val2 = (Gun)(object)((val is Gun) ? val : null); if (val2 != null) { return ((NetworkBehaviour)val2).OwnerClientId; } Player val3 = (Player)(object)((val is Player) ? val : null); if (val3 != null) { return ((NetworkBehaviour)val3).OwnerClientId; } Gun val4 = (Gun)(object)((source is Gun) ? source : null); if (val4 != null) { return ((NetworkBehaviour)val4).OwnerClientId; } } catch { } return ulong.MaxValue; } } [HarmonyPatch(typeof(Gun), "OnAmmoLoaded")] internal static class BallisticSniperReloadHook { [HarmonyPostfix] private static void Postfix(Gun __instance) { try { if ((Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsOwner || !BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour)) { return; } if (!behaviour.SingleRoundReload) { if (__instance.RemainingAmmoCount >= __instance.GunData.magazineSize) { behaviour.OnFullReloadCompleted(__instance); } } else { LoadOneRound(__instance, behaviour); } } catch (Exception arg) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)$"[BallisticSniper] OnAmmoLoaded hook failed: {arg}"); } } } private static void LoadOneRound(Gun gun, BallisticSniperBehaviour behaviour) { ref GunData gunData = ref gun.GunData; int num = Mathf.Max(gunData.magazineSize, 1); int remainingAmmoCount = gun.RemainingAmmoCount; if (remainingAmmoCount >= num) { behaviour.IsTubeReloading = false; behaviour.OnFullReloadCompleted(gun); return; } bool flag = false; if (gunData.hasLimitedAmmo) { if (gun.StoredAmmo >= 1f) { gun.StoredAmmo -= 1f; gun.RemainingAmmo = remainingAmmoCount + 1; flag = true; } } else { gun.RemainingAmmo = remainingAmmoCount + 1; flag = true; } if (!flag) { behaviour.IsTubeReloading = false; return; } if (gun.RemainingAmmoCount < num && (!gunData.hasLimitedAmmo || gun.StoredAmmo >= 1f)) { behaviour.IsTubeReloading = true; ((MonoBehaviour)gun).StartCoroutine(ContinueReloadAfterCurrent(gun)); return; } behaviour.IsTubeReloading = false; if (gun.RemainingAmmoCount >= num) { behaviour.OnFullReloadCompleted(gun); } } private static IEnumerator ContinueReloadAfterCurrent(Gun gun) { float timeout = 5f; while ((Object)(object)gun != (Object)null && gun.Reloading && timeout > 0f) { timeout -= Time.unscaledDeltaTime; yield return null; } yield return null; if ((Object)(object)gun == (Object)null || !((NetworkBehaviour)gun).IsOwner || !gun.Active || !BallisticSniperBehaviour.TryGet((IGear)(object)gun, out var behaviour) || !behaviour.IsTubeReloading || !behaviour.SingleRoundReload || gun.Reloading) { yield break; } ref GunData gunData = ref gun.GunData; if (gun.RemainingAmmoCount >= gunData.magazineSize) { behaviour.IsTubeReloading = false; yield break; } if (gunData.hasLimitedAmmo && gun.StoredAmmo < 1f) { behaviour.IsTubeReloading = false; yield break; } try { gun.Reload(); } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] Continue reload: " + ex.Message)); } behaviour.IsTubeReloading = false; } } } [HarmonyPatch(typeof(Gun), "Update")] internal static class BallisticSniperReloadInterruptHook { [HarmonyPrefix] private static void Prefix(Gun __instance) { try { if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && __instance.Active && BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour) && behaviour.SingleRoundReload && (__instance.Reloading || behaviour.IsTubeReloading) && __instance.RemainingAmmoCount >= 1 && IsFirePressedOrHeld()) { behaviour.InterruptTubeReload(__instance); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] Reload interrupt: " + ex.Message)); } } } private static bool IsFirePressedOrHeld() { //IL_0010: 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) try { if (PlayerInput.Controls == null) { return false; } PlayerActions player = PlayerInput.Controls.Player; InputAction fire = ((PlayerActions)(ref player)).Fire; return fire.IsPressed() || fire.WasPressedThisFrame(); } catch { return false; } } } [HarmonyPatch(typeof(Gun), "GetReloadDuration")] internal static class BallisticSniperReloadDurationHook { [HarmonyPostfix] private static void Postfix(Gun __instance, ref float __result) { try { if (!((Object)(object)__instance == (Object)null) && BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour) && behaviour.SingleRoundReload) { int num = Mathf.Max(__instance.GunData.magazineSize, 1); __result = Mathf.Max(__result / (float)num, 0.12f); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] GetReloadDuration: " + ex.Message)); } } } } [HarmonyPatch(typeof(Gun), "GetSpread")] internal static class BallisticSniperSpreadHook { private const float AdsSpread = 0.04f; private const float AdsMovingSpread = 1.15f; [HarmonyPostfix] private static void Postfix(Gun __instance, ref Vector2 __result) { //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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null || !BallisticSniperBehaviour.TryGet((IGear)(object)__instance, out var behaviour)) { return; } if (behaviour.IsDeadboltActive()) { __result = Vector2.zero; return; } bool isAiming = __instance.IsAiming; if (behaviour.WeaponData.autoTrigger && isAiming) { float autoTriggerAdsSpread = behaviour.WeaponData.autoTriggerAdsSpread; float num = Random.Range(0f, MathF.PI * 2f); float num2 = Random.Range(0f, autoTriggerAdsSpread); __result = new Vector2(Mathf.Cos(num) * num2, Mathf.Sin(num) * num2); } else if (isAiming) { float num3 = (IsMovingWhileScoped(__instance) ? 1.15f : 0.04f); if (num3 <= 0.001f) { __result = Vector2.zero; return; } float num4 = Random.Range(0f, MathF.PI * 2f); float num5 = Random.Range(0f, num3); __result = new Vector2(Mathf.Cos(num4) * num5, Mathf.Sin(num4) * num5); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogDebug((object)("[BallisticSniper] GetSpread: " + ex.Message)); } } } private static bool IsMovingWhileScoped(Gun gun) { //IL_002a: 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) try { Player player = gun.Player; if ((Object)(object)player == (Object)null) { return false; } if (player.IsSprinting || player.Sliding) { return true; } try { Vector3 velocity = player.Velocity; velocity.y = 0f; if (((Vector3)(ref velocity)).sqrMagnitude > 0.122499995f) { return true; } } catch { } } catch { } return false; } } [Serializable] public class MatchGradeRoundsProperty : UpgradeProperty { public Range damageBonus = new Range(0.12f, 0.22f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Damage:", damageBonus, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //IL_0015: 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) IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { float value = damageBonus.GetValue(ref rand, upgrade, default(BoostParams)); val.GunData.damage *= 1f + value; } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { IWeapon val2 = (IWeapon)(object)((prefab is IWeapon) ? prefab : null); if (val2 != null) { val.GunData.damage = val2.GunData.damage; } } } } [BepInPlugin("sparroh.antimaterialrifle", "AntiMaterialRifle", "1.2.0")] [MycoMod(/*Could not decode attribute arguments.*/)] public class SparrohPlugin : BaseUnityPlugin { public const string PluginGUID = "sparroh.antimaterialrifle"; public const string PluginName = "AntiMaterialRifle"; public const string PluginVersion = "1.2.0"; public const int GearId = 87421; public const string GearApiName = "ballistic_sniper"; public const string GearDisplayName = "Anti-Material Rifle"; public const string GearDescription = "Heavy kinetic bolt-action rifle. High single-shot damage, low capacity, and a deliberate single-round reload. Built for long-range elimination."; public const string BaseTypeName = "CartridgeSMG"; internal static ManualLogSource Logger; internal static SparrohPlugin Instance; internal static ConfigEntry GrantAllUpgrades; public static IUpgradable CustomWeaponPrefab; private Harmony _harmony; private bool _gearRegistered; private void Awake() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; GrantAllUpgrades = ((BaseUnityPlugin)this).Config.Bind("Debug", "GrantAllUpgrades", true, "Grant one unlocked inventory instance of each Anti-Material Rifle upgrade on load. Idempotent (tops up to 1). Disable before shipping if players should earn drops normally."); _harmony = new Harmony("sparroh.antimaterialrifle"); _harmony.PatchAll(typeof(GlobalLoadHook)); _harmony.PatchAll(typeof(PlayerDataPersistenceHooks)); _harmony.PatchAll(typeof(BallisticSniperReloadHook)); _harmony.PatchAll(typeof(BallisticSniperReloadInterruptHook)); _harmony.PatchAll(typeof(BallisticSniperReloadDurationHook)); _harmony.PatchAll(typeof(BallisticSniperSpreadHook)); _harmony.PatchAll(typeof(GearSelectionWindowHooks)); PlayerData.AddRegisterUpgradesCallback((Action)RegisterUpgrades); BallisticSniperCombatHooks.Apply(_harmony); SpawnGearHooks.Apply(_harmony); TryRegisterGear("Awake"); if (PlayerData.Instance != null) { RegisterUpgrades(); } Logger.LogInfo((object)"AntiMaterialRifle v1.2.0 loaded."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; Instance = null; } internal void TryRegisterGear(string reason) { if (_gearRegistered) { return; } if ((Object)(object)Global.Instance == (Object)null || Global.Instance.AllGear == null || Global.Instance.AllGear.Length == 0) { Logger.LogDebug((object)("[BallisticSniper] Global.AllGear not ready yet (" + reason + ").")); return; } try { if (WeaponRegistration.TryCreateAndRegister("sparroh.antimaterialrifle", 87421, "ballistic_sniper", "Anti-Material Rifle", "Heavy kinetic bolt-action rifle. High single-shot damage, low capacity, and a deliberate single-round reload. Built for long-range elimination.", "CartridgeSMG", autoUnlock: true, Logger, out CustomWeaponPrefab)) { _gearRegistered = true; Logger.LogInfo((object)("[BallisticSniper] Registered gear 'Anti-Material Rifle' " + string.Format("(api={0}, id={1}) via {2}.", "ballistic_sniper", 87421, reason))); if (PlayerData.Instance != null) { RegisterUpgrades(); } } } catch (Exception arg) { Logger.LogError((object)$"[BallisticSniper] Gear registration failed: {arg}"); } } internal void RegisterUpgrades() { try { if (PlayerData.Instance == null) { Logger.LogDebug((object)"[BallisticSniper] Deferring upgrades — PlayerData.Instance null."); return; } IUpgradable val = ResolveRegisteredGear(); if (val == null) { Logger.LogDebug((object)"[BallisticSniper] Deferring upgrades until gear is registered."); return; } WeaponRegistration.EnsureGearData(val, autoUnlock: true, Logger); if (PlayerData.GetGearData(val) == null && PlayerData.GetGearData(val.Info.ID) == null) { Logger.LogDebug((object)"[BallisticSniper] Deferring upgrades — GearData not bound yet."); return; } CustomWeaponPrefab = val; SniperUpgrades.RegisterAll(Logger); } catch (Exception arg) { Logger.LogError((object)$"[BallisticSniper] Upgrade registration failed: {arg}"); } } internal static IUpgradable ResolveRegisteredGear() { if (CustomWeaponPrefab != null) { return CustomWeaponPrefab; } if (WeaponRegistration.CatalogGear != null) { return WeaponRegistration.CatalogGear; } return WeaponRegistration.FindGearSafe("ballistic_sniper", 87421); } } [HarmonyPatch(typeof(Global), "LoadInstance")] internal static class GlobalLoadHook { [HarmonyPostfix] private static void Postfix() { SparrohPlugin.Instance?.TryRegisterGear("Global.LoadInstance"); } } [HarmonyPatch(typeof(PlayerData), "OnAwake")] internal static class PlayerDataPersistenceHooks { [HarmonyPrefix] private static void Prefix() { SparrohPlugin.Instance?.TryRegisterGear("PlayerData.OnAwake.Prefix"); } [HarmonyPostfix] private static void Postfix() { try { SparrohPlugin.Instance?.TryRegisterGear("PlayerData.OnAwake.Postfix"); SparrohPlugin.Instance?.RegisterUpgrades(); IUpgradable val = SparrohPlugin.ResolveRegisteredGear(); if (val == null) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogWarning((object)"[BallisticSniper] Persistence: gear missing after OnAwake."); } return; } GearData gearData = PlayerData.GetGearData(val); if (gearData == null) { WeaponRegistration.EnsureGearData(val, autoUnlock: true, SparrohPlugin.Logger); gearData = PlayerData.GetGearData(val); } else { gearData.Gear = val; } if (gearData != null) { if (!gearData.IsUnlocked) { gearData.Unlock(); } ManualLogSource logger2 = SparrohPlugin.Logger; if (logger2 != null) { string text = $"[BallisticSniper] Persistence OK: level={gearData.Level} unlocked={gearData.IsUnlocked} "; string text2 = $"equipped={gearData.EquippedUpgradeCount} xp={gearData.LevelXP} "; object arg = PlayerData.HasUpgrades(val); GearInfo info = val.Info; logger2.LogInfo((object)(text + text2 + $"HasUpgrades={arg} HasGrid={((info != null) ? new bool?(info.HasUpgradeGrid) : ((bool?)null))}.")); } } SniperUpgrades.GrantAllInstances(SparrohPlugin.Logger); } catch (Exception arg2) { ManualLogSource logger3 = SparrohPlugin.Logger; if (logger3 != null) { logger3.LogError((object)$"[BallisticSniper] Persistence postfix failed: {arg2}"); } } } } public static class SniperUpgradePatterns { public static HexMap Small() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0027: Expected O, but got Unknown HexMap val = new HexMap(2, 2); Set(val, 0, 0, enabled: true, 4); Set(val, 1, 0, enabled: true, 16); Set(val, 0, 1, enabled: true, 1); return val; } public static HexMap Line() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0028: Expected O, but got Unknown HexMap val = new HexMap(3, 1); Set(val, 0, 0, enabled: true, 4); Set(val, 1, 0, enabled: true, 20); Set(val, 2, 0, enabled: true, 16); return val; } public static HexMap Medium() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_003b: Expected O, but got Unknown HexMap val = new HexMap(3, 2); Set(val, 0, 0, enabled: true, 8); Set(val, 1, 0, enabled: true, 16); Set(val, 2, 0, enabled: true, 0); Set(val, 0, 1, enabled: true, 4); Set(val, 1, 1, enabled: true, 2); return val; } public static HexMap Large() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_003a: Expected O, but got Unknown HexMap val = new HexMap(3, 3); Set(val, 1, 0, enabled: true, 4); Set(val, 0, 1, enabled: true, 2); Set(val, 1, 1, enabled: true, 0); Set(val, 2, 1, enabled: true, 0); Set(val, 1, 2, enabled: true, 1); return val; } public static HexMap Wide() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_0045: Expected O, but got Unknown HexMap val = new HexMap(4, 2); Set(val, 0, 0, enabled: true, 4); Set(val, 1, 0, enabled: true, 8); Set(val, 2, 0, enabled: true, 16); Set(val, 1, 1, enabled: true, 1); Set(val, 2, 1, enabled: true, 1); Set(val, 3, 1, enabled: true, 0); return val; } public static HexMap Exotic() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0059: Expected O, but got Unknown HexMap val = new HexMap(4, 3); Set(val, 1, 0, enabled: true, 4); Set(val, 2, 0, enabled: true, 16); Set(val, 0, 1, enabled: true, 2); Set(val, 1, 1, enabled: true, 0); Set(val, 2, 1, enabled: true, 0); Set(val, 3, 1, enabled: true, 0); Set(val, 1, 2, enabled: true, 1); Set(val, 2, 2, enabled: true, 1); return val; } public static HexMap BoundaryIncursion() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0012: Expected O, but got Unknown HexMap val = new HexMap(1, 1); Set(val, 0, 0, enabled: true, 0); return val; } private static void Set(HexMap map, int x, int y, bool enabled, byte connections) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) ref Node reference = ref map[x, y]; reference.enabled = enabled; reference.connections = (Direction)connections; } } [Serializable] public class SniperProp_Hullbreaker : UpgradeProperty { public Range mult = new Range(1.9f, 2.3f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Shell damage:", mult, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //IL_0022: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.shellDamageMult *= mult.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.shellDamageMult = behaviour.GetPrefabSnapshot().shellDamageMult; } } } [Serializable] public class SniperProp_Subsonic : UpgradeProperty { public Range mult = new Range(2.1f, 2.6f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Full-HP damage:", mult, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //IL_0022: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.fullHpDamageMult *= mult.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.fullHpDamageMult = behaviour.GetPrefabSnapshot().fullHpDamageMult; } } } [Serializable] public class SniperProp_RicochetProtocol : UpgradeProperty { public Range bounces = new Range(2, 3); public Range homing = new Range(8f, 12f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Bounces:", bounces, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams)); yield return StatData.Create("Post-bounce homing:", homing, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //IL_0022: 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_004b: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.bonusBounces += bounces.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.postBounceHoming = Mathf.Max(behaviour.WeaponData.postBounceHoming, homing.GetValue(ref rand, upgrade, default(BoostParams))); IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { val.GunData.maxBounces = Mathf.Max(val.GunData.maxBounces, behaviour.WeaponData.bonusBounces); } } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (!BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { return; } BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.bonusBounces = prefabSnapshot.bonusBounces; behaviour.WeaponData.postBounceHoming = prefabSnapshot.postBounceHoming; IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { IWeapon val2 = (IWeapon)(object)((prefab is IWeapon) ? prefab : null); if (val2 != null) { val.GunData.maxBounces = val2.GunData.maxBounces; } } } } [Serializable] public class SniperProp_Overpressure : UpgradeProperty { public Range charge = new Range(0.55f, 0.7f); public Range dmgMult = new Range(1.85f, 2.2f); public Range moveMult = new Range(0.55f, 0.65f); public Range magPenalty = new Range(2, 2); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Charge time:", charge, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Damage:", dmgMult, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Move while charging:", moveMult, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Magazine penalty:", magPenalty, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams)); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //IL_0027: 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_0048: 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_0069: 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_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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.overpressure = true; behaviour.WeaponData.overpressureChargeDuration = charge.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.overpressureDamageMult = dmgMult.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.overpressureMoveMult = moveMult.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.overpressureMagPenalty = magPenalty.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.overpressure = prefabSnapshot.overpressure; behaviour.WeaponData.overpressureChargeDuration = prefabSnapshot.overpressureChargeDuration; behaviour.WeaponData.overpressureDamageMult = prefabSnapshot.overpressureDamageMult; behaviour.WeaponData.overpressureMoveMult = prefabSnapshot.overpressureMoveMult; behaviour.WeaponData.overpressureMagPenalty = prefabSnapshot.overpressureMagPenalty; } } } [Serializable] public class SniperProp_TwinLink : UpgradeProperty { public Range extra = new Range(1, 1); public Range fenceDmg = new Range(90f, 130f); public Range fenceR = new Range(3.5f, 5f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Extra pellets:", extra, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams)); yield return StatData.Create("Fence damage:", fenceDmg, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //IL_0022: 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_0040: 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_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) //IL_0093: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.extraBulletsPerShot += extra.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.twinLinkFenceDamage = fenceDmg.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.twinLinkFenceRadius = fenceR.GetValue(ref rand, upgrade, default(BoostParams)); IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { val.GunData.bulletsPerShot += extra.GetValue(ref rand, upgrade, default(BoostParams)); } } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (!BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { return; } BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.extraBulletsPerShot = prefabSnapshot.extraBulletsPerShot; behaviour.WeaponData.twinLinkFenceDamage = prefabSnapshot.twinLinkFenceDamage; behaviour.WeaponData.twinLinkFenceRadius = prefabSnapshot.twinLinkFenceRadius; IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { IWeapon val2 = (IWeapon)(object)((prefab is IWeapon) ? prefab : null); if (val2 != null) { val.GunData.bulletsPerShot = val2.GunData.bulletsPerShot; } } } } [Serializable] public class SniperProp_Exhaustion : UpgradeProperty { public Range cd = new Range(3.5f, 4.5f); public Range dur = new Range(3.5f, 5f); public Range strength = new Range(12f, 18f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Mark cooldown:", cd, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Slow duration:", dur, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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_003c: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.exhaustionCooldown = cd.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.exhaustionSlowDuration = dur.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.exhaustionSlowStrength = strength.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.exhaustionCooldown = prefabSnapshot.exhaustionCooldown; behaviour.WeaponData.exhaustionSlowDuration = prefabSnapshot.exhaustionSlowDuration; behaviour.WeaponData.exhaustionSlowStrength = prefabSnapshot.exhaustionSlowStrength; } } } [Serializable] public class SniperProp_Longwatch : UpgradeProperty { public Range aimSec = new Range(3f, 3f); public Range range = new Range(80f, 120f); public Range grav = new Range(0.25f, 0.4f); public Range speed = new Range(1.45f, 1.7f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("ADS hold:", aimSec, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Range:", range, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Bullet speed:", speed, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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_003c: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.longwatchAimSeconds = aimSec.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.longwatchRangeBonus = range.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.longwatchGravityMult = grav.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.longwatchSpeedMult = speed.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.longwatchAimSeconds = prefabSnapshot.longwatchAimSeconds; behaviour.WeaponData.longwatchRangeBonus = prefabSnapshot.longwatchRangeBonus; behaviour.WeaponData.longwatchGravityMult = prefabSnapshot.longwatchGravityMult; behaviour.WeaponData.longwatchSpeedMult = prefabSnapshot.longwatchSpeedMult; } } } [Serializable] public class SniperProp_Scouter : UpgradeProperty { public Range interval = new Range(2.5f, 3f); public Range radius = new Range(45f, 60f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Pulse interval:", interval, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Pulse range:", radius, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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_003c: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.scouterInterval = interval.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.scouterRadius = radius.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.scouterInterval = prefabSnapshot.scouterInterval; behaviour.WeaponData.scouterRadius = prefabSnapshot.scouterRadius; } } } [Serializable] public class SniperProp_Perforator : UpgradeProperty { public Range pierce = new Range(5, 5); public Range falloff = new Range(0.22f, 0.28f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Pierce targets:", pierce, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams)); yield return StatData.Create("Dmg loss/pierce:", falloff, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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_003c: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.pierceTargets = pierce.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.pierceFalloff = falloff.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.pierceTargets = prefabSnapshot.pierceTargets; behaviour.WeaponData.pierceFalloff = prefabSnapshot.pierceFalloff; } } } [Serializable] public class SniperProp_Spotter : UpgradeProperty { public Range radius = new Range(8f, 12f); public Range duration = new Range(6f, 8f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Mark radius:", radius, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Mark duration:", duration, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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_003c: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.spotterRadius = radius.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.spotterDuration = duration.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.spotterRadius = prefabSnapshot.spotterRadius; behaviour.WeaponData.spotterDuration = prefabSnapshot.spotterDuration; } } } [Serializable] public class SniperProp_Deadbolt : UpgradeProperty { public Range duration = new Range(3f, 3.5f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Perfect accuracy:", duration, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.deadboltDuration = duration.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.deadboltDuration = behaviour.GetPrefabSnapshot().deadboltDuration; } } } [Serializable] public class SniperProp_DeathMark : UpgradeProperty { public Range fuse = new Range(1.6f, 2.2f); public Range radius = new Range(5f, 7f); public Range dmgScale = new Range(1.4f, 1.8f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Fuse:", fuse, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Blast radius:", radius, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Blast damage:", dmgScale, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //IL_0027: 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_0048: 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_0069: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.deathMark = true; behaviour.WeaponData.deathMarkFuse = fuse.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.deathMarkRadius = radius.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.deathMarkDamageScale = dmgScale.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.deathMarkHeadshotFuseMult = 0.55f; behaviour.WeaponData.deathMarkStackScale = 0.4f; } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.deathMark = prefabSnapshot.deathMark; behaviour.WeaponData.deathMarkFuse = prefabSnapshot.deathMarkFuse; behaviour.WeaponData.deathMarkRadius = prefabSnapshot.deathMarkRadius; behaviour.WeaponData.deathMarkDamageScale = prefabSnapshot.deathMarkDamageScale; } } } [Serializable] public class SniperProp_AutoTrigger : UpgradeProperty { public Range interval = new Range(0.26f, 0.32f); public Range dmgMult = new Range(0.4f, 0.48f); public Range mag = new Range(8, 10); public Range adsSpread = new Range(0.9f, 1.2f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Fire interval:", interval, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Damage:", dmgMult, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Magazine:", mag, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams)); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //IL_0027: 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_0048: 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_0069: 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_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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.autoTrigger = true; behaviour.WeaponData.autoTriggerFireInterval = interval.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.autoTriggerDamageMult = dmgMult.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.autoTriggerMagBonus = mag.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.autoTriggerAdsSpread = adsSpread.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.autoTrigger = prefabSnapshot.autoTrigger; behaviour.WeaponData.autoTriggerFireInterval = prefabSnapshot.autoTriggerFireInterval; behaviour.WeaponData.autoTriggerDamageMult = prefabSnapshot.autoTriggerDamageMult; behaviour.WeaponData.autoTriggerMagBonus = prefabSnapshot.autoTriggerMagBonus; behaviour.WeaponData.autoTriggerAdsSpread = prefabSnapshot.autoTriggerAdsSpread; } } } [Serializable] public class SniperProp_HighExplosive : UpgradeProperty { public Range dmg = new Range(240f, 320f); public Range radius = new Range(9f, 12f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("C4 damage:", dmg, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("C4 radius:", radius, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //IL_0027: 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_0048: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.highExplosive = true; behaviour.WeaponData.c4Damage = dmg.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.c4Radius = radius.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.c4ThrowForce = 20f; behaviour.WeaponData.c4ArmTime = 0.4f; } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.highExplosive = prefabSnapshot.highExplosive; behaviour.WeaponData.c4Damage = prefabSnapshot.c4Damage; behaviour.WeaponData.c4Radius = prefabSnapshot.c4Radius; } } } [Serializable] public class SniperProp_Clipped : UpgradeProperty { public Range reloadMult = new Range(0.28f, 0.38f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Reload time:", reloadMult, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //IL_0027: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.clipped = true; behaviour.WeaponData.clippedReloadMult = reloadMult.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.singleRoundReload = false; IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { val.GunData.refillAmmoOnReload = true; val.GunData.reloadDuration *= behaviour.WeaponData.clippedReloadMult; } } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (!BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { return; } BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.clipped = prefabSnapshot.clipped; behaviour.WeaponData.clippedReloadMult = prefabSnapshot.clippedReloadMult; behaviour.WeaponData.singleRoundReload = prefabSnapshot.singleRoundReload; IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { IWeapon val2 = (IWeapon)(object)((prefab is IWeapon) ? prefab : null); if (val2 != null) { val.GunData.refillAmmoOnReload = val2.GunData.refillAmmoOnReload; val.GunData.reloadDuration = val2.GunData.reloadDuration; } } } } [Serializable] public class SniperProp_Anchor : UpgradeProperty { public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) yield return StatData.Create("Stationary recoil:", new Range(0f, 0f), upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.anchor = true; behaviour.WeaponData.anchorSpeedThreshold = 0.2f; } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.anchor = behaviour.GetPrefabSnapshot().anchor; } } } [Serializable] public class SniperProp_OneInChamber : UpgradeProperty { public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) yield return StatData.Create("Bonus round after full reload:", new Range(1, 1), upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams)); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.oneInTheChamber = true; } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.oneInTheChamber = behaviour.GetPrefabSnapshot().oneInTheChamber; } } } [Serializable] public class SniperProp_Disrupt : UpgradeProperty { public Range duration = new Range(10f, 10f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Shield disrupt:", duration, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.disruptDuration = duration.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.disruptDuration = behaviour.GetPrefabSnapshot().disruptDuration; } } } [Serializable] public class SniperProp_HeavyGrain : UpgradeProperty { public Range mult = new Range(1.4f, 1.6f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Damage:", mult, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //IL_0015: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { float value = mult.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.heavyGrainDamageMult *= value; IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { val.GunData.damage *= value; } } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (!BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { return; } behaviour.WeaponData.heavyGrainDamageMult = behaviour.GetPrefabSnapshot().heavyGrainDamageMult; IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { IWeapon val2 = (IWeapon)(object)((prefab is IWeapon) ? prefab : null); if (val2 != null) { val.GunData.damage = val2.GunData.damage; } } } } [Serializable] public class SniperProp_ReserveLoad : UpgradeProperty { public Range mult = new Range(1.5f, 1.75f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Reserve ammo:", mult, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //IL_0015: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { float value = mult.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.reserveAmmoMult *= value; IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { val.GunData.ammoCapacity = Mathf.Max(1, Mathf.RoundToInt((float)val.GunData.ammoCapacity * value)); } } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (!BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { return; } behaviour.WeaponData.reserveAmmoMult = behaviour.GetPrefabSnapshot().reserveAmmoMult; IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { IWeapon val2 = (IWeapon)(object)((prefab is IWeapon) ? prefab : null); if (val2 != null) { val.GunData.ammoCapacity = val2.GunData.ammoCapacity; } } } } [Serializable] public class SniperProp_MycoSplash : UpgradeProperty { public Range rot = new Range(10f, 14f); public Range radius = new Range(4f, 5.5f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Rot:", rot, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Splash radius:", radius, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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_003c: 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_005e: Unknown result type (might be due to invalid IL or missing references) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.rotAmount = rot.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.rotSplashRadius = radius.GetValue(ref rand, upgrade, default(BoostParams)); IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { val.GunData.damageEffect = (EffectType)7; val.GunData.damageEffectAmount = Mathf.Max(val.GunData.damageEffectAmount, behaviour.WeaponData.rotAmount); } } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { //IL_0054: 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) if (!BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { return; } BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.rotAmount = prefabSnapshot.rotAmount; behaviour.WeaponData.rotSplashRadius = prefabSnapshot.rotSplashRadius; IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { IWeapon val2 = (IWeapon)(object)((prefab is IWeapon) ? prefab : null); if (val2 != null) { val.GunData.damageEffect = val2.GunData.damageEffect; val.GunData.damageEffectAmount = val2.GunData.damageEffectAmount; } } } } [Serializable] public class SniperProp_WetRounds : UpgradeProperty { public Range water = new Range(10f, 14f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Wet:", water, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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_003e: Unknown result type (might be due to invalid IL or missing references) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.waterAmount = water.GetValue(ref rand, upgrade, default(BoostParams)); IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { val.GunData.damageEffect = (EffectType)9; val.GunData.damageEffectAmount = Mathf.Max(val.GunData.damageEffectAmount, behaviour.WeaponData.waterAmount); } } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { //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) if (!BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { return; } behaviour.WeaponData.waterAmount = behaviour.GetPrefabSnapshot().waterAmount; IWeapon val = (IWeapon)(object)((gear is IWeapon) ? gear : null); if (val != null) { IWeapon val2 = (IWeapon)(object)((prefab is IWeapon) ? prefab : null); if (val2 != null) { val.GunData.damageEffect = val2.GunData.damageEffect; val.GunData.damageEffectAmount = val2.GunData.damageEffectAmount; } } } } [Serializable] public class SniperProp_Reposition : UpgradeProperty { public Range moveBonus = new Range(0.28f, 0.38f); public Range adsMult = new Range(0.5f, 0.6f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Move speed:", moveBonus, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("ADS move:", adsMult, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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_003c: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.repositionMoveBonus = moveBonus.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.repositionAdsMoveMult = adsMult.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.repositionMoveBonus = prefabSnapshot.repositionMoveBonus; behaviour.WeaponData.repositionAdsMoveMult = prefabSnapshot.repositionAdsMoveMult; } } } [Serializable] public class SniperProp_PoweredEcho : UpgradeProperty { public Range delay = new Range(0.18f, 0.28f); public Range dmgScale = new Range(0.75f, 0.95f); public Range shock = new Range(8f, 12f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Echo delay:", delay, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Echo damage:", dmgScale, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Electrocute:", shock, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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_003c: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.echoDelay = delay.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.echoDamageScale = dmgScale.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.echoShockAmount = shock.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.echoDelay = prefabSnapshot.echoDelay; behaviour.WeaponData.echoDamageScale = prefabSnapshot.echoDamageScale; behaviour.WeaponData.echoShockAmount = prefabSnapshot.echoShockAmount; } } } [Serializable] public class SniperProp_TransferRelay : UpgradeProperty { public Range scale = new Range(0.85f, 1.15f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Transferred damage:", scale, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.transferRelayScale = scale.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.transferRelayScale = behaviour.GetPrefabSnapshot().transferRelayScale; } } } [Serializable] public class SniperProp_Synchronize : UpgradeProperty { public Range window = new Range(3f, 3f); public Range mult = new Range(2.6f, 3.2f); public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //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) yield return StatData.Create("Ally window:", window, upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); yield return StatData.Create("Sync damage:", mult, upgrade, ref rand, (OverrideType)2, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { //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_003c: 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) if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.syncWindow = window.GetValue(ref rand, upgrade, default(BoostParams)); behaviour.WeaponData.syncDamageMult = mult.GetValue(ref rand, upgrade, default(BoostParams)); } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { BallisticSniperBehaviour.Data prefabSnapshot = behaviour.GetPrefabSnapshot(); behaviour.WeaponData.syncWindow = prefabSnapshot.syncWindow; behaviour.WeaponData.syncDamageMult = prefabSnapshot.syncDamageMult; } } } [Serializable] public class SniperProp_Overkill : UpgradeProperty { public override IEnumerator GetStatData(Random rand, IUpgradable gear, UpgradeInstance upgrade) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) yield return StatData.Create("Shell overflow carry:", new Range(1f, 1f), upgrade, ref rand, (OverrideType)1, (LabelType)1, default(BoostParams), (Range?)null); } public override void Apply(IGear gear, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.overkill = true; } } public override void Remove(IGear gear, IGear prefab, UpgradeInstance upgrade, ref Random rand) { if (BallisticSniperBehaviour.TryGet(gear, out var behaviour)) { behaviour.WeaponData.overkill = behaviour.GetPrefabSnapshot().overkill; } } } public static class SniperUpgrades { public const int IdHeavyGrain = 87422; public const int IdReserveLoad = 87423; public const int IdHullbreaker = 87424; public const int IdSubsonic = 87425; public const int IdRicochetProtocol = 87426; public const int IdOverpressure = 87427; public const int IdTwinLink = 87428; public const int IdMarkOfExhaustion = 87429; public const int IdLongwatch = 87430; public const int IdScouter = 87431; public const int IdPerforator = 87432; public const int IdSpotter = 87433; public const int IdDeadbolt = 87434; public const int IdDeathMark = 87435; public const int IdAutoTrigger = 87436; public const int IdHighExplosive = 87437; public const int IdClipped = 87438; public const int IdAnchor = 87439; public const int IdOneInTheChamber = 87440; public const int IdDisruptChannel = 87441; public const int IdMycoSplash = 87442; public const int IdWetRounds = 87443; public const int IdReposition = 87444; public const int IdPoweredEcho = 87445; public const int IdTransferRelay = 87446; public const int IdBoundaryIncursion = 87447; public const int IdSynchronize = 87448; public const int IdOverkill = 87449; private const UpgradeFlags FlagStack = (UpgradeFlags)8u; private const UpgradeFlags FlagMissionStack = (UpgradeFlags)16384u; private const UpgradeFlags FlagNone = (UpgradeFlags)0u; private const UpgradeFlags FlagSpatialMissionStack = (UpgradeFlags)540672u; private static bool _registered; public static void RegisterAll(ManualLogSource log = null) { //IL_05c2: Unknown result type (might be due to invalid IL or missing references) //IL_05c8: Expected O, but got Unknown if (_registered) { GrantAllInstances(log); return; } if (PlayerData.Instance == null) { if (log != null) { log.LogDebug((object)"[SniperUpgrades] PlayerData.Instance null — deferring."); } return; } IUpgradable val = SparrohPlugin.ResolveRegisteredGear(); if (val == null) { if (log != null) { log.LogDebug((object)"[SniperUpgrades] Gear not ready — deferring."); } return; } WeaponRegistration.EnsureGearData(val, autoUnlock: true, log); if (PlayerData.GetGearData(val) == null && PlayerData.GetGearData(val.Info.ID) == null) { if (log != null) { log.LogDebug((object)"[SniperUpgrades] GearData missing — deferring."); } return; } int num = 0; if (Reg(val, 87422, "Heavy Grain", "Dense projectiles. Large damage increase.", (Rarity)0, (UpgradeFlags)8, 0, SniperUpgradePatterns.Small(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_HeavyGrain() }, log)) { num++; } if (Reg(val, 87423, "Reserve Load", "Expanded reserve capacity.", (Rarity)0, (UpgradeFlags)8, 0, SniperUpgradePatterns.Small(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_ReserveLoad() }, log)) { num++; } if (Reg(val, 87424, "Hullbreaker", "Massively increased damage to enemy shells and armor plating.", (Rarity)1, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Medium(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Hullbreaker() }, log)) { num++; } if (Reg(val, 87425, "Subsonic", "Devastating damage against full-health targets.", (Rarity)1, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Medium(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Subsonic() }, log)) { num++; } if (Reg(val, 87426, "Ricochet Protocol", "Extra bounces. After bouncing, rounds home aggressively.", (Rarity)2, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Large(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_RicochetProtocol() }, log)) { num++; } if (Reg(val, 87427, "Overpressure", "Shots charge before firing. Huge damage, slower move while charging, smaller mag.", (Rarity)2, (UpgradeFlags)0, 1, SniperUpgradePatterns.Large(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Overpressure() }, log)) { num++; } if (Reg(val, 87428, "Twin Link", "Fires an extra projectile. Hitting two different targets fences them with shock damage.", (Rarity)2, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Wide(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_TwinLink() }, log)) { num++; } if (Reg(val, 87429, "Mark of Exhaustion", "Periodically, the next shot slows the target and cripples tracking.", (Rarity)1, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Medium(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Exhaustion() }, log)) { num++; } if (Reg(val, 87430, "Longwatch", "After 3s continuous ADS: more range, less drop, faster bullets.", (Rarity)1, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Line(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Longwatch() }, log)) { num++; } if (Reg(val, 87431, "Scouter", "While aiming, pulse-highlight threats every few seconds.", (Rarity)0, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Small(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Scouter() }, log)) { num++; } if (Reg(val, 87432, "Perforator", "Pierce up to 5 targets. Damage falls off per pierce.", (Rarity)2, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Large(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Perforator() }, log)) { num++; } if (Reg(val, 87433, "Spotter", "Hits mark the target and nearby enemies for allies.", (Rarity)1, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Medium(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Spotter() }, log)) { num++; } if (Reg(val, 87434, "Deadbolt", "After a kill, perfect accuracy for several seconds (hip and ADS).", (Rarity)1, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Medium(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Deadbolt() }, log)) { num++; } if (Reg(val, 87435, "Death Mark", "Hits apply a delayed explosive mark. Stacks cook harder. Headshots shorten the fuse.", (Rarity)2, (UpgradeFlags)16384, 1, SniperUpgradePatterns.Exotic(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_DeathMark() }, log)) { num++; } if (Reg(val, 87436, "Auto Trigger", "Full-auto precision fire. Higher mag, lower damage, worse ADS bloom.", (Rarity)2, (UpgradeFlags)0, 1, SniperUpgradePatterns.Wide(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_AutoTrigger() }, log)) { num++; } if (Reg(val, 87437, "High Explosive", "Hold reload to throw C4. Hold reload again to detonate a massive blast.", (Rarity)3, (UpgradeFlags)0, 2, SniperUpgradePatterns.Exotic(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_HighExplosive() }, log)) { num++; } if (Reg(val, 87438, "Clipped", "Dramatic reload speed. Uses full magazine reload instead of single-round.", (Rarity)1, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Medium(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Clipped() }, log)) { num++; } if (Reg(val, 87439, "Anchor", "While completely stationary, recoil is fully negated.", (Rarity)1, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Small(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Anchor() }, log)) { num++; } if (Reg(val, 87440, "One in the Chamber", "After a full top-off reload, fire one extra round from empty before reloading.", (Rarity)1, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Small(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_OneInChamber() }, log)) { num++; } if (Reg(val, 87441, "Disrupt Channel", "Hitting a shield blasts it with massive ignore-immunity damage.", (Rarity)2, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Large(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Disrupt() }, log)) { num++; } if (Reg(val, 87442, "Myco Splash", "Applies heavy Rot on hit and splashes Rot to nearby targets.", (Rarity)1, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Medium(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_MycoSplash() }, log)) { num++; } if (Reg(val, 87443, "Wet Rounds", "Applies heavy Wet (Water) buildup on hit.", (Rarity)1, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Small(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_WetRounds() }, log)) { num++; } if (Reg(val, 87444, "Reposition", "Faster movement. Strongly reduced move speed while aiming.", (Rarity)0, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Small(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Reposition() }, log)) { num++; } if (Reg(val, 87445, "Powered Echo", "A second projectile echoes along the same path shortly after, applying Shock.", (Rarity)2, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Large(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_PoweredEcho() }, log)) { num++; } if (Reg(val, 87446, "Transfer Relay", "When damage is negated (immunity), a large ignore-immunity pulse still lands.", (Rarity)3, (UpgradeFlags)0, 2, SniperUpgradePatterns.Exotic(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_TransferRelay() }, log)) { num++; } if (Reg(val, 87447, "Boundary Incursion", "Adds a row or column to the upgrade grid.", (Rarity)4, (UpgradeFlags)540672, -100, SniperUpgradePatterns.BoundaryIncursion(), (UpgradeProperty[])(object)new UpgradeProperty[1] { (UpgradeProperty)new UpgradeProperty_GrowGrid() }, log)) { num++; } if (Reg(val, 87448, "Synchronize", "If an ally damaged the same target within 3 seconds, deal massive bonus damage.", (Rarity)2, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Large(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Synchronize() }, log)) { num++; } if (Reg(val, 87449, "Overkill", "When damage destroys a shell, leftover damage carries over to the layer underneath.", (Rarity)1, (UpgradeFlags)16384, 0, SniperUpgradePatterns.Medium(), (UpgradeProperty[])(object)new UpgradeProperty[1] { new SniperProp_Overkill() }, log)) { num++; } if (num == 28) { _registered = true; if (log != null) { log.LogInfo((object)$"[SniperUpgrades] Registered {num}/{28} upgrades."); } } else { if (log != null) { log.LogWarning((object)$"[SniperUpgrades] Registered {num}/{28} upgrades (partial)."); } if (num > 0) { _registered = true; } } if (_registered) { GrantAllInstances(log); } } public static void GrantAllInstances(ManualLogSource log = null) { if (SparrohPlugin.GrantAllUpgrades != null && !SparrohPlugin.GrantAllUpgrades.Value) { if (log != null) { log.LogDebug((object)"[SniperUpgrades] GrantAllUpgrades disabled via config."); } return; } if (PlayerData.Instance == null) { if (log != null) { log.LogDebug((object)"[SniperUpgrades] GrantAllInstances: PlayerData.Instance null — skip."); } return; } IUpgradable val = SparrohPlugin.ResolveRegisteredGear(); object obj; if (val == null) { obj = null; } else { GearInfo info = val.Info; obj = ((info != null) ? info.Upgrades : null); } if (obj == null) { if (log != null) { log.LogDebug((object)"[SniperUpgrades] GrantAllInstances: gear/upgrades not ready — skip."); } return; } int num = 0; int num2 = 0; int num3 = 0; List upgrades = val.Info.Upgrades; for (int i = 0; i < upgrades.Count; i++) { Upgrade val2 = upgrades[i]; if ((Object)(object)val2 == (Object)null || val2 is SkinUpgrade) { continue; } try { UpgradeInfo upgradeInfo = PlayerData.GetUpgradeInfo(val, val2); if (((upgradeInfo?.Instances != null) ? upgradeInfo.Instances.Count : 0) >= 1) { if (upgradeInfo.Instances != null) { for (int j = 0; j < upgradeInfo.Instances.Count; j++) { UpgradeInstance val3 = upgradeInfo.Instances[j]; if (val3 != null && !val3.IsUnlocked) { val3.Unlock(true); } } } num2++; } else if (UpgradeRegistration.GrantTestInstance(val, val2) != null) { num++; } else { num3++; } } catch (Exception ex) { num3++; if (log != null) { log.LogWarning((object)$"[SniperUpgrades] Grant failed for '{val2.Name}' (id={val2.NumberID}): {ex.Message}"); } } } if (log != null) { log.LogInfo((object)$"[SniperUpgrades] GrantAllInstances: granted={num} alreadyOwned={num2} failed={num3}."); } } private static bool Reg(IUpgradable gear, int id, string name, string description, Rarity rarity, UpgradeFlags flags, int priority, HexMap pattern, UpgradeProperty[] properties, ManualLogSource log) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!UpgradeRegistration.TryCreateGunUpgrade("sparroh.antimaterialrifle", gear, "ballistic_sniper", id, name, description, rarity, properties, pattern, flags, null, log, out var upgrade, priority, (CollectionSource)0)) { if (log != null) { log.LogWarning((object)$"[SniperUpgrades] Failed '{name}' (id={id})."); } return false; } if (log != null) { log.LogInfo((object)$"[SniperUpgrades] + {name} (id={id}, {rarity})."); } return (Object)(object)upgrade != (Object)null; } } internal static class SpawnGearHooks { [ThreadStatic] private static bool RemappingCustomSpawn; [ThreadStatic] private static int RemappedSlot; public static void Apply(Harmony harmony) { //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown //IL_018c: Expected O, but got Unknown Type typeFromHandle = typeof(Player); MethodInfo methodInfo = AccessTools.Method(typeFromHandle, "SpawnGear_Server", new Type[6] { typeof(int), typeof(int), typeof(bool), typeof(bool), typeof(int), typeof(int) }, (Type[])null); if (methodInfo == null) { methodInfo = AccessTools.Method(typeFromHandle, "SpawnGear_Server", new Type[4] { typeof(int), typeof(int), typeof(bool), typeof(bool) }, (Type[])null); } if (methodInfo == null) { foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(typeFromHandle)) { if (declaredMethod.Name == "SpawnGear_Server") { methodInfo = declaredMethod; break; } } } if (methodInfo == null) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)"[BallisticSniper] Could not find Player.SpawnGear_Server to patch."); } return; } MethodInfo methodInfo2 = AccessTools.Method(typeof(SpawnGearHooks), "SpawnGearServerPrefix_6", (Type[])null, (Type[])null); ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 4) { methodInfo2 = AccessTools.Method(typeof(SpawnGearHooks), "SpawnGearServerPrefix_4", (Type[])null, (Type[])null); } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), new HarmonyMethod(typeof(SpawnGearHooks), "SpawnGearServerPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ManualLogSource logger2 = SparrohPlugin.Logger; if (logger2 != null) { logger2.LogInfo((object)("[BallisticSniper] Patched " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name + " " + $"({parameters.Length} params) with {methodInfo2.Name}.")); } } private static void SpawnGearServerPrefix_6(Player __instance, int slot, ref int allGearIndex, bool equip, bool despawn, int skinID, int skinSeed) { TryRemap(slot, ref allGearIndex); } private static void SpawnGearServerPrefix_4(Player __instance, int slot, ref int allGearIndex, bool equip, bool despawn) { TryRemap(slot, ref allGearIndex); } private static void TryRemap(int slot, ref int allGearIndex) { RemappingCustomSpawn = false; if (Global.Instance?.AllGear == null || allGearIndex < 0 || allGearIndex >= Global.Instance.AllGear.Length) { return; } IUpgradable val = Global.Instance.AllGear[allGearIndex]; if (!IsOurCatalogGear(val)) { return; } int num = ResolveBaseIndex(); if (num < 0) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)"[BallisticSniper] Cannot remap spawn — base gun AllGear index unknown. Aborting custom equip to avoid NRE."); } return; } ManualLogSource logger2 = SparrohPlugin.Logger; if (logger2 != null) { string text = $"[BallisticSniper] Remap SpawnGear slot={slot} index {allGearIndex} → base {num} "; GearInfo info = val.Info; logger2.LogInfo((object)(text + "(api=" + ((info != null) ? info.APIName : null) + ").")); } allGearIndex = num; RemappingCustomSpawn = true; RemappedSlot = slot; } private static int ResolveBaseIndex() { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) if (Global.Instance?.AllGear == null) { return -1; } int baseAllGearIndex = WeaponRegistration.BaseAllGearIndex; if (baseAllGearIndex >= 0 && baseAllGearIndex < Global.Instance.AllGear.Length) { IUpgradable val = Global.Instance.AllGear[baseAllGearIndex]; if (val != null && !IsOurCatalogGear(val)) { return baseAllGearIndex; } } if ((Object)(object)WeaponRegistration.BaseGunPrefab != (Object)null) { int num = Array.IndexOf(Global.Instance.AllGear, (IUpgradable)(object)WeaponRegistration.BaseGunPrefab); if (num >= 0) { WeaponRegistration.SetBaseAllGearIndex(num); return num; } } if ((Object)(object)WeaponRegistration.BaseNetworkPrefab != (Object)null) { for (int i = 0; i < Global.Instance.AllGear.Length; i++) { IUpgradable obj = Global.Instance.AllGear[i]; Component val2 = (Component)(object)((obj is Component) ? obj : null); if (val2 != null && (Object)(object)val2.gameObject == (Object)(object)WeaponRegistration.BaseNetworkPrefab && !IsOurCatalogGear(Global.Instance.AllGear[i])) { WeaponRegistration.SetBaseAllGearIndex(i); return i; } } } for (int j = 0; j < Global.Instance.AllGear.Length; j++) { IUpgradable obj2 = Global.Instance.AllGear[j]; Gun val3 = (Gun)(object)((obj2 is Gun) ? obj2 : null); if (val3 != null && (int)val3.GearType == 0 && !IsOurCatalogGear(Global.Instance.AllGear[j])) { WeaponRegistration.SetBaseAllGearIndex(j); return j; } } return -1; } private static void SpawnGearServerPostfix(Player __instance) { if (!RemappingCustomSpawn) { return; } RemappingCustomSpawn = false; int remappedSlot = RemappedSlot; try { StampCustomIdentityOnSlot(__instance, remappedSlot); } catch (Exception arg) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)$"[BallisticSniper] Post-spawn stamp failed: {arg}"); } } } private static void StampCustomIdentityOnSlot(Player player, int slot) { if (((player != null) ? player.Gear : null) == null || slot < 0 || slot >= player.Gear.Length) { return; } IGear val = player.Gear[slot]; if (val == null) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogWarning((object)$"[BallisticSniper] Post-spawn Gear[{slot}] is null — base spawn may have failed."); } return; } IUpgradable val2 = SparrohPlugin.CustomWeaponPrefab ?? WeaponRegistration.CatalogGear ?? WeaponRegistration.FindGearSafe("ballistic_sniper", 87421); if (val2 == null) { ManualLogSource logger2 = SparrohPlugin.Logger; if (logger2 != null) { logger2.LogWarning((object)"[BallisticSniper] Catalog gear missing during stamp."); } } else { RebindLiveGear(val, val2, slot); } } internal static void RebindLiveGear(IGear live, IUpgradable catalog, int slot = -1) { if (live == null || catalog == null) { return; } ((IUpgradable)live).Prefab = catalog; if ((Object)(object)catalog.Info != (Object)null) { TryAssignInfo(live, catalog.Info); } if ((Object)(object)live.gameObject != (Object)null) { BallisticSniperBehaviour ballisticSniperBehaviour = live.gameObject.GetComponent(); if ((Object)(object)ballisticSniperBehaviour == (Object)null) { ballisticSniperBehaviour = live.gameObject.AddComponent(); } BallisticSniperBehaviour ballisticSniperBehaviour2 = null; Component val = (Component)(object)((catalog is Component) ? catalog : null); if (val != null) { ballisticSniperBehaviour2 = val.GetComponent(); } ballisticSniperBehaviour.InitializeAsPrefab(((Object)(object)ballisticSniperBehaviour2 != (Object)null) ? ballisticSniperBehaviour2.Description : "Heavy kinetic bolt-action rifle. High single-shot damage, low capacity, and a deliberate single-round reload. Built for long-range elimination."); if ((Object)(object)ballisticSniperBehaviour2 != (Object)null) { ballisticSniperBehaviour.CopyFrom(ballisticSniperBehaviour2); } } try { live.ApplyUpgrades(); } catch (Exception arg) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)$"[BallisticSniper] ApplyUpgrades after rebind failed (slot={slot}): {arg}"); } } Gun val2 = (Gun)(object)((live is Gun) ? live : null); if (val2 != null) { Gun val3 = (Gun)(object)((catalog is Gun) ? catalog : null); if (val3 != null) { if (val2.GunData.damage < 100f && val3.GunData.damage >= 100f) { WeaponRegistration.ApplyBallisticSniperStats(val2); } if (BallisticSniperBehaviour.TryGet((IGear)(object)val2, out var behaviour)) { behaviour.OnUpgradesApplied(val2); } WeaponRegistration.EnsureProjectileBullet(val2); } } ManualLogSource logger2 = SparrohPlugin.Logger; if (logger2 != null) { string[] obj = new string[6] { string.Format("[BallisticSniper] Rebound Gear[{0}] → {1} ", slot, "ballistic_sniper"), "(Info=", null, null, null, null }; GearInfo info = ((IUpgradable)live).Info; obj[2] = ((info != null) ? info.APIName : null); obj[3] = ", Prefab="; IUpgradable prefab = ((IUpgradable)live).Prefab; IUpgradable obj2 = ((prefab is Component) ? prefab : null); obj[4] = ((obj2 != null) ? ((Object)obj2).name : null); obj[5] = ")."; logger2.LogInfo((object)string.Concat(obj)); } } internal static bool IsOurCatalogGear(IUpgradable gear) { if (gear == null) { return false; } if (gear == SparrohPlugin.CustomWeaponPrefab || gear == WeaponRegistration.CatalogGear) { return true; } if ((Object)(object)gear.Info != (Object)null && gear.Info.APIName == "ballistic_sniper") { return true; } if ((Object)(object)gear.Info != (Object)null && gear.Info.ID == 87421) { return true; } return false; } private static void TryAssignInfo(IGear live, GearInfo info) { Type type = ((object)live).GetType(); while (type != null) { FieldInfo fieldInfo = type.GetField("k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("Info", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null) { fieldInfo.SetValue(live, info); break; } PropertyInfo property = type.GetProperty("Info", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanWrite) { property.SetValue(live, info); break; } type = type.BaseType; } } } [HarmonyPatch(typeof(GearSelectionWindow))] internal static class GearSelectionWindowHooks { [HarmonyPatch("OnOpen")] [HarmonyPrefix] private static void OnOpenPrefix(GearSelectionWindow __instance) { } [HarmonyPatch("OnOpen")] [HarmonyFinalizer] private static Exception OnOpenFinalizer(Exception __exception) { if (__exception is NullReferenceException) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)("[BallisticSniper] GearSelectionWindow.OnOpen NRE (null Gear slot after failed spawn).\n" + __exception)); } return null; } return __exception; } [HarmonyPatch("OnCloseCallback")] [HarmonyPrefix] private static bool OnCloseCallbackPrefix(GearSelectionWindow __instance) { try { return SafeOnCloseCallback(__instance); } catch (Exception arg) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)$"[BallisticSniper] Safe OnCloseCallback failed: {arg}"); } return true; } } [HarmonyPatch("OnCloseCallback")] [HarmonyFinalizer] private static Exception OnCloseFinalizer(Exception __exception) { if (__exception is NullReferenceException) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)("[BallisticSniper] GearSelectionWindow.OnCloseCallback NRE (null Gear[i] after failed spawn).\n" + __exception)); } return null; } return __exception; } private static bool SafeOnCloseCallback(GearSelectionWindow window) { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Invalid comparison between Unknown and I4 //IL_007e: 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_0157: Unknown result type (might be due to invalid IL or missing references) GearSlot[] value = Traverse.Create((object)window).Field("gearEquipSlots").GetValue(); if (value == null) { return true; } if (Traverse.Create(typeof(GearSelectionWindow)).Field("DisableGearSwitching").GetValue()) { return true; } Player localPlayer = Player.LocalPlayer; if (((localPlayer != null) ? localPlayer.Gear : null) == null || Global.Instance?.AllGear == null) { return true; } for (int i = 0; i < value.Length; i++) { GearSlot val = value[i]; if ((Object)(object)val == (Object)null) { continue; } GearType val2 = (GearType)0; IUpgradable val3 = null; try { val2 = val.GearType; val3 = val.Gear; } catch { val3 = Traverse.Create((object)val).Property("Gear", (object[])null).GetValue() ?? Traverse.Create((object)val).Field("gear").GetValue(); val2 = Traverse.Create((object)val).Property("GearType", (object[])null).GetValue(); } if ((int)val2 == 6 || i == 2 || i >= localPlayer.Gear.Length || val3 == null) { continue; } IGear obj2 = localPlayer.Gear[i]; if (((obj2 != null) ? ((IUpgradable)obj2).Prefab : null) == val3 || !SpawnGearHooks.IsOurCatalogGear(val3)) { continue; } int num = WeaponRegistration.BaseAllGearIndex; if (num < 0) { for (int j = 0; j < Global.Instance.AllGear.Length; j++) { IUpgradable obj3 = Global.Instance.AllGear[j]; Gun val4 = (Gun)(object)((obj3 is Gun) ? obj3 : null); if (val4 != null && (int)val4.GearType == 0 && !SpawnGearHooks.IsOurCatalogGear(Global.Instance.AllGear[j])) { num = j; WeaponRegistration.SetBaseAllGearIndex(j); break; } } } if (num < 0) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)$"[BallisticSniper] OnClose: no base index for custom equip slot {i}."); } continue; } ManualLogSource logger2 = SparrohPlugin.Logger; if (logger2 != null) { logger2.LogInfo((object)$"[BallisticSniper] OnClose equip slot {i} custom → SpawnGear baseIndex={num}."); } bool flag = i == 0; localPlayer.SpawnGear_ServerRpc(i, num, flag, true); try { StampAfterClose(localPlayer, i); } catch (Exception ex) { ManualLogSource logger3 = SparrohPlugin.Logger; if (logger3 != null) { logger3.LogWarning((object)("[BallisticSniper] OnClose stamp: " + ex.Message)); } } } return true; } private static void StampAfterClose(Player player, int slot) { if (((player != null) ? player.Gear : null) == null || slot < 0 || slot >= player.Gear.Length) { return; } IGear val = player.Gear[slot]; if (val != null) { IUpgradable val2 = SparrohPlugin.CustomWeaponPrefab ?? WeaponRegistration.CatalogGear ?? WeaponRegistration.FindGearSafe("ballistic_sniper", 87421); if (val2 != null) { SpawnGearHooks.RebindLiveGear(val, val2, slot); } } } } public static class UpgradeRegistration { public static bool TryCreateGunUpgrade(string modGuid, IUpgradable gear, string gearApiName, int upgradeId, string name, string description, Rarity rarity, UpgradeProperty[] properties, HexMap pattern, UpgradeFlags flags, Sprite icon, ManualLogSource log, out Upgrade upgrade, int priority = 0, CollectionSource collectionSource = (CollectionSource)0) { //IL_006b: 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_0077: 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_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_0093: 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) upgrade = null; if (string.IsNullOrEmpty(modGuid)) { if (log != null) { log.LogError((object)"[UpgradeRegistration] modGuid is null/empty."); } return false; } if (properties == null || properties.Length == 0) { if (log != null) { log.LogError((object)"[UpgradeRegistration] properties array is null/empty."); } return false; } if (gear == null) { gear = WeaponRegistration.FindGearSafe(gearApiName); } if (gear == null) { if (log != null) { log.LogError((object)("[UpgradeRegistration] Gear \"" + gearApiName + "\" not found. Register gear first.")); } return false; } CustomUpgradeParams val = CustomUpgradeParams.Create(gear, upgradeId, name, description, rarity, icon); val.flags = flags; val.priority = priority; val.collectionSource = collectionSource; val.upgradeType = (Type)3; val.useDefaultUnlockCost = true; if (pattern != null) { val.pattern = pattern; } try { upgrade = PlayerData.CreateUpgrade(modGuid, val, properties); } catch (Exception arg) { if (log != null) { log.LogError((object)$"[UpgradeRegistration] CreateUpgrade threw: {arg}"); } upgrade = null; return false; } if ((Object)(object)upgrade == (Object)null) { if (log != null) { log.LogError((object)"[UpgradeRegistration] CreateUpgrade returned null."); } return false; } if (pattern != null) { upgrade.SetPattern(pattern); } return true; } public static HexMap CreateSamplePattern() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_002d: 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_0041: Expected O, but got Unknown HexMap val = new HexMap(3, 3); val[0, 0].enabled = true; val[1, 0].enabled = true; val[1, 0].connections = (Direction)36; val[2, 1].enabled = true; return val; } public static UpgradeInstance GrantTestInstance(IUpgradable gear, Upgrade upgrade, bool unlock = true, bool quietUnlock = true, ManualLogSource log = null) { if (gear == null || (Object)(object)upgrade == (Object)null) { if (log != null) { log.LogError((object)"[UpgradeRegistration] GrantTestInstance: gear or upgrade is null."); } return null; } UpgradeInstance val = PlayerData.CollectInstance(gear, upgrade, (UnlockFlags)1); if (val == null) { if (log != null) { log.LogError((object)"[UpgradeRegistration] CollectInstance returned null."); } return null; } if (unlock) { val.Unlock(quietUnlock); } if (log != null) { log.LogInfo((object)("[UpgradeRegistration] Granted test instance of '" + upgrade.Name + "'.")); } return val; } } public static class WeaponRegistration { private static IBullet _cachedProjectilePrefab; private static bool _projectileSearchDone; public static IUpgradable CatalogGear { get; private set; } public static Gun BaseGunPrefab { get; private set; } public static GameObject BaseNetworkPrefab { get; private set; } public static int BaseAllGearIndex { get; private set; } = -1; public static void SetBaseAllGearIndex(int index) { BaseAllGearIndex = index; } public static IUpgradable FindGearSafe(string apiName, int gearId = -1) { if (CatalogGear != null && (Object)(object)CatalogGear.Info != (Object)null && (CatalogGear.Info.APIName == apiName || (gearId >= 0 && CatalogGear.Info.ID == gearId))) { return CatalogGear; } if (Global.Instance?.AllGear != null) { IUpgradable[] allGear = Global.Instance.AllGear; foreach (IUpgradable val in allGear) { if (!((Object)(object)((val != null) ? val.Info : null) == (Object)null)) { if (!string.IsNullOrEmpty(apiName) && val.Info.APIName == apiName) { return val; } if (gearId >= 0 && val.Info.ID == gearId) { return val; } } } } try { if (PlayerData.Instance != null && !string.IsNullOrEmpty(apiName)) { IUpgradable val2 = PlayerData.FindGear(apiName); if (val2 != null) { return val2; } } } catch { } return null; } public static bool TryCreateAndRegister(string modGuid, int gearId, string apiName, string displayName, string description, string baseTypeName, bool autoUnlock, ManualLogSource log, out IUpgradable registeredGear) { registeredGear = null; if (string.IsNullOrEmpty(modGuid) || string.IsNullOrEmpty(apiName)) { if (log != null) { log.LogError((object)"[WeaponRegistration] modGuid / apiName required."); } return false; } if ((Object)(object)Global.Instance == (Object)null || Global.Instance.AllGear == null) { if (log != null) { log.LogError((object)"[WeaponRegistration] Global.Instance.AllGear is null."); } return false; } IUpgradable val = FindGearSafe(apiName, gearId); if (val != null) { CatalogGear = val; registeredGear = val; TryRefreshBaseIndex(baseTypeName, log); RegisterGearTextBlocks(apiName, displayName, "Primary Weapon", description, log); if ((Object)(object)val.Info != (Object)null) { TrySetMember(val.Info, "_localizedName", displayName); } EnsureGearData(val, autoUnlock, log); if (log != null) { log.LogInfo((object)("[WeaponRegistration] Gear '" + apiName + "' already present — reusing.")); } return true; } if (!TryFindBaseGun(baseTypeName, log, out var gear, out var go, out var allGearIndex)) { return false; } BaseGunPrefab = gear; BaseNetworkPrefab = go; BaseAllGearIndex = allGearIndex; if (log != null) { log.LogInfo((object)$"[WeaponRegistration] Base spawn prefab index={allGearIndex} type={((object)gear).GetType().Name}."); } GameObject val2 = Object.Instantiate(go); ((Object)val2).name = "[" + modGuid + "] " + displayName; val2.SetActive(false); Object.DontDestroyOnLoad((Object)(object)val2); NetworkObject val3 = default(NetworkObject); if (val2.TryGetComponent(ref val3)) { Object.DestroyImmediate((Object)(object)val3); if (log != null) { log.LogDebug((object)"[WeaponRegistration] Stripped NetworkObject from catalog clone (spawn uses base prefab)."); } } Gun component = val2.GetComponent(); if ((Object)(object)component == (Object)null) { if (log != null) { log.LogError((object)"[WeaponRegistration] Clone lost Gun component."); } Object.Destroy((Object)(object)val2); return false; } GearInfo val4 = CreateGearInfo(gearId, apiName, displayName, description, gear.Info, autoUnlock, log); if ((Object)(object)val4 == (Object)null) { Object.Destroy((Object)(object)val2); return false; } if (!TryAssignGearInfo(component, val4, log)) { Object.Destroy((Object)(object)val2); return false; } if ((Object)(object)component.Info == (Object)null || component.Info.ID != gearId || component.Info.APIName != apiName) { if (log != null) { log.LogError((object)("[WeaponRegistration] GearInfo verification failed (Info=" + (((Object)(object)component.Info == (Object)null) ? "null" : (component.Info.APIName + "/" + component.Info.ID)) + ").")); } Object.Destroy((Object)(object)val2); return false; } BallisticSniperBehaviour ballisticSniperBehaviour = val2.GetComponent(); if ((Object)(object)ballisticSniperBehaviour == (Object)null) { ballisticSniperBehaviour = val2.AddComponent(); } ballisticSniperBehaviour.InitializeAsPrefab(description); ApplyBallisticSniperStats(component, log); if (!InjectIntoAllGear((IUpgradable)(object)component, log)) { Object.Destroy((Object)(object)val2); return false; } InjectIntoPlayerData((IUpgradable)(object)component, autoUnlock, log); ModelImportHooks.ApplyPlaceholderHooks(val2, log); CatalogGear = (IUpgradable)(object)component; registeredGear = (IUpgradable)(object)component; return true; } public static void EnsureProjectileBullet(Gun gun, ManualLogSource log = null) { if ((Object)(object)gun == (Object)null) { return; } try { object? obj = typeof(Gun).GetField("bulletPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(gun); IBullet val = (IBullet)((obj is IBullet) ? obj : null); if (val != null && IsSafeBallisticProjectile(val)) { return; } if (_projectileSearchDone && !IsSafeBallisticProjectile(_cachedProjectilePrefab)) { _projectileSearchDone = false; _cachedProjectilePrefab = null; } if (!_projectileSearchDone) { _projectileSearchDone = true; _cachedProjectilePrefab = FindSimpleProjectilePrefab(log); } if (_cachedProjectilePrefab == null) { if (log != null) { log.LogWarning((object)"[WeaponRegistration] No safe SimpleProjectileBullet prefab found — keeping rail bullet."); } ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogWarning((object)"[BallisticSniper] No safe SimpleProjectileBullet prefab found — keeping rail bullet."); } return; } gun.SetBullet(_cachedProjectilePrefab, gun.CreateBulletPool()); try { gun.SetBulletPrefabOnObservers_Owner(); } catch { } if (log != null) { log.LogInfo((object)("[WeaponRegistration] Swapped bullet → " + ((object)_cachedProjectilePrefab).GetType().Name + " (" + ((Object)_cachedProjectilePrefab.gameObject).name + ").")); } ManualLogSource logger2 = SparrohPlugin.Logger; if (logger2 != null) { logger2.LogInfo((object)("[BallisticSniper] Projectile bullet set: " + ((object)_cachedProjectilePrefab).GetType().Name + ".")); } } catch (Exception ex) { if (log != null) { log.LogWarning((object)("[WeaponRegistration] EnsureProjectileBullet failed: " + ex.Message)); } ManualLogSource logger3 = SparrohPlugin.Logger; if (logger3 != null) { logger3.LogWarning((object)("[BallisticSniper] EnsureProjectileBullet: " + ex.Message)); } } } private static IBullet FindSimpleProjectilePrefab(ManualLogSource log) { IBullet val = FindProjectileFromAllGear(log); if (val != null) { return val; } IBullet val2 = FindProjectileFromSyncedObjects(log); if (val2 != null) { return val2; } IBullet val3 = FindProjectileFromResources(log); if (val3 != null) { return val3; } if (log != null) { log.LogWarning((object)"[WeaponRegistration] No safe SimpleProjectileBullet found (AllGear + syncedObjects + Resources)."); } ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogWarning((object)"[BallisticSniper] No safe SimpleProjectileBullet found after full scan."); } return null; } private static IBullet FindProjectileFromAllGear(ManualLogSource log) { if (Global.Instance?.AllGear == null) { return null; } string[] array = new string[4] { "BounceShotgun", "BurrowerGun", "Bruiser", "Scattergun" }; IBullet val = null; IBullet val2 = null; IUpgradable[] allGear = Global.Instance.AllGear; for (int i = 0; i < 2; i++) { foreach (IUpgradable obj in allGear) { Gun val3 = (Gun)(object)((obj is Gun) ? obj : null); if (val3 == null || (Object)(object)val3 == (Object)null || IsOurCatalogOrSmG(val3)) { continue; } if (i == 0) { string name = ((object)val3).GetType().Name; bool flag = false; for (int k = 0; k < array.Length; k++) { if (string.Equals(name, array[k], StringComparison.Ordinal)) { flag = true; break; } } if (!flag) { continue; } } IBullet val4 = ReadBulletPrefab(val3); if (!IsSafeBallisticProjectile(val4)) { continue; } Type type = ((object)val4).GetType(); if (log != null) { log.LogInfo((object)("[WeaponRegistration] AllGear candidate: gun=" + ((object)val3).GetType().Name + " bullet=" + type.Name + ".")); } if (type == typeof(SimpleProjectileBullet)) { if (i == 0) { return val4; } if (val == null) { val = val4; } } else { if (i == 0) { return val4; } if (val2 == null) { val2 = val4; } } } } return val ?? val2; } private static IBullet FindProjectileFromSyncedObjects(ManualLogSource log) { try { if ((Object)(object)Global.Instance == (Object)null) { return null; } if (!(typeof(Global).GetField("syncedObjects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(Global.Instance) is GameObject[] array) || array.Length == 0) { return null; } IBullet val = null; IBullet val2 = null; for (int i = 0; i < array.Length; i++) { GameObject val3 = array[i]; if ((Object)(object)val3 == (Object)null) { continue; } IBullet val4 = val3.GetComponent() ?? val3.GetComponentInChildren(true); if (IsSafeBallisticProjectile(val4)) { Type type = ((object)val4).GetType(); if (log != null) { log.LogInfo((object)$"[WeaponRegistration] syncedObjects[{i}] candidate: {((Object)val3).name} → {type.Name}."); } if (type == typeof(SimpleProjectileBullet)) { return val4; } if (val == null && type == typeof(SimpleProjectileBullet)) { val = val4; } else if (val2 == null) { val2 = val4; } } } return val ?? val2; } catch (Exception ex) { if (log != null) { log.LogDebug((object)("[WeaponRegistration] syncedObjects scan: " + ex.Message)); } return null; } } private static IBullet FindProjectileFromResources(ManualLogSource log) { //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_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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_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) try { SimpleProjectileBullet[] array = Resources.FindObjectsOfTypeAll(); if (array == null || array.Length == 0) { return null; } IBullet val = null; IBullet val2 = null; foreach (SimpleProjectileBullet val3 in array) { if ((Object)(object)val3 == (Object)null) { continue; } Scene scene; try { scene = ((Component)val3).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { scene = ((Component)val3).gameObject.scene; if (((Scene)(ref scene)).isLoaded && (val != null || val2 != null)) { continue; } } } catch { } if (!IsSafeBallisticProjectile((IBullet)(object)val3)) { continue; } if (((object)val3).GetType() == typeof(SimpleProjectileBullet)) { if (log != null) { log.LogInfo((object)("[WeaponRegistration] Resources exact: " + ((Object)((Component)val3).gameObject).name + ".")); } try { scene = ((Component)val3).gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { goto IL_00e9; } scene = ((Component)val3).gameObject.scene; if (!((Scene)(ref scene)).isLoaded) { goto IL_00e9; } goto end_IL_00bb; IL_00e9: return (IBullet)(object)val3; end_IL_00bb:; } catch { return (IBullet)(object)val3; } if (val == null) { val = (IBullet)(object)val3; } } else if (val2 == null) { val2 = (IBullet)(object)val3; } } if (val != null) { if (log != null) { log.LogInfo((object)("[WeaponRegistration] Resources fallback exact: " + ((Object)val.gameObject).name + ".")); } return val; } if (val2 != null) { if (log != null) { log.LogInfo((object)("[WeaponRegistration] Resources allowlisted: " + ((object)val2).GetType().Name + " (" + ((Object)val2.gameObject).name + ").")); } return val2; } } catch (Exception ex) { if (log != null) { log.LogDebug((object)("[WeaponRegistration] Resources scan: " + ex.Message)); } } return null; } private static bool IsSafeBallisticProjectile(IBullet bullet) { if (bullet == null) { return false; } if (!(bullet is SimpleProjectileBullet)) { return false; } Type type = ((object)bullet).GetType(); if (type == typeof(SimpleProjectileBullet)) { return true; } if (type == typeof(BurrowerBullet)) { return true; } return false; } private static bool IsOurCatalogOrSmG(Gun g) { if ((Object)(object)g == (Object)null) { return true; } if (g is CartridgeSMG) { return true; } if ((Object)(object)g.Info != (Object)null && (g.Info.APIName == "ballistic_sniper" || g.Info.ID == 87421)) { return true; } return false; } private static IBullet ReadBulletPrefab(Gun gun) { try { object? obj = typeof(Gun).GetField("_bulletPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(gun); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (val != null && (Object)(object)val != (Object)null) { IBullet val2 = val.GetComponent() ?? val.GetComponentInChildren(true); if (val2 != null) { return val2; } } object? obj2 = typeof(Gun).GetField("bulletPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(gun); IBullet val3 = (IBullet)((obj2 is IBullet) ? obj2 : null); if (val3 != null) { return val3; } } catch { } return null; } public static void ApplyBallisticSniperStats(Gun gun, ManualLogSource log = null) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)gun == (Object)null)) { ref GunData gunData = ref gun.GunData; gunData.damage = 145f; gunData.damageEffect = (EffectType)0; gunData.damageEffectAmount = 0f; gunData.fireInterval = 1.25f; gunData.fireAnimationSpeedMultiplier = Mathf.Max(gunData.fireAnimationSpeedMultiplier, 0.35f); gunData.automatic = 0; gunData.bulletsPerShot = 1; gunData.burstSize = 1; gunData.burstFireInterval = 0f; gunData.useAmmoOnFire = 1; gunData.doesEachBulletInShotRemoveAmmo = 0; gunData.doesEachBulletInShotTriggerEffects = false; gunData.magazineSize = 5; gunData.hasLimitedAmmo = true; gunData.ammoCapacity = 20; gunData.ammoCollectMultiplier = Mathf.Max(gunData.ammoCollectMultiplier, 0.75f); gunData.storedAmmoCollectMultiplier = Mathf.Max(gunData.storedAmmoCollectMultiplier, 0.75f); gunData.ammoGenerationEfficiency = 0f; gunData.useAmmoWhileFiringInterval = 0f; gunData.refillAmmoOnReload = false; gunData.reloadDuration = 3.1f; gunData.autoReloadWhenEmpty = true; gunData.bulletSpeed = 220f; gunData.bulletGravity = 9.5f; gunData.maxBounces = 0; gunData.bulletMagnetismSurface = 0f; gunData.bulletMagnetismTarget = 0f; gunData.rangeData.falloffStartDistance = 140f; gunData.rangeData.falloffEndDistance = 200f; gunData.rangeData.maxDamageRange = 250f; gunData.rangeData.maxFalloffDamageMultiplier = 0.65f; gunData.hitForce = Mathf.Max(gunData.hitForce * 2.5f, 28f); gunData.hitVFXSize = Mathf.Max(gunData.hitVFXSize, 1.4f); gunData.spreadData.spreadType = (SpreadType)0; gunData.spreadData.spreadSize = new Vector2(3.8f, 3.8f); gunData.firstShotSpreadMultiplier = 1f; gunData.recoilData.recoilX = new Vector2(0.05f, 0.18f); gunData.recoilData.recoilY = new Vector2(2.8f, 3.6f); gunData.recoilData.recoilZ = new Vector2(0.1f, 0.35f); gunData.recoilData.maxRecoilZ = 2f; gunData.recoilData.translateZ = new Vector2(0.04f, 0.08f); gunData.recoilData.maxTranslateZ = 0.12f; gunData.recoilData.aimTranslateMultiplier = 0.85f; gunData.recoilData.recoilSpeed = Mathf.Max(gunData.recoilData.recoilSpeed, 18f); gunData.recoilData.recoilRecoverySpeed = 6f; gunData.recoilData.translateSpeed = Mathf.Max(gunData.recoilData.translateSpeed, 14f); gunData.recoilData.translateRecoverySpeed = 5f; gunData.recoilData.recoilTargetDecaySpeed = 4f; gunData.recoilData.aimRecoilMultiplier = new Vector3(0.55f, 0.7f, 0.55f); gunData.bulletShakeTranslation = Mathf.Max(gunData.bulletShakeTranslation, 0.08f); gunData.bulletShakeRotation = Mathf.Max(gunData.bulletShakeRotation, 0.6f); gunData.chargeData.duration = 0f; gunData.chargeData.coolDownSpeed = 0f; gunData.chargeData.fireWhenFullyCharged = false; gunData.chargeData.fireOnRelease = false; gunData.chargeData.canFireWhileCharging = false; gunData.chargeData.time = 0f; gunData.fireConstraints.canFireWhileSprinting = (ActionFireMode)2; gunData.fireConstraints.canFireWhileSliding = (ActionFireMode)2; gunData.fireConstraints.canAimWhileSliding = (ActionFireMode)0; gunData.fireConstraints.canAimWhileReloading = false; gunData.fireConstraints.canReloadWhileSprinting = (ActionFireMode)2; gun.IsAimEnabled = true; gun.AimFOV = 28f; TrySetAimTransitionDuration(gun, 0.55f); if (log != null) { log.LogInfo((object)($"[WeaponRegistration] Applied ballistic sniper stats: dmg={gunData.damage}, " + $"rpm≈{60f / gunData.fireInterval:0}, mag={gunData.magazineSize}, reserve={gunData.ammoCapacity}, " + $"reload={gunData.reloadDuration}s, speed={gunData.bulletSpeed}, grav={gunData.bulletGravity}.")); } } } private static void TrySetAimTransitionDuration(Gun gun, float duration) { FieldInfo field = typeof(Gun).GetField("aimTransitionDuration", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(float)) { field.SetValue(gun, duration); } } private static void TryRefreshBaseIndex(string preferredTypeName, ManualLogSource log) { if (Global.Instance?.AllGear == null) { return; } if ((Object)(object)BaseGunPrefab != (Object)null) { int num = Array.IndexOf(Global.Instance.AllGear, (IUpgradable)(object)BaseGunPrefab); if (num >= 0) { BaseAllGearIndex = num; return; } } if (TryFindBaseGun(preferredTypeName, log, out var gear, out var go, out var allGearIndex)) { BaseGunPrefab = gear; BaseNetworkPrefab = go; BaseAllGearIndex = allGearIndex; } } private static bool TryFindBaseGun(string preferredTypeName, ManualLogSource log, out Gun gear, out GameObject go, out int allGearIndex) { //IL_0037: 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_0046: Invalid comparison between Unknown and I4 //IL_00ca: Unknown result type (might be due to invalid IL or missing references) gear = null; go = null; allGearIndex = -1; Gun val = null; GameObject val2 = null; int num = -1; IUpgradable[] allGear = Global.Instance.AllGear; for (int i = 0; i < allGear.Length; i++) { IUpgradable obj = allGear[i]; Gun val3 = (Gun)(object)((obj is Gun) ? obj : null); if (val3 == null) { continue; } if ((int)val3.GearType != 0 && (int)val3.GearType != -1) { if ((Object)(object)val == (Object)null) { val = val3; val2 = ((Component)val3).gameObject; num = i; } continue; } GameObject gameObject = ((Component)val3).gameObject; string name = ((object)val3).GetType().Name; if (!string.IsNullOrEmpty(preferredTypeName) && string.Equals(name, preferredTypeName, StringComparison.Ordinal)) { gear = val3; go = gameObject; allGearIndex = i; if (log != null) { log.LogInfo((object)$"[WeaponRegistration] Base gun: {name} ({((Object)gameObject).name}) index={i}."); } return true; } if ((Object)(object)val == (Object)null || (int)val.GearType != 0) { val = val3; val2 = gameObject; num = i; } } if ((Object)(object)val != (Object)null) { gear = val; go = val2; allGearIndex = num; if (log != null) { log.LogWarning((object)("[WeaponRegistration] '" + preferredTypeName + "' not found — " + $"falling back to {((object)val).GetType().Name} ({((Object)val2).name}) index={num}.")); } return true; } if (log != null) { log.LogError((object)"[WeaponRegistration] No Gun found in Global.AllGear."); } return false; } private static GearInfo CreateGearInfo(int gearId, string apiName, string displayName, string description, GearInfo template, bool autoUnlock, ManualLogSource log) { //IL_014b: Unknown result type (might be due to invalid IL or missing references) GearInfo val = ScriptableObject.CreateInstance(); ((Object)val).name = apiName; TrySetMember(val, "ID", gearId); TrySetMember(val, "k__BackingField", gearId); TrySetMember(val, "_name", apiName); TrySetMember(val, "id", gearId); RegisterGearTextBlocks(apiName, displayName, "Primary Weapon", description, log); TrySetMember(val, "_localizedName", displayName); if ((Object)(object)template != (Object)null) { object member = GetMember(template, "grid"); if (member != null) { TrySetMember(val, "grid", member); } if ((Object)(object)template.Icon != (Object)null) { TrySetMember(val, "k__BackingField", template.Icon); } if (template.UnlockCost != null) { val.UnlockCost = template.UnlockCost; } val.CanGainXP = template.CanGainXP; val.XPGainMultilier = template.XPGainMultilier; val.MaxLevel = template.MaxLevel; val.MinUnlockLevel = 0; val.HideWhenNotCollected = false; } else if ((Object)(object)Global.Instance != (Object)null && (Object)(object)Global.Instance.WarningIcon != (Object)null) { TrySetMember(val, "k__BackingField", Global.Instance.WarningIcon); } val.UnlockAutomatically = autoUnlock; val.UnlockState = (UnlockState)(autoUnlock ? 2 : 0); TrySetMember(val, "upgrades", Array.Empty()); TrySetMember(val, "skins", Array.Empty()); TrySetMember(val, "combinedUpgradeList", new List()); TrySetMember(val, "defaultSkin", null); TrySetMember(val, "k__BackingField", null); _ = val.Upgrades; if (!val.HasUpgradeGrid && log != null) { log.LogWarning((object)"[WeaponRegistration] GearInfo has no upgrade grid — UI may hide hex inventory."); } if (log != null) { log.LogDebug((object)$"[WeaponRegistration] GearInfo created id={gearId} api={apiName} name={displayName}"); } return val; } private static void RegisterGearTextBlocks(string apiName, string displayName, string typeName, string description, ManualLogSource log) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if (string.IsNullOrEmpty(apiName)) { return; } try { TextBlockGroup val = new TextBlockGroup(0); val.blocks = (TextBlock[])(object)new TextBlock[3] { new TextBlock(displayName ?? apiName, apiName), new TextBlock(typeName ?? "Primary Weapon", apiName), new TextBlock(description ?? string.Empty, apiName) }; TextBlockGroup value = val; TextBlocks.strings[apiName] = value; if (log != null) { log.LogDebug((object)("[WeaponRegistration] Registered TextBlocks for '" + apiName + "' → '" + displayName + "'.")); } } catch (Exception ex) { if (log != null) { log.LogWarning((object)("[WeaponRegistration] TextBlocks registration failed: " + ex.Message)); } } } private static bool TryAssignGearInfo(Gun gear, GearInfo info, ManualLogSource log) { if (TrySetMember(gear, "k__BackingField", info) || TrySetMember(gear, "Info", info)) { return true; } if (log != null) { log.LogError((object)"[WeaponRegistration] Failed to assign GearInfo onto clone (reflection)."); } return false; } private static bool InjectIntoAllGear(IUpgradable gear, ManualLogSource log) { IUpgradable[] allGear = Global.Instance.AllGear; for (int i = 0; i < allGear.Length; i++) { if (allGear[i] != null && (Object)(object)allGear[i].Info != (Object)null && allGear[i].Info.ID == gear.Info.ID) { if (log != null) { log.LogWarning((object)$"[WeaponRegistration] AllGear already contains id={gear.Info.ID}."); } return true; } } IUpgradable[] array = (IUpgradable[])(object)new IUpgradable[allGear.Length + 1]; Array.Copy(allGear, array, allGear.Length); array[allGear.Length] = gear; Global.Instance.AllGear = array; Component val = (Component)(object)((gear is Component) ? gear : null); if (val != null) { TryAppendObjectArray(Global.Instance, "_allGear", (Object)(object)val.gameObject); } if (log != null) { log.LogInfo((object)$"[WeaponRegistration] Injected into AllGear (count={array.Length})."); } return true; } private static void InjectIntoPlayerData(IUpgradable gear, bool autoUnlock, ManualLogSource log) { EnsureGearData(gear, autoUnlock, log); } public static void EnsureGearData(IUpgradable gear, bool autoUnlock, ManualLogSource log) { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown if ((Object)(object)((gear != null) ? gear.Info : null) == (Object)null) { return; } if (PlayerData.Instance == null) { if (log != null) { log.LogWarning((object)"[WeaponRegistration] PlayerData.Instance null — gear may appear on next InitializeCollectedGear."); } return; } GearData gearData = PlayerData.GetGearData(gear); if (gearData != null) { gearData.Gear = gear; if (autoUnlock && !gearData.IsUnlocked) { gearData.Unlock(); } if (log != null) { log.LogDebug((object)"[WeaponRegistration] Bound existing GearData entry."); } return; } gearData = PlayerData.GetGearData(gear.Info.ID); if (gearData != null) { gearData.Gear = gear; if (autoUnlock && !gearData.IsUnlocked) { gearData.Unlock(); } if (log != null) { log.LogInfo((object)"[WeaponRegistration] Re-bound GearData by id after load."); } } else if (typeof(PlayerData).GetField("collectedGear", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(PlayerData.Instance) is IDictionary dictionary) { GearData val = new GearData(gear, (UnlockState)(autoUnlock ? 2 : 0)); dictionary[gear.Info.ID] = val; if (autoUnlock) { val.Unlock(); } if (log != null) { log.LogInfo((object)"[WeaponRegistration] Added GearData to collectedGear."); } } else if (log != null) { log.LogWarning((object)"[WeaponRegistration] Could not inject GearData directly."); } } private static bool TrySetMember(object target, string name, object value) { if (target == null) { return false; } Type type = target.GetType(); PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanWrite) { property.SetValue(target, value); return true; } FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(target, value); return true; } Type baseType = type.BaseType; while (baseType != null) { field = baseType.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(target, value); return true; } property = baseType.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanWrite) { property.SetValue(target, value); return true; } baseType = baseType.BaseType; } return false; } private static object GetMember(object target, string name) { if (target == null) { return null; } Type type = target.GetType(); object obj = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(target); if (obj == null) { PropertyInfo? property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if ((object)property == null) { return null; } obj = property.GetValue(target); } return obj; } private static void TryAppendObjectArray(object host, string fieldName, Object item) { FieldInfo field = host.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field == null) && field.GetValue(host) is Array array) { Type elementType = array.GetType().GetElementType(); if (!(elementType == null) && elementType.IsInstanceOfType(item)) { Array array2 = Array.CreateInstance(elementType, array.Length + 1); Array.Copy(array, array2, array.Length); array2.SetValue(item, array.Length); field.SetValue(host, array2); } } } } public static class ModelImportHooks { public static void ApplyPlaceholderHooks(GameObject gearRoot, ManualLogSource log) { if (log != null) { log.LogDebug((object)"[ModelImportHooks] Placeholder only — using vanilla CartridgeSMG visuals."); } } public static bool ApplyMesh(GameObject root, Mesh mesh, Material material = null) { if ((Object)(object)root == (Object)null || (Object)(object)mesh == (Object)null) { return false; } MeshFilter componentInChildren = root.GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { return false; } componentInChildren.sharedMesh = mesh; MeshRenderer val = default(MeshRenderer); if ((Object)(object)material != (Object)null && ((Component)componentInChildren).TryGetComponent(ref val)) { ((Renderer)val).sharedMaterial = material; } return true; } public static bool TrySetBulletPrefab(Gun gun, GameObject bulletPrefab) { if ((Object)(object)gun == (Object)null || (Object)(object)bulletPrefab == (Object)null) { return false; } FieldInfo fieldInfo = typeof(Gun).GetField("_bulletPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(Gun).GetField("bulletPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo == null) { return false; } fieldInfo.SetValue(gun, bulletPrefab); return true; } } namespace AntiMaterialRifle { public static class MyPluginInfo { public const string PLUGIN_GUID = "AntiMaterialRifle"; public const string PLUGIN_NAME = "AntiMaterialRifle"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }