using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using FistVR; using HarmonyLib; using OpenScripts2; using OtherLoader; using UnityEngine; [assembly: Debuggable(DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] public class MovableStopMag : MovableObjectPart { public enum ClosedEndChoice { LowerLimit, UpperLimit } [Header("Firearm / Magazine")] [Tooltip("Gun to inspect for a non-null Magazine to consider 'inserted'.")] public FVRFireArm Firearm; [Header("Which end is CLOSED?")] [Tooltip("Tell the script which limit means 'fully closed'.")] public ClosedEndChoice ClosedEnd = ClosedEndChoice.LowerLimit; [Header("Block point (where folding should stop if a mag is inserted)")] [Tooltip("If true, use BlockedAngleAbsolute directly (deg along MovementAxis).")] public bool UseAbsoluteBlockedAngle = true; [Tooltip("Absolute angle (deg) along MovementAxis that cannot be crossed when folding CLOSED with a mag. Example: -72.")] public float BlockedAngleAbsolute = -72f; [Tooltip("If not absolute: offset in degrees from the CLOSED end toward open. Example: with closed=-180 and block=-72, set 108.")] public float BlockOffsetFromClosed = 108f; [Header("Closed detection for toggling")] [Tooltip("How close (deg) to the CLOSED end counts as 'closed' for toggling.")] public float ClosedTolerance = 5f; [Header("Objects to toggle")] [Tooltip("These objects are disabled when CLOSED, enabled otherwise (e.g., reload well).")] public List DisableWhenClosed = new List(); [Tooltip("These objects are enabled when CLOSED, disabled otherwise (optional).")] public List EnableWhenClosed = new List(); [Header("Debug")] public bool LogDebug = false; private bool _isInteracting = false; private float _lastAngleNorm = 0f; private Quaternion _lastRotation; public override void BeginInteraction(FVRViveHand hand) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) ((MovableObjectPart)this).BeginInteraction(hand); _isInteracting = true; _lastAngleNorm = GetCurrentAxisAngleNorm(); _lastRotation = ((!((Object)(object)base.ObjectToMove != (Object)null)) ? Quaternion.identity : base.ObjectToMove.localRotation); } public override void UpdateInteraction(FVRViveHand hand) { ((MovableObjectPart)this).UpdateInteraction(hand); EnforceClampIfNeeded(); } public override void EndInteraction(FVRViveHand hand) { ((MovableObjectPart)this).EndInteraction(hand); _isInteracting = false; } private void LateUpdate() { ToggleClosedObjects(); EnforceClampIfNeeded(); } private void EnforceClampIfNeeded() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)base.ObjectToMove == (Object)null || (int)base.MovementMode != 2) { return; } float num = GetCurrentAxisAngleNorm(); float num2 = NormalizeDeg((ClosedEnd != 0) ? base.UpperLimit : base.LowerLimit); float num3 = ComputeBlockAngle(num2); float lastAngleNorm = _lastAngleNorm; if (IsMagazineInserted()) { float num4 = Mathf.Abs(Mathf.DeltaAngle(num, num2)); float num5 = Mathf.Abs(Mathf.DeltaAngle(lastAngleNorm, num2)); float num6 = Mathf.Abs(Mathf.DeltaAngle(num3, num2)); bool flag = num4 < num5; bool flag2 = num4 < num6; bool flag3 = num5 < num6; if (flag && flag2) { if (!flag3) { ApplyAxisAngle(num3); num = num3; if (LogDebug) { Debug.Log((object)("[MovableStopMag] Clamp at block angle (deg): " + num3)); } } else { ApplyLocalRotation(_lastRotation); num = lastAngleNorm; if (LogDebug) { Debug.Log((object)"[MovableStopMag] Prevented further closing while already past block."); } } } } _lastAngleNorm = num; _lastRotation = base.ObjectToMove.localRotation; } private void ToggleClosedObjects() { if ((Object)(object)base.ObjectToMove == (Object)null) { return; } float currentAxisAngleNorm = GetCurrentAxisAngleNorm(); float num = NormalizeDeg((ClosedEnd != 0) ? base.UpperLimit : base.LowerLimit); bool flag = Mathf.Abs(Mathf.DeltaAngle(currentAxisAngleNorm, num)) <= ClosedTolerance; if (DisableWhenClosed != null) { for (int i = 0; i < DisableWhenClosed.Count; i++) { GameObject val = DisableWhenClosed[i]; if ((Object)(object)val != (Object)null) { bool flag2 = !flag; if (val.activeSelf != flag2) { val.SetActive(flag2); } } } } if (EnableWhenClosed != null) { for (int j = 0; j < EnableWhenClosed.Count; j++) { GameObject val2 = EnableWhenClosed[j]; if ((Object)(object)val2 != (Object)null) { bool flag3 = flag; if (val2.activeSelf != flag3) { val2.SetActive(flag3); } } } } if (LogDebug) { Debug.Log((object)("[MovableStopMag] Angle: " + currentAxisAngleNorm + " | ClosedAt: " + num + " | IsClosed: " + flag)); } } private bool IsMagazineInserted() { return (Object)(object)Firearm != (Object)null && (Object)(object)Firearm.Magazine != (Object)null; } private float ComputeBlockAngle(float closedAngleNorm) { if (UseAbsoluteBlockedAngle) { return NormalizeDeg(BlockedAngleAbsolute); } return NormalizeDeg(closedAngleNorm + BlockOffsetFromClosed); } private float GetCurrentAxisAngleNorm() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 if ((Object)(object)base.ObjectToMove == (Object)null) { return 0f; } Vector3 localEulerAngles = base.ObjectToMove.localEulerAngles; float a = (((int)base.MovementAxis == 0) ? localEulerAngles.x : (((int)base.MovementAxis != 1) ? localEulerAngles.z : localEulerAngles.y)); return NormalizeDeg(a); } private void ApplyAxisAngle(float angleDegNorm) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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) Quaternion targetQuaternionFromAxis = OpenScripts2_BasePlugin.GetTargetQuaternionFromAxis(angleDegNorm, base.MovementAxis); ApplyLocalRotation(targetQuaternionFromAxis); } private void ApplyLocalRotation(Quaternion q) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)base.ObjectToMove != (Object)null) { base.ObjectToMove.localRotation = q; } } private static float NormalizeDeg(float a) { return Mathf.DeltaAngle(0f, a); } } public class LeverActionRifleSafety : LeverActionFirearm { [Header("Safety Params")] public bool HasSafety = true; public Transform SafetyLever; public float SafetyOnAngle = 0f; public float SafetyOffAngle = 45f; public float SafetyAnimSpeed = 10f; private bool _isSafetyEngaged = true; public bool IsSafetyEngaged => _isSafetyEngaged; protected void Awake() { ((LeverActionFirearm)this).Awake(); UpdateSafetyVisual(); } public override void UpdateInteraction(FVRViveHand hand) { if (_isSafetyEngaged && hand.Input.TriggerDown) { if (base.m_isHammerCocked) { base.m_isHammerCocked = false; } else if (base.UsesSecondChamber && base.m_isHammerCocked2) { base.m_isHammerCocked2 = false; } ((FVRFireArm)this).PlayAudioEvent((FirearmAudioEventType)6, 1f); ((FVRFireArm)this).PlayAudioEvent((FirearmAudioEventType)14, 1f); hand.Buzz(hand.Buzzer.Buzz_OnHoverInteractive); return; } ((LeverActionFirearm)this).UpdateInteraction(hand); if (hand.IsInStreamlinedMode) { if (hand.Input.BYButtonDown) { ToggleSafety(); } } else if (hand.Input.TouchpadDown && hand.Input.TouchpadAxes.x < -0.5f) { ToggleSafety(); } } public bool Fire() { if (_isSafetyEngaged) { if (base.m_isHammerCocked) { base.m_isHammerCocked = false; } else if (base.UsesSecondChamber && base.m_isHammerCocked2) { base.m_isHammerCocked2 = false; } ((FVRFireArm)this).PlayAudioEvent((FirearmAudioEventType)6, 1f); return false; } ((LeverActionFirearm)this).Fire(); return true; } private void ToggleSafety() { _isSafetyEngaged = !_isSafetyEngaged; ((FVRFireArm)this).PlayAudioEvent((FirearmAudioEventType)14, 1f); UpdateSafetyVisual(); } private void UpdateSafetyVisual() { //IL_0039: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)SafetyLever != (Object)null) { float num = ((!_isSafetyEngaged) ? SafetyOffAngle : SafetyOnAngle); Vector3 localEulerAngles = default(Vector3); ((Vector3)(ref localEulerAngles))..ctor(num, SafetyLever.localEulerAngles.y, SafetyLever.localEulerAngles.z); SafetyLever.localEulerAngles = localEulerAngles; } } } namespace Volks.FC5_ARC; [BepInPlugin("Volks.FC5_ARC", "FC5_ARC", "1.0.0")] [BepInProcess("h3vr.exe")] [Description("Built with MeatKit")] [BepInDependency("h3vr.otherloader", "1.3.0")] public class FC5_ARCPlugin : BaseUnityPlugin { private static readonly string BasePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); internal static ManualLogSource Logger; private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; LoadAssets(); } private void LoadAssets() { Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Volks.FC5_ARC"); OtherLoader.RegisterDirectLoad(BasePath, "Volks.FC5_ARC", "", "", "fc5_arc", ""); } } public class MagPush : FVRInteractiveObject { public enum Mode { Translation, Rotation, Folding } public enum Axis { X, Y, Z } public enum E_State { Open, Mid, Closed } public FVRFireArm FireArm; public FVRFireArmReloadTriggerWell ReloadTriggerWell; public Transform ObjectToMove; public Transform Root; public Mode MovementMode; public Axis MovementAxis; public float LowerLimit; public float UpperLimit; public bool SnapsToEndStops = true; public float LimitWiggleRoom = 0.02f; public AudioEvent CloseSounds; public AudioEvent OpenSounds; public AudioEvent BeginInteractionSounds; public AudioEvent EndInteractionSounds; private FVRFireArmMagazine magazine; private bool isAttached = false; private bool isLoaded = false; private Vector3 _lastHandPos; private float _currentPositionValue; private Vector3 _origPos; public E_State State; private E_State _lastState; public override void Start() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) ((FVRInteractiveObject)this).Start(); _origPos = ObjectToMove.localPosition; } private void Update() { //IL_003d: 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 (!isAttached && (Object)(object)ReloadTriggerWell.FireArm.Magazine != (Object)null && Vector3.Distance(((Component)ReloadTriggerWell.FireArm.Magazine).transform.position, ObjectToMove.position) < 0.1f) { magazine = ReloadTriggerWell.FireArm.Magazine; isAttached = true; FireArm.PlayAudioEvent((FirearmAudioEventType)20, 1f); FireArm.Magazine = null; } } public override void BeginInteraction(FVRViveHand hand) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) ((FVRInteractiveObject)this).BeginInteraction(hand); _lastHandPos = ((HandInput)(ref hand.Input)).Pos; SM.PlayGenericSound(BeginInteractionSounds, ObjectToMove.position); } public override void UpdateInteraction(FVRViveHand hand) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) ((FVRInteractiveObject)this).UpdateInteraction(hand); if (isAttached && !isLoaded) { Vector3 val = ((HandInput)(ref hand.Input)).Pos - _lastHandPos; Vector3 vector = ObjectToMove.localPosition + val; float num = vector.GetAxisValue(MovementAxis) - _origPos.GetAxisValue(MovementAxis); _currentPositionValue = Mathf.Clamp(num, LowerLimit, UpperLimit); if (SnapsToEndStops && Mathf.Abs(_currentPositionValue - LowerLimit) < LimitWiggleRoom) { _currentPositionValue = LowerLimit; } else if (SnapsToEndStops && Mathf.Abs(_currentPositionValue - UpperLimit) < LimitWiggleRoom) { _currentPositionValue = UpperLimit; } ObjectToMove.ModifyLocalPositionAxisValue(MovementAxis, _currentPositionValue); _lastHandPos = ((HandInput)(ref hand.Input)).Pos; float lerp = Mathf.InverseLerp(LowerLimit, UpperLimit, _currentPositionValue); CheckSound(lerp); if (Mathf.Abs(_currentPositionValue - UpperLimit) < LimitWiggleRoom) { isLoaded = true; FireArm.PlayAudioEvent((FirearmAudioEventType)21, 1f); FireArm.Magazine = magazine; } } } public override void EndInteraction(FVRViveHand hand) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) ((FVRInteractiveObject)this).EndInteraction(hand); SM.PlayGenericSound(EndInteractionSounds, ObjectToMove.position); } private void OnEnable() { FireArm.Magazine = null; } public bool IsFirearmReady() { return isLoaded && FireArm.IsLoaded(); } public bool NeedsMagazinePush() { return isAttached && !isLoaded; } private void CheckSound(float lerp) { //IL_0067: 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) if (lerp < LimitWiggleRoom) { State = E_State.Open; } else if (lerp > 1f - LimitWiggleRoom) { State = E_State.Closed; } else { State = E_State.Mid; } if (State == E_State.Open && _lastState != 0) { SM.PlayGenericSound(OpenSounds, ObjectToMove.position); } if (State == E_State.Closed && _lastState != E_State.Closed) { SM.PlayGenericSound(CloseSounds, ObjectToMove.position); } _lastState = State; } } public static class TransformExtensions { public static float GetAxisValue(this Vector3 vector, MagPush.Axis axis) { return axis switch { MagPush.Axis.X => vector.x, MagPush.Axis.Y => vector.y, MagPush.Axis.Z => vector.z, _ => 0f, }; } public static void ModifyLocalPositionAxisValue(this Transform transform, MagPush.Axis axis, float value) { //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_0049: Unknown result type (might be due to invalid IL or missing references) Vector3 localPosition = transform.localPosition; switch (axis) { case MagPush.Axis.X: localPosition.x = value; break; case MagPush.Axis.Y: localPosition.y = value; break; case MagPush.Axis.Z: localPosition.z = value; break; } transform.localPosition = localPosition; } }