using System.Collections.Generic; using System.ComponentModel; 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.Logging; using FistVR; using H3VRUtils; using HarmonyLib; using OtherLoader; using UnityEngine; using UnityEngine.UI; [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 SecondaryMagPos : MonoBehaviour { [Header("References")] public FVRFireArm FireArm; public FVRFireArmReloadTriggerWell TriggerWell; [Header("Mount Override")] public Transform MountPos; public Transform EjectPos; private Transform m_defaultMountPos; private Transform m_defaultEjectPos; private Vector3 m_defaultMountLocalPos; private Quaternion m_defaultMountLocalRot; private Vector3 m_defaultEjectLocalPos; private Quaternion m_defaultEjectLocalRot; private bool m_initialized = false; private bool m_overrideActive = false; private FVRFireArmMagazine m_pendingMag; private int m_pendingStableFrames; private const int kStableFramesRequired = 2; private FVRFireArmMagazine m_appliedMag; private void Start() { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)FireArm == (Object)null || (Object)(object)TriggerWell == (Object)null) { ((Behaviour)this).enabled = false; return; } if ((Object)(object)MountPos == (Object)null) { ((Behaviour)this).enabled = false; return; } m_defaultMountPos = FireArm.MagazineMountPos; m_defaultEjectPos = FireArm.MagazineEjectPos; if ((Object)(object)m_defaultMountPos == (Object)null) { ((Behaviour)this).enabled = false; return; } m_defaultMountLocalPos = m_defaultMountPos.localPosition; m_defaultMountLocalRot = m_defaultMountPos.localRotation; if ((Object)(object)m_defaultEjectPos != (Object)null) { m_defaultEjectLocalPos = m_defaultEjectPos.localPosition; m_defaultEjectLocalRot = m_defaultEjectPos.localRotation; } m_initialized = true; m_pendingMag = null; m_pendingStableFrames = 0; m_appliedMag = null; } private void Update() { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) if (!m_initialized) { return; } FVRFireArmMagazine magazine = FireArm.Magazine; if ((Object)(object)magazine == (Object)(object)m_pendingMag) { if (m_pendingStableFrames < 2) { m_pendingStableFrames++; } } else { m_pendingMag = magazine; m_pendingStableFrames = 0; } if (m_pendingStableFrames < 2 || (Object)(object)m_pendingMag == (Object)(object)m_appliedMag) { return; } FireArmMagazineType val = ((!TriggerWell.UsesTypeOverride) ? FireArm.MagazineType : TriggerWell.TypeOverride); if ((Object)(object)m_pendingMag != (Object)null && m_pendingMag.MagazineType == val) { m_overrideActive = true; m_appliedMag = m_pendingMag; return; } if (m_overrideActive) { m_overrideActive = false; RestoreDefaults(); } m_appliedMag = null; } private void LateUpdate() { //IL_0028: 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_0077: 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 (m_initialized && m_overrideActive) { m_defaultMountPos.position = MountPos.position; m_defaultMountPos.rotation = MountPos.rotation; if ((Object)(object)m_defaultEjectPos != (Object)null && (Object)(object)EjectPos != (Object)null) { m_defaultEjectPos.position = EjectPos.position; m_defaultEjectPos.rotation = EjectPos.rotation; } } } private void RestoreDefaults() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) m_defaultMountPos.localPosition = m_defaultMountLocalPos; m_defaultMountPos.localRotation = m_defaultMountLocalRot; if ((Object)(object)m_defaultEjectPos != (Object)null) { m_defaultEjectPos.localPosition = m_defaultEjectLocalPos; m_defaultEjectPos.localRotation = m_defaultEjectLocalRot; } } private void OnDisable() { if (m_initialized) { RestoreDefaults(); } } private void OnDestroy() { if (m_initialized) { RestoreDefaults(); } } } namespace Iqsbasiczz.M110K1; [BepInPlugin("Iqsbasiczz.M110K1", "M110K1", "1.0.1")] [BepInProcess("h3vr.exe")] [Description("Built with MeatKit")] [BepInDependency("h3vr.otherloader", "1.3.0")] public class M110K1Plugin : 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(), "Iqsbasiczz.M110K1"); OtherLoader.RegisterDirectLoad(BasePath, "Iqsbasiczz.M110K1", "", "", "m110k1sass", ""); } } public class ExpandedAmmoDisplay : MonoBehaviour { [Header("Ammo Counter Settings")] [Tooltip("Text to display ammo left in the gun.")] public Text UItext; [Tooltip("Text to display maximum ammo.")] public Text MaxAmmoText; [Tooltip("Text to display the type of ammo.")] public Text ammoTypeText; [Tooltip("Adds a minimum character count. See tooltip for MinCharLength for more.")] public bool AddMinCharLength; [Tooltip("i.e if MinCharLength is 2 and the amount of rounds left is 5, it will display 05 instead of 5.")] public int MinCharLength; [Tooltip("Will not instantly be the correct amount of rounds, but will tick up/down until it is.")] public bool enableDispLerp; [Tooltip("MaxAmmo will also lerp according to the DispLerpAmt")] public bool enableLerpForMaxAmmo; [Tooltip("EnabledObjects will also lerp according to the DispLerpAmt")] public bool enableLerpForEnabledObjects; [Tooltip("From 0-1. The % amount moved towards its correct amount every 50th of a second.")] [Range(0f, 0.2f)] public float DispLerpAmt; [Header("Alternate Displays")] [Tooltip("Enables enabling/disabling objects based on rounds left in mag.")] public bool EnabledObjects; [Tooltip("Object enabled when there is no magazine.")] public GameObject ObjectWhenEmpty; [Tooltip("Element no. corresponds to rounds left. 0 means no rounds, 1 means one round. Enables the 5th object if there are 5 rounds, and so on.")] public List Objects; [Tooltip("Enables all objects under the round count. Enables the 0th, 1st, 2nd, 3rd objects if there are 3 rounds left, and so on.")] public bool EnableAllUnderAmount; [Tooltip("Overrides Objects. #0 means Objects' #0 displays from 0% to #0%, #1 means Objects' #1 displays from #0% to #1%, etc- written normally, not mathmatically (e.g 57.32)")] public bool EnableBasedOnPercentage; public List ObjectPercentages; [Header("Fire Mode Display")] [Tooltip("Text to display the fire mode (e.g., Safe, Single, FullAuto, Burst).")] public Text fireModeText; [Tooltip("Image to display fire mode visually.")] public Image fireModeImage; [Tooltip("Sprites for each fire mode: 0=Safe, 1=Single, 2=FullAuto, 3=Burst, 4=Other.")] public Sprite[] fireModeSprites; [Header("Low Ammo Warning")] [Tooltip("Enable sound and blink effects when ammo drops to a percentage of max.")] public bool enableLowAmmoWarning; [Tooltip("Percentage of max ammo at which the warning triggers (e.g. 25 means 25%).")] [Range(0f, 100f)] public float lowAmmoThresholdPercent = 25f; [Tooltip("AudioSource used to play warning sounds.")] public AudioSource warningAudioSource; [Tooltip("Sound played once when ammo drops to or below the low ammo threshold.")] public AudioClip lowAmmoClip; [Tooltip("Sound played once when ammo is fully depleted (0 rounds).")] public AudioClip depletedAmmoClip; [Tooltip("Enable blinking on the ammo text when at or below the low ammo threshold.")] public bool enableLowAmmoBlink; [Tooltip("How many times per second the text blinks on/off.")] public float blinkRate = 4f; [Header("Chamber Indicator (optional)")] [Tooltip("Enable a visual/text indicator when there is a round in the chamber.")] public bool showChamberIndicator = false; [Tooltip("If true the indicator will use an Image; otherwise it will use Text.")] public bool chamberIndicatorUseImage = true; [Tooltip("Image used to indicate a round is chambered. Assign only if using image mode.")] public Image chamberIndicatorImage; [Tooltip("Text used to indicate a round is chambered. Assign only if using text mode.")] public Text chamberIndicatorText; [Tooltip("Text shown when a round is chambered (used when chamberIndicatorUseImage == false).")] public string chamberIndicatorString = "CH"; private FVRFireArm _fa; private FVRFireArmMagazine _mag; private FVRFirearmMovingProxyRound[] proxies; private FVRFireArmChamber[] chambers; private int lastAmountOfBullets; private int lastAmountOfMaxBullets; private int lastAmountOfBulletsForEnableObjects; private bool _hasPlayedLowAmmoSound; private bool _hasPlayedDepletedSound; private bool _isBlinking; private float _blinkTimer; private int _previousAmmoCount = -1; private bool _hadMagLastFrame; private bool _isChamberIndicatorImageNotNull; private bool _isChamberIndicatorTextNotNull; private bool _isUItextNotNull; private bool _isMaxAmmoTextNotNull; private bool _isammoTypeTextNotNull; private bool _isfireModeTextNotNull; private bool _isfireModeImageNotNull; private void Start() { NullCheck(); } private void GetFirearmAndMag() { _fa = ((Component)this).GetComponent() ?? ((Component)this).GetComponentInParent(); if ((Object)(object)_fa != (Object)null) { _mag = _fa.Magazine; if (chambers == null) { chambers = GetFireArmDeets.GetFireArmChamber(_fa); } proxies = GetFireArmDeets.GetFireArmProxySwitch(_fa, false); } else { _mag = null; chambers = null; proxies = null; } } private void Update() { GetFirearmAndMag(); int ammoCount = GetAmmoCount(); int maxAmmoCount = GetMaxAmmoCount(); bool flag = (Object)(object)_mag != (Object)null; if (_isUItextNotNull) { string text = CalculateAmmoCounterAmount(ammoCount, ref lastAmountOfBullets, enableDispLerp, DispLerpAmt, AddMinCharLength, MinCharLength); UItext.text = text; } if (_isMaxAmmoTextNotNull) { string text2 = CalculateAmmoCounterAmount(maxAmmoCount, ref lastAmountOfMaxBullets, enableLerpForMaxAmmo, DispLerpAmt, AddMinCharLength, MinCharLength); MaxAmmoText.text = text2; } if (_isammoTypeTextNotNull) { ammoTypeText.text = GetAmmoType(); } if (_isfireModeTextNotNull || _isfireModeImageNotNull) { string fireMode = GetFireMode(); if (_isfireModeTextNotNull) { fireModeText.text = fireMode; } if (_isfireModeImageNotNull && fireModeSprites != null && fireModeSprites.Length > 0) { int spriteIndexForMode = GetSpriteIndexForMode(fireMode); if (spriteIndexForMode >= 0 && spriteIndexForMode < fireModeSprites.Length) { fireModeImage.sprite = fireModeSprites[spriteIndexForMode]; } } } if (EnabledObjects) { int num = int.Parse(CalculateAmmoCounterAmount(ammoCount, ref lastAmountOfBulletsForEnableObjects, enableLerpForEnabledObjects, DispLerpAmt)); if (EnableBasedOnPercentage) { SetEnabledObjectsPercentage(num); } else { SetEnabledObjects(num); } } if (enableLowAmmoWarning) { UpdateLowAmmoWarning(ammoCount, maxAmmoCount, flag); } else { ResetWarningState(); } if (showChamberIndicator) { int num2 = 0; if (chambers != null) { num2 = chambers.Count((FVRFireArmChamber chamber) => chamber.IsFull && !chamber.IsSpent); } bool flag2 = num2 > 0; if (chamberIndicatorUseImage) { if (_isChamberIndicatorImageNotNull && (Object)(object)chamberIndicatorImage != (Object)null) { ((Component)chamberIndicatorImage).gameObject.SetActive(flag2); } } else if (_isChamberIndicatorTextNotNull && (Object)(object)chamberIndicatorText != (Object)null) { ((Component)chamberIndicatorText).gameObject.SetActive(flag2); if (flag2) { chamberIndicatorText.text = chamberIndicatorString; } } } else { if (_isChamberIndicatorImageNotNull && (Object)(object)chamberIndicatorImage != (Object)null) { ((Component)chamberIndicatorImage).gameObject.SetActive(false); } if (_isChamberIndicatorTextNotNull && (Object)(object)chamberIndicatorText != (Object)null) { ((Component)chamberIndicatorText).gameObject.SetActive(false); } } _previousAmmoCount = ammoCount; _hadMagLastFrame = flag; } private void UpdateLowAmmoWarning(int currentAmmo, int maxAmmo, bool hasMag) { if (!hasMag) { ResetWarningState(); return; } bool flag = hasMag && !_hadMagLastFrame; bool flag2 = false; bool flag3 = false; if (maxAmmo > 0) { if (currentAmmo > 0) { float num = (float)currentAmmo / (float)maxAmmo * 100f; flag2 = num <= lowAmmoThresholdPercent; } if (_previousAmmoCount > 0) { float num2 = (float)_previousAmmoCount / (float)maxAmmo * 100f; flag3 = num2 <= lowAmmoThresholdPercent; } } if (flag2 && (!flag3 || flag)) { PlayWarningClip(lowAmmoClip); } if (currentAmmo <= 0) { bool flag4 = _previousAmmoCount > 0; bool flag5 = flag; if ((flag4 || flag5) && !_hasPlayedDepletedSound) { PlayWarningClip(depletedAmmoClip); _hasPlayedDepletedSound = true; } } if (maxAmmo > 0 && currentAmmo > 0) { float num3 = (float)currentAmmo / (float)maxAmmo * 100f; if (num3 > lowAmmoThresholdPercent) { _hasPlayedDepletedSound = false; } } if (enableLowAmmoBlink && _isUItextNotNull && (flag2 || _hasPlayedDepletedSound)) { _isBlinking = true; _blinkTimer += Time.deltaTime; float num4 = ((!(blinkRate > 0f)) ? 1f : (1f / blinkRate)); bool enabled = _blinkTimer % num4 < num4 * 0.5f; ((Behaviour)UItext).enabled = enabled; } else if (_isBlinking) { _isBlinking = false; _blinkTimer = 0f; if (_isUItextNotNull) { ((Behaviour)UItext).enabled = true; } } } private void ResetWarningState() { if (_isBlinking) { _isBlinking = false; _blinkTimer = 0f; if (_isUItextNotNull) { ((Behaviour)UItext).enabled = true; } } _hasPlayedLowAmmoSound = false; _hasPlayedDepletedSound = false; } private void PlayWarningClip(AudioClip clip) { if ((Object)(object)clip != (Object)null && (Object)(object)warningAudioSource != (Object)null) { warningAudioSource.PlayOneShot(clip); } } private int GetAmmoCount() { if ((Object)(object)_mag != (Object)null) { return _mag.m_numRounds; } int num = 0; if ((Object)(object)_fa != (Object)null) { if (chambers != null) { num += chambers.Count((FVRFireArmChamber chamber) => chamber.IsFull && !chamber.IsSpent); } if (proxies != null) { FVRFirearmMovingProxyRound[] array = proxies; foreach (FVRFirearmMovingProxyRound val in array) { if (val.IsFull) { num++; } } } if ((Object)(object)_fa.BeltDD != (Object)null) { num += _fa.BeltDD.m_roundsOnBelt; } } return num; } private int GetMaxAmmoCount() { if ((Object)(object)_mag != (Object)null) { return _mag.m_capacity; } if ((Object)(object)_fa != (Object)null && !_fa.UsesMagazines) { return (chambers != null) ? chambers.Length : 0; } return 0; } private string GetAmmoType() { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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_003e: 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) //IL_009b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_fa != (Object)null) { List chamberRoundList = _fa.GetChamberRoundList(); if (chamberRoundList != null && chamberRoundList.Count > 0) { return AM.GetFullRoundName(_fa.RoundType, chamberRoundList[0]); } if ((Object)(object)_fa.BeltDD != (Object)null && _fa.BeltDD.m_roundsOnBelt > 0) { return AM.GetFullRoundName(_fa.RoundType, _fa.BeltDD.BeltRounds[0].LR_Class); } } if ((Object)(object)_mag != (Object)null && _mag.m_numRounds > 0) { return AM.GetFullRoundName(_mag.RoundType, _mag.LoadedRounds[0].LR_Class); } return string.Empty; } private string GetFireMode() { if ((Object)(object)_fa == (Object)null) { return "N/A"; } FVRFireArm fa = _fa; Handgun val = (Handgun)(object)((fa is Handgun) ? fa : null); if ((Object)(object)val == (Object)null) { return "N/A"; } if (val.IsSafetyEngaged) { return "Safe"; } if (val.FireSelectorModes != null && val.FireSelectorModes.Length > 0) { FireSelectorMode val2 = val.FireSelectorModes[val.FireSelectorModeIndex]; return ((object)(FireSelectorModeType)(ref val2.ModeType)).ToString(); } return "N/A"; } private int GetSpriteIndexForMode(string mode) { return mode switch { "Safe" => 0, "Single" => 1, "FullAuto" => 2, "Burst" => 3, _ => 4, }; } public static string CalculateAmmoCounterAmount(int currentammo, ref int lastammo, bool lerp = false, float lerpAmt = 0f, bool pad = false, int padAmt = 0) { if (lerp) { currentammo = LerpInt(lastammo, currentammo, lerpAmt); } string text = currentammo.ToString(); if (pad) { text = PadStringNumberToAmt(text, padAmt); } lastammo = currentammo; return text; } public static string PadStringNumberToAmt(string str, int minCharLength) { int num = minCharLength - str.Length; for (int i = 0; i < num; i++) { str = "0" + str; } return str; } public static int LerpInt(int a, int b, float lerp) { bool flag = a == 0; a = Mathf.CeilToInt(Mathf.Lerp((float)a, (float)b, lerp)); if (a == 1 && flag) { a = 0; } return a; } private void SetEnabledObjects(int amt) { amt = Mathf.Clamp(amt, 0, Objects.Count - 1); for (int i = 0; i < Objects.Count; i++) { Objects[i].SetActive(false); } if ((Object)(object)ObjectWhenEmpty != (Object)null) { ObjectWhenEmpty.SetActive(false); } if ((Object)(object)_mag == (Object)null && (Object)(object)ObjectWhenEmpty != (Object)null) { ObjectWhenEmpty.SetActive(true); return; } for (int j = 0; j < Objects.Count; j++) { if (j < amt) { if (EnableAllUnderAmount) { Objects[j].SetActive(true); } } else if (j == amt) { Objects[j].SetActive(true); } } } private void SetEnabledObjectsPercentage(int amt) { amt = Mathf.Clamp(amt, 0, Objects.Count - 1); int maxAmmoCount = GetMaxAmmoCount(); if (maxAmmoCount <= 0) { return; } float num = (float)amt / (float)maxAmmoCount; for (int i = 0; i < Objects.Count; i++) { Objects[i].SetActive(false); } if ((Object)(object)ObjectWhenEmpty != (Object)null) { ObjectWhenEmpty.SetActive(false); } if ((Object)(object)_mag == (Object)null && (Object)(object)ObjectWhenEmpty != (Object)null) { ObjectWhenEmpty.SetActive(true); return; } for (int j = 0; j < Objects.Count; j++) { float num2 = ObjectPercentages[j] / 100f; float num3 = 0f; if (j > 0) { num3 = ObjectPercentages[j - 1] / 100f; } if (!(num > num2)) { continue; } if (num > num3) { if (EnableAllUnderAmount) { Objects[j].SetActive(true); } } else { Objects[j].SetActive(true); } } } public void NullCheck() { _isammoTypeTextNotNull = (Object)(object)ammoTypeText != (Object)null; _isMaxAmmoTextNotNull = (Object)(object)MaxAmmoText != (Object)null; _isUItextNotNull = (Object)(object)UItext != (Object)null; _isfireModeTextNotNull = (Object)(object)fireModeText != (Object)null; _isfireModeImageNotNull = (Object)(object)fireModeImage != (Object)null; _isChamberIndicatorImageNotNull = (Object)(object)chamberIndicatorImage != (Object)null; _isChamberIndicatorTextNotNull = (Object)(object)chamberIndicatorText != (Object)null; } }