using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using OtherLoader;
using UnityEngine;
using UnityEngine.Rendering;
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace printerjoe.ServiceWithASmile;
[BepInPlugin("printerjoe.ServiceWithASmile", "ServiceWithASmile", "1.0.1")]
[BepInProcess("h3vr.exe")]
[Description("Built with MeatKit")]
[BepInDependency("h3vr.otherloader", "1.3.0")]
public class ServiceWithASmilePlugin : BaseUnityPlugin
{
private static readonly string BasePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
internal static ManualLogSource Logger;
private void Awake()
{
Logger = ((BaseUnityPlugin)this).Logger;
LoadAssets();
}
private void LoadAssets()
{
Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "printerjoe.ServiceWithASmile");
OtherLoader.RegisterDirectLoad(BasePath, "printerjoe.ServiceWithASmile", "", "", "servicewithasmile", "");
}
}
public class KeyRingController : MonoBehaviour
{
public MonoBehaviour Firearm;
public Rigidbody[] Slides;
public Rigidbody[] Swings;
public Collider[] KeyColliders;
public Collider[] RingColliders;
public Collider[] SolidColliders;
public bool HangStraightDownInQuickbelt = true;
public float MaxAngularVelocity = 12f;
private Quaternion[] _slideRest;
private Quaternion[] _swingRest;
private Vector3[] _swingRestPos;
private HingeJoint[] _hinges;
private bool _frozen;
private FieldInfo _slotField;
private PropertyInfo _slotProp;
private bool _slotLookedUp;
private float[] _poseAngle;
private const float RePoseThreshold = 3f;
private void ApplyCollisionFilter()
{
Collider[] keyColliders = KeyColliders;
foreach (Collider val in keyColliders)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
Collider[] ringColliders = RingColliders;
foreach (Collider val2 in ringColliders)
{
if ((Object)(object)val2 != (Object)null)
{
Physics.IgnoreCollision(val, val2, true);
}
}
Collider[] solidColliders = SolidColliders;
foreach (Collider val3 in solidColliders)
{
if ((Object)(object)val3 != (Object)null)
{
Physics.IgnoreCollision(val, val3, false);
}
}
}
}
private static void TrySet(object target, string member, object value)
{
PropertyInfo property = target.GetType().GetProperty(member);
if ((object)property != null && property.CanWrite)
{
property.SetValue(target, value, null);
}
}
private void Awake()
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_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_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
ApplyCollisionFilter();
int num = Slides.Length;
_slideRest = (Quaternion[])(object)new Quaternion[num];
_swingRest = (Quaternion[])(object)new Quaternion[num];
_swingRestPos = (Vector3[])(object)new Vector3[num];
_hinges = (HingeJoint[])(object)new HingeJoint[num];
for (int i = 0; i < num; i++)
{
ref Quaternion reference = ref _slideRest[i];
reference = ((Component)Slides[i]).transform.localRotation;
ref Quaternion reference2 = ref _swingRest[i];
reference2 = ((Component)Swings[i]).transform.localRotation;
ref Vector3 reference3 = ref _swingRestPos[i];
reference3 = ((Component)Swings[i]).transform.localPosition;
_hinges[i] = ((Component)Slides[i]).GetComponent<HingeJoint>();
Slides[i].maxAngularVelocity = MaxAngularVelocity;
Swings[i].maxAngularVelocity = MaxAngularVelocity;
TrySet(Slides[i], "maxDepenetrationVelocity", 1f);
TrySet(Swings[i], "maxDepenetrationVelocity", 1f);
TrySet(Slides[i], "solverIterations", 20);
TrySet(Swings[i], "solverIterations", 20);
}
}
private IEnumerator Start()
{
yield return null;
ApplyCollisionFilter();
}
private bool InQuickbelt()
{
if ((Object)(object)Firearm == (Object)null)
{
return false;
}
if (!_slotLookedUp)
{
_slotLookedUp = true;
Type type = ((object)Firearm).GetType();
while ((object)type != null && (object)_slotField == null && (object)_slotProp == null)
{
_slotField = type.GetField("m_quickbeltSlot", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if ((object)_slotField == null)
{
_slotProp = type.GetProperty("QuickbeltSlot", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
type = type.BaseType;
}
}
object obj = null;
if ((object)_slotField != null)
{
obj = _slotField.GetValue(Firearm);
}
else if ((object)_slotProp != null)
{
obj = _slotProp.GetValue(Firearm, null);
}
Object val = (Object)((obj is Object) ? obj : null);
return val != (Object)null;
}
private void FixedUpdate()
{
if (Time.frameCount % 5 == 0 || _frozen)
{
bool flag = InQuickbelt();
if (flag && !_frozen)
{
SetFrozen(freeze: true);
}
else if (!flag && _frozen)
{
SetFrozen(freeze: false);
}
if (_frozen)
{
Pose(force: false);
}
}
}
private void SetFrozen(bool freeze)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
_frozen = freeze;
for (int i = 0; i < Slides.Length; i++)
{
if (!freeze)
{
Slides[i].isKinematic = false;
Swings[i].isKinematic = false;
Slides[i].velocity = Vector3.zero;
Slides[i].angularVelocity = Vector3.zero;
Swings[i].velocity = Vector3.zero;
Swings[i].angularVelocity = Vector3.zero;
}
else
{
Slides[i].isKinematic = true;
Swings[i].isKinematic = true;
}
}
if (freeze)
{
Pose(force: true);
}
}
private void Pose(bool force)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: 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_013a: Unknown result type (might be due to invalid IL or missing references)
//IL_015d: 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_00ac: 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_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)
Transform parent = ((Component)Slides[0]).transform.parent;
Vector3 val = parent.InverseTransformDirection(Vector3.down);
float num = Mathf.Atan2(0f - val.z, 0f - val.y) * 57.29578f;
if (_poseAngle == null)
{
_poseAngle = new float[Slides.Length];
force = true;
}
for (int i = 0; i < Slides.Length; i++)
{
float num2 = 0f;
if (HangStraightDownInQuickbelt)
{
num2 = num;
if ((Object)(object)_hinges[i] != (Object)null && _hinges[i].useLimits)
{
float num3 = num2;
JointLimits limits = _hinges[i].limits;
float min = ((JointLimits)(ref limits)).min;
JointLimits limits2 = _hinges[i].limits;
num2 = Mathf.Clamp(num3, min, ((JointLimits)(ref limits2)).max);
}
}
if (force || !(Mathf.Abs(Mathf.DeltaAngle(num2, _poseAngle[i])) < 3f))
{
_poseAngle[i] = num2;
((Component)Slides[i]).transform.localRotation = _slideRest[i] * Quaternion.Euler(num2, 0f, 0f);
((Component)Swings[i]).transform.localRotation = _swingRest[i];
((Component)Swings[i]).transform.localPosition = _swingRestPos[i];
}
}
}
}
public class SWAS_FlashOnFire : MonoBehaviour
{
public GameObject FlashPrefab;
private bool _done;
private void Awake()
{
//IL_001e: 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_0055: Unknown result type (might be due to invalid IL or missing references)
if (!_done)
{
_done = true;
SWAS_KeyCollisionFilter.ShieldGunsNear(((Component)this).transform.position);
if (!((Object)(object)FlashPrefab == (Object)null))
{
Object.Instantiate<GameObject>(FlashPrefab, ((Component)this).transform.position, ((Component)this).transform.rotation);
}
}
}
}
public class SWAS_KeyCollisionFilter : MonoBehaviour
{
[Tooltip("Colliders that belong to the gun body / ring.")]
public Collider[] GunColliders;
[Tooltip("Colliders that belong to the keys.")]
public Collider[] KeyColliders;
[Tooltip("Rotational inertia given to the collider-less Key_*_Slide bodies. Without this Unity gives them a huge default inertia, which makes the joint chain unstable.")]
public float SlideInertia = 0.002f;
[Tooltip("Cap on how fast the key bodies may spin (rad/s).")]
public float MaxKeyAngularVelocity = 10f;
[Tooltip("Turn gravity off on the gun's own rigidbody while it is held, so it feels weightless in the hand. The keys keep their gravity.")]
public bool WeightlessWhenHeld = true;
[Tooltip("Make sure every chamber is loaded when the gun spawns. Uses the chamber's own round type and tries its AutoChamberClass first, then any other class that exists for that round type.")]
public bool PreloadChambers = true;
[Tooltip("How many frames the gun stays invisible to bullet raycasts after a shot. The muzzle sits inside the barrel collider, so without this the bullet hits the gun on its first frame.")]
public int BulletShieldFrames = 4;
[Tooltip("Minimum real time (seconds) the shield lasts, in case the frame rate is very high.")]
public float BulletShieldMinTime = 0.05f;
[Tooltip("A bullet spawning this close (metres) to any of the gun's colliders counts as fired by this gun.")]
public float BulletShieldRadius = 0.3f;
[Header("Muzzle rescue (works for every bullet this gun fires, not just the key)")]
[Tooltip("The shield above only runs when the custom key projectile spawns. Any other bullet (a hacked-in round, another prefab) gets stopped dead by the gun's own colliders. With this on, a bullet that was stopped by this gun right next to the muzzle is put back in flight.")]
public bool RescueStoppedBullets = true;
[Tooltip("Only bullets stopped within this distance (metres) of the muzzle are rescued.")]
public float RescueRadius = 0.5f;
[Tooltip("Seconds after a chamber changes state (a shot) during which bullets are looked for.")]
public float RescueWindowTime = 0.3f;
[Tooltip("A bullet is rescued at most this many times.")]
public int MaxRescuesPerBullet = 8;
[Tooltip("Log what stopped a bullet next to the muzzle (collider, layer, trigger or not) so the real blocker can be seen in the log.")]
public bool DebugRescue = false;
[Tooltip("A bullet that spawns at the muzzle and is never launched by the game (no speed after UnfiredGraceFrames frames) is launched by hand along the muzzle direction.")]
public bool LaunchUnfiredBullets = true;
public int UnfiredGraceFrames = 0;
[Header("Clean-up")]
[Tooltip("Delete the gun when any chamber is not holding an unspent round (so it is not fully loaded), while it is not held and not in a quickbelt slot.")]
public bool DespawnWhenEmptyAndDropped = true;
[Tooltip("Seconds the gun has to stay not fully loaded and dropped before it is deleted.")]
public float DespawnDelay = 5f;
[Tooltip("Hierarchy index of the chamber that fires first on a fresh gun. The chambers then fire in hierarchy order, wrapping round (with 8 chambers and 1 here: 1,2,3,4,5,6,7,0).")]
public int FirstChamber = 1;
[Tooltip("Optional. Only fill this in if the firing order is not just 'FirstChamber, then onwards in hierarchy order'. Hierarchy indices of the chambers in firing order, first shot first. Leave empty otherwise.")]
public int[] FiringOrder;
private const int IgnoreRaycastLayer = 2;
private static readonly List<SWAS_KeyCollisionFilter> _all = new List<SWAS_KeyCollisionFilter>();
private readonly Dictionary<GameObject, int> _shielded = new Dictionary<GameObject, int>();
private int _shieldUntilFrame;
private float _shieldUntilTime;
private FVRPhysicalObject _phys;
private Rigidbody _rb;
private float _nextDespawnCheck;
private static BallisticProjectile[] _bulletCache;
private static int _bulletCacheFrame = -1;
private static bool[] _lockedPattern;
private string _lastLockLog;
private static int _lockedOwner;
private float _spawnTime = -1f;
private float _emptyDroppedTime;
private FieldInfo _slotField;
private bool _slotLooked;
private FVRFireArm _fa;
private FVRFireArmChamber[] _chambers;
private int[] _chamberState;
private float _rescueUntil;
private readonly Dictionary<BallisticProjectile, int> _seen = new Dictionary<BallisticProjectile, int>();
private readonly Dictionary<BallisticProjectile, int> _rescued = new Dictionary<BallisticProjectile, int>();
private void OnEnable()
{
if (!_all.Contains(this))
{
_all.Add(this);
}
if (RescueStoppedBullets && DebugRescue)
{
Debug.Log((object)("[SWAS] KeyCollisionFilter v3 (firing-order quickbelt) active on " + ((Object)this).name));
}
}
private void OnDisable()
{
if (_lockedOwner == ((Object)this).GetInstanceID())
{
_lockedPattern = null;
_lockedOwner = 0;
}
_all.Remove(this);
RestoreShield();
}
public static void ShieldGunsNear(Vector3 point)
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < _all.Count; i++)
{
SWAS_KeyCollisionFilter sWAS_KeyCollisionFilter = _all[i];
if ((Object)(object)sWAS_KeyCollisionFilter != (Object)null && sWAS_KeyCollisionFilter.IsNear(point))
{
sWAS_KeyCollisionFilter.ShieldFromBullets();
}
}
}
private bool IsNear(Vector3 point)
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
float num = BulletShieldRadius * BulletShieldRadius;
if (GunColliders != null)
{
for (int i = 0; i < GunColliders.Length; i++)
{
if ((Object)(object)GunColliders[i] != (Object)null)
{
Bounds bounds = GunColliders[i].bounds;
if (((Bounds)(ref bounds)).SqrDistance(point) <= num)
{
return true;
}
}
}
}
if (KeyColliders != null)
{
for (int j = 0; j < KeyColliders.Length; j++)
{
if ((Object)(object)KeyColliders[j] != (Object)null)
{
Bounds bounds2 = KeyColliders[j].bounds;
if (((Bounds)(ref bounds2)).SqrDistance(point) <= num)
{
return true;
}
}
}
}
return false;
}
public void ShieldFromBullets()
{
_shieldUntilFrame = Time.frameCount + Mathf.Max(1, BulletShieldFrames);
_shieldUntilTime = Time.time + BulletShieldMinTime;
ShieldList(GunColliders);
ShieldList(KeyColliders);
}
private void ShieldList(Collider[] list)
{
if (list == null)
{
return;
}
for (int i = 0; i < list.Length; i++)
{
if (!((Object)(object)list[i] == (Object)null))
{
GameObject gameObject = ((Component)list[i]).gameObject;
if (!_shielded.ContainsKey(gameObject))
{
_shielded[gameObject] = gameObject.layer;
gameObject.layer = 2;
}
}
}
}
private void RestoreShield()
{
foreach (KeyValuePair<GameObject, int> item in _shielded)
{
if ((Object)(object)item.Key != (Object)null && item.Key.layer == 2)
{
item.Key.layer = item.Value;
}
}
_shielded.Clear();
}
private void LateUpdate()
{
if (_shielded.Count > 0 && Time.frameCount >= _shieldUntilFrame && Time.time >= _shieldUntilTime)
{
RestoreShield();
}
if (RescueStoppedBullets)
{
RescueTick();
}
if (DespawnWhenEmptyAndDropped && Time.time >= _nextDespawnCheck)
{
_nextDespawnCheck = Time.time + 0.25f;
DespawnTick(0.25f);
}
RememberTick();
}
private FVRFireArmChamber[] EnsureChambers()
{
if (_chambers == null)
{
_fa = ((Component)this).GetComponent<FVRFireArm>();
_chambers = ((Component)this).GetComponentsInChildren<FVRFireArmChamber>(true);
_chamberState = new int[_chambers.Length];
for (int i = 0; i < _chambers.Length; i++)
{
_chamberState[i] = ChamberSig(_chambers[i]);
}
}
return _chambers;
}
private static BallisticProjectile[] GetBullets()
{
if (_bulletCacheFrame != Time.frameCount)
{
_bulletCacheFrame = Time.frameCount;
_bulletCache = Object.FindObjectsOfType<BallisticProjectile>();
}
return _bulletCache;
}
private static string ChamberStates(FVRFireArmChamber[] ch)
{
string text = "";
for (int i = 0; i < ch.Length; i++)
{
string text2 = text;
text = text2 + i + ":" + ((!((Object)(object)ch[i] == (Object)null)) ? (((Object)ch[i]).name + "=" + ((!ch[i].IsFull) ? "." : ((!ch[i].IsSpent) ? "L" : "S"))) : "null") + " ";
}
return text;
}
private void RememberTick()
{
if ((Object)(object)_phys == (Object)null)
{
return;
}
int instanceID = ((Object)this).GetInstanceID();
if (_phys.m_isSpawnLock)
{
FVRFireArmChamber[] array = EnsureChambers();
if (_lockedPattern == null || _lockedPattern.Length != array.Length)
{
_lockedPattern = new bool[array.Length];
}
int num = 0;
for (int i = 0; i < array.Length; i++)
{
if ((Object)(object)array[i] != (Object)null && array[i].IsFull && !array[i].IsSpent)
{
num++;
}
}
if (DebugRescue)
{
string text = ChamberStates(array);
if (text != _lastLockLog)
{
_lastLockLog = text;
Debug.Log((object)("[SWAS] item-locked gun now holds " + num + " loaded: " + text));
}
}
for (int j = 0; j < array.Length; j++)
{
_lockedPattern[j] = j < num;
}
_lockedOwner = instanceID;
}
else if (_lockedOwner == instanceID)
{
_lockedPattern = null;
_lockedOwner = 0;
}
}
private bool InQuickbeltSlot()
{
if ((Object)(object)_phys == (Object)null)
{
return false;
}
if (!_slotLooked)
{
_slotLooked = true;
Type type = ((object)_phys).GetType();
while ((object)type != null && (object)_slotField == null)
{
_slotField = type.GetField("m_quickbeltSlot", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
type = type.BaseType;
}
}
if ((object)_slotField == null)
{
return false;
}
object? value = _slotField.GetValue(_phys);
Object val = (Object)((value is Object) ? value : null);
return val != (Object)null;
}
private void DespawnTick(float step)
{
if ((Object)(object)_phys == (Object)null)
{
return;
}
if (_spawnTime < 0f)
{
_spawnTime = Time.time;
}
if (Time.time - _spawnTime < 3f)
{
_emptyDroppedTime = 0f;
return;
}
FVRFireArmChamber[] array = EnsureChambers();
bool flag = array.Length > 0;
for (int i = 0; i < array.Length; i++)
{
if (!flag)
{
break;
}
if ((Object)(object)array[i] == (Object)null || !array[i].IsFull || array[i].IsSpent)
{
flag = false;
}
}
if (flag || ((FVRInteractiveObject)_phys).IsHeld || InQuickbeltSlot())
{
_emptyDroppedTime = 0f;
return;
}
_emptyDroppedTime += step;
if (_emptyDroppedTime >= DespawnDelay)
{
if (DebugRescue)
{
Debug.Log((object)("[SWAS] gun is not fully loaded and was dropped " + DespawnDelay.ToString("F0") + " s ago, despawning"));
}
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
private void RescueTick()
{
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_0161: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_0236: Unknown result type (might be due to invalid IL or missing references)
//IL_023c: Unknown result type (might be due to invalid IL or missing references)
//IL_0453: Unknown result type (might be due to invalid IL or missing references)
//IL_0459: Unknown result type (might be due to invalid IL or missing references)
//IL_039f: Unknown result type (might be due to invalid IL or missing references)
//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
//IL_0576: Unknown result type (might be due to invalid IL or missing references)
//IL_056b: Unknown result type (might be due to invalid IL or missing references)
//IL_057b: Unknown result type (might be due to invalid IL or missing references)
//IL_0580: Unknown result type (might be due to invalid IL or missing references)
//IL_0585: Unknown result type (might be due to invalid IL or missing references)
//IL_058c: Unknown result type (might be due to invalid IL or missing references)
//IL_0591: Unknown result type (might be due to invalid IL or missing references)
//IL_0596: Unknown result type (might be due to invalid IL or missing references)
EnsureChambers();
for (int i = 0; i < _chambers.Length; i++)
{
int num = ChamberSig(_chambers[i]);
if (num != _chamberState[i])
{
_chamberState[i] = num;
_rescueUntil = Time.time + RescueWindowTime;
if (DebugRescue)
{
Debug.Log((object)("[SWAS] chamber " + i + " changed state (full=" + _chambers[i].IsFull + ", spent=" + _chambers[i].IsSpent + ") -> watching for bullets"));
}
}
}
if (Time.time > _rescueUntil)
{
return;
}
Transform val = ((!((Object)(object)_fa != (Object)null) || !((Object)(object)_fa.MuzzlePos != (Object)null)) ? ((Component)this).transform : _fa.MuzzlePos);
float num2 = RescueRadius * RescueRadius;
BallisticProjectile[] bullets = GetBullets();
foreach (BallisticProjectile val2 in bullets)
{
if ((Object)(object)val2 == (Object)null)
{
continue;
}
Vector3 val3 = ((Component)val2).transform.position - val.position;
if (((Vector3)(ref val3)).sqrMagnitude > num2)
{
continue;
}
_seen.TryGetValue(val2, out var value);
_seen[val2] = value + 1;
if (DebugRescue && value < 6)
{
Debug.Log((object)("[SWAS] bullet '" + ((Object)val2).name + "' near muzzle: moving=" + val2.m_isMoving + ", initialVel=" + val2.m_initialMuzzleVelocity.ToString("F1") + ", vel=" + ((Vector3)(ref val2.m_velocity)).magnitude.ToString("F1") + ", dist=" + Vector3.Distance(((Component)val2).transform.position, val.position).ToString("F3") + ", lastHit=" + ((!((Object)(object)val2.m_lastColliderHit != (Object)null)) ? "none" : ((Object)val2.m_lastColliderHit).name) + ", hasPierce=" + ((Object)(object)((Component)val2).GetComponent<SWAS_Pierce>() != (Object)null) + ", frame=" + value));
}
if (val2.m_isMoving)
{
continue;
}
if (val2.m_initialMuzzleVelocity <= 0f)
{
_rescued.TryGetValue(val2, out var value2);
if (LaunchUnfiredBullets && value >= UnfiredGraceFrames && value2 == 0)
{
_rescued[val2] = 1;
float speed = ((!(val2.MuzzleVelocityBase > 0f)) ? 200f : val2.MuzzleVelocityBase);
if (DebugRescue)
{
Debug.Log((object)("[SWAS] bullet '" + ((Object)val2).name + "' was never launched by the game; launching it at " + speed.ToString("F0") + " m/s"));
}
Vector3 position = ((Component)val2).transform.position;
Vector3 forward = ((Component)val2).transform.forward;
val2.m_startPoint = position;
Rearm(val2, position, forward, speed);
}
continue;
}
SWAS_Pierce component = ((Component)val2).GetComponent<SWAS_Pierce>();
if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled)
{
continue;
}
Collider lastColliderHit = val2.m_lastColliderHit;
bool flag = (Object)(object)lastColliderHit != (Object)null && (Object)(object)((Component)lastColliderHit).GetComponentInParent<SWAS_KeyCollisionFilter>() == (Object)(object)this;
if (DebugRescue)
{
Debug.Log((object)("[SWAS] bullet '" + ((Object)val2).name + "' stopped " + Vector3.Distance(((Component)val2).transform.position, val.position).ToString("F3") + " m from the muzzle by " + ((!((Object)(object)lastColliderHit != (Object)null)) ? "nothing" : ("'" + ((Object)lastColliderHit).name + "' (layer " + ((Component)lastColliderHit).gameObject.layer + ", trigger=" + lastColliderHit.isTrigger + ")")) + ((!flag) ? " -> not this gun, left alone" : " -> own gun, rescuing")));
}
if (flag)
{
_rescued.TryGetValue(val2, out var value3);
if (value3 < MaxRescuesPerBullet)
{
_rescued[val2] = value3 + 1;
Vector3 val4 = ((!(((Vector3)(ref val2.m_forward)).sqrMagnitude > 0.5f)) ? val.forward : ((Vector3)(ref val2.m_forward)).normalized);
Rearm(val2, val.position + val4 * 0.03f, val4, val2.m_initialMuzzleVelocity);
}
}
}
if (_seen.Count > 64)
{
_seen.Clear();
}
if (_rescued.Count <= 32)
{
return;
}
List<BallisticProjectile> list = new List<BallisticProjectile>();
foreach (KeyValuePair<BallisticProjectile, int> item in _rescued)
{
if ((Object)(object)item.Key == (Object)null)
{
list.Add(item.Key);
}
}
for (int k = 0; k < list.Count; k++)
{
_rescued.Remove(list[k]);
}
}
private static int ChamberSig(FVRFireArmChamber c)
{
return (!((Object)(object)c == (Object)null)) ? ((c.IsFull ? 1 : 0) | (c.IsSpent ? 2 : 0)) : 0;
}
private static void Rearm(BallisticProjectile bp, Vector3 start, Vector3 dir, float speed)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_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_006d: 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_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
((Component)bp).transform.position = start;
((Component)bp).transform.rotation = Quaternion.LookRotation(dir);
bp.m_isInReferenceTransform = false;
bp.m_transReference = null;
bp.m_localReferencePoint = Vector3.zero;
bp.m_isTumbling = false;
bp.m_stallFrames = 0;
bp.movesThisFrame = 0;
bp.needsSecondCast = false;
bp.distMoved = 0f;
bp.m_lastColliderHit = null;
bp.m_initialMuzzleVelocity = speed;
bp.m_velocity = dir * speed;
bp.m_forward = dir;
bp.m_lastPoint = start;
bp.m_isMoving = true;
bp.m_dieTimerTick = bp.m_dieTimerMax;
bp.waitOneFrame = false;
bp.hasTurnedOffRends = false;
if ((Object)(object)bp.BulletRenderer != (Object)null)
{
bp.BulletRenderer.enabled = true;
}
}
private IEnumerator Start()
{
if (!PreloadChambers)
{
yield break;
}
yield return null;
yield return null;
FVRFireArmChamber[] chambers = ((Component)this).GetComponentsInChildren<FVRFireArmChamber>(true);
bool usePattern = _lockedPattern != null && _lockedPattern.Length == chambers.Length && (!((Object)(object)_phys != (Object)null) || !_phys.m_isSpawnLock);
if (DebugRescue && usePattern)
{
int num = 0;
for (int i = 0; i < _lockedPattern.Length; i++)
{
if (_lockedPattern[i])
{
num++;
}
}
Debug.Log((object)("[SWAS] copy from quickbelt: remembered " + num + " of " + _lockedPattern.Length + " chambers loaded"));
}
if (DebugRescue && !usePattern)
{
Debug.Log((object)("[SWAS] no quickbelt pattern used (pattern stored=" + (_lockedPattern != null) + ", this gun is item-locked=" + ((Object)(object)_phys != (Object)null && _phys.m_isSpawnLock) + ") -> every empty chamber is loaded"));
}
int[] rank = FiringRanks(chambers);
for (int j = 0; j < chambers.Length; j++)
{
FVRFireArmChamber val = chambers[j];
if ((Object)(object)val == (Object)null)
{
continue;
}
if (usePattern && !_lockedPattern[rank[j]])
{
if (val.IsFull)
{
FVRFireArmRound round = val.GetRound();
val.SetRound((FVRFireArmRound)null, false);
if ((Object)(object)round != (Object)null)
{
Object.Destroy((Object)(object)((Component)round).gameObject);
}
if (DebugRescue)
{
Debug.Log((object)("[SWAS] chamber " + j + " was already loaded by the game, emptied to match the quickbelt pattern"));
}
}
}
else
{
if (val.IsFull || TryLoad(val, val.AutoChamberClass))
{
continue;
}
foreach (FireArmRoundClass value in Enum.GetValues(typeof(FireArmRoundClass)))
{
if (TryLoad(val, value))
{
break;
}
}
}
}
if (DebugRescue)
{
((MonoBehaviour)this).StartCoroutine(LogFinalState(chambers, rank));
}
}
private int[] FiringRanks(FVRFireArmChamber[] ch)
{
int num = ch.Length;
int[] array = new int[num];
bool flag = FiringOrder != null && FiringOrder.Length == num;
if (flag)
{
bool[] array2 = new bool[num];
for (int i = 0; i < num; i++)
{
int num2 = FiringOrder[i];
if (num2 < 0 || num2 >= num || array2[num2])
{
flag = false;
break;
}
array2[num2] = true;
array[i] = num2;
}
}
if (!flag)
{
int num3 = ((num > 0) ? ((FirstChamber % num + num) % num) : 0);
for (int j = 0; j < num; j++)
{
array[j] = (num3 + j) % num;
}
}
int[] array3 = new int[num];
for (int k = 0; k < num; k++)
{
array3[array[k]] = k;
}
if (DebugRescue)
{
string text = "[SWAS] firing order (" + ((!flag) ? ("FirstChamber " + FirstChamber) : "FiringOrder field") + "):";
for (int l = 0; l < num; l++)
{
string text2 = text;
text = text2 + " " + array[l] + "(" + ((!((Object)(object)ch[array[l]] != (Object)null)) ? "null" : ((Object)ch[array[l]]).name) + ")";
}
Debug.Log((object)text);
}
return array3;
}
private IEnumerator LogFinalState(FVRFireArmChamber[] chambers, int[] rank)
{
yield return null;
yield return null;
string s = "[SWAS] copy chambers after load (hierarchy idx:name=state@rank, local pos): ";
for (int i = 0; i < chambers.Length; i++)
{
FVRFireArmChamber val = chambers[i];
if ((Object)(object)val == (Object)null)
{
s = s + i + ":null ";
continue;
}
string text = s;
object[] obj = new object[10]
{
text,
i,
":",
((Object)val).name,
"=",
(!val.IsFull) ? "." : ((!val.IsSpent) ? "L" : "S"),
"@",
rank[i],
null,
null
};
Vector3 val2 = ((Component)this).transform.InverseTransformPoint(((Component)val).transform.position);
obj[8] = ((Vector3)(ref val2)).ToString("F2");
obj[9] = " ";
s = string.Concat(obj);
}
Debug.Log((object)s);
}
private static bool TryLoad(FVRFireArmChamber c, FireArmRoundClass rc)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
if (!AM.DoesClassExistForType(rc, c.RoundType))
{
return false;
}
c.Autochamber(rc);
return true;
}
private void FixedUpdate()
{
if (WeightlessWhenHeld && !((Object)(object)_phys == (Object)null) && !((Object)(object)_rb == (Object)null) && ((FVRInteractiveObject)_phys).IsHeld && _rb.useGravity)
{
_rb.useGravity = false;
}
}
private void Awake()
{
_phys = ((Component)this).GetComponent<FVRPhysicalObject>();
_rb = ((Component)this).GetComponent<Rigidbody>();
StabiliseKeyBodies();
if (GunColliders == null || GunColliders.Length == 0 || KeyColliders == null || KeyColliders.Length == 0)
{
List<Collider> list = new List<Collider>();
List<Collider> list2 = new List<Collider>();
Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren<Collider>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
if (IsKey(((Component)componentsInChildren[i]).transform))
{
list2.Add(componentsInChildren[i]);
}
else
{
list.Add(componentsInChildren[i]);
}
}
GunColliders = list.ToArray();
KeyColliders = list2.ToArray();
}
for (int j = 0; j < GunColliders.Length; j++)
{
if ((Object)(object)GunColliders[j] == (Object)null)
{
continue;
}
for (int k = 0; k < KeyColliders.Length; k++)
{
if (!((Object)(object)KeyColliders[k] == (Object)null))
{
Physics.IgnoreCollision(GunColliders[j], KeyColliders[k], true);
}
}
}
}
private void StabiliseKeyBodies()
{
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
Rigidbody[] componentsInChildren = ((Component)this).GetComponentsInChildren<Rigidbody>(true);
foreach (Rigidbody val in componentsInChildren)
{
if (!((Object)(object)((Component)val).gameObject == (Object)(object)((Component)this).gameObject) && IsKey(((Component)val).transform))
{
val.maxAngularVelocity = MaxKeyAngularVelocity;
if ((Object)(object)((Component)val).GetComponent<Collider>() == (Object)null)
{
val.inertiaTensor = new Vector3(SlideInertia, SlideInertia, SlideInertia);
val.inertiaTensorRotation = Quaternion.identity;
}
}
}
}
private bool IsKey(Transform t)
{
while ((Object)(object)t != (Object)null && (Object)(object)t != (Object)(object)((Component)this).transform)
{
if (((Object)t).name.StartsWith("Key_"))
{
return true;
}
t = t.parent;
}
return false;
}
}
public class SWAS_KeyholeImprint : MonoBehaviour
{
private const int MaxLive = 24;
private static readonly List<SWAS_KeyholeImprint> _live = new List<SWAS_KeyholeImprint>();
public float Lifetime = 8f;
[Tooltip("Fraction of the lifetime the imprint stays at full brightness before it starts to fade.")]
public float HoldFraction = 0.15f;
public Color HotColor = new Color(1f, 1f, 1f, 1f);
public Color CoolColor = new Color(1f, 0.35f, 0.08f, 1f);
private Mesh _mesh;
private Color[] _colors = (Color[])(object)new Color[4];
private float _t;
private float _nextColor;
private const float ColorStep = 1f / 15f;
private static MaterialPropertyBlock _block;
public static SWAS_KeyholeImprint Spawn(Material material, float size, float lifetime, Vector3 point, Vector3 normal, Vector3 upHint, Transform parent)
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Expected O, but got Unknown
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: 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_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)material == (Object)null)
{
return null;
}
normal = ((!(((Vector3)(ref normal)).sqrMagnitude < 0.0001f)) ? ((Vector3)(ref normal)).normalized : Vector3.up);
Vector3 val = Vector3.ProjectOnPlane(Vector3.up, normal);
if (((Vector3)(ref val)).sqrMagnitude < 0.05f)
{
val = Vector3.ProjectOnPlane(upHint, normal);
}
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
val = Vector3.ProjectOnPlane(Vector3.forward, normal);
}
((Vector3)(ref val)).Normalize();
GameObject val2 = new GameObject("SWAS_KeyholeImprint");
val2.transform.position = point + normal * 0.01f;
val2.transform.rotation = Quaternion.LookRotation(-normal, val);
if ((Object)(object)parent != (Object)null && IsUniform(parent.lossyScale))
{
val2.transform.SetParent(parent, true);
}
SWAS_KeyholeImprint sWAS_KeyholeImprint = val2.AddComponent<SWAS_KeyholeImprint>();
sWAS_KeyholeImprint.Lifetime = Mathf.Max(0.1f, lifetime);
sWAS_KeyholeImprint.Build(material, size);
_live.Add(sWAS_KeyholeImprint);
while (_live.Count > 24)
{
if ((Object)(object)_live[0] != (Object)null)
{
Object.Destroy((Object)(object)((Component)_live[0]).gameObject);
}
_live.RemoveAt(0);
}
return sWAS_KeyholeImprint;
}
private static bool IsUniform(Vector3 s)
{
float num = Mathf.Max(s.x, Mathf.Max(s.y, s.z));
if (num <= 0.0001f)
{
return false;
}
return Mathf.Min(s.x, Mathf.Min(s.y, s.z)) / num > 0.9f;
}
private void Build(Material material, float size)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Expected O, but got Unknown
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: 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_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_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_017b: 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)
//IL_0191: 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_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_01be: Unknown result type (might be due to invalid IL or missing references)
//IL_0211: Unknown result type (might be due to invalid IL or missing references)
//IL_021b: Expected O, but got Unknown
float num = size * 0.5f;
_mesh = new Mesh();
((Object)_mesh).name = "SWAS_KeyholeImprintQuad";
_mesh.vertices = (Vector3[])(object)new Vector3[4]
{
new Vector3(0f - num, 0f - num, 0f),
new Vector3(num, 0f - num, 0f),
new Vector3(0f - num, num, 0f),
new Vector3(num, num, 0f)
};
_mesh.uv = (Vector2[])(object)new Vector2[4]
{
new Vector2(0f, 0f),
new Vector2(1f, 0f),
new Vector2(0f, 1f),
new Vector2(1f, 1f)
};
_mesh.triangles = new int[6] { 0, 2, 1, 2, 3, 1 };
_mesh.normals = (Vector3[])(object)new Vector3[4]
{
-Vector3.forward,
-Vector3.forward,
-Vector3.forward,
-Vector3.forward
};
_mesh.bounds = new Bounds(Vector3.zero, new Vector3(size, size, 0.05f));
SetColor(HotColor, 1f);
MeshFilter val = ((Component)this).gameObject.AddComponent<MeshFilter>();
val.sharedMesh = _mesh;
MeshRenderer val2 = ((Component)this).gameObject.AddComponent<MeshRenderer>();
((Renderer)val2).sharedMaterial = material;
((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
((Renderer)val2).receiveShadows = false;
if (_block == null)
{
_block = new MaterialPropertyBlock();
_block.SetFloat("_InvFade", 1000f);
}
((Renderer)val2).SetPropertyBlock(_block);
}
private void SetColor(Color c, float alpha)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
c.a = alpha;
for (int i = 0; i < 4; i++)
{
_colors[i] = c;
}
_mesh.colors = _colors;
}
private void Update()
{
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: 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)
_t += Time.deltaTime;
float num = Mathf.Clamp01(_t / Lifetime);
if (num >= 1f)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
}
else if (!(_t < _nextColor))
{
_nextColor = _t + 1f / 15f;
float num2 = Mathf.Clamp01((num - HoldFraction) / Mathf.Max(0.01f, 1f - HoldFraction));
float num3 = 1f - num2 * num2 * (3f - 2f * num2);
num3 *= num3;
Color c = Color.Lerp(HotColor, CoolColor, Mathf.Clamp01(num2 * 1.6f));
SetColor(c, num3);
}
}
private void OnDestroy()
{
_live.Remove(this);
if ((Object)(object)_mesh != (Object)null)
{
Object.Destroy((Object)(object)_mesh);
}
}
}
public class SWAS_MuzzleFlash : MonoBehaviour
{
public Light FlashLight;
public float LightPeak = 4.5f;
public float LightDuration = 0.4f;
public float Lifetime = 2.2f;
private float _t;
private float _seed;
private void Awake()
{
_seed = Random.value * 100f;
Object.Destroy((Object)(object)((Component)this).gameObject, Lifetime);
}
private void Update()
{
_t += Time.deltaTime;
if (!((Object)(object)FlashLight == (Object)null))
{
if (_t >= LightDuration)
{
((Behaviour)FlashLight).enabled = false;
return;
}
float num = 1f - _t / LightDuration;
float num2 = 0.65f + 0.35f * Mathf.PerlinNoise(_seed, _t * 38f);
FlashLight.intensity = LightPeak * num * num * num2;
}
}
}
public class SWAS_Pierce : MonoBehaviour
{
[Tooltip("Fraction of the damage kept after each thing the key goes through (1 = keeps all of it, 0.5 = loses 50%).")]
public float DamageRetained = 1f;
[Tooltip("The key stops for good after going through this many things.")]
public int MaxPierces = 10;
[Tooltip("Colliders on these layers always count as walls (default: Environment).")]
public LayerMask WallLayers = LayerMask.op_Implicit(524288);
[Tooltip("How far (metres) to look for the far side of the thing that was hit. Anything thicker than this is passed through for only a short distance.")]
public float MaxPierceDepth = 2f;
[Header("Walls")]
[Tooltip("The key goes through walls too (it comes out the far side and carries on). Off = walls stop it, as before.")]
public bool PhaseThroughWalls = true;
[Tooltip("How far (metres) to look for the far side of a wall. If it is thicker than this the key is simply put a short way inside it and carries on from there.")]
public float WallPierceDepth = 8f;
[Tooltip("How far (metres) into a wall the key is put when the far side could not be found.")]
public float WallFallbackAdvance = 0.3f;
[Tooltip("The key stops for good after going through this many walls (stops it getting stuck in a loop).")]
public int MaxWallPhases = 64;
[Header("Leaving the map")]
[Tooltip("After going through a wall, the key is despawned when nothing is left on its path to hit.")]
public bool DespawnWhenLeavingMap = true;
[Tooltip("Colliders on these layers count as part of the map when looking ahead along the key's path (default: the game's own bullet layers).")]
public LayerMask MapLayers = LayerMask.op_Implicit(1639425);
[Tooltip("How many seconds ahead (gravity included) the key's path is checked.")]
public float PredictSeconds = 2.5f;
[Tooltip("Seconds between path checks.")]
public float VoidCheckInterval = 0.1f;
[Tooltip("The key is despawned once it has fallen this many metres below where it was fired from.")]
public float VoidDepth = 250f;
[Tooltip("The key is despawned once it has flown this many metres in total (a wall resets the game's own range limit).")]
public float MaxTotalRange = 800f;
[Header("Keyhole imprint")]
[Tooltip("Material for the filled-in keyhole left behind. Leave empty for no imprints.")]
public Material ImprintMaterial;
[Tooltip("Width and height (metres) of the imprint's quad. The keyhole fills about 86% of the height.")]
public float ImprintSize = 0.16f;
[Tooltip("Seconds an imprint takes to cool and fade away.")]
public float ImprintLifetime = 8f;
[Tooltip("Also leave an imprint where the key comes out the far side of something it pierced.")]
public bool ImprintOnExit = false;
[Header("Piercing")]
[Tooltip("How far (metres) past the far side the key restarts, so it does not hit the same surface again.")]
public float ExitNudge = 0.01f;
[Header("Debugging")]
[Tooltip("Write one line to the log each time the key stops (what it hit, wall or not, how many times it has pierced).")]
public bool DebugLog = false;
[Tooltip("Most times the key may be stopped by the gun it was fired from before it is ended. These stops are passed through without counting as a pierce.")]
public int MaxSelfHits = 8;
private BallisticProjectile _bp;
private int _selfHits;
private Vector3 _spawnPos;
private bool _seenMoving;
private Vector3 _prev;
private Vector3 _lastVel;
private bool _phased;
private float _totalDist;
private float _nextVoidCheck;
public bool IsLanded { get; private set; }
public int PierceCount { get; private set; }
public Vector3 LandPoint { get; private set; }
public Vector3 LandNormal { get; private set; }
public Collider LandCollider { get; private set; }
public bool LandedOnWall { get; private set; }
public bool Despawned { get; private set; }
public int WallPhases { get; private set; }
private void Awake()
{
//IL_0014: 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_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
_bp = ((Component)this).GetComponent<BallisticProjectile>();
_prev = ((Component)this).transform.position;
_spawnPos = _prev;
if ((Object)(object)_bp == (Object)null)
{
((Behaviour)this).enabled = false;
}
}
private void LateUpdate()
{
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_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)
if (IsLanded || (Object)(object)_bp == (Object)null)
{
return;
}
if (_bp.m_isMoving)
{
_seenMoving = true;
if (((Vector3)(ref _bp.m_velocity)).sqrMagnitude > 1f)
{
_lastVel = _bp.m_velocity;
}
float totalDist = _totalDist;
Vector3 val = ((Component)this).transform.position - _prev;
_totalDist = totalDist + ((Vector3)(ref val)).magnitude;
_prev = ((Component)this).transform.position;
if (_phased && DespawnWhenLeavingMap)
{
CheckLeftMap();
}
}
else if (_seenMoving || !(_bp.m_initialMuzzleVelocity <= 0f))
{
OnStopped();
}
}
private void OnStopped()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: 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_00a7: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: 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_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00e0: 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_00e9: 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)
//IL_00fa: 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_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_01cc: 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_01d4: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_01de: Unknown result type (might be due to invalid IL or missing references)
//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
//IL_01f4: 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_021b: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0224: Unknown result type (might be due to invalid IL or missing references)
//IL_0229: Unknown result type (might be due to invalid IL or missing references)
//IL_022e: Unknown result type (might be due to invalid IL or missing references)
//IL_0213: Unknown result type (might be due to invalid IL or missing references)
//IL_0218: Unknown result type (might be due to invalid IL or missing references)
//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
//IL_0339: Unknown result type (might be due to invalid IL or missing references)
//IL_033e: Unknown result type (might be due to invalid IL or missing references)
//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
//IL_03df: Unknown result type (might be due to invalid IL or missing references)
//IL_03f7: Unknown result type (might be due to invalid IL or missing references)
//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0401: Unknown result type (might be due to invalid IL or missing references)
//IL_0404: Unknown result type (might be due to invalid IL or missing references)
//IL_0406: Unknown result type (might be due to invalid IL or missing references)
//IL_0409: Unknown result type (might be due to invalid IL or missing references)
//IL_040e: Unknown result type (might be due to invalid IL or missing references)
//IL_0413: Unknown result type (might be due to invalid IL or missing references)
//IL_0414: Unknown result type (might be due to invalid IL or missing references)
//IL_0419: Unknown result type (might be due to invalid IL or missing references)
//IL_0475: Unknown result type (might be due to invalid IL or missing references)
//IL_0477: Unknown result type (might be due to invalid IL or missing references)
//IL_047e: Unknown result type (might be due to invalid IL or missing references)
//IL_0483: Unknown result type (might be due to invalid IL or missing references)
//IL_0488: Unknown result type (might be due to invalid IL or missing references)
//IL_042f: Unknown result type (might be due to invalid IL or missing references)
//IL_0434: Unknown result type (might be due to invalid IL or missing references)
//IL_0444: Unknown result type (might be due to invalid IL or missing references)
//IL_0449: Unknown result type (might be due to invalid IL or missing references)
//IL_044b: Unknown result type (might be due to invalid IL or missing references)
//IL_044d: Unknown result type (might be due to invalid IL or missing references)
//IL_0467: Unknown result type (might be due to invalid IL or missing references)
//IL_0469: Unknown result type (might be due to invalid IL or missing references)
//IL_046b: Unknown result type (might be due to invalid IL or missing references)
//IL_045d: Unknown result type (might be due to invalid IL or missing references)
//IL_045f: Unknown result type (might be due to invalid IL or missing references)
//IL_0464: Unknown result type (might be due to invalid IL or missing references)
Vector3 position = ((Component)this).transform.position;
Collider lastColliderHit = _bp.m_lastColliderHit;
Vector3 normalized;
if (((Vector3)(ref _lastVel)).sqrMagnitude > 0.01f)
{
normalized = ((Vector3)(ref _lastVel)).normalized;
}
else
{
Vector3 val = position - _prev;
normalized = ((Vector3)(ref val)).normalized;
}
Vector3 val2 = normalized;
if (((Vector3)(ref val2)).sqrMagnitude < 0.5f)
{
val2 = ((Component)this).transform.forward;
}
if (((Vector3)(ref _lastVel)).sqrMagnitude <= 1f)
{
_lastVel = val2 * _bp.m_initialMuzzleVelocity;
}
Vector3 val3 = position;
Vector3 val4 = -val2;
Vector3 val5 = position - _prev;
float magnitude = ((Vector3)(ref val5)).magnitude;
RaycastHit val7 = default(RaycastHit);
if ((Object)(object)lastColliderHit != (Object)null && magnitude > 0.0001f)
{
Vector3 val6 = val5 / magnitude;
if (lastColliderHit.Raycast(new Ray(_prev - val6 * 0.05f, val6), ref val7, magnitude + 0.5f))
{
val3 = ((RaycastHit)(ref val7)).point;
val4 = ((RaycastHit)(ref val7)).normal;
}
}
if (Vector3.Dot(val4, val2) > 0f)
{
val4 = -val4;
}
if ((Object)(object)lastColliderHit != (Object)null && _selfHits < MaxSelfHits && (Object)(object)((Component)lastColliderHit).GetComponentInParent<SWAS_KeyCollisionFilter>() != (Object)null)
{
_selfHits++;
if (DebugLog)
{
Debug.Log((object)("[SWAS] key stopped by its own gun (" + ((Object)lastColliderHit).name + "), passing through (" + _selfHits + ")"));
}
Vector3 val8 = val3 + val2 * 0.1f;
if (lastColliderHit.Raycast(new Ray(val3 + val2 * MaxPierceDepth, -val2), ref val7, MaxPierceDepth))
{
val8 = ((RaycastHit)(ref val7)).point;
}
Resume(val8 + val2 * ExitNudge, val2, ((Vector3)(ref _lastVel)).magnitude, countsAsPierce: false);
return;
}
bool flag = (Object)(object)lastColliderHit == (Object)null || IsWall(lastColliderHit);
bool flag2 = flag && (Object)(object)lastColliderHit != (Object)null && PhaseThroughWalls && WallPhases < MaxWallPhases;
if (DebugLog)
{
Debug.Log((object)("[SWAS] key stopped: hit=" + ((!((Object)(object)lastColliderHit != (Object)null)) ? "nothing" : (((Object)lastColliderHit).name + " layer " + ((Component)lastColliderHit).gameObject.layer)) + ", wall=" + flag + ", pierces=" + PierceCount + ", speed=" + ((Vector3)(ref _lastVel)).magnitude.ToString("F0") + ", metres from muzzle=" + Vector3.Distance(_spawnPos, val3).ToString("F2")));
}
if (flag2)
{
WallPhases++;
_phased = true;
_nextVoidCheck = 0f;
}
else if (flag || PierceCount >= MaxPierces)
{
Land(val3, val4, lastColliderHit, flag);
return;
}
LeaveImprint(val3, val4, val2, lastColliderHit);
float num = ((!flag2) ? MaxPierceDepth : WallPierceDepth);
Vector3 val9 = val3 + val2 * ((!flag2) ? 0.1f : WallFallbackAdvance);
if (lastColliderHit.Raycast(new Ray(val3 + val2 * num, -val2), ref val7, num))
{
val9 = ((RaycastHit)(ref val7)).point;
if (ImprintOnExit)
{
Vector3 val10 = ((RaycastHit)(ref val7)).normal;
if (Vector3.Dot(val10, val2) < 0f)
{
val10 = -val10;
}
LeaveImprint(val9, val10, val2, lastColliderHit);
}
}
Resume(val9 + val2 * ExitNudge, val2, ((Vector3)(ref _lastVel)).magnitude, !flag2);
}
private void CheckLeftMap()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: 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)
Vector3 position = ((Component)this).transform.position;
if (position.y < _spawnPos.y - VoidDepth)
{
Despawn("fell " + VoidDepth.ToString("F0") + " m below where it was fired");
}
else if (_totalDist > MaxTotalRange)
{
Despawn("flew more than " + MaxTotalRange.ToString("F0") + " m");
}
else if (!(Time.time < _nextVoidCheck))
{
_nextVoidCheck = Time.time + Mathf.Max(0.02f, VoidCheckInterval);
if (!PathHitsMap(position, _bp.m_velocity))
{
Despawn("nothing left on its path");
}
}
}
private bool PathHitsMap(Vector3 p, Vector3 v)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: 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_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = Physics.gravity * _bp.GravityMultiplier;
int num = Mathf.Max(1, Mathf.CeilToInt(PredictSeconds / 0.1f));
for (int i = 0; i < num; i++)
{
Vector3 val2 = v * 0.1f;
float magnitude = ((Vector3)(ref val2)).magnitude;
if (magnitude < 0.0001f)
{
return true;
}
if (Physics.Raycast(p, val2 / magnitude, magnitude, LayerMask.op_Implicit(MapLayers), (QueryTriggerInteraction)1))
{
return true;
}
p += val2;
v += val * 0.1f;
}
return false;
}
private void Despawn(string reason)
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
if (DebugLog)
{
Debug.Log((object)("[SWAS] key left the map (" + reason + "), despawning after " + WallPhases + " walls"));
}
Despawned = true;
IsLanded = true;
LandPoint = ((Component)this).transform.position;
LandNormal = Vector3.up;
LandCollider = null;
LandedOnWall = false;
_bp.m_isMoving = false;
Object.Destroy((Object)(object)((Component)this).gameObject);
}
private void Resume(Vector3 start, Vector3 dir, float speed, bool countsAsPierce)
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: 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_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: 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_017a: 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)
if (countsAsPierce)
{
PierceCount++;
BallisticProjectile bp = _bp;
bp.Mass *= DamageRetained;
BallisticProjectile bp2 = _bp;
bp2.AirDragMultiplier *= DamageRetained;
}
((Component)this).transform.position = start;
((Component)this).transform.rotation = Quaternion.LookRotation(dir);
_bp.m_isInReferenceTransform = false;
_bp.m_transReference = null;
_bp.m_localReferencePoint = Vector3.zero;
_bp.m_isTumbling = false;
_bp.m_stallFrames = 0;
_bp.movesThisFrame = 0;
_bp.needsSecondCast = false;
_bp.distMoved = 0f;
_bp.m_lastColliderHit = null;
_bp.m_initialMuzzleVelocity = speed;
_bp.m_velocity = dir * speed;
_bp.m_forward = dir;
_bp.m_lastPoint = start;
_bp.m_isMoving = true;
_bp.m_dieTimerTick = _bp.m_dieTimerMax;
_bp.waitOneFrame = false;
_bp.hasTurnedOffRends = false;
if ((Object)(object)_bp.BulletRenderer != (Object)null)
{
_bp.BulletRenderer.enabled = true;
}
_prev = start;
_lastVel = dir * speed;
}
private void Land(Vector3 point, Vector3 normal, Collider col, bool wall)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
IsLanded = true;
LandPoint = point;
LandNormal = normal;
LandCollider = col;
LandedOnWall = wall;
if ((Object)(object)col != (Object)null)
{
LeaveImprint(point, normal, _lastVel, col);
}
}
private void LeaveImprint(Vector3 point, Vector3 normal, Vector3 upHint, Collider on)
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)ImprintMaterial == (Object)null))
{
Transform parent = ((!((Object)(object)on != (Object)null) || !((Object)(object)on.attachedRigidbody != (Object)null)) ? null : ((Component)on.attachedRigidbody).transform);
SWAS_KeyholeImprint.Spawn(ImprintMaterial, ImprintSize, ImprintLifetime, point, normal, upHint, parent);
}
}
private bool IsWall(Collider c)
{
if ((Object)(object)c == (Object)null)
{
return true;
}
if ((((LayerMask)(ref WallLayers)).value & (1 << ((Component)c).gameObject.layer)) != 0)
{
return true;
}
if (((Component)c).GetComponentInParent<IFVRDamageable>() != null)
{
return false;
}
Rigidbody attachedRigidbody = c.attachedRigidbody;
return (Object)(object)attachedRigidbody == (Object)null || attachedRigidbody.isKinematic;
}
}
public class SWAS_TrailFade : MonoBehaviour
{
public float Duration = 0.7f;
[Tooltip("Higher = the brightness drops off faster at the start and has a longer faint tail.")]
public float Falloff = 1.8f;
[Tooltip("How much of its width the trail keeps at the very end (0 = thins to nothing).")]
public float EndWidth = 0.35f;
[Tooltip("Colour the trail cools towards as it fades.")]
public Color CoolColor = new Color(1f, 0.42f, 0.08f, 1f);
private TrailRenderer _trail;
private GradientColorKey[] _colorKeys;
private GradientAlphaKey[] _alphaKeys;
private GradientColorKey[] _workColor;
private GradientAlphaKey[] _workAlpha;
private Gradient _work;
private float _baseWidth;
private float _t;
private void Awake()
{
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Expected O, but got Unknown
_trail = ((Component)this).GetComponent<TrailRenderer>();
if ((Object)(object)_trail == (Object)null)
{
((Behaviour)this).enabled = false;
return;
}
Gradient colorGradient = _trail.colorGradient;
_colorKeys = colorGradient.colorKeys;
_alphaKeys = colorGradient.alphaKeys;
_workColor = (GradientColorKey[])(object)new GradientColorKey[_colorKeys.Length];
_workAlpha = (GradientAlphaKey[])(object)new GradientAlphaKey[_alphaKeys.Length];
_work = new Gradient();
_baseWidth = _trail.widthMultiplier;
}
private void Update()
{
//IL_009a: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: 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_00d1: 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_0129: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_trail == (Object)null))
{
_t += Time.deltaTime;
float num = Mathf.Clamp01(_t / Mathf.Max(0.01f, Duration));
float num2 = Mathf.Pow(1f - num, Falloff);
num2 *= num2 * (3f - 2f * num2) * 0.5f + 0.5f * num2;
float num3 = Mathf.Clamp01(num * 1.4f);
for (int i = 0; i < _colorKeys.Length; i++)
{
Color val = Color.Lerp(_colorKeys[i].color, CoolColor, num3);
ref GradientColorKey reference = ref _workColor[i];
reference = new GradientColorKey(val, _colorKeys[i].time);
}
for (int j = 0; j < _alphaKeys.Length; j++)
{
ref GradientAlphaKey reference2 = ref _workAlpha[j];
reference2 = new GradientAlphaKey(_alphaKeys[j].alpha * num2, _alphaKeys[j].time);
}
_work.SetKeys(_workColor, _workAlpha);
_trail.colorGradient = _work;
_trail.widthMultiplier = _baseWidth * Mathf.Lerp(1f, EndWidth, num);
if (num >= 1f)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
}
}
public class SWAS_TrailJitter : MonoBehaviour
{
public float Amplitude = 0.07f;
public float Frequency = 14f;
public float WidthFlutter = 0.35f;
public TrailRenderer Trail;
public Transform Follow;
private float _seed;
private float _baseWidth;
private void Awake()
{
_seed = Random.value * 100f;
if ((Object)(object)Trail == (Object)null)
{
Trail = ((Component)this).GetComponent<TrailRenderer>();
}
if ((Object)(object)Trail != (Object)null)
{
_baseWidth = Trail.widthMultiplier;
}
}
private void LateUpdate()
{
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
float num = Time.time * Frequency;
Vector3 val = default(Vector3);
((Vector3)(ref val))..ctor((Mathf.PerlinNoise(_seed, num) - 0.5f) * 2f * Amplitude, (Mathf.PerlinNoise(_seed + 31.7f, num) - 0.5f) * 2f * Amplitude, 0f);
if ((Object)(object)Follow != (Object)null)
{
((Component)this).transform.position = Follow.TransformPoint(val);
}
else
{
((Component)this).transform.localPosition = val;
}
if ((Object)(object)Trail != (Object)null)
{
Trail.widthMultiplier = _baseWidth * (1f - WidthFlutter + WidthFlutter * 2f * Mathf.PerlinNoise(_seed + 77.3f, num * 0.8f));
}
}
}
public class SWAS_TrailLanding : MonoBehaviour
{
[Tooltip("Frames to wait after spawning before checking whether the key has landed.")]
public int GraceFrames = 2;
[Tooltip("Fallback landing test: the key counts as landed after not moving for this long (game seconds).")]
public float StillTimeToLand = 0.08f;
[Tooltip("A frame with less movement than this (metres) counts as standing still.")]
public float StillDistance = 0.002f;
[Tooltip("Extra seconds a trail lingers after it has finished fading, before it is deleted.")]
public float ExtraLinger = 0.2f;
[Tooltip("How long (seconds) the tracer takes to fade out once the key has landed. The trail cools from white-hot to orange while it fades.")]
public float TrailFadeDuration = 0.7f;
private TrailRenderer _trail;
private SWAS_TrailJitter _jitter;
private ParticleSystem _holes;
private BallisticProjectile _projectile;
private SWAS_Pierce _pierce;
private FieldInfo _movingField;
private Vector3 _last;
private int _frames;
private float _stillTime;
private bool _released;
private static bool _quitting;
private void Awake()
{
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
_trail = ((Component)this).GetComponentInChildren<TrailRenderer>(true);
_jitter = ((Component)this).GetComponentInChildren<SWAS_TrailJitter>(true);
_holes = ((Component)this).GetComponentInChildren<ParticleSystem>(true);
_projectile = ((Component)this).GetComponent<BallisticProjectile>();
_pierce = ((Component)this).GetComponent<SWAS_Pierce>();
if ((Object)(object)_projectile != (Object)null)
{
_movingField = typeof(BallisticProjectile).GetField("m_isMoving", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
_last = ((Component)this).transform.position;
if ((Object)(object)_trail != (Object)null)
{
((Component)_trail).transform.SetParent((Transform)null, true);
if ((Object)(object)_jitter != (Object)null)
{
_jitter.Follow = ((Component)this).transform;
}
}
if ((Object)(object)_holes != (Object)null)
{
((Component)_holes).transform.SetParent((Transform)null, true);
}
}
private void LateUpdate()
{
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: 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_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
if (_released)
{
return;
}
if ((Object)(object)_holes != (Object)null)
{
((Component)_holes).transform.position = ((Component)this).transform.position;
((Component)_holes).transform.rotation = ((Component)this).transform.rotation;
}
_frames++;
float deltaTime = Time.deltaTime;
Vector3 val = ((Component)this).transform.position - _last;
float magnitude = ((Vector3)(ref val)).magnitude;
_last = ((Component)this).transform.position;
if (deltaTime <= 0f)
{
return;
}
if (magnitude < StillDistance)
{
_stillTime += deltaTime;
}
else
{
_stillTime = 0f;
}
if (_frames <= GraceFrames)
{
return;
}
bool flag;
if ((Object)(object)_pierce != (Object)null && ((Behaviour)_pierce).enabled)
{
flag = _pierce.IsLanded;
}
else
{
flag = _stillTime >= StillTimeToLand;
if (!flag && (object)_movingField != null && (Object)(object)_projectile != (Object)null)
{
object value = _movingField.GetValue(_projectile);
if (value is bool && !(bool)value)
{
flag = true;
}
}
}
if (flag)
{
Release();
}
}
private void OnApplicationQuit()
{
_quitting = true;
}
private void OnDestroy()
{
if (!_quitting)
{
Release();
}
}
private void Release()
{
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: 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)
if (!_released)
{
_released = true;
if ((Object)(object)_jitter != (Object)null)
{
((Behaviour)_jitter).enabled = false;
}
if ((Object)(object)_trail != (Object)null)
{
((Renderer)_trail).enabled = true;
SWAS_TrailFade sWAS_TrailFade = ((Component)_trail).gameObject.AddComponent<SWAS_TrailFade>();
sWAS_TrailFade.Duration = TrailFadeDuration;
Object.Destroy((Object)(object)((Component)_trail).gameObject, TrailFadeDuration + _trail.time + ExtraLinger);
}
if ((Object)(object)_holes != (Object)null)
{
_holes.Stop(false, (ParticleSystemStopBehavior)1);
MainModule main = _holes.main;
MinMaxCurve startLifetime = ((MainModule)(ref main)).startLifetime;
float constantMax = ((MinMaxCurve)(ref startLifetime)).constantMax;
Object.Destroy((Object)(object)((Component)_holes).gameObject, constantMax + ExtraLinger);
}
}
}
}
[DefaultExecutionOrder(1000)]
public class TwoHandStabilizer : MonoBehaviour
{
private struct Accessor
{
public FieldInfo Field;
public PropertyInfo Prop;
}
[DefaultExecutionOrder(-10000)]
private class RestoreHook : MonoBehaviour
{
public TwoHandStabilizer Owner;
private void FixedUpdate()
{
if ((Object)(object)Owner != (Object)null)
{
Owner.RestoreRaw();
}
}
private void Update()
{
if ((Object)(object)Owner != (Object)null)
{
Owner.RestoreRaw();
}
}
}
public MonoBehaviour Firearm;
public Transform RecoilHolder;
public Transform GripPose;
public float HandsTogetherDistance = 0.16f;
public float ReleaseDistanceMultiplier = 1.4f;
public float RecoilMultiplier = 0.4f;
public float BlendSpeed = 6f;
public bool Debug = false;
private float _stab;
private bool _together;
private bool _warned;
private Vector3 _restPos;
private Quaternion _restRot;
private Vector3 _rawPos;
private Quaternion _rawRot;
private bool _modified;
private RestoreHook _hook;
private static readonly Dictionary<Type, Dictionary<string, Accessor>> _accessors = new Dictionary<Type, Dictionary<string, Accessor>>();
public bool IsTwoHanded => _stab > 0.5f;
private void Awake()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_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)
if ((Object)(object)RecoilHolder != (Object)null)
{
_restPos = RecoilHolder.localPosition;
_restRot = RecoilHolder.localRotation;
_hook = ((Component)this).gameObject.AddComponent<RestoreHook>();
_hook.Owner = this;
((Behaviour)_hook).enabled = false;
}
}
private void OnDisable()
{
RestoreRaw();
}
internal void RestoreRaw()
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
if (_modified && !((Object)(object)RecoilHolder == (Object)null))
{
RecoilHolder.localPosition = _rawPos;
RecoilHolder.localRotation = _rawRot;
_modified = false;
}
}
private static Accessor Resolve(Type type, string name)
{
if (!_accessors.TryGetValue(type, out var value))
{
value = new Dictionary<string, Accessor>();
_accessors[type] = value;
}
if (value.TryGetValue(name, out var value2))
{
return value2;
}
Type type2 = type;
while ((object)type2 != null)
{
FieldInfo field = type2.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if ((object)field != null)
{
value2.Field = field;
break;
}
PropertyInfo property = type2.GetProperty(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if ((object)property != null && property.CanRead && property.GetIndexParameters().Length == 0)
{
value2.Prop = property;
break;
}
type2 = type2.BaseType;
}
value[name] = value2;
return value2;
}
private static object Get(object o, string name)
{
if (o == null)
{
return null;
}
Accessor accessor = Resolve(o.GetType(), name);
if ((object)accessor.Field != null)
{
return accessor.Field.GetValue(o);
}
if ((object)accessor.Prop != null)
{
return accessor.Prop.GetValue(o, null);
}
return null;
}
private bool TwoHandsTogether()
{
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
object obj = Get(Firearm, "m_hand");
Component val = (Component)((obj is Component) ? obj : null);
if ((Object)(object)val == (Object)null)
{
return false;
}
object obj2 = Get(val, "OtherHand");
Component val2 = (Component)((obj2 is Component) ? obj2 : null);
if ((Object)(object)val2 == (Object)null)
{
if (Debug && !_warned)
{
_warned = true;
Debug.LogWarning((object)"TwoHandStabilizer: couldn't read OtherHand from the hand component.");
}
return false;
}
object obj3 = Get(val2, "CurrentInteractable");
Object val3 = (Object)((obj3 is Object) ? obj3 : null);
if (val3 != (Object)null)
{
return false;
}
float num = ((!_together) ? HandsTogetherDistance : (HandsTogetherDistance * ReleaseDistanceMultiplier));
float num2 = Vector3.Distance(val.transform.position, val2.transform.position);
if (num2 > num)
{
return false;
}
float num3 = ((!_together) ? 0.3f : (0.3f * ReleaseDistanceMultiplier));
if ((Object)(object)GripPose != (Object)null && Vector3.Distance(GripPose.position, val2.transform.position) > num3)
{
return false;
}
return true;
}
private void LateUpdate()
{
//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_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_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_0164: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Firearm == (Object)null || (Object)(object)RecoilHolder == (Object)null)
{
return;
}
if (_stab <= 0f && Get(Firearm, "m_hand") == null)
{
_together = false;
return;
}
_together = TwoHandsTogether();
float num = ((!_together) ? 0f : 1f);
_stab = Mathf.MoveTowards(_stab, num, BlendSpeed * Time.deltaTime);
if (_stab <= 0f)
{
_modified = false;
if ((Object)(object)_hook != (Object)null)
{
((Behaviour)_hook).enabled = false;
}
return;
}
if ((Object)(object)_hook != (Object)null)
{
((Behaviour)_hook).enabled = true;
}
_rawPos = RecoilHolder.localPosition;
_rawRot = RecoilHolder.localRotation;
float num2 = Mathf.SmoothStep(0f, 1f, _stab);
float num3 = Mathf.Lerp(1f, RecoilMultiplier, num2);
RecoilHolder.localPosition = Vector3.Lerp(_restPos, _rawPos, num3);
RecoilHolder.localRotation = Quaternion.Slerp(_restRot, _rawRot, num3);
_modified = true;
}
}