using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("TwoPinPull")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+64c7a9b39f510fb8ba21ab3b80c61d1e1a46ae57")]
[assembly: AssemblyProduct("TwoPinPull")]
[assembly: AssemblyTitle("TwoPinPull")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace TwoPinPull;
[BepInPlugin("invent60.h3vr.twopinpull", "Two Pin Pull", "0.1.0")]
public class Plugin : BaseUnityPlugin
{
internal static ManualLogSource Log;
internal static ConfigEntry<bool> Enabled;
internal static ConfigEntry<bool> NeedGrip;
internal static ConfigEntry<bool> DebugLog;
private void Awake()
{
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Holding a grenade's pin ring and pulling the trigger too pulls all of its pins at once. false = one pin at a time, as in the game.\nExample: Enabled = false");
NeedGrip = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Grip and trigger", true, "true = both pins come out only while the grip AND the trigger are held (grip alone = one pin). false = the trigger alone is enough\n(for players who grab with the trigger: then every pull takes all pins).\nExample: Grip and trigger = false");
DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Log", false, "Writes a line each time pins are pulled together (which grenade, how many pins).\nExample: Log = true");
if (!Rings.Ready())
{
Log.LogWarning((object)"Two Pin Pull: the game's grenade ring fields were not found (game update?); the mod does nothing.");
return;
}
new Harmony("invent60.h3vr.twopinpull").PatchAll(typeof(RingPatch));
if (DebugLog.Value)
{
Log.LogInfo((object)"Two Pin Pull ready.");
}
}
}
internal static class Rings
{
private const BindingFlags Inst = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
private static readonly FieldInfo s_rings = typeof(PinnedGrenade).GetField("m_rings", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo s_posMin = typeof(PinnedGrenadeRing).GetField("m_posMin", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo s_posMax = typeof(PinnedGrenadeRing).GetField("m_posMax", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo s_posCurrent = typeof(PinnedGrenadeRing).GetField("m_posCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo s_detached = typeof(PinnedGrenadeRing).GetField("m_hasPinDetached", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo s_swapped = typeof(PinnedGrenadeRing).GetField("m_hasSwapped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
public static bool Ready()
{
if ((object)s_rings != null && (object)s_posMin != null && (object)s_posMax != null && (object)s_posCurrent != null && (object)s_detached != null)
{
return (object)s_swapped != null;
}
return false;
}
public static List<PinnedGrenadeRing> Of(PinnedGrenade g)
{
if (!((Object)(object)g != (Object)null))
{
return null;
}
return s_rings.GetValue(g) as List<PinnedGrenadeRing>;
}
public static float Out(PinnedGrenadeRing r)
{
return Mathf.InverseLerp((float)s_posMin.GetValue(r), (float)s_posMax.GetValue(r), (float)s_posCurrent.GetValue(r));
}
public static void SetOut(PinnedGrenadeRing r, float f)
{
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
if (f <= Out(r))
{
return;
}
float num = Mathf.Lerp((float)s_posMin.GetValue(r), (float)s_posMax.GetValue(r), Mathf.Clamp01(f) * 0.999f);
s_posCurrent.SetValue(r, num);
Vector3 localPosition = ((Component)r).transform.localPosition;
((Component)r).transform.localPosition = new Vector3(localPosition.x, localPosition.y, num);
if ((Object)(object)r.Pin != (Object)null)
{
Vector3 localPosition2 = ((Component)r.Pin).transform.localPosition;
((Component)r.Pin).transform.localPosition = new Vector3(localPosition2.x, localPosition2.y, num);
}
if (r.UsesSwapPin && !(bool)s_swapped.GetValue(r) && (Object)(object)r.Pin != (Object)null)
{
s_swapped.SetValue(r, true);
MeshFilter component = ((Component)r.Pin).GetComponent<MeshFilter>();
if ((Object)(object)component != (Object)null)
{
component.mesh = r.SwapPin;
}
}
}
public static void Free(PinnedGrenadeRing r, FVRViveHand hand)
{
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
if (!r.HasPinDetached() && !((Object)(object)r.Pin == (Object)null))
{
s_detached.SetValue(r, true);
if (((FVRInteractiveObject)r).IsHeld)
{
((FVRInteractiveObject)r).ForceBreakInteraction();
}
Rigidbody val = ((Component)r.Pin).gameObject.GetComponent<Rigidbody>();
if ((Object)(object)val == (Object)null)
{
val = ((Component)r.Pin).gameObject.AddComponent<Rigidbody>();
}
val.mass = 0.02f;
r.Pin.RootRigidbody = val;
((Component)r).transform.SetParent(((Component)r.Pin).transform);
((Behaviour)r.Pin).enabled = true;
if ((Object)(object)hand != (Object)null)
{
val.velocity = hand.Input.VelLinearWorld;
}
Collider component = ((Component)r).GetComponent<Collider>();
if ((Object)(object)component != (Object)null)
{
component.enabled = false;
}
((Behaviour)r).enabled = false;
}
}
}
[HarmonyPatch(typeof(PinnedGrenadeRing), "FVRUpdate")]
internal static class RingPatch
{
private static bool Pulling(PinnedGrenadeRing r)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
if (!Plugin.Enabled.Value || !((FVRInteractiveObject)r).IsHeld || (Object)(object)((FVRInteractiveObject)r).m_hand == (Object)null || r.HasPinDetached())
{
return false;
}
HandInput input = ((FVRInteractiveObject)r).m_hand.Input;
if (input.TriggerPressed)
{
if (Plugin.NeedGrip.Value)
{
return input.GripPressed;
}
return true;
}
return false;
}
private static void Prefix(PinnedGrenadeRing __instance, out FVRViveHand __state)
{
__state = (Pulling(__instance) ? ((FVRInteractiveObject)__instance).m_hand : null);
}
private static void Postfix(PinnedGrenadeRing __instance, FVRViveHand __state)
{
if ((Object)(object)__state == (Object)null)
{
return;
}
List<PinnedGrenadeRing> list = Rings.Of(__instance.G);
if (list == null || list.Count < 2)
{
return;
}
bool flag = __instance.HasPinDetached();
float f = (flag ? 1f : Rings.Out(__instance));
int num = 0;
foreach (PinnedGrenadeRing item in list)
{
if (!((Object)(object)item == (Object)null) && item != __instance && !item.HasPinDetached() && !((FVRInteractiveObject)item).IsHeld)
{
if (flag)
{
Rings.Free(item, __state);
}
else
{
Rings.SetOut(item, f);
}
num++;
}
}
if (flag && num > 0 && Plugin.DebugLog.Value)
{
Plugin.Log.LogInfo((object)("Two Pin Pull: " + ((Object)__instance.G).name + ": " + (num + 1) + " pins pulled together"));
}
}
}