using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
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 H3VRUtils;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("BetterMagRelease")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BetterMagRelease")]
[assembly: AssemblyTitle("BetterMagRelease")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace BetterMagRelease
{
public class Extractor
{
[HarmonyPatch(typeof(BreakActionWeapon), "Awake")]
[HarmonyPrefix]
public static bool ExtractedRoundsReleasePatch(BreakActionWeapon __instance)
{
if (!Plugin.ExtractedRounds_IsEnabled.Value)
{
return true;
}
if (MagReplacerData.SavedExtractedRoundsData.Contains(((FVRPhysicalObject)__instance).ObjectWrapper.ItemID))
{
__instance.SetEjectOnOpen(false);
}
return true;
}
[HarmonyPatch(typeof(BreakActionWeapon), "FVRFixedUpdate")]
[HarmonyPrefix]
public static bool ExtractedRoundsShuckPatch(BreakActionWeapon __instance)
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
if (!MagReplacerData.SavedExtractedRoundsData.Contains(((FVRPhysicalObject)__instance).ObjectWrapper.ItemID) || !Plugin.Shucking_IsEnabled.Value)
{
return true;
}
float num = 0f;
BreakActionBarrel[] barrels = __instance.Barrels;
foreach (BreakActionBarrel val in barrels)
{
if ((Object)(object)((FVRInteractiveObject)__instance).m_hand != (Object)null)
{
num = Vector3.Dot(Vector3.back, ((Component)__instance).transform.InverseTransformDirection(((FVRInteractiveObject)__instance).m_hand.Input.VelLinearWorld));
}
if (!__instance.IsLatched && val.Chamber.IsFull && num > Plugin.Shucking_Strength.Value)
{
((FVRFireArm)__instance).PlayAudioEvent((FirearmAudioEventType)29, 1f);
Vector3 val2 = Random.onUnitSphere * 10f;
val.Chamber.EjectRound(((Component)val.Chamber).transform.position + ((Component)val.Chamber).transform.forward * __instance.EjectOffset, ((Component)val.Chamber).transform.forward * (0f - num), val2, false);
}
}
return true;
}
}
[BepInPlugin("dll.potatoes1286.bettermagrelease", "Better Mag Release", "4.0.1")]
[BepInProcess("h3vr.exe")]
public class Plugin : BaseUnityPlugin
{
public enum LogType
{
Default,
Debug
}
public static ConfigEntry<bool> DebugMode_IsEnabled;
public static ConfigEntry<bool> StartedUp_Has;
public static ConfigEntry<bool> ForegripRelease_IsEnabled;
public static ConfigEntry<bool> ExtractedRounds_IsEnabled;
public static ConfigEntry<bool> Shucking_IsEnabled;
public static ConfigEntry<float> Shucking_Strength;
public static ManualLogSource Log;
public void Start()
{
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
DebugMode_IsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General Settings", "Enable Debugging", false, "Logs to console if a firearm spawned does not have a mag release setting.");
StartedUp_Has = ((BaseUnityPlugin)this).Config.Bind<bool>("General Settings", "Has Started Up", false, "Enables mag release if false, then sets to true.");
ForegripRelease_IsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General Settings", "Enable Foregrip Release", true, "Enables foregrip release feature, allowing a mag to be released while holding the foregrip.");
ExtractedRounds_IsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General Settings", "Enable Extracting Rounds", true, "Enables extracting release feature, where some shotguns require rounds to be manually removed.");
Shucking_IsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General Settings", "Enable Shucking", true, "Enables shucking. Thrusting break-action shotguns backwards will eject rounds.");
Shucking_Strength = ((BaseUnityPlugin)this).Config.Bind<float>("General Settings", "Shucking Strength", 2f, new ConfigDescription("Thust strength required to eject rounds via shucking.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), new object[0]));
if (!StartedUp_Has.Value)
{
StartedUp_Has.Value = true;
UtilsBepInExLoader.EnablePaddleMagRelease();
}
MagReplacerData.AssembleData();
Harmony.CreateAndPatchAll(typeof(Plugin), (string)null);
Harmony.CreateAndPatchAll(typeof(Extractor), (string)null);
}
public static void log(object data, LogType type = LogType.Default)
{
if (type != LogType.Debug)
{
Log.LogInfo(data);
}
}
[HarmonyPatch(typeof(FVRInteractiveObject), "Awake")]
[HarmonyPrefix]
public static bool ClosedBoltMagEjectionTriggerPatch(FVRInteractiveObject __instance)
{
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_0205: Unknown result type (might be due to invalid IL or missing references)
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0339: Unknown result type (might be due to invalid IL or missing references)
//IL_032f: Unknown result type (might be due to invalid IL or missing references)
if (__instance is ClosedBoltMagEjectionTrigger)
{
ClosedBoltMagEjectionTrigger val = (ClosedBoltMagEjectionTrigger)(object)((__instance is ClosedBoltMagEjectionTrigger) ? __instance : null);
if (val.IsSecondarySlotGrab)
{
return true;
}
string[] magDropData = MagReplacerData.GetMagDropData();
string[] paddleData = MagReplacerData.GetPaddleData();
if (paddleData.Concat(magDropData).ToArray().Contains(((FVRPhysicalObject)val.Receiver).ObjectWrapper.ItemID))
{
Component obj = ((Component)val).gameObject.AddComponent(typeof(H3VRUtilsMagRelease));
H3VRUtilsMagRelease val2 = (H3VRUtilsMagRelease)(object)((obj is H3VRUtilsMagRelease) ? obj : null);
((FVRInteractiveObject)val2).PositionInterpSpeed = 4f;
((FVRInteractiveObject)val2).RotationInterpSpeed = 4f;
((FVRInteractiveObject)val2).EndInteractionIfDistant = true;
((FVRInteractiveObject)val2).EndInteractionDistance = 0.25f;
val2.ClosedBoltReceiver = val.Receiver;
val2.PressDownToRelease = true;
if (paddleData.Contains(((FVRPhysicalObject)val.Receiver).ObjectWrapper.ItemID))
{
val2.TouchpadDir = (TouchpadDirType)1;
}
else
{
val2.TouchpadDir = (TouchpadDirType)5;
val.Receiver.HasMagReleaseButton = true;
}
val2.setWepType();
Object.Destroy((Object)(object)val);
}
else if (DebugMode_IsEnabled.Value)
{
Debug.LogWarning((object)(((FVRPhysicalObject)val.Receiver).ObjectWrapper.ItemID + " (name " + ((Object)((FVRPhysicalObject)val.Receiver).ObjectWrapper).name + ") does not have a setting!"));
}
}
if (__instance is OpenBoltMagReleaseTrigger)
{
OpenBoltMagReleaseTrigger val3 = (OpenBoltMagReleaseTrigger)(object)((__instance is OpenBoltMagReleaseTrigger) ? __instance : null);
if (val3.IsSecondarySlotGrab)
{
return true;
}
string[] magDropData2 = MagReplacerData.GetMagDropData();
string[] paddleData2 = MagReplacerData.GetPaddleData();
if (paddleData2.Concat(magDropData2).ToArray().Contains(((FVRPhysicalObject)val3.Receiver).ObjectWrapper.ItemID))
{
Component obj2 = ((Component)val3).gameObject.AddComponent(typeof(H3VRUtilsMagRelease));
H3VRUtilsMagRelease val4 = (H3VRUtilsMagRelease)(object)((obj2 is H3VRUtilsMagRelease) ? obj2 : null);
((FVRInteractiveObject)val4).PositionInterpSpeed = 4f;
((FVRInteractiveObject)val4).RotationInterpSpeed = 4f;
((FVRInteractiveObject)val4).EndInteractionIfDistant = true;
((FVRInteractiveObject)val4).EndInteractionDistance = 0.25f;
val4.OpenBoltWeapon = val3.Receiver;
val4.PressDownToRelease = true;
if (paddleData2.Contains(((FVRPhysicalObject)val3.Receiver).ObjectWrapper.ItemID))
{
val4.TouchpadDir = (TouchpadDirType)1;
}
else
{
val4.TouchpadDir = (TouchpadDirType)5;
}
val4.setWepType();
Object.Destroy((Object)(object)val3);
}
else if (DebugMode_IsEnabled.Value)
{
Debug.LogWarning((object)(((FVRPhysicalObject)val3.Receiver).ObjectWrapper.ItemID + " (name " + ((Object)((FVRPhysicalObject)val3.Receiver).ObjectWrapper).name + ") does not have a setting!"));
}
}
if (__instance is BoltActionMagEjectionTrigger)
{
BoltActionMagEjectionTrigger val5 = (BoltActionMagEjectionTrigger)(object)((__instance is BoltActionMagEjectionTrigger) ? __instance : null);
if (val5.IsSecondarySlotGrab)
{
return true;
}
string[] magDropData3 = MagReplacerData.GetMagDropData();
string[] paddleData3 = MagReplacerData.GetPaddleData();
if (paddleData3.Concat(magDropData3).ToArray().Contains(((FVRPhysicalObject)val5.Rifle).ObjectWrapper.ItemID))
{
Component obj3 = ((Component)val5).gameObject.AddComponent(typeof(H3VRUtilsMagRelease));
H3VRUtilsMagRelease val6 = (H3VRUtilsMagRelease)(object)((obj3 is H3VRUtilsMagRelease) ? obj3 : null);
((FVRInteractiveObject)val6).PositionInterpSpeed = 4f;
((FVRInteractiveObject)val6).RotationInterpSpeed = 4f;
((FVRInteractiveObject)val6).EndInteractionIfDistant = true;
((FVRInteractiveObject)val6).EndInteractionDistance = 0.25f;
val6.BoltActionWeapon = val5.Rifle;
val6.PressDownToRelease = true;
if (paddleData3.Contains(((FVRPhysicalObject)val5.Rifle).ObjectWrapper.ItemID))
{
val6.TouchpadDir = (TouchpadDirType)1;
}
else
{
val6.TouchpadDir = (TouchpadDirType)5;
}
val6.setWepType();
Object.Destroy((Object)(object)val5);
}
else if (DebugMode_IsEnabled.Value)
{
Log.LogWarning((object)(((FVRPhysicalObject)val5.Rifle).ObjectWrapper.ItemID + " does not have a setting!"));
}
}
return true;
}
[HarmonyPatch(typeof(FVRPhysicalObject), "Awake")]
[HarmonyPrefix]
public static bool justfuckingnotifyme(FVRPhysicalObject __instance)
{
if ((__instance is Derringer || __instance is RollingBlock || __instance is BreakActionWeapon) && !MagReplacerData.SavedExtractedRoundsData.Contains(__instance.ObjectWrapper.ItemID) && DebugMode_IsEnabled.Value)
{
Log.LogWarning((object)(__instance.ObjectWrapper.ItemID + " may not have a proper setting!"));
}
return true;
}
[HarmonyPatch(typeof(FVRAlternateGrip), "UpdateInteraction")]
[HarmonyPrefix]
public static bool ForegripReleasePatch(FVRAlternateGrip __instance, ref FVRViveHand hand)
{
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: 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)
if (!ForegripRelease_IsEnabled.Value || !(__instance.PrimaryObject is FVRFireArm))
{
return true;
}
FVRPhysicalObject primaryObject = __instance.PrimaryObject;
FVRFireArm val = (FVRFireArm)(object)((primaryObject is FVRFireArm) ? primaryObject : null);
if (MagReplacerData.SavedForegripReleaseData.Contains(((FVRPhysicalObject)val).ObjectWrapper.ItemID) && ((Vector2.Angle(hand.Input.TouchpadAxes, Vector2.down) <= 45f && hand.Input.TouchpadDown && ((Vector2)(ref hand.Input.TouchpadAxes)).magnitude > 0.2f) || (hand.IsInStreamlinedMode && hand.Input.AXButtonPressed)))
{
if ((Object)(object)val.Magazine == (Object)null)
{
return true;
}
if ((double)Vector3.Distance(((Component)val.Magazine).transform.position, ((Component)hand.PalmTransform).transform.position) <= 0.15)
{
FVRFireArmMagazine magazine = val.Magazine;
val.EjectMag(false);
((FVRInteractiveObject)__instance).EndInteraction(hand);
hand.ForceSetInteractable((FVRInteractiveObject)(object)magazine);
((FVRInteractiveObject)magazine).BeginInteraction(hand);
}
}
return true;
}
}
internal static class MagReplacerData
{
private static string[] _savedPaddleData = new string[0];
private static string[] _savedMagDropData = new string[0];
public static string[] SavedForegripReleaseData = new string[0];
public static string[] SavedExtractedRoundsData = new string[0];
public static string[] GetPaddleData(bool reset = false)
{
if (reset)
{
AssembleData();
}
return _savedPaddleData;
}
public static string[] GetMagDropData(bool reset = false)
{
if (reset)
{
AssembleData();
}
return _savedMagDropData;
}
public static void AssembleData()
{
List<string> list = LoadData("*_BMR_Paddle.txt").Distinct().ToList();
List<string> list2 = LoadData("*_BMR_Eject.txt").Distinct().ToList();
List<string> list3 = LoadData("*_BMR_ForegripRelease.txt").Distinct().ToList();
List<string> list4 = LoadData("*_BMR_ExtractingRounds.txt").Distinct().ToList();
foreach (string item in list.Intersect(list2).ToList())
{
int num = list.IndexOf(item);
int num2 = list2.IndexOf(item);
if (num < num2)
{
list2.RemoveAt(num2);
Debug.LogError((object)("BetterMagRelease: There are conflicting sources for " + item + "! Chose Paddle."));
}
else
{
list.RemoveAt(num);
}
Debug.LogError((object)("BetterMagRelease: There are conflicting sources for " + item + "! Chose Mag Drop."));
}
_savedPaddleData = list.ToArray();
_savedMagDropData = list2.ToArray();
SavedForegripReleaseData = list3.ToArray();
SavedExtractedRoundsData = list4.ToArray();
}
public static List<string> LoadData(string searchPattern)
{
new List<string>();
List<string[]> list = new List<string[]>();
foreach (string item in Directory.GetFiles(Paths.BepInExRootPath, searchPattern, SearchOption.AllDirectories).ToList())
{
Debug.Log((object)("BetterMagRelease: Adding source " + item));
list.Add(File.ReadAllLines(item));
}
list = list.OrderBy((string[] x) => x.Length).Reverse().ToList();
IEnumerable<string> enumerable = Enumerable.Empty<string>();
foreach (string[] item2 in list)
{
enumerable = enumerable.Concat(item2);
}
return enumerable.ToList();
}
}
internal static class PluginInfo
{
internal const string NAME = "Better Mag Release";
internal const string GUID = "dll.potatoes1286.bettermagrelease";
internal const string VERSION = "4.0.1";
}
}