using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("Niko666")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Sweep your gun/magazine/clip/speedloader over a quickbelt slot that holds magazine/cartridge/clip/speedloader and the gun/magazine/clip/speedloader reloads itself, arcade style.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Niko666.ArcadeReload")]
[assembly: AssemblyTitle("ArcadeReload")]
[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;
}
}
}
namespace BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
{
}
}
}
namespace Niko666
{
internal static class AmmoTransfer
{
public static bool TryArcadeReload(ReloadTarget target, FVRQuickBeltSlot slot, bool replaceSpentCasings, int maxRounds, int roundOffset, out string report)
{
report = null;
if (!target.IsValid || (Object)(object)slot == (Object)null)
{
return false;
}
FVRPhysicalObject curObject = slot.CurObject;
if ((Object)(object)curObject == (Object)null)
{
return false;
}
bool isSpawnLock = curObject.m_isSpawnLock;
FVRFireArmMagazine val = (FVRFireArmMagazine)(object)((curObject is FVRFireArmMagazine) ? curObject : null);
FVRFireArmRound beltRounds = (FVRFireArmRound)(object)((curObject is FVRFireArmRound) ? curObject : null);
FVRFireArmClip val2 = (FVRFireArmClip)(object)((curObject is FVRFireArmClip) ? curObject : null);
if (target.IsHeldContainer)
{
if ((Object)(object)target.HeldSpeedloader != (Object)null)
{
if ((Object)(object)val2 != (Object)null)
{
return SpeedloaderFromClip(target, val2, isSpawnLock, maxRounds, roundOffset, out report);
}
if ((Object)(object)beltRounds != (Object)null)
{
return SpeedloaderFromRounds(target, ref beltRounds, slot, isSpawnLock, maxRounds, roundOffset, out report);
}
return false;
}
if ((Object)(object)val != (Object)null)
{
return HeldFromMagazine(target, val, isSpawnLock, out report);
}
if ((Object)(object)val2 != (Object)null)
{
return HeldFromClip(target, val2, isSpawnLock, maxRounds, roundOffset, out report);
}
if ((Object)(object)beltRounds != (Object)null)
{
return HeldFromRounds(target, ref beltRounds, slot, isSpawnLock, maxRounds, roundOffset, out report);
}
return false;
}
Speedloader val3 = (Speedloader)(object)((curObject is Speedloader) ? curObject : null);
if ((Object)(object)val3 != (Object)null)
{
return LoadCylinderFromSpeedloader(target, val3, isSpawnLock, out report);
}
if ((Object)(object)val != (Object)null)
{
return BeltMagazineIntoGun(target, val, isSpawnLock, out report);
}
if ((Object)(object)val2 != (Object)null)
{
return BeltClipIntoGun(target, val2, isSpawnLock, maxRounds, roundOffset, out report);
}
if ((Object)(object)beltRounds != (Object)null)
{
return BeltRoundsIntoGun(target, ref beltRounds, slot, isSpawnLock, replaceSpentCasings, maxRounds, roundOffset, out report);
}
return false;
}
private static bool HeldFromMagazine(ReloadTarget target, FVRFireArmMagazine beltMagazine, bool spawnLocked, out string report)
{
report = null;
FVRFireArmMagazine heldMagazine = target.HeldMagazine;
if ((Object)(object)heldMagazine == (Object)null)
{
return false;
}
return FillMagazineFromMagazine(target, heldMagazine, beltMagazine, spawnLocked, out report);
}
private static bool HeldFromClip(ReloadTarget target, FVRFireArmClip beltClip, bool spawnLocked, int maxRounds, int roundOffset, out string report)
{
//IL_0034: 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)
report = null;
FVRFireArmMagazine heldMagazine = target.HeldMagazine;
if ((Object)(object)heldMagazine != (Object)null)
{
return FillMagazineFromClip(target, heldMagazine, beltClip, spawnLocked, maxRounds, roundOffset, out report);
}
FVRFireArmClip heldClip = target.HeldClip;
if ((Object)(object)heldClip != (Object)null && heldClip.ClipType == beltClip.ClipType)
{
return FillClipFromClip(target, heldClip, beltClip, spawnLocked, maxRounds, roundOffset, out report);
}
return false;
}
private static bool HeldFromRounds(ReloadTarget target, ref FVRFireArmRound beltRounds, FVRQuickBeltSlot slot, bool spawnLocked, int maxRounds, int roundOffset, out string report)
{
report = null;
FVRFireArmMagazine heldMagazine = target.HeldMagazine;
if ((Object)(object)heldMagazine != (Object)null)
{
return FillMagazineFromRounds(target, heldMagazine, ref beltRounds, slot, spawnLocked, maxRounds, roundOffset, out report);
}
FVRFireArmClip heldClip = target.HeldClip;
if ((Object)(object)heldClip != (Object)null)
{
return FillClipFromRounds(target, heldClip, ref beltRounds, slot, spawnLocked, maxRounds, roundOffset, out report);
}
return false;
}
private static bool SpeedloaderFromRounds(ReloadTarget target, ref FVRFireArmRound beltRounds, FVRQuickBeltSlot slot, bool spawnLocked, int maxRounds, int roundOffset, out string report)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
report = null;
Speedloader heldSpeedloader = target.HeldSpeedloader;
if ((Object)(object)heldSpeedloader == (Object)null)
{
return false;
}
if (beltRounds.RoundType != ReloadTarget.SpeedloaderChamberType(heldSpeedloader))
{
return false;
}
int num = ReloadTarget.FreeSpeedloaderChambers(heldSpeedloader);
if (num <= 0)
{
return false;
}
int num2 = Mathf.Min(num, CountRoundsInStack(beltRounds));
if (maxRounds > 0 && num2 > maxRounds)
{
num2 = maxRounds;
}
if (num2 <= 0)
{
return false;
}
int num3 = 0;
for (int i = 0; i < num2; i++)
{
FireArmRoundClass roundClass;
if (spawnLocked)
{
roundClass = PeekRoundClass(beltRounds, roundOffset + i);
}
else if (!TryTakeRound(ref beltRounds, slot, out roundClass))
{
break;
}
if (!LoadSpeedloaderChamber(heldSpeedloader, roundClass))
{
break;
}
num3++;
}
if (num3 <= 0)
{
return false;
}
report = num3 + " round(s) from the belt into the speedloader";
return true;
}
private static bool SpeedloaderFromClip(ReloadTarget target, FVRFireArmClip beltClip, bool spawnLocked, int maxRounds, int roundOffset, out string report)
{
//IL_0017: 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_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_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
report = null;
Speedloader heldSpeedloader = target.HeldSpeedloader;
if ((Object)(object)heldSpeedloader == (Object)null)
{
return false;
}
if (beltClip.RoundType != ReloadTarget.SpeedloaderChamberType(heldSpeedloader))
{
return false;
}
int num = ReloadTarget.FreeSpeedloaderChambers(heldSpeedloader);
int numRounds = beltClip.m_numRounds;
if (num <= 0 || numRounds <= 0)
{
return false;
}
int num2 = Mathf.Min(num, numRounds);
if (maxRounds > 0 && num2 > maxRounds)
{
num2 = maxRounds;
}
int num3 = 0;
for (int i = 0; i < num2; i++)
{
FireArmRoundClass roundClass;
if (spawnLocked)
{
int num4 = PeekClipIndex(numRounds, roundOffset + i);
if (num4 < 0 || num4 >= beltClip.LoadedRounds.Length || beltClip.LoadedRounds[num4] == null)
{
break;
}
roundClass = beltClip.LoadedRounds[num4].LR_Class;
}
else
{
if (beltClip.m_numRounds <= 0)
{
break;
}
roundClass = beltClip.RemoveRoundReturnClass();
}
if (!LoadSpeedloaderChamber(heldSpeedloader, roundClass))
{
break;
}
num3++;
}
if (num3 <= 0)
{
return false;
}
report = num3 + " round(s) from a clip into the speedloader";
return true;
}
private static bool LoadSpeedloaderChamber(Speedloader loader, FireArmRoundClass roundClass)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
List<SpeedloaderChamber> list = (((Object)(object)loader == (Object)null) ? null : loader.Chambers);
if (list == null)
{
return false;
}
for (int i = 0; i < list.Count; i++)
{
SpeedloaderChamber val = list[i];
if (!((Object)(object)val == (Object)null) && !val.IsLoaded)
{
val.Load(roundClass, true);
return true;
}
}
return false;
}
private static bool BeltMagazineIntoGun(ReloadTarget target, FVRFireArmMagazine beltMagazine, bool spawnLocked, out string report)
{
//IL_0031: 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_005c: 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_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
report = null;
if (target.FireArm is RevolvingShotgun || target.FireArm is GrappleGun)
{
return false;
}
FVRFireArmMagazine gunMagazine = target.GunMagazine;
if ((Object)(object)gunMagazine != (Object)null && gunMagazine.MagazineType == beltMagazine.MagazineType && !gunMagazine.IsFull())
{
return FillMagazineFromMagazine(target, gunMagazine, beltMagazine, spawnLocked, out report);
}
if ((Object)(object)gunMagazine == (Object)null && (int)target.MagazineType != 0 && beltMagazine.MagazineType == target.MagazineType && (Object)(object)target.GetMagMountPos(beltMagazine.IsBeltBox) != (Object)null)
{
return InsertMagazine(target, beltMagazine, spawnLocked, out report);
}
SecondaryMagazineSlot[] secondarySlots = target.SecondarySlots;
if (secondarySlots == null)
{
return false;
}
FVRFireArmMagazine val = FindSecondaryMagazine(secondarySlots, beltMagazine.MagazineType, beltMagazine.RoundType);
if ((Object)(object)val != (Object)null)
{
return FillMagazineFromMagazine(target, val, beltMagazine, spawnLocked, out report);
}
if (beltMagazine.MagazineType != target.MagazineType)
{
return false;
}
int num = FindEmptySecondarySlot(secondarySlots);
if (num >= 0)
{
return InsertMagazineIntoSecondary(target, beltMagazine, num, spawnLocked, out report);
}
return false;
}
private static bool InsertMagazineIntoSecondary(ReloadTarget target, FVRFireArmMagazine beltMagazine, int slotIndex, bool spawnLocked, out string report)
{
report = null;
if ((Object)(object)target.FireArm == (Object)null)
{
return false;
}
FVRFireArmMagazine val = beltMagazine;
if (spawnLocked)
{
GameObject val2 = ((FVRPhysicalObject)beltMagazine).DuplicateFromSpawnLock((FVRViveHand)null);
if ((Object)(object)val2 == (Object)null)
{
return false;
}
val = val2.GetComponent<FVRFireArmMagazine>();
if ((Object)(object)val == (Object)null)
{
Object.Destroy((Object)(object)val2);
return false;
}
}
else
{
((FVRPhysicalObject)val).ClearQuickbeltState();
}
((FVRPhysicalObject)val).m_isSpawnLock = false;
val.LoadIntoSecondary(target.FireArm, slotIndex);
SecondaryMagazineSlot[] secondarySlots = target.SecondarySlots;
if (secondarySlots == null || slotIndex < 0 || slotIndex >= secondarySlots.Length || secondarySlots[slotIndex] == null || (Object)(object)secondarySlots[slotIndex].Magazine != (Object)(object)val)
{
return false;
}
report = (spawnLocked ? "spawn locked magazine copied into the secondary slot" : "magazine parked in the secondary slot");
return true;
}
private static FVRFireArmMagazine FindSecondaryMagazine(SecondaryMagazineSlot[] secondaries, FireArmMagazineType magazineType, FireArmRoundType roundType)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < secondaries.Length; i++)
{
FVRFireArmMagazine val = ((secondaries[i] == null) ? null : secondaries[i].Magazine);
if (!((Object)(object)val == (Object)null) && !val.IsFull() && val.MagazineType == magazineType && val.RoundType == roundType)
{
return val;
}
}
return null;
}
private static int FindEmptySecondarySlot(SecondaryMagazineSlot[] secondaries)
{
for (int i = 0; i < secondaries.Length; i++)
{
if (secondaries[i] != null && (Object)(object)secondaries[i].Magazine == (Object)null)
{
return i;
}
}
return -1;
}
private static FVRFireArmMagazine FindMagazineWithSpace(ReloadTarget target, FireArmRoundType roundType)
{
//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_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
FVRFireArmMagazine gunMagazine = target.GunMagazine;
if ((Object)(object)gunMagazine != (Object)null && gunMagazine.RoundType == roundType && !gunMagazine.IsFull())
{
return gunMagazine;
}
SecondaryMagazineSlot[] secondarySlots = target.SecondarySlots;
if (secondarySlots == null)
{
return null;
}
for (int i = 0; i < secondarySlots.Length; i++)
{
FVRFireArmMagazine val = ((secondarySlots[i] == null) ? null : secondarySlots[i].Magazine);
if ((Object)(object)val != (Object)null && val.RoundType == roundType && !val.IsFull())
{
return val;
}
}
return null;
}
private static bool BeltClipIntoGun(ReloadTarget target, FVRFireArmClip beltClip, bool spawnLocked, int maxRounds, int roundOffset, out string report)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: 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_0080: Unknown result type (might be due to invalid IL or missing references)
report = null;
FVRFireArmMagazine val = FindMagazineWithSpace(target, beltClip.RoundType);
if ((Object)(object)val != (Object)null)
{
return FillMagazineFromClip(target, val, beltClip, spawnLocked, maxRounds, roundOffset, out report);
}
FVRFireArmClip gunClip = target.GunClip;
if ((Object)(object)gunClip != (Object)null && gunClip.ClipType == beltClip.ClipType)
{
return FillClipFromClip(target, gunClip, beltClip, spawnLocked, maxRounds, roundOffset, out report);
}
if ((Object)(object)target.GunMagazine == (Object)null && (int)target.ClipType != 0 && !target.IsAttachable && beltClip.ClipType == target.ClipType && (Object)(object)target.ClipMountPos != (Object)null)
{
return InsertClip(target, beltClip, spawnLocked, out report);
}
return false;
}
private static bool BeltRoundsIntoGun(ReloadTarget target, ref FVRFireArmRound beltRounds, FVRQuickBeltSlot slot, bool spawnLocked, bool replaceSpentCasings, int maxRounds, int roundOffset, out string report)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
report = null;
FVRFireArmMagazine val = FindMagazineWithSpace(target, beltRounds.RoundType);
if ((Object)(object)val != (Object)null)
{
return FillMagazineFromRounds(target, val, ref beltRounds, slot, spawnLocked, maxRounds, roundOffset, out report);
}
FVRFireArmClip gunClip = target.GunClip;
if ((Object)(object)gunClip != (Object)null && gunClip.RoundType == beltRounds.RoundType)
{
return FillClipFromRounds(target, gunClip, ref beltRounds, slot, spawnLocked, maxRounds, roundOffset, out report);
}
return FillChambers(target, ref beltRounds, slot, spawnLocked, replaceSpentCasings, maxRounds, roundOffset, out report);
}
private static bool FillMagazineFromMagazine(ReloadTarget target, FVRFireArmMagazine gunMagazine, FVRFireArmMagazine beltMagazine, bool spawnLocked, out string report)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
report = null;
if (beltMagazine.RoundType != gunMagazine.RoundType)
{
return false;
}
int num = gunMagazine.m_capacity - gunMagazine.m_numRounds;
int numRounds = beltMagazine.m_numRounds;
if (num <= 0 || numRounds <= 0)
{
return false;
}
int num2 = Mathf.Min(num, numRounds);
int num3 = 0;
for (int i = 0; i < num2; i++)
{
FireArmRoundClass lR_Class;
if (spawnLocked)
{
int num4 = beltMagazine.m_numRounds - 1 - i;
if (num4 < 0 || beltMagazine.LoadedRounds[num4] == null)
{
break;
}
lR_Class = beltMagazine.LoadedRounds[num4].LR_Class;
}
else
{
if (beltMagazine.m_numRounds <= 0)
{
break;
}
FVRLoadedRound val = beltMagazine.RemoveRound(beltMagazine.m_numRounds - 1);
if (val == null)
{
break;
}
lR_Class = val.LR_Class;
}
gunMagazine.AddRound(lR_Class, false, false);
num3++;
}
if (num3 <= 0)
{
return false;
}
gunMagazine.UpdateBulletDisplay();
target.PlayReloadSound();
report = num3 + " round(s) from a magazine into the magazine";
return true;
}
private static bool FillMagazineFromClip(ReloadTarget target, FVRFireArmMagazine gunMagazine, FVRFireArmClip beltClip, bool spawnLocked, int maxRounds, int roundOffset, out string report)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: 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_00b9: 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)
report = null;
if (beltClip.RoundType != gunMagazine.RoundType)
{
return false;
}
if ((int)target.ClipType != 0 && beltClip.ClipType != target.ClipType)
{
return false;
}
int num = gunMagazine.m_capacity - gunMagazine.m_numRounds;
int numRounds = beltClip.m_numRounds;
if (num <= 0 || numRounds <= 0)
{
return false;
}
int num2 = Mathf.Min(num, numRounds);
if (maxRounds > 0 && num2 > maxRounds)
{
num2 = maxRounds;
}
int num3 = 0;
for (int i = 0; i < num2; i++)
{
FireArmRoundClass val;
if (spawnLocked)
{
int num4 = PeekClipIndex(numRounds, roundOffset + i);
if (num4 < 0 || num4 >= beltClip.LoadedRounds.Length || beltClip.LoadedRounds[num4] == null)
{
break;
}
val = beltClip.LoadedRounds[num4].LR_Class;
}
else
{
if (beltClip.m_numRounds <= 0)
{
break;
}
val = beltClip.RemoveRoundReturnClass();
}
gunMagazine.AddRound(val, false, false);
num3++;
}
if (num3 <= 0)
{
return false;
}
gunMagazine.UpdateBulletDisplay();
target.PlayReloadSound();
report = num3 + " round(s) from a clip into the magazine";
return true;
}
private static bool FillMagazineFromRounds(ReloadTarget target, FVRFireArmMagazine gunMagazine, ref FVRFireArmRound beltRounds, FVRQuickBeltSlot slot, bool spawnLocked, int maxRounds, int roundOffset, out string report)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
report = null;
if (beltRounds.RoundType != gunMagazine.RoundType)
{
return false;
}
int num = Mathf.Min(gunMagazine.m_capacity - gunMagazine.m_numRounds, CountRoundsInStack(beltRounds));
if (maxRounds > 0 && num > maxRounds)
{
num = maxRounds;
}
if (num <= 0)
{
return false;
}
int num2 = 0;
for (int i = 0; i < num; i++)
{
FireArmRoundClass roundClass;
if (spawnLocked)
{
roundClass = PeekRoundClass(beltRounds, roundOffset + i);
}
else if (!TryTakeRound(ref beltRounds, slot, out roundClass))
{
break;
}
gunMagazine.AddRound(roundClass, false, false);
num2++;
}
if (num2 <= 0)
{
return false;
}
gunMagazine.UpdateBulletDisplay();
target.PlayReloadSound();
report = num2 + " round(s) from the belt into the magazine";
return true;
}
private static bool FillClipFromClip(ReloadTarget target, FVRFireArmClip gunClip, FVRFireArmClip beltClip, bool spawnLocked, int maxRounds, int roundOffset, out string report)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_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_009f: 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)
report = null;
if (beltClip.RoundType != gunClip.RoundType)
{
return false;
}
int num = gunClip.m_capacity - gunClip.m_numRounds;
int numRounds = beltClip.m_numRounds;
if (num <= 0 || numRounds <= 0)
{
return false;
}
int num2 = Mathf.Min(num, numRounds);
if (maxRounds > 0 && num2 > maxRounds)
{
num2 = maxRounds;
}
int num3 = 0;
for (int i = 0; i < num2; i++)
{
FireArmRoundClass val;
if (spawnLocked)
{
int num4 = PeekClipIndex(numRounds, roundOffset + i);
if (num4 < 0 || num4 >= beltClip.LoadedRounds.Length || beltClip.LoadedRounds[num4] == null)
{
break;
}
val = beltClip.LoadedRounds[num4].LR_Class;
}
else
{
if (beltClip.m_numRounds <= 0)
{
break;
}
val = beltClip.RemoveRoundReturnClass();
}
gunClip.AddRound(val, false, false);
num3++;
}
if (num3 <= 0)
{
return false;
}
gunClip.UpdateBulletDisplay();
report = num3 + " round(s) from a clip into the clip";
return true;
}
private static bool FillClipFromRounds(ReloadTarget target, FVRFireArmClip gunClip, ref FVRFireArmRound beltRounds, FVRQuickBeltSlot slot, bool spawnLocked, int maxRounds, int roundOffset, out string report)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
report = null;
if (beltRounds.RoundType != gunClip.RoundType)
{
return false;
}
int num = Mathf.Min(gunClip.m_capacity - gunClip.m_numRounds, CountRoundsInStack(beltRounds));
if (maxRounds > 0 && num > maxRounds)
{
num = maxRounds;
}
if (num <= 0)
{
return false;
}
int num2 = 0;
for (int i = 0; i < num; i++)
{
FireArmRoundClass roundClass;
if (spawnLocked)
{
roundClass = PeekRoundClass(beltRounds, roundOffset + i);
}
else if (!TryTakeRound(ref beltRounds, slot, out roundClass))
{
break;
}
gunClip.AddRound(roundClass, false, false);
num2++;
}
if (num2 <= 0)
{
return false;
}
gunClip.UpdateBulletDisplay();
report = num2 + " round(s) from the belt into the clip";
return true;
}
private static int PeekClipIndex(int available, int position)
{
if (available <= 0)
{
return -1;
}
int num = position % available;
if (num < 0)
{
num += available;
}
return available - 1 - num;
}
private static bool InsertMagazine(ReloadTarget target, FVRFireArmMagazine beltMagazine, bool spawnLocked, out string report)
{
report = null;
FVRFireArmMagazine val = beltMagazine;
if (spawnLocked)
{
GameObject val2 = ((FVRPhysicalObject)beltMagazine).DuplicateFromSpawnLock((FVRViveHand)null);
if ((Object)(object)val2 == (Object)null)
{
return false;
}
val = val2.GetComponent<FVRFireArmMagazine>();
if ((Object)(object)val == (Object)null)
{
Object.Destroy((Object)(object)val2);
return false;
}
}
else
{
((FVRPhysicalObject)val).ClearQuickbeltState();
}
((FVRPhysicalObject)val).m_isSpawnLock = false;
target.InsertMagazine(val);
if (!target.MagazineIsPresent(val))
{
return false;
}
report = (spawnLocked ? "spawn locked magazine copied into the gun" : "magazine from the belt inserted");
return true;
}
private static bool InsertClip(ReloadTarget target, FVRFireArmClip beltClip, bool spawnLocked, out string report)
{
report = null;
FVRFireArmClip val = beltClip;
if (spawnLocked)
{
GameObject val2 = ((FVRPhysicalObject)beltClip).DuplicateFromSpawnLock((FVRViveHand)null);
if ((Object)(object)val2 == (Object)null)
{
return false;
}
val = val2.GetComponent<FVRFireArmClip>();
if ((Object)(object)val == (Object)null)
{
Object.Destroy((Object)(object)val2);
return false;
}
}
else
{
((FVRPhysicalObject)val).ClearQuickbeltState();
}
((FVRPhysicalObject)val).m_isSpawnLock = false;
val.Load(target.FireArm);
if ((Object)(object)target.GunClip != (Object)(object)val)
{
return false;
}
report = (spawnLocked ? "spawn locked clip copied into the gun" : "clip from the belt inserted");
return true;
}
private static bool LoadCylinderFromSpeedloader(ReloadTarget target, Speedloader beltSpeedloader, bool spawnLocked, out string report)
{
//IL_00b3: 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)
report = null;
List<SpeedloaderChamber> chambers = beltSpeedloader.Chambers;
if (chambers == null || chambers.Count == 0)
{
return false;
}
FVRFireArm fireArm = target.FireArm;
RevolvingShotgun val = (RevolvingShotgun)(object)((fireArm is RevolvingShotgun) ? fireArm : null);
if ((Object)(object)val != (Object)null)
{
return InsertCylinderIntoRevolvingShotgun(val, beltSpeedloader, spawnLocked, out report);
}
FVRFireArm fireArm2 = target.FireArm;
GrappleGun val2 = (GrappleGun)(object)((fireArm2 is GrappleGun) ? fireArm2 : null);
if ((Object)(object)val2 != (Object)null)
{
return InsertCylinderIntoGrappleGun(val2, beltSpeedloader, spawnLocked, out report);
}
if (target.ChamberCount == 0)
{
return false;
}
if (!HasSpareChamber(target))
{
return false;
}
if (!HasLiveRound(chambers))
{
return false;
}
FVRFireArm fireArm3 = target.FireArm;
Revolver val3 = (Revolver)(object)((fireArm3 is Revolver) ? fireArm3 : null);
if ((Object)(object)val3 != (Object)null && (Object)(object)val3.Cylinder != (Object)null)
{
if ((Object)(object)chambers[0] == (Object)null || chambers[0].Type != target.RoundType)
{
return false;
}
if (!((FVRInteractiveObject)val3.Cylinder).IsInteractable() || !val3.Cylinder.CanAccept())
{
return false;
}
Speedloader val4 = beltSpeedloader;
if (spawnLocked)
{
val4 = DuplicateSpeedloader(beltSpeedloader);
if ((Object)(object)val4 == (Object)null)
{
return false;
}
}
else
{
((FVRPhysicalObject)val4).ClearQuickbeltState();
}
val3.Cylinder.LoadFromSpeedLoader(val4);
if (val4.InjectsOnInsertion)
{
Object.Destroy((Object)(object)((Component)val4).gameObject);
}
report = "cylinder loaded from a speedloader";
return true;
}
return FillChambersFromSpeedloader(target, chambers, spawnLocked, out report);
}
private static bool InsertCylinderIntoRevolvingShotgun(RevolvingShotgun gun, Speedloader beltCylinder, bool spawnLocked, out string report)
{
//IL_000f: 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)
report = null;
if (gun.CylinderLoaded)
{
return false;
}
if (!CylinderFitsGun(beltCylinder, ((FVRFireArm)gun).RoundType, gun.SLType, (gun.Chambers != null) ? gun.Chambers.Length : 0))
{
return false;
}
Speedloader val = beltCylinder;
if (spawnLocked)
{
val = DuplicateSpeedloader(beltCylinder);
if ((Object)(object)val == (Object)null)
{
return false;
}
}
else
{
((FVRPhysicalObject)val).ClearQuickbeltState();
}
gun.LoadCylinder(val);
if (!gun.CylinderLoaded)
{
return false;
}
Object.Destroy((Object)(object)((Component)val).gameObject);
report = (spawnLocked ? "spawn locked cylinder copied into the gun" : "cylinder from the belt inserted");
return true;
}
private static bool InsertCylinderIntoGrappleGun(GrappleGun gun, Speedloader beltCylinder, bool spawnLocked, out string report)
{
//IL_000f: 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)
report = null;
if (gun.IsMagLoaded)
{
return false;
}
if (!CylinderFitsGun(beltCylinder, ((FVRFireArm)gun).RoundType, gun.SLType, 0))
{
return false;
}
Speedloader val = beltCylinder;
if (spawnLocked)
{
val = DuplicateSpeedloader(beltCylinder);
if ((Object)(object)val == (Object)null)
{
return false;
}
}
else
{
((FVRPhysicalObject)val).ClearQuickbeltState();
}
gun.LoadCylinder(val);
if (!gun.IsMagLoaded)
{
return false;
}
Object.Destroy((Object)(object)((Component)val).gameObject);
report = (spawnLocked ? "spawn locked grapple cylinder copied into the gun" : "grapple cylinder from the belt inserted");
return true;
}
private static bool CylinderFitsGun(Speedloader cylinder, FireArmRoundType roundType, SpeedLoaderType slType, int chamberCount)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)cylinder == (Object)null || cylinder.SLType != slType)
{
return false;
}
List<SpeedloaderChamber> chambers = cylinder.Chambers;
if (chambers == null || chambers.Count == 0 || (Object)(object)chambers[0] == (Object)null || chambers[0].Type != roundType)
{
return false;
}
if (chamberCount > 0 && chambers.Count < chamberCount)
{
return false;
}
return HasLiveRound(chambers);
}
private static bool FillChambersFromSpeedloader(ReloadTarget target, List<SpeedloaderChamber> loaderChambers, bool spawnLocked, out string report)
{
//IL_0026: 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_009e: 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_0063: 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)
report = null;
int num = 0;
int num2 = 0;
for (int i = 0; i < target.ChamberCount; i++)
{
FVRFireArmChamber val = target.ChamberAt(i);
if ((Object)(object)val == (Object)null || !ChamberAcceptsRound(target, val, val.RoundType, replaceSpentCasings: false))
{
continue;
}
SpeedloaderChamber val2 = null;
while (num < loaderChambers.Count)
{
SpeedloaderChamber val3 = loaderChambers[num];
num++;
if ((Object)(object)val3 != (Object)null && val3.IsLoaded && !val3.IsSpent && val3.Type == val.RoundType)
{
val2 = val3;
break;
}
}
if ((Object)(object)val2 == (Object)null)
{
break;
}
FireArmRoundClass loadedClass = val2.LoadedClass;
if (!spawnLocked)
{
val2.Unload();
}
LoadRoundIntoChamber(val, loadedClass, replaceSpentCasing: false);
num2++;
}
if (num2 <= 0)
{
return false;
}
PlayChamberingSound(target);
report = num2 + " round(s) from a speedloader";
return true;
}
private static Speedloader DuplicateSpeedloader(Speedloader template)
{
GameObject val = ((FVRPhysicalObject)template).DuplicateFromSpawnLock((FVRViveHand)null);
if ((Object)(object)val == (Object)null)
{
return null;
}
Speedloader component = val.GetComponent<Speedloader>();
if ((Object)(object)component == (Object)null)
{
Object.Destroy((Object)(object)val);
return null;
}
((FVRPhysicalObject)component).m_isSpawnLock = false;
return component;
}
private static bool FillChambers(ReloadTarget target, ref FVRFireArmRound beltRounds, FVRQuickBeltSlot slot, bool spawnLocked, bool replaceSpentCasings, int maxRounds, int roundOffset, out string report)
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
report = null;
if (target.ChamberCount == 0)
{
return false;
}
int num = CountRoundsInStack(beltRounds);
if (maxRounds > 0 && num > maxRounds)
{
num = maxRounds;
}
if (num <= 0)
{
return false;
}
int num2 = 0;
int num3 = 0;
for (int i = 0; i < target.ChamberCount; i++)
{
FVRFireArmChamber chamber = target.ChamberAt(i);
if (ChamberAcceptsRound(target, chamber, beltRounds.RoundType, replaceSpentCasings))
{
if (num3 >= num)
{
break;
}
FireArmRoundClass roundClass;
if (spawnLocked)
{
roundClass = PeekRoundClass(beltRounds, roundOffset + num3);
}
else if (!TryTakeRound(ref beltRounds, slot, out roundClass))
{
break;
}
num3++;
LoadRoundIntoChamber(chamber, roundClass, replaceSpentCasings);
num2++;
}
}
if (num2 <= 0)
{
return false;
}
PlayChamberingSound(target);
report = num2 + " round(s) from the belt into the chamber(s)";
return true;
}
private static bool ChamberAcceptsRound(ReloadTarget target, FVRFireArmChamber chamber, FireArmRoundType roundType, bool replaceSpentCasings)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)chamber == (Object)null || chamber.RoundType != roundType)
{
return false;
}
if (chamber.IsFull && (!replaceSpentCasings || !chamber.IsSpent))
{
return false;
}
if (IsCylinderStyle(target))
{
if (CylinderTracksOpenState(target))
{
return chamber.IsAccessible;
}
FVRFireArm fireArm = target.FireArm;
RevolvingShotgun val = (RevolvingShotgun)(object)((fireArm is RevolvingShotgun) ? fireArm : null);
if ((Object)(object)val != (Object)null)
{
return val.CylinderLoaded;
}
return true;
}
if (chamber.IsManuallyChamberable)
{
return chamber.IsAccessible;
}
return false;
}
private static bool CylinderTracksOpenState(ReloadTarget target)
{
FVRFireArm fireArm = target.FireArm;
if (!(fireArm is Revolver))
{
return fireArm is SingleActionRevolver;
}
return true;
}
private static void LoadRoundIntoChamber(FVRFireArmChamber chamber, FireArmRoundClass roundClass, bool replaceSpentCasing)
{
//IL_001e: 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_002f: 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_0041: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)chamber == (Object)null)
{
return;
}
try
{
if (chamber.IsFull)
{
if (!replaceSpentCasing)
{
return;
}
chamber.Unload();
}
if (AM.DoesClassExistForType(roundClass, chamber.RoundType))
{
chamber.SetRound(roundClass, ((Component)chamber).transform.position, ((Component)chamber).transform.rotation);
}
}
catch (Exception)
{
}
}
private static bool IsCylinderStyle(ReloadTarget target)
{
if (target.IsAttachable)
{
return false;
}
FVRFireArm fireArm = target.FireArm;
if (!(fireArm is Revolver) && !(fireArm is SingleActionRevolver))
{
return fireArm is RevolvingShotgun;
}
return true;
}
private static bool HasSpareChamber(ReloadTarget target)
{
for (int i = 0; i < target.ChamberCount; i++)
{
FVRFireArmChamber val = target.ChamberAt(i);
if ((Object)(object)val != (Object)null && !val.IsFull)
{
return true;
}
}
return false;
}
private static bool HasLiveRound(List<SpeedloaderChamber> chambers)
{
for (int i = 0; i < chambers.Count; i++)
{
SpeedloaderChamber val = chambers[i];
if ((Object)(object)val != (Object)null && val.IsLoaded && !val.IsSpent)
{
return true;
}
}
return false;
}
public static int CountRoundsInStack(FVRFireArmRound stack)
{
if ((Object)(object)stack == (Object)null)
{
return 0;
}
return 1 + (stack.ProxyRounds?.Count ?? 0);
}
private static FireArmRoundClass PeekRoundClass(FVRFireArmRound stack, int index)
{
//IL_0032: 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_005f: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)stack == (Object)null)
{
return (FireArmRoundClass)0;
}
List<ProxyRound> proxyRounds = stack.ProxyRounds;
int num = 1 + (proxyRounds?.Count ?? 0);
int num2 = index % num;
if (num2 < 0)
{
num2 += num;
}
if (num2 <= 0)
{
return stack.RoundClass;
}
int num3 = num2 - 1;
if (proxyRounds == null || num3 >= proxyRounds.Count || proxyRounds[num3] == null)
{
return stack.RoundClass;
}
return proxyRounds[num3].Class;
}
private static bool TryTakeRound(ref FVRFireArmRound stack, FVRQuickBeltSlot slot, out FireArmRoundClass roundClass)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Expected I4, but got Unknown
if ((Object)(object)stack == (Object)null)
{
roundClass = (FireArmRoundClass)0;
return false;
}
roundClass = (FireArmRoundClass)(int)stack.RoundClass;
List<ProxyRound> proxyRounds = stack.ProxyRounds;
int num = proxyRounds?.Count ?? 0;
if (num == 0)
{
((FVRPhysicalObject)stack).ClearQuickbeltState();
Object.Destroy((Object)(object)((Component)stack).gameObject);
return true;
}
if (IsStackUniform(stack))
{
int index = num - 1;
ProxyRound val = proxyRounds[index];
if ((Object)(object)val.GO != (Object)null)
{
Object.Destroy((Object)(object)val.GO);
}
proxyRounds.RemoveAt(index);
RefreshStackDisplay(stack);
return true;
}
if (PromoteFirstProxy(stack, slot, out var promoted))
{
stack = promoted;
return true;
}
return false;
}
private static bool IsStackUniform(FVRFireArmRound stack)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
FireArmRoundClass roundClass = stack.RoundClass;
List<ProxyRound> proxyRounds = stack.ProxyRounds;
if (proxyRounds == null)
{
return true;
}
for (int i = 0; i < proxyRounds.Count; i++)
{
if (proxyRounds[i] == null || proxyRounds[i].Class != roundClass)
{
return false;
}
}
return true;
}
private static bool PromoteFirstProxy(FVRFireArmRound stack, FVRQuickBeltSlot slot, out FVRFireArmRound promoted)
{
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
promoted = null;
List<ProxyRound> proxyRounds = stack.ProxyRounds;
if (proxyRounds == null || proxyRounds.Count == 0)
{
return false;
}
ProxyRound val = proxyRounds[0];
if (val == null || (Object)(object)val.ObjectWrapper == (Object)null)
{
return false;
}
GameObject val2 = null;
try
{
val2 = Object.Instantiate<GameObject>(((AnvilAsset)val.ObjectWrapper).GetGameObject(), ((Component)stack).transform.position, ((Component)stack).transform.rotation);
FVRFireArmRound component = val2.GetComponent<FVRFireArmRound>();
if ((Object)(object)component == (Object)null)
{
Object.Destroy((Object)(object)val2);
return false;
}
for (int i = 1; i < proxyRounds.Count; i++)
{
ProxyRound val3 = proxyRounds[i];
if (val3 != null && !((Object)(object)val3.GO == (Object)null))
{
val3.GO.transform.SetParent(((Component)component).transform, true);
component.ProxyRounds.Add(val3);
}
}
if ((Object)(object)val.GO != (Object)null)
{
Object.Destroy((Object)(object)val.GO);
}
proxyRounds.Clear();
((FVRPhysicalObject)stack).ClearQuickbeltState();
Object.Destroy((Object)(object)((Component)stack).gameObject);
component.UpdateProxyDisplay();
if ((Object)(object)slot != (Object)null)
{
((FVRPhysicalObject)component).SetQuickBeltSlot(slot);
}
promoted = component;
return true;
}
catch (Exception)
{
if ((Object)(object)val2 != (Object)null)
{
try
{
Object.Destroy((Object)(object)val2);
}
catch (Exception)
{
}
}
return false;
}
}
private static void RefreshStackDisplay(FVRFireArmRound stack)
{
try
{
stack.UpdateProxyDisplay();
}
catch (Exception)
{
}
}
private static void PlayChamberingSound(ReloadTarget target)
{
for (int i = 0; i < target.ChamberCount; i++)
{
FVRFireArmChamber val = target.ChamberAt(i);
if (!((Object)(object)val == (Object)null))
{
try
{
val.PlayChamberingAudio();
break;
}
catch (Exception)
{
break;
}
}
}
}
}
internal static class FireArmProbe
{
public static Vector3 GetFireArmProbePoint(FVRFireArm gun)
{
//IL_0009: 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_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: 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_0115: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)gun == (Object)null)
{
return Vector3.zero;
}
Revolver val = (Revolver)(object)((gun is Revolver) ? gun : null);
if ((Object)(object)val != (Object)null && (Object)(object)val.Cylinder != (Object)null)
{
return ((Component)val.Cylinder).transform.position;
}
SingleActionRevolver val2 = (SingleActionRevolver)(object)((gun is SingleActionRevolver) ? gun : null);
if ((Object)(object)val2 != (Object)null && (Object)(object)val2.Cylinder != (Object)null)
{
return ((Component)val2.Cylinder).transform.position;
}
RevolvingShotgun val3 = (RevolvingShotgun)(object)((gun is RevolvingShotgun) ? gun : null);
if ((Object)(object)val3 != (Object)null && (Object)(object)val3.ProxyCylinder != (Object)null)
{
return val3.ProxyCylinder.position;
}
Transform reloadTriggerWell = GetReloadTriggerWell(gun);
if ((Object)(object)reloadTriggerWell != (Object)null)
{
return reloadTriggerWell.position;
}
if ((Object)(object)gun.MagazineMountPos != (Object)null)
{
return gun.MagazineMountPos.position;
}
List<FVRFireArmChamber> chambers = gun.GetChambers();
if (chambers != null)
{
for (int i = 0; i < chambers.Count; i++)
{
if ((Object)(object)chambers[i] != (Object)null)
{
return ((Component)chambers[i]).transform.position;
}
}
}
return ((Component)gun).transform.position;
}
public static Vector3 GetHeldObjectProbePoint(FVRPhysicalObject held)
{
//IL_0009: 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_0021: 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_003a: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)held == (Object)null)
{
return Vector3.zero;
}
try
{
Rigidbody rootRigidbody = held.RootRigidbody;
if ((Object)(object)rootRigidbody != (Object)null)
{
return rootRigidbody.worldCenterOfMass;
}
}
catch (Exception)
{
}
return ((Component)held).transform.position;
}
public static void CollectAttachedFireArms(FVRFireArm gun, List<AttachableFirearm> results)
{
if ((Object)(object)gun == (Object)null || results == null)
{
return;
}
try
{
List<FVRFireArmAttachment> attachments = ((FVRPhysicalObject)gun).Attachments;
if (attachments == null)
{
return;
}
for (int i = 0; i < attachments.Count; i++)
{
FVRFireArmAttachment obj = attachments[i];
AttachableFirearmPhysicalObject val = (AttachableFirearmPhysicalObject)(object)((obj is AttachableFirearmPhysicalObject) ? obj : null);
if ((Object)(object)val != (Object)null && (Object)(object)val.FA != (Object)null)
{
results.Add(val.FA);
}
}
}
catch (Exception)
{
}
}
public static Vector3 GetAttachableProbePoint(AttachableFirearm attachable)
{
//IL_0009: 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_0038: 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_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)attachable == (Object)null)
{
return Vector3.zero;
}
AttachableTubeFed val = (AttachableTubeFed)(object)((attachable is AttachableTubeFed) ? attachable : null);
if ((Object)(object)val != (Object)null && (Object)(object)val.ReloadTriggerWell != (Object)null)
{
return val.ReloadTriggerWell.transform.position;
}
if ((Object)(object)attachable.MagazineMountPos != (Object)null)
{
return attachable.MagazineMountPos.position;
}
FVRFireArmChamber val2 = ReloadTarget.AttachableChamber(attachable);
if ((Object)(object)val2 != (Object)null)
{
return ((Component)val2).transform.position;
}
if ((Object)(object)attachable.Attachment != (Object)null)
{
return ((Component)attachable.Attachment).transform.position;
}
return ((Component)attachable).transform.position;
}
private static Transform GetReloadTriggerWell(FVRFireArm gun)
{
Handgun val = (Handgun)(object)((gun is Handgun) ? gun : null);
if ((Object)(object)val != (Object)null && (Object)(object)val.ReloadTriggerWell != (Object)null)
{
return val.ReloadTriggerWell.transform;
}
OpenBoltReceiver val2 = (OpenBoltReceiver)(object)((gun is OpenBoltReceiver) ? gun : null);
if ((Object)(object)val2 != (Object)null && (Object)(object)val2.ReloadTriggerWell != (Object)null)
{
return val2.ReloadTriggerWell.transform;
}
BoltActionRifle val3 = (BoltActionRifle)(object)((gun is BoltActionRifle) ? gun : null);
if ((Object)(object)val3 != (Object)null && (Object)(object)val3.ReloadTriggerWell != (Object)null)
{
return val3.ReloadTriggerWell.transform;
}
BAP val4 = (BAP)(object)((gun is BAP) ? gun : null);
if ((Object)(object)val4 != (Object)null && (Object)(object)val4.ReloadTriggerWell != (Object)null)
{
return val4.ReloadTriggerWell.transform;
}
TubeFedShotgun val5 = (TubeFedShotgun)(object)((gun is TubeFedShotgun) ? gun : null);
if ((Object)(object)val5 != (Object)null && (Object)(object)val5.ReloadTriggerWell != (Object)null)
{
return val5.ReloadTriggerWell.transform;
}
RailTater val6 = (RailTater)(object)((gun is RailTater) ? gun : null);
if ((Object)(object)val6 != (Object)null && (Object)(object)val6.ReloadTriggerWell != (Object)null)
{
return val6.ReloadTriggerWell.transform;
}
GrappleGun val7 = (GrappleGun)(object)((gun is GrappleGun) ? gun : null);
if ((Object)(object)val7 != (Object)null && (Object)(object)val7.ReloadTriggerWell != (Object)null)
{
return val7.ReloadTriggerWell.transform;
}
return null;
}
public static bool SlotContains(FVRQuickBeltSlot slot, Vector3 point, float radiusMultiplier)
{
//IL_000d: 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_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: 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_00a2: 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_0062: 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_0068: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)slot == (Object)null)
{
return false;
}
try
{
if (slot.IsPointInsideMe(point))
{
return true;
}
if (radiusMultiplier <= 1f)
{
return false;
}
float num = 0.5f * radiusMultiplier;
if ((int)slot.Shape == 0)
{
Transform val = (((Object)(object)slot.HoverGeo != (Object)null) ? slot.HoverGeo.transform : null);
if ((Object)(object)val != (Object)null)
{
Vector3 val2 = val.InverseTransformPoint(point);
if (((Vector3)(ref val2)).magnitude < num)
{
return true;
}
}
}
else if ((Object)(object)slot.RectBounds != (Object)null)
{
Vector3 val3 = slot.RectBounds.InverseTransformPoint(point);
if (Mathf.Abs(val3.x) < num && Mathf.Abs(val3.y) < num && Mathf.Abs(val3.z) < num)
{
return true;
}
}
return false;
}
catch (Exception)
{
return false;
}
}
}
[BepInProcess("h3vr.exe")]
[BepInPlugin("Niko666.ArcadeReload", "ArcadeReload", "1.0.0")]
public class ArcadeReload : BaseUnityPlugin
{
private struct ConfigSnapshot
{
public bool Enabled;
public float Cooldown;
public float RoundInterval;
public float Radius;
public bool AddedSlots;
public bool SpentCasings;
public bool Verbose;
}
private sealed class FeedState
{
public Object Owner;
public FVRQuickBeltSlot LastSlot;
public float LastReloadTime;
public bool Feeding;
public float NextRoundTime;
public int RoundsFed;
public int LastFrame = -1;
public int LastTakeFrame = -1;
public int LastContainerRounds = -1;
public float ContainerQuietUntil;
public bool ContactDisqualified;
public bool ContainerArmed;
public float AwayFromBeltSince = -1f;
}
public static ConfigEntry<bool> ModEnabled;
public static ConfigEntry<float> ReloadCooldown;
public static ConfigEntry<float> RoundFeedInterval;
public static ConfigEntry<float> BeltTriggerRadius;
public static ConfigEntry<bool> IncludeAddedBeltSlots;
public static ConfigEntry<bool> ReplaceSpentCasings;
public static ConfigEntry<bool> VerboseLogging;
private static ConfigSnapshot _cfg;
private static string _configFilePath;
private static long _configFileStamp = -1L;
private static readonly Dictionary<int, FeedState> _feedStates = new Dictionary<int, FeedState>();
private static readonly List<ReloadTarget> _targetScratch = new List<ReloadTarget>();
private static readonly List<AttachableFirearm> _attachableScratch = new List<AttachableFirearm>();
private static float _lastStatePrune;
private int _updateErrors;
private static float _lastConfigCheck;
private const float EmptySlotPenalty = 1000f;
private const float ContainerQuietTime = 1.2f;
private const float HeldContainerArmDelay = 0.25f;
public const string Id = "Niko666.ArcadeReload";
public static ArcadeReload Instance { get; private set; }
internal static ManualLogSource Logger { get; private set; }
public static string Name => "ArcadeReload";
public static string Version => "1.0.0";
private void BindConfig()
{
ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch for the arcade reload.");
ReloadCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ReloadCooldown", 0.2f, "Seconds before the same gun can be arcade reloaded again. A sweep that enters a belt slot reloads once; leaving the slot and coming back reloads again. (0-2)");
RoundFeedInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RoundFeedInterval", 0.15f, "Seconds between rounds when rounds are loaded one at a time, the way you would push them in by hand: loose rounds in the belt, and clips. The gun keeps taking one round at this pace for as long as it stays over the slot, so a short stack - or a spawn locked one - fills the gun completely, and a spawn locked stack cycles through its round types. Whole magazines and speedloaders always load in one go. (0.05-2)");
BeltTriggerRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BeltTriggerRadius", 1.5f, "How big the quickbelt slots are for this mod, as a multiplier of their real pickup volume. 1.0 = exactly the vanilla slot volume, which is small and easy to sweep past in one frame. (1-3)");
IncludeAddedBeltSlots = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IncludeAddedBeltSlots", true, "Also accept ammo from extra slots that are not part of the base belt (chest rigs, backpacks and other added slots).");
ReplaceSpentCasings = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ReplaceSpentCasings", false, "Off: a chamber or cylinder position that still holds a fired casing is left alone and only genuinely empty ones get a new round. On: the spent casing is thrown away and replaced.");
VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VerboseLogging", false, "Log every arcade reload to the BepInEx console. Useful when a gun does not reload the way you expect.");
AddSettingChangedListener<bool>(ModEnabled);
AddSettingChangedListener<float>(ReloadCooldown);
AddSettingChangedListener<float>(RoundFeedInterval);
AddSettingChangedListener<float>(BeltTriggerRadius);
AddSettingChangedListener<bool>(IncludeAddedBeltSlots);
AddSettingChangedListener<bool>(ReplaceSpentCasings);
AddSettingChangedListener<bool>(VerboseLogging);
}
private static void AddSettingChangedListener<T>(ConfigEntry<T> entry)
{
entry.SettingChanged += delegate
{
ReloadConfigSnapshot();
};
}
private static void ReloadConfigSnapshot()
{
_cfg = new ConfigSnapshot
{
Enabled = ModEnabled.Value,
Cooldown = Mathf.Clamp(ReloadCooldown.Value, 0f, 2f),
RoundInterval = Mathf.Clamp(RoundFeedInterval.Value, 0.05f, 2f),
Radius = Mathf.Clamp(BeltTriggerRadius.Value, 1f, 3f),
AddedSlots = IncludeAddedBeltSlots.Value,
SpentCasings = ReplaceSpentCasings.Value,
Verbose = VerboseLogging.Value
};
}
private static void ReloadConfigFromDisk()
{
try
{
if ((Object)(object)Instance != (Object)null && ((BaseUnityPlugin)Instance).Config != null)
{
((BaseUnityPlugin)Instance).Config.Reload();
}
}
catch (Exception ex)
{
if (Logger != null)
{
Logger.LogWarning((object)("Config reload failed: " + ex.Message));
}
}
ReloadConfigSnapshot();
RememberConfigFileStamp();
}
private static void RememberConfigFileStamp()
{
if (string.IsNullOrEmpty(_configFilePath))
{
return;
}
try
{
_configFileStamp = (File.Exists(_configFilePath) ? File.GetLastWriteTimeUtc(_configFilePath).Ticks : (-1));
}
catch (Exception)
{
_configFileStamp = -1L;
}
}
private static void CheckConfigFileChanged()
{
if (string.IsNullOrEmpty(_configFilePath))
{
return;
}
try
{
if (File.Exists(_configFilePath) && File.GetLastWriteTimeUtc(_configFilePath).Ticks != _configFileStamp)
{
Logger.LogMessage((object)"Config file changed on disk, reloading it.");
ReloadConfigFromDisk();
}
}
catch (Exception)
{
}
}
private static bool TryGetState(ReloadTarget target, float now, out FeedState state)
{
state = null;
Object identity = target.Identity;
if (identity == (Object)null)
{
return false;
}
int instanceID = identity.GetInstanceID();
if (!_feedStates.TryGetValue(instanceID, out state) || state == null)
{
state = new FeedState();
state.Owner = identity;
_feedStates[instanceID] = state;
}
PruneStates(now);
return true;
}
private static void PruneStates(float now)
{
if (now - _lastStatePrune < 5f || _feedStates.Count < 24)
{
return;
}
_lastStatePrune = now;
List<int> list = null;
foreach (KeyValuePair<int, FeedState> feedState in _feedStates)
{
if (feedState.Value == null || feedState.Value.Owner == (Object)null)
{
if (list == null)
{
list = new List<int>();
}
list.Add(feedState.Key);
}
}
if (list != null)
{
for (int i = 0; i < list.Count; i++)
{
_feedStates.Remove(list[i]);
}
}
}
private static void ResetAllFeedStates()
{
foreach (KeyValuePair<int, FeedState> feedState in _feedStates)
{
if (feedState.Value != null)
{
feedState.Value.LastSlot = null;
FeedStop(feedState.Value);
}
}
}
private static void FeedStop(FeedState state)
{
state.Feeding = false;
state.NextRoundTime = 0f;
state.RoundsFed = 0;
}
private static ReloadTarget ResolveTarget(FVRViveHand hand)
{
FVRInteractiveObject currentInteractable = hand.CurrentInteractable;
if ((Object)(object)currentInteractable == (Object)null)
{
return default(ReloadTarget);
}
FVRFireArm val = (FVRFireArm)(object)((currentInteractable is FVRFireArm) ? currentInteractable : null);
if ((Object)(object)val != (Object)null)
{
return ReloadTarget.ForFireArm(val);
}
AttachableFirearmPhysicalObject val2 = (AttachableFirearmPhysicalObject)(object)((currentInteractable is AttachableFirearmPhysicalObject) ? currentInteractable : null);
if ((Object)(object)val2 != (Object)null && (Object)(object)val2.FA != (Object)null)
{
return ReloadTarget.ForAttachable(val2.FA);
}
AttachableFirearmInterface val3 = (AttachableFirearmInterface)(object)((currentInteractable is AttachableFirearmInterface) ? currentInteractable : null);
if ((Object)(object)val3 != (Object)null && (Object)(object)val3.FA != (Object)null)
{
return ReloadTarget.ForAttachable(val3.FA);
}
FVRAlternateGrip val4 = (FVRAlternateGrip)(object)((currentInteractable is FVRAlternateGrip) ? currentInteractable : null);
if ((Object)(object)val4 != (Object)null)
{
AttachableForegrip lastGrabbedInGrip = val4.LastGrabbedInGrip;
AttachableFirearmInterface val5 = (AttachableFirearmInterface)(object)((lastGrabbedInGrip is AttachableFirearmInterface) ? lastGrabbedInGrip : null);
if ((Object)(object)val5 != (Object)null && (Object)(object)val5.FA != (Object)null)
{
return ReloadTarget.ForAttachable(val5.FA);
}
return default(ReloadTarget);
}
FVRFireArmMagazine val6 = (FVRFireArmMagazine)(object)((currentInteractable is FVRFireArmMagazine) ? currentInteractable : null);
if ((Object)(object)val6 != (Object)null)
{
return ReloadTarget.ForHeldMagazine(val6);
}
FVRFireArmClip val7 = (FVRFireArmClip)(object)((currentInteractable is FVRFireArmClip) ? currentInteractable : null);
if ((Object)(object)val7 != (Object)null)
{
return ReloadTarget.ForHeldClip(val7);
}
Speedloader val8 = (Speedloader)(object)((currentInteractable is Speedloader) ? currentInteractable : null);
if ((Object)(object)val8 != (Object)null)
{
return ReloadTarget.ForHeldSpeedloader(val8);
}
return default(ReloadTarget);
}
private static void CollectTargets(FVRViveHand hand)
{
_targetScratch.Clear();
ReloadTarget reloadTarget = ResolveTarget(hand);
if (!reloadTarget.IsValid)
{
return;
}
_targetScratch.Add(reloadTarget);
if ((Object)(object)reloadTarget.FireArm == (Object)null)
{
return;
}
_attachableScratch.Clear();
FireArmProbe.CollectAttachedFireArms(reloadTarget.FireArm, _attachableScratch);
for (int i = 0; i < _attachableScratch.Count; i++)
{
ReloadTarget item = ReloadTarget.ForAttachable(_attachableScratch[i]);
if (!item.SameAs(reloadTarget))
{
_targetScratch.Add(item);
}
}
}
private static void UpdateSweep(FeedState state, ReloadTarget target, FVRPlayerBody body, float now, FeedState primaryState)
{
FVRQuickBeltSlot val = FindBeltSlot(target, body);
bool flag = (Object)(object)val != (Object)(object)state.LastSlot;
if (flag)
{
state.LastSlot = val;
FeedStop(state);
}
if (target.IsHeldContainer)
{
int containerRoundCount = target.ContainerRoundCount;
if (state.LastContainerRounds >= 0 && containerRoundCount >= 0 && containerRoundCount < state.LastContainerRounds)
{
state.ContainerQuietUntil = now + 1.2f;
state.ContactDisqualified = true;
FeedStop(state);
}
state.LastContainerRounds = containerRoundCount;
}
if ((Object)(object)val == (Object)null)
{
state.ContactDisqualified = false;
if (target.IsHeldContainer)
{
if (state.AwayFromBeltSince < 0f)
{
state.AwayFromBeltSince = now;
}
else if (now - state.AwayFromBeltSince >= 0.25f)
{
state.ContainerArmed = true;
}
}
return;
}
state.AwayFromBeltSince = -1f;
if ((Object)(object)val.CurObject == (Object)null)
{
FeedStop(state);
return;
}
if (target.IsHeldContainer)
{
if (!state.ContainerArmed)
{
FeedStop(state);
return;
}
if (state.ContactDisqualified || now < state.ContainerQuietUntil)
{
FeedStop(state);
return;
}
}
if (primaryState != null && (Object)(object)primaryState.LastSlot == (Object)(object)val && (primaryState.Feeding || primaryState.LastTakeFrame == Time.frameCount))
{
FeedStop(state);
return;
}
bool flag2 = IsSlowFeedSource(val);
if (flag)
{
if (now - state.LastReloadTime < _cfg.Cooldown)
{
return;
}
}
else if (!state.Feeding || !flag2 || now < state.NextRoundTime)
{
return;
}
bool flag3;
string report;
try
{
flag3 = AmmoTransfer.TryArcadeReload(target, val, _cfg.SpentCasings, flag2 ? 1 : 0, state.RoundsFed, out report);
}
catch (Exception ex)
{
FeedStop(state);
if (_cfg.Verbose)
{
Logger.LogWarning((object)("Arcade reload attempt failed: " + ex));
}
return;
}
if (!flag3)
{
if (flag && _cfg.Verbose)
{
Logger.LogMessage((object)("Arcade reload: swept into a slot holding " + DescribeSlotItem(val) + " but nothing could be loaded [" + target.Name + "]"));
}
if (flag2 && !state.ContactDisqualified)
{
state.Feeding = true;
state.NextRoundTime = now + _cfg.RoundInterval;
}
else
{
FeedStop(state);
}
return;
}
state.LastReloadTime = now;
state.LastTakeFrame = Time.frameCount;
if (flag2)
{
state.Feeding = true;
state.RoundsFed++;
state.NextRoundTime = now + _cfg.RoundInterval;
}
else
{
FeedStop(state);
}
if (_cfg.Verbose)
{
Logger.LogMessage((object)("Arcade reload: " + report + " [" + target.Name + "]"));
}
}
private static bool IsSlowFeedSource(FVRQuickBeltSlot slot)
{
FVRPhysicalObject val = (((Object)(object)slot == (Object)null) ? null : slot.CurObject);
if ((Object)(object)val == (Object)null)
{
return false;
}
if (!(val is FVRFireArmRound))
{
return val is FVRFireArmClip;
}
return true;
}
public void Awake()
{
Instance = this;
Logger = ((BaseUnityPlugin)this).Logger;
BindConfig();
ReloadConfigSnapshot();
try
{
if ((Object)(object)Instance != (Object)null && ((BaseUnityPlugin)Instance).Config != null)
{
_configFilePath = ((BaseUnityPlugin)Instance).Config.ConfigFilePath;
}
}
catch (Exception)
{
}
RememberConfigFileStamp();
Logger.LogMessage((object)("Hello, world! Sent from Niko666.ArcadeReload " + Version));
}
public void Update()
{
try
{
float unscaledTime = Time.unscaledTime;
if (unscaledTime - _lastConfigCheck >= 1f)
{
_lastConfigCheck = unscaledTime;
CheckConfigFileChanged();
}
if (!_cfg.Enabled)
{
return;
}
FVRMovementManager val = null;
try
{
val = GM.CurrentMovementManager;
}
catch (Exception)
{
}
FVRPlayerBody val2 = null;
try
{
val2 = GM.CurrentPlayerBody;
}
catch (Exception)
{
}
FVRViveHand[] array = (((Object)(object)val == (Object)null) ? null : val.Hands);
if (array == null || (Object)(object)val2 == (Object)null)
{
ResetAllFeedStates();
return;
}
foreach (FVRViveHand val3 in array)
{
if ((Object)(object)val3 == (Object)null)
{
continue;
}
CollectTargets(val3);
FeedState feedState = null;
for (int j = 0; j < _targetScratch.Count; j++)
{
ReloadTarget target = _targetScratch[j];
if (!TryGetState(target, unscaledTime, out var state))
{
continue;
}
if (j == 0)
{
feedState = state;
}
if (state.LastFrame < 0)
{
state.LastSlot = FindBeltSlot(target, val2);
if (target.IsHeldContainer)
{
state.LastContainerRounds = target.ContainerRoundCount;
}
}
if (state.LastFrame != Time.frameCount)
{
state.LastFrame = Time.frameCount;
UpdateSweep(state, target, val2, unscaledTime, (j == 0) ? null : feedState);
}
}
}
}
catch (Exception ex3)
{
if (_updateErrors < 3)
{
_updateErrors++;
Logger.LogError((object)("Arcade Reload update failed: " + ex3));
}
}
}
private static string DescribeSlotItem(FVRQuickBeltSlot slot)
{
FVRPhysicalObject val = (((Object)(object)slot == (Object)null) ? null : slot.CurObject);
if ((Object)(object)val == (Object)null)
{
return "nothing";
}
FVRFireArmMagazine val2 = (FVRFireArmMagazine)(object)((val is FVRFireArmMagazine) ? val : null);
if ((Object)(object)val2 != (Object)null)
{
return ((object)Unsafe.As<FireArmMagazineType, FireArmMagazineType>(ref val2.MagazineType)/*cast due to .constrained prefix*/).ToString() + " magazine (" + val2.m_numRounds + "/" + val2.m_capacity + ")";
}
FVRFireArmClip val3 = (FVRFireArmClip)(object)((val is FVRFireArmClip) ? val : null);
if ((Object)(object)val3 != (Object)null)
{
return ((object)Unsafe.As<FireArmClipType, FireArmClipType>(ref val3.ClipType)/*cast due to .constrained prefix*/).ToString() + " clip (" + val3.m_numRounds + "/" + val3.m_capacity + ")";
}
FVRFireArmRound val4 = (FVRFireArmRound)(object)((val is FVRFireArmRound) ? val : null);
if ((Object)(object)val4 != (Object)null)
{
return ((object)Unsafe.As<FireArmRoundType, FireArmRoundType>(ref val4.RoundType)/*cast due to .constrained prefix*/).ToString() + " round(s), stack of " + (1 + ((val4.ProxyRounds != null) ? val4.ProxyRounds.Count : 0));
}
if ((Object)(object)((val is Speedloader) ? val : null) != (Object)null)
{
return "speedloader";
}
return ((Object)val).name;
}
private static FVRQuickBeltSlot FindBeltSlot(ReloadTarget target, FVRPlayerBody body)
{
//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_001d: 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)
Vector3 probePoint;
try
{
probePoint = target.GetProbePoint();
}
catch (Exception)
{
return null;
}
FVRQuickBeltSlot best = null;
float bestScore = float.MaxValue;
best = ConsiderSlots(body.QBSlots_Internal, probePoint, best, ref bestScore);
if (_cfg.AddedSlots)
{
best = ConsiderSlots(body.QBSlots_Added, probePoint, best, ref bestScore);
}
return best;
}
private static FVRQuickBeltSlot ConsiderSlots(List<FVRQuickBeltSlot> slots, Vector3 probe, FVRQuickBeltSlot best, ref float bestScore)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: 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)
if (slots == null)
{
return best;
}
for (int i = 0; i < slots.Count; i++)
{
FVRQuickBeltSlot val = slots[i];
if (!((Object)(object)val == (Object)null) && val.IsSelectable && FireArmProbe.SlotContains(val, probe, _cfg.Radius))
{
Vector3 val2 = (((Object)(object)val.PoseOverride != (Object)null) ? val.PoseOverride : ((Component)val).transform).position - probe;
float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
float num = (((Object)(object)val.CurObject != (Object)null) ? sqrMagnitude : (sqrMagnitude + 1000f));
if (num < bestScore)
{
bestScore = num;
best = val;
}
}
}
return best;
}
}
internal struct ReloadTarget
{
public readonly FVRFireArm FireArm;
public readonly AttachableFirearm Attachable;
public readonly FVRFireArmMagazine HeldMagazine;
public readonly FVRFireArmClip HeldClip;
public readonly Speedloader HeldSpeedloader;
public bool IsValid
{
get
{
if (!IsGun)
{
return IsHeldContainer;
}
return true;
}
}
public bool IsGun
{
get
{
if (!((Object)(object)FireArm != (Object)null))
{
return (Object)(object)Attachable != (Object)null;
}
return true;
}
}
public bool IsAttachable => (Object)(object)Attachable != (Object)null;
public bool IsHeldContainer
{
get
{
if (!((Object)(object)HeldMagazine != (Object)null) && !((Object)(object)HeldClip != (Object)null))
{
return (Object)(object)HeldSpeedloader != (Object)null;
}
return true;
}
}
public Object Identity
{
get
{
if ((Object)(object)FireArm != (Object)null)
{
return (Object)(object)FireArm;
}
if ((Object)(object)Attachable != (Object)null)
{
return (Object)(object)Attachable;
}
if ((Object)(object)HeldMagazine != (Object)null)
{
return (Object)(object)HeldMagazine;
}
if ((Object)(object)HeldClip != (Object)null)
{
return (Object)(object)HeldClip;
}
return (Object)(object)HeldSpeedloader;
}
}
public string Name
{
get
{
Object identity = Identity;
if (!(identity == (Object)null))
{
return identity.name;
}
return "(none)";
}
}
public FireArmRoundType RoundType
{
get
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: 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_0062: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)FireArm != (Object)null)
{
return FireArm.RoundType;
}
if ((Object)(object)Attachable != (Object)null)
{
return Attachable.RoundType;
}
if ((Object)(object)HeldMagazine != (Object)null)
{
return HeldMagazine.RoundType;
}
if ((Object)(object)HeldClip != (Object)null)
{
return HeldClip.RoundType;
}
return SpeedloaderChamberType(HeldSpeedloader);
}
}
public FireArmMagazineType MagazineType
{
get
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)FireArm != (Object)null)
{
return FireArm.MagazineType;
}
if ((Object)(object)Attachable != (Object)null)
{
return Attachable.MagazineType;
}
if ((Object)(object)HeldMagazine != (Object)null)
{
return HeldMagazine.MagazineType;
}
return (FireArmMagazineType)0;
}
}
public int ContainerRoundCount
{
get
{
if ((Object)(object)HeldMagazine != (Object)null)
{
return HeldMagazine.m_numRounds;
}
if ((Object)(object)HeldClip != (Object)null)
{
return HeldClip.m_numRounds;
}
if ((Object)(object)HeldSpeedloader != (Object)null)
{
return LoadedSpeedloaderChambers(HeldSpeedloader);
}
return -1;
}
}
public FVRFireArmMagazine GunMagazine
{
get
{
if ((Object)(object)FireArm != (Object)null)
{
return FireArm.Magazine;
}
if ((Object)(object)Attachable != (Object)null)
{
return Attachable.Magazine;
}
return null;
}
}
public FVRFireArmClip GunClip
{
get
{
if ((Object)(object)FireArm != (Object)null)
{
return FireArm.Clip;
}
if ((Object)(object)Attachable != (Object)null)
{
return Attachable.Clip;
}
return null;
}
}
public FireArmClipType ClipType
{
get
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)FireArm != (Object)null))
{
return (FireArmClipType)0;
}
return FireArm.ClipType;
}
}
public Transform ClipMountPos
{
get
{
if ((Object)(object)FireArm != (Object)null)
{
return FireArm.ClipMountPos;
}
if ((Object)(object)Attachable != (Object)null)
{
return Attachable.ClipMountPos;
}
return null;
}
}
public SecondaryMagazineSlot[] SecondarySlots
{
get
{
if (!((Object)(object)FireArm != (Object)null))
{
return null;
}
return FireArm.SecondaryMagazineSlots;
}
}
public int ChamberCount
{
get
{
if ((Object)(object)FireArm != (Object)null)
{
return FireArm.GetChambers()?.Count ?? 0;
}
return ((Object)(object)AttachableChamber(Attachable) != (Object)null) ? 1 : 0;
}
}
private ReloadTarget(FVRFireArm fireArm, AttachableFirearm attachable, FVRFireArmMagazine heldMagazine, FVRFireArmClip heldClip, Speedloader heldSpeedloader)
{
FireArm = fireArm;
Attachable = attachable;
HeldMagazine = heldMagazine;
HeldClip = heldClip;
HeldSpeedloader = heldSpeedloader;
}
public static ReloadTarget ForFireArm(FVRFireArm gun)
{
return new ReloadTarget(gun, null, null, null, null);
}
public static ReloadTarget ForAttachable(AttachableFirearm attachable)
{
return new ReloadTarget(null, attachable, null, null, null);
}
public static ReloadTarget ForHeldMagazine(FVRFireArmMagazine magazine)
{
return new ReloadTarget(null, null, magazine, null, null);
}
public static ReloadTarget ForHeldClip(FVRFireArmClip clip)
{
return new ReloadTarget(null, null, null, clip, null);
}
public static ReloadTarget ForHeldSpeedloader(Speedloader speedloader)
{
return new ReloadTarget(null, null, null, null, speedloader);
}
public bool SameAs(ReloadTarget other)
{
if ((Object)(object)FireArm == (Object)(object)other.FireArm && (Object)(object)Attachable == (Object)(object)other.Attachable && (Object)(object)HeldMagazine == (Object)(object)other.HeldMagazine && (Object)(object)HeldClip == (Object)(object)other.HeldClip)
{
return (Object)(object)HeldSpeedloader == (Object)(object)other.HeldSpeedloader;
}
return false;
}
public static FireArmRoundType SpeedloaderChamberType(Speedloader loader)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
List<SpeedloaderChamber> list = (((Object)(object)loader == (Object)null) ? null : loader.Chambers);
if (list == null || list.Count == 0 || (Object)(object)list[0] == (Object)null)
{
return (FireArmRoundType)0;
}
return list[0].Type;
}
public static int FreeSpeedloaderChambers(Speedloader loader)
{
List<SpeedloaderChamber> list = (((Object)(object)loader == (Object)null) ? null : loader.Chambers);
if (list == null)
{
return 0;
}
int num = 0;
for (int i = 0; i < list.Count; i++)
{
if ((Object)(object)list[i] != (Object)null && !list[i].IsLoaded)
{
num++;
}
}
return num;
}
public static int LoadedSpeedloaderChambers(Speedloader loader)
{
List<SpeedloaderChamber> list = (((Object)(object)loader == (Object)null) ? null : loader.Chambers);
if (list == null)
{
return 0;
}
int num = 0;
for (int i = 0; i < list.Count; i++)
{
if ((Object)(object)list[i] != (Object)null && list[i].IsLoaded)
{
num++;
}
}
return num;
}
public Transform GetMagMountPos(bool isBeltBox)
{
if ((Object)(object)FireArm != (Object)null)
{
return FireArm.GetMagMountPos(isBeltBox);
}
if (!((Object)(object)Attachable != (Object)null))
{
return null;
}
return Attachable.MagazineMountPos;
}
public FVRFireArmChamber ChamberAt(int index)
{
if ((Object)(object)FireArm != (Object)null)
{
List<FVRFireArmChamber> chambers = FireArm.GetChambers();
if (chambers == null || index < 0 || index >= chambers.Count)
{
return null;
}
return chambers[index];
}
if (index != 0)
{
return null;
}
return AttachableChamber(Attachable);
}
public static FVRFireArmChamber AttachableChamber(AttachableFirearm attachable)
{
if ((Object)(object)attachable == (Object)null)
{
return null;
}
AttachableClosedBoltWeapon val = (AttachableClosedBoltWeapon)(object)((attachable is AttachableClosedBoltWeapon) ? attachable : null);
if ((Object)(object)val != (Object)null)
{
return val.Chamber;
}
AttachableTubeFed val2 = (AttachableTubeFed)(object)((attachable is AttachableTubeFed) ? attachable : null);
if ((Object)(object)val2 != (Object)null)
{
return val2.Chamber;
}
AttachableBreakActions val3 = (AttachableBreakActions)(object)((attachable is AttachableBreakActions) ? attachable : null);
if ((Object)(object)val3 != (Object)null)
{
return val3.Chamber;
}
GP25 val4 = (GP25)(object)((attachable is GP25) ? attachable : null);
if ((Object)(object)val4 != (Object)null)
{
return val4.Chamber;
}
M203 val5 = (M203)(object)((attachable is M203) ? attachable : null);
if ((Object)(object)val5 != (Object)null)
{
return val5.Chamber;
}
return null;
}
public void InsertMagazine(FVRFireArmMagazine magazine)
{
if (!((Object)(object)magazine == (Object)null))
{
if ((Object)(object)FireArm != (Object)null)
{
magazine.Load(FireArm);
}
else if ((Object)(object)Attachable != (Object)null)
{
magazine.Load(Attachable);
}
}
}
public bool MagazineIsPresent(FVRFireArmMagazine magazine)
{
return (Object)(object)GunMagazine == (Object)(object)magazine;
}
public Vector3 GetProbePoint()
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)FireArm != (Object)null)
{
return FireArmProbe.GetFireArmProbePoint(FireArm);
}
if ((Object)(object)Attachable != (Object)null)
{
return FireArmProbe.GetAttachableProbePoint(Attachable);
}
return FireArmProbe.GetHeldObjectProbePoint((FVRPhysicalObject)(((Object)(object)HeldMagazine != (Object)null) ? HeldMagazine : (((object)HeldClip) ?? ((object)HeldSpeedloader))));
}
public void PlayReloadSound()
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((Object)(object)FireArm != (Object)null)
{
FireArm.PlayAudioEvent((FirearmAudioEventType)28, 1f);
return;
}
if ((Object)(object)Attachable != (Object)null)
{
Attachable.PlayAudioEvent((FirearmAudioEventType)28, 1f);
return;
}
FVRFireArmMagazine heldMagazine = HeldMagazine;
if ((Object)(object)heldMagazine != (Object)null)
{
SM.PlayGenericSound(heldMagazine.Profile.MagazineInsertRound, ((Component)heldMagazine).transform.position);
}
}
catch (Exception)
{
}
}
}
}