Decompiled source of ReloadTimerPlus v1.1.0

Zose_ReloadTimerPlus.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using AK;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CellMenu;
using GameData;
using Gear;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Microsoft.CodeAnalysis;
using Player;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Zose_ReloadTimerPlus")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Zose_ReloadTimerPlus")]
[assembly: AssemblyTitle("Zose_ReloadTimerPlus")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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 Zose_ReloadTimerPlus
{
	public static class PluginData
	{
		public const string GUID = "Zose_ReloadTimerPlus";

		public const string Name = "Zose_ReloadTimerPlus";

		public const string Version = "1.6.0";
	}
	public enum ReloadSoundOption
	{
		None,
		HACKING_PUZZLE_CORRECT,
		BUTTONGENERICBLIPCONFIRM,
		BUTTONGENERICSEQUENCEDONE,
		HUD_TIMER_RUSH,
		CustomLocalFile
	}
	[BepInPlugin("Zose_ReloadTimerPlus", "Zose_ReloadTimerPlus", "1.6.0")]
	public class EntryPoint : BasePlugin
	{
		public static EntryPoint? Instance;

		public static ConfigEntry<float>? ConfigOffset;

		public static ConfigEntry<string>? ConfigChargeColor;

		public static ConfigEntry<float>? ConfigLowAmmoThreshold;

		public static ConfigEntry<string>? ConfigLowAmmoColor;

		public static ConfigEntry<ReloadSoundOption>? ConfigReloadSoundCue;

		public static ConfigEntry<string>? ConfigCustomSoundFileName;

		public static ConfigEntry<bool>? ConfigEnableChargeCircleEffects;

		public static ConfigEntry<bool>? ConfigEnableLowAmmoWarning;

		public static Color ParsedChargeColor = new Color(0f, 1f, 0f, 0.8f);

		public static Color ParsedLowAmmoColor = new Color(1f, 0f, 0f, 0.8f);

		public static bool NeedsConfigReload = false;

		private static Harmony? harmony;

		private static FileSystemWatcher? _configWatcher;

		public override void Load()
		{
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Expected O, but got Unknown
			Instance = this;
			ClassInjector.RegisterTypeInIl2Cpp<Zose_ReloadTimerPlus>();
			ConfigOffset = ((BasePlugin)this).Config.Bind<float>("Settings", "TextOffset", 85f, "Vertical offset of the reload text from the crosshair.");
			ConfigOffset.SettingChanged += delegate
			{
				Zose_ReloadTimerPlus.Instance?.UpdateUIPosition();
			};
			ConfigChargeColor = ((BasePlugin)this).Config.Bind<string>("Settings", "ChargeColor", "#00FF0080", "Color of the reload charge circle in Hex format (#RRGGBBAA).");
			ConfigEnableChargeCircleEffects = ((BasePlugin)this).Config.Bind<bool>("Settings", "EnableChargeCircleEffects", true, "Enable the reload charge circle progress, ready effects, and text timer.");
			ConfigEnableLowAmmoWarning = ((BasePlugin)this).Config.Bind<bool>("AmmoWarning", "EnableLowAmmoWarning", true, "Enable the low ammo 'RELOAD' warning text.");
			ConfigLowAmmoThreshold = ((BasePlugin)this).Config.Bind<float>("AmmoWarning", "LowAmmoThreshold", 0.35f, "Ammo threshold (0.0-1.0) for warning.");
			ConfigLowAmmoColor = ((BasePlugin)this).Config.Bind<string>("AmmoWarning", "LowAmmoColor", "#FF000080", "Color of the 'RELOAD' warning text in Hex format (#RRGGBBAA).");
			ConfigReloadSoundCue = ((BasePlugin)this).Config.Bind<ReloadSoundOption>("Sound", "ReloadSoundCue", ReloadSoundOption.HACKING_PUZZLE_CORRECT, "Sound event name to play on reload complete. Select 'None' to disable. Select 'CustomLocalFile' to use a local audio file.");
			ConfigCustomSoundFileName = ((BasePlugin)this).Config.Bind<string>("Sound", "CustomSoundFileName", "custom_reload.wav", "The name of the audio file (.wav/.ogg) to play when ReloadSoundCue is set to CustomLocalFile.\nPlace this file inside the 'BepInEx/config/Zose_ReloadTimerPlus' folder.");
			UpdateParsedColor();
			ConfigChargeColor.SettingChanged += delegate
			{
				UpdateParsedColor();
			};
			ConfigLowAmmoColor.SettingChanged += delegate
			{
				UpdateParsedColor();
			};
			SetupConfigWatcher();
			harmony = new Harmony("Zose_ReloadTimerPlus");
			harmony.PatchAll();
			Zose_ReloadTimerPlus.LoadCache();
			Logger.Info("Zose_ReloadTimerPlus 1.6.0 loaded.");
		}

		public void ReloadConfig()
		{
			((BasePlugin)this).Config.Reload();
			UpdateParsedColor();
			SoundHelper.InvalidateCache();
			Logger.Info("Config reloaded from disk.");
		}

		private void UpdateParsedColor()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			Color parsedChargeColor = default(Color);
			if (ConfigChargeColor != null && ColorUtility.TryParseHtmlString(ConfigChargeColor.Value, ref parsedChargeColor))
			{
				ParsedChargeColor = parsedChargeColor;
			}
			Color parsedLowAmmoColor = default(Color);
			if (ConfigLowAmmoColor != null && ColorUtility.TryParseHtmlString(ConfigLowAmmoColor.Value, ref parsedLowAmmoColor))
			{
				ParsedLowAmmoColor = parsedLowAmmoColor;
			}
		}

		private void SetupConfigWatcher()
		{
			try
			{
				_configWatcher = new FileSystemWatcher(Path.GetDirectoryName(((BasePlugin)this).Config.ConfigFilePath), Path.GetFileName(((BasePlugin)this).Config.ConfigFilePath));
				_configWatcher.NotifyFilter = NotifyFilters.LastWrite;
				_configWatcher.Changed += delegate
				{
					NeedsConfigReload = true;
				};
				_configWatcher.EnableRaisingEvents = true;
			}
			catch (Exception ex)
			{
				Logger.Error("Failed to setup ConfigWatcher: " + ex.Message);
			}
		}
	}
	internal static class Logger
	{
		private static readonly ManualLogSource _Logger;

		static Logger()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			_Logger = new ManualLogSource("Zose_ReloadTimerPlus");
			Logger.Sources.Add((ILogSource)(object)_Logger);
		}

		public static void Info(string str)
		{
			_Logger.LogMessage((object)str);
		}

		public static void Info(object data)
		{
			_Logger.LogMessage((object)data?.ToString());
		}

		public static void Debug(string str)
		{
			_Logger.LogDebug((object)str);
		}

		public static void Debug(object data)
		{
			_Logger.LogDebug((object)data?.ToString());
		}

		public static void Error(string str)
		{
			_Logger.LogError((object)str);
		}

		public static void Error(object data)
		{
			_Logger.LogError((object)data?.ToString());
		}

		public static void Fatal(string str)
		{
			_Logger.LogFatal((object)str);
		}

		public static void Fatal(object data)
		{
			_Logger.LogFatal((object)data?.ToString());
		}

		public static void Warn(string str)
		{
			_Logger.LogWarning((object)str);
		}

		public static void Warn(object data)
		{
			_Logger.LogWarning((object)data?.ToString());
		}
	}
	public class Zose_ReloadTimerPlus : MonoBehaviour
	{
		private TextMeshProUGUI _textMesh = null;

		private TextMeshProUGUI _glitchTextMesh2 = null;

		private GameObject _uiRoot = null;

		public static Zose_ReloadTimerPlus Instance;

		private bool _isReloading = false;

		private float _reloadStartTime = 0f;

		private float _lastReloadDuration = 0f;

		private string _currentWeaponName = "";

		private int _lastClipCount = -1;

		private AudioSource? _audioSource;

		private AudioClip? _customClip;

		private string _lastLoadedFileName = "";

		private static Dictionary<string, float> _persistentRatioMap = new Dictionary<string, float>();

		private string _currFingerprint = "";

		private bool _ammoFilledThisReload = false;

		private bool _isStutteringDuringReload = false;

		private float _readyEffectStartTime = -1f;

		private bool _hasTriggeredReadyEffect = false;

		private bool _isAnimatingReady = false;

		private bool _waitingForNativeReloadToEnd = false;

		private bool _isChargeWeapon = false;

		private float _lastGlitchTime = 0f;

		private string _currGlitchedText = "";

		private const string GLITCH_CHARS = "#@&!$%01X?";

		private bool _chargeShown = false;

		private static bool _reflectionChecked = false;

		private Color _originalChargeColor;

		private static MethodInfo? _setChargeUpVisibleAndProgressMethod;

		private static Il2CppObjectBase? _circleTarget;

		private static MethodInfo? _setChargeMethod;

		private static MethodInfo? _showChargeMethod;

		private static MethodInfo? _setChargeColorMethod;

		private static FieldInfo? _chargeUpColOrgField;

		private static FieldInfo? _isAimingField;

		private IntPtr _lastWieldPointer = IntPtr.Zero;

		private BulletWeapon? _cachedBulletWeapon;

		private static MethodInfo? _getIdentifierMethod;

		private PlayerAgent? _localPlayer;

		private const float MAX_SWAY_OFFSET = 12f;

		private const float SWAY_SENSITIVITY = 1.2f;

		private const float SWAY_SMOOTHING = 0.12f;

		private const float ADS_SWAY_MULTIPLIER = 0.25f;

		private Vector2 _currentSwayOffset = Vector2.zero;

		private Vector2 _swayVelocity = Vector2.zero;

		private bool _isFirstSwayFrame = true;

		private static string _cachePath = Path.Combine(Paths.ConfigPath, "Zose_ReloadTimerPlus_Cache.txt");

		private static bool _cacheLoaded = false;

		private static string _cachedRundownInfo = "";

		private Vector3 _lastCamForward = Vector3.one;

		public void Awake()
		{
			//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_005a: Expected O, but got Unknown
			//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_009a: Expected O, but got Unknown
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Expected O, but got Unknown
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Logger.Info("Zose_ReloadTimerPlus INITIALIZED.");
			_audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			_audioSource.playOnAwake = false;
			if (!_cacheLoaded)
			{
				LoadCache();
			}
			_uiRoot = new GameObject("ReloadTimer")
			{
				layer = 5
			};
			_uiRoot.transform.SetParent(((Component)GuiManager.CrosshairLayer.m_circleCrosshair).transform.parent, false);
			UpdateUIPosition();
			GameObject val = new GameObject("MainText")
			{
				layer = 5
			};
			val.transform.SetParent(_uiRoot.transform, false);
			_textMesh = SetupTextMesh(val, new Color(1f, 1f, 1f, 1f));
			GameObject val2 = new GameObject("GlitchR")
			{
				layer = 5
			};
			val2.transform.SetParent(_uiRoot.transform, false);
			GameObject val3 = new GameObject("GlitchC")
			{
				layer = 5
			};
			val3.transform.SetParent(_uiRoot.transform, false);
			_glitchTextMesh2 = SetupTextMesh(val3, new Color(1f, 1f, 1f, 0f));
		}

		public string GetWeaponFingerprint(BulletWeapon weapon)
		{
			if ((Object)(object)weapon == (Object)null)
			{
				return "";
			}
			if (string.IsNullOrEmpty(_cachedRundownInfo) || _cachedRundownInfo == "RD_UNK")
			{
				_cachedRundownInfo = "";
				try
				{
					Type typeFromHandle = typeof(RundownManager);
					BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
					string[] array = new string[3] { "CurrentlySelectedRundownKey", "ActiveRundownData", "m_activeRundownKey" };
					string[] array2 = array;
					foreach (string name in array2)
					{
						try
						{
							PropertyInfo property = typeFromHandle.GetProperty(name, bindingAttr);
							FieldInfo field = typeFromHandle.GetField(name, bindingAttr);
							object obj = property?.GetValue(null) ?? field?.GetValue(null);
							if (obj != null)
							{
								string text = ((obj is string text2) ? text2 : obj.ToString());
								if (!string.IsNullOrEmpty(text) && text != "0" && !text.Contains("DataBlock"))
								{
									_cachedRundownInfo = "RD_" + text;
									break;
								}
							}
						}
						catch
						{
						}
					}
					if (string.IsNullOrEmpty(_cachedRundownInfo))
					{
						try
						{
							Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
							foreach (Assembly assembly in assemblies)
							{
								string fullName = assembly.FullName;
								if (fullName.Contains("System") || fullName.Contains("Unity") || fullName.Contains("mscorlib") || fullName.Contains("BepInEx"))
								{
									continue;
								}
								Type[] types = assembly.GetTypes();
								foreach (Type type in types)
								{
									if (type.Name.Contains("Config") || type.Name.Contains("Rundown") || type.Name.Contains("Archive") || type.Name.Contains("Global"))
									{
										PropertyInfo[] properties = type.GetProperties(bindingAttr);
										foreach (PropertyInfo propertyInfo in properties)
										{
											if (!(propertyInfo.PropertyType == typeof(string)) || (!propertyInfo.Name.Contains("Rundown") && !propertyInfo.Name.Contains("SelectedKey")))
											{
												continue;
											}
											try
											{
												string text3 = propertyInfo.GetValue(null)?.ToString();
												if (!string.IsNullOrEmpty(text3) && text3.Length > 2 && !text3.Contains(" ") && !text3.Contains("/"))
												{
													_cachedRundownInfo = text3;
													break;
												}
											}
											catch
											{
											}
										}
										if (!string.IsNullOrEmpty(_cachedRundownInfo))
										{
											break;
										}
										FieldInfo[] fields = type.GetFields(bindingAttr);
										foreach (FieldInfo fieldInfo in fields)
										{
											if (!(fieldInfo.FieldType == typeof(string)) || (!fieldInfo.Name.Contains("Rundown") && !fieldInfo.Name.Contains("ActiveKey")))
											{
												continue;
											}
											try
											{
												string text4 = fieldInfo.GetValue(null)?.ToString();
												if (!string.IsNullOrEmpty(text4) && text4.Length > 2 && !text4.Contains(" "))
												{
													_cachedRundownInfo = text4;
													break;
												}
											}
											catch
											{
											}
										}
									}
									if (!string.IsNullOrEmpty(_cachedRundownInfo))
									{
										break;
									}
								}
								if (!string.IsNullOrEmpty(_cachedRundownInfo))
								{
									break;
								}
							}
						}
						catch
						{
						}
					}
					if (string.IsNullOrEmpty(_cachedRundownInfo))
					{
						try
						{
							object obj6 = typeFromHandle.GetMethod("GetActiveRundownData", bindingAttr)?.Invoke(null, null);
							if (obj6 != null)
							{
								_cachedRundownInfo = (obj6.GetType().GetProperty("name") ?? obj6.GetType().GetProperty("Key"))?.GetValue(obj6)?.ToString() ?? "RD_UNK";
							}
						}
						catch
						{
						}
					}
					if (string.IsNullOrEmpty(_cachedRundownInfo))
					{
						_cachedRundownInfo = "RD_UNK";
					}
					if (_cachedRundownInfo != "RD_UNK")
					{
						_cachedRundownInfo = Regex.Replace(_cachedRundownInfo, "[^a-zA-Z0-9_-]", "");
						Logger.Info("Rundown Identified: " + _cachedRundownInfo);
					}
				}
				catch (Exception ex)
				{
					Logger.Error("Rundown Scan Error: " + ex.Message);
				}
			}
			return $"{_cachedRundownInfo}_{((GameDataBlockBase<ArchetypeDataBlock>)(object)((ItemEquippable)weapon).ArchetypeData).persistentID}_{((Item)weapon).PublicName}_{((ItemEquippable)weapon).ArchetypeData.DefaultReloadTime:F2}_{((ItemEquippable)weapon).ClipSize}";
		}

		public static void LoadCache()
		{
			if (string.IsNullOrEmpty(_cachePath))
			{
				return;
			}
			try
			{
				if (!File.Exists(_cachePath))
				{
					Logger.Info("No existing calibration cache found. Starting fresh.");
					_cacheLoaded = true;
					return;
				}
				string[] array = File.ReadAllLines(_cachePath);
				string[] array2 = array;
				foreach (string text in array2)
				{
					if (!string.IsNullOrWhiteSpace(text))
					{
						string[] array3 = text.Split('=');
						if (array3.Length == 2 && float.TryParse(array3[1], out var result))
						{
							_persistentRatioMap[array3[0]] = result;
						}
					}
				}
				_cacheLoaded = true;
				Logger.Info($"SUCCESS: Loaded {_persistentRatioMap.Count} calibrated weapon profiles from disk.");
			}
			catch (Exception ex)
			{
				Logger.Error("Cache Load Error: " + ex.Message);
			}
		}

		private static void SaveCache()
		{
			try
			{
				List<string> list = new List<string>();
				foreach (KeyValuePair<string, float> item in _persistentRatioMap)
				{
					list.Add($"{item.Key}={item.Value:F4}");
				}
				File.WriteAllLines(_cachePath, list);
			}
			catch (Exception ex)
			{
				Logger.Error("Cache Save Error: " + ex.Message);
			}
		}

		private TextMeshProUGUI SetupTextMesh(GameObject go, Color col)
		{
			//IL_0024: 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)
			TextMeshProUGUI val = go.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val).alignment = (TextAlignmentOptions)514;
			((Component)val).GetComponent<RectTransform>().sizeDelta = new Vector2(400f, 100f);
			((TMP_Text)val).fontSize = 20f;
			((TMP_Text)val).font = ((TMP_Text)GuiManager.PlayerLayer.m_playerStatus.m_healthText).font;
			((Graphic)val).color = col;
			((TMP_Text)val).characterSpacing = 0f;
			((TMP_Text)val).richText = true;
			return val;
		}

		public void OnAmmoRefreshed()
		{
			if (!_isReloading || _ammoFilledThisReload)
			{
				return;
			}
			_ammoFilledThisReload = true;
			if (_isStutteringDuringReload)
			{
				Logger.Info("Stutter detected during reload, skipping calibration to maintain accuracy.");
			}
			else
			{
				float num = Time.time - _reloadStartTime;
				if (_lastReloadDuration > 0f && !string.IsNullOrEmpty(_currFingerprint))
				{
					float num2 = Mathf.Clamp(num / _lastReloadDuration, 0.3f, 0.98f);
					if (!_persistentRatioMap.ContainsKey(_currFingerprint))
					{
						_persistentRatioMap[_currFingerprint] = num2;
						SaveCache();
					}
					else
					{
						float num3 = _persistentRatioMap[_currFingerprint];
						if (Mathf.Abs(num2 - num3) > 0.01f)
						{
							float value = (num3 * 4f + num2) / 5f;
							_persistentRatioMap[_currFingerprint] = value;
							SaveCache();
						}
					}
				}
			}
			if (!_hasTriggeredReadyEffect)
			{
				_readyEffectStartTime = Time.time;
				_hasTriggeredReadyEffect = true;
				_isAnimatingReady = true;
				PlayReloadCue();
			}
		}

		private void Update()
		{
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<ReloadSoundOption>? configReloadSoundCue = EntryPoint.ConfigReloadSoundCue;
			if (configReloadSoundCue != null && configReloadSoundCue.Value == ReloadSoundOption.CustomLocalFile)
			{
				string text = EntryPoint.ConfigCustomSoundFileName?.Value ?? "custom_reload.wav";
				if (text != _lastLoadedFileName)
				{
					_lastLoadedFileName = text;
					string text2 = Path.Combine(Paths.ConfigPath, "Zose_ReloadTimerPlus");
					if (!Directory.Exists(text2))
					{
						Directory.CreateDirectory(text2);
					}
					string text3 = Path.Combine(text2, text);
					if (File.Exists(text3))
					{
						Logger.Info("Loading custom WAV audio from: " + text3);
						try
						{
							_customClip = WavUtility.ToAudioClip(text3, text);
							if ((Object)(object)_customClip != (Object)null)
							{
								((Object)_customClip).hideFlags = (HideFlags)32;
								Logger.Info("Successfully loaded custom WAV audio: " + text);
							}
							else
							{
								Logger.Error("Failed to parse WAV file: " + text3 + ". Ensure it is a valid RIFF/WAVE file.");
							}
						}
						catch (Exception ex)
						{
							Logger.Error("Error loading custom WAV audio: " + ex.Message);
						}
					}
					else
					{
						Logger.Error("Custom audio file not found: " + text3);
					}
				}
			}
			if (EntryPoint.NeedsConfigReload)
			{
				EntryPoint.NeedsConfigReload = false;
				EntryPoint.Instance?.ReloadConfig();
				UpdateUIPosition();
			}
			if ((Object)(object)_localPlayer == (Object)null)
			{
				_localPlayer = PlayerManager.GetLocalPlayerAgent();
				if ((Object)(object)_localPlayer == (Object)null)
				{
					return;
				}
			}
			PlayerInventoryBase inventory = _localPlayer.Inventory;
			ItemEquippable val = ((inventory != null) ? inventory.WieldedItem : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (((Il2CppObjectBase)val).Pointer != _lastWieldPointer)
			{
				_lastWieldPointer = ((Il2CppObjectBase)val).Pointer;
				_cachedBulletWeapon = ((Il2CppObjectBase)val).TryCast<BulletWeapon>();
				ResetReloadState();
				if ((Object)(object)_cachedBulletWeapon != (Object)null)
				{
					_currentWeaponName = ((Item)_cachedBulletWeapon).PublicName;
					_currFingerprint = GetWeaponFingerprint(_cachedBulletWeapon);
					_lastReloadDuration = ((ItemEquippable)_cachedBulletWeapon).ArchetypeData.DefaultReloadTime * GetWeaponMultiplier(_cachedBulletWeapon);
					_isChargeWeapon = DetectIsChargeWeapon(_cachedBulletWeapon);
				}
				UpdateUIPosition();
			}
			if ((Object)(object)_cachedBulletWeapon == (Object)null)
			{
				return;
			}
			if (!_reflectionChecked && GuiManager.CrosshairLayer != null)
			{
				InitializeReflection();
			}
			bool isReloading = ((ItemEquippable)_cachedBulletWeapon).IsReloading;
			if (isReloading && !_isReloading && !_waitingForNativeReloadToEnd)
			{
				_isReloading = true;
				_ammoFilledThisReload = false;
				_reloadStartTime = Time.time;
				_currGlitchedText = string.Empty;
				_lastReloadDuration = ((ItemEquippable)_cachedBulletWeapon).ArchetypeData.DefaultReloadTime * GetWeaponMultiplier(_cachedBulletWeapon);
				bool flag = EntryPoint.ConfigEnableChargeCircleEffects?.Value ?? true;
				if (!_chargeShown && _circleTarget != null && flag)
				{
					if (_chargeUpColOrgField != null)
					{
						_originalChargeColor = (Color)_chargeUpColOrgField.GetValue(_circleTarget);
					}
					_setChargeColorMethod?.Invoke(_circleTarget, new object[1] { EntryPoint.ParsedChargeColor });
					_chargeUpColOrgField?.SetValue(_circleTarget, EntryPoint.ParsedChargeColor);
					_setChargeUpVisibleAndProgressMethod?.Invoke(GuiManager.CrosshairLayer, new object[2] { true, 0f });
					_showChargeMethod?.Invoke(_circleTarget, new object[1] { true });
					_chargeShown = true;
				}
				_isStutteringDuringReload = false;
			}
			if (_isReloading && !_ammoFilledThisReload && Time.deltaTime > 0.1f)
			{
				_isStutteringDuringReload = true;
			}
			else if (!isReloading)
			{
				_waitingForNativeReloadToEnd = false;
				if (_isReloading)
				{
					if (!_isAnimatingReady)
					{
						ResetReloadState();
					}
					else
					{
						_isReloading = false;
					}
				}
			}
			if (_isAnimatingReady && Time.time - _readyEffectStartTime >= 0.5f)
			{
				ResetReloadState();
			}
			if (isReloading || _isAnimatingReady)
			{
				return;
			}
			ConfigEntry<bool>? configEnableLowAmmoWarning = EntryPoint.ConfigEnableLowAmmoWarning;
			if (configEnableLowAmmoWarning != null && !configEnableLowAmmoWarning.Value)
			{
				return;
			}
			int clip = _cachedBulletWeapon.m_clip;
			int clipSize = ((ItemEquippable)_cachedBulletWeapon).ClipSize;
			_lastClipCount = clip;
			if (isReloading || _isAnimatingReady)
			{
				return;
			}
			float num = ((clipSize <= 20) ? 0.5f : (EntryPoint.ConfigLowAmmoThreshold?.Value ?? 0.35f));
			if ((float)clip <= (float)clipSize * num)
			{
				if (Time.time - _lastGlitchTime > 0.08f)
				{
					_lastGlitchTime = Time.time;
					bool flag2 = clip == 0;
					string original = "RELOAD";
					_currGlitchedText = GetGlitchedText(original, flag2 ? 0.4f : 0.25f);
				}
			}
			else
			{
				_currGlitchedText = string.Empty;
			}
		}

		private void LateUpdate()
		{
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0577: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			//IL_067b: Unknown result type (might be due to invalid IL or missing references)
			//IL_069f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0872: Unknown result type (might be due to invalid IL or missing references)
			//IL_0896: Unknown result type (might be due to invalid IL or missing references)
			//IL_08b8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_cachedBulletWeapon == (Object)null || (Object)(object)_localPlayer == (Object)null)
			{
				return;
			}
			ApplyHUDSway();
			bool isReloading = ((ItemEquippable)_cachedBulletWeapon).IsReloading;
			bool flag = _isAnimatingReady && Time.time - _readyEffectStartTime < 0.5f;
			bool flag2 = isReloading && !_ammoFilledThisReload;
			if (flag2 || flag || !string.IsNullOrEmpty(_currGlitchedText))
			{
				string text = "";
				if (flag)
				{
					text = "0.00s";
					bool flag3 = EntryPoint.ConfigEnableChargeCircleEffects?.Value ?? true;
					if (_circleTarget != null && flag3)
					{
						float num = Mathf.Clamp01((Time.time - _readyEffectStartTime) / 0.5f);
						float num2 = Mathf.Lerp(1.25f, 1f, num);
						GameObject gameObject = _circleTarget.Cast<Component>().gameObject;
						if ((Object)(object)gameObject != (Object)null)
						{
							gameObject.transform.localScale = new Vector3(num2, num2, 1f);
						}
						_showChargeMethod?.Invoke(_circleTarget, new object[1] { true });
						_setChargeMethod?.Invoke(_circleTarget, new object[1] { 1f });
						_setChargeUpVisibleAndProgressMethod?.Invoke(GuiManager.CrosshairLayer, new object[2] { true, 1f });
					}
				}
				else if (flag2)
				{
					float num3 = Time.time - _reloadStartTime;
					float num4 = 0.9f;
					if (!string.IsNullOrEmpty(_currFingerprint) && _persistentRatioMap.ContainsKey(_currFingerprint))
					{
						num4 = _persistentRatioMap[_currFingerprint];
					}
					else if (((ItemEquippable)_cachedBulletWeapon).ArchetypeData.DefaultClipSize > 10)
					{
						num4 = 0.6f;
					}
					float num5 = _lastReloadDuration * num4;
					float num6 = Mathf.Clamp01(num3 / num5);
					float num7 = Mathf.Max(0f, num5 - num3);
					text = ((num7 > 0f) ? $"{num7:0.00}s" : "");
					bool flag4 = EntryPoint.ConfigEnableChargeCircleEffects?.Value ?? true;
					if (_circleTarget != null && flag4)
					{
						_showChargeMethod?.Invoke(_circleTarget, new object[1] { true });
						_setChargeMethod?.Invoke(_circleTarget, new object[1] { num6 });
						_setChargeUpVisibleAndProgressMethod?.Invoke(GuiManager.CrosshairLayer, new object[2] { true, num6 });
						GameObject gameObject2 = _circleTarget.Cast<Component>().gameObject;
						if ((Object)(object)gameObject2 != (Object)null)
						{
							gameObject2.transform.localScale = Vector3.one;
						}
					}
				}
				else if (!string.IsNullOrEmpty(_currGlitchedText))
				{
					text = _currGlitchedText;
				}
				bool flag5 = EntryPoint.ConfigEnableChargeCircleEffects?.Value ?? true;
				if (!flag5 && (flag || flag2))
				{
					text = "";
				}
				((TMP_Text)_textMesh).text = text;
				if (flag && flag5)
				{
					((Graphic)_textMesh).color = new Color(0f, 1f, 0f, 0.8f);
				}
				else if (!string.IsNullOrEmpty(_currGlitchedText) && !isReloading)
				{
					float a = ((Mathf.Floor(Time.time * 5f) % 2f == 0f) ? 0.85f : 0.75f);
					Color parsedLowAmmoColor = EntryPoint.ParsedLowAmmoColor;
					parsedLowAmmoColor.a = a;
					((Graphic)_textMesh).color = parsedLowAmmoColor;
					float value = Random.value;
					float num8 = 0f;
					if (value < 0.04f)
					{
						num8 = Random.Range(-6f, 6f);
					}
					else if (value < 0.05f)
					{
						num8 = Random.Range(-12f, 12f);
					}
					((Transform)((TMP_Text)_textMesh).rectTransform).localPosition = new Vector3(num8, 0f, 0f);
				}
				else
				{
					((Graphic)_textMesh).color = Color.white;
					((Transform)((TMP_Text)_textMesh).rectTransform).localPosition = Vector3.zero;
				}
			}
			else
			{
				((TMP_Text)_textMesh).text = string.Empty;
			}
			ClearGlitchLayers();
			if (_circleTarget == null)
			{
				return;
			}
			bool flag6 = EntryPoint.ConfigEnableChargeCircleEffects?.Value ?? true;
			if (flag6)
			{
				if (flag)
				{
					_setChargeColorMethod?.Invoke(_circleTarget, new object[1] { ((Graphic)_textMesh).color });
				}
				else if (flag2)
				{
					_setChargeColorMethod?.Invoke(_circleTarget, new object[1] { EntryPoint.ParsedChargeColor });
				}
			}
			if (!flag6 && _chargeShown)
			{
				_setChargeUpVisibleAndProgressMethod?.Invoke(GuiManager.CrosshairLayer, new object[2] { false, 0f });
				_showChargeMethod?.Invoke(_circleTarget, new object[1] { false });
				_setChargeMethod?.Invoke(_circleTarget, new object[1] { 0f });
				GameObject gameObject3 = _circleTarget.Cast<Component>().gameObject;
				if ((Object)(object)gameObject3 != (Object)null)
				{
					gameObject3.transform.localScale = Vector3.one;
				}
				_setChargeColorMethod?.Invoke(_circleTarget, new object[1] { _originalChargeColor });
				_chargeUpColOrgField?.SetValue(_circleTarget, _originalChargeColor);
				_chargeShown = false;
			}
			else
			{
				if (flag2 || flag || !_chargeShown)
				{
					return;
				}
				if (isReloading)
				{
					_setChargeUpVisibleAndProgressMethod?.Invoke(GuiManager.CrosshairLayer, new object[2] { false, 0f });
					_showChargeMethod?.Invoke(_circleTarget, new object[1] { false });
					_setChargeMethod?.Invoke(_circleTarget, new object[1] { 0f });
					GameObject gameObject4 = _circleTarget.Cast<Component>().gameObject;
					if ((Object)(object)gameObject4 != (Object)null)
					{
						gameObject4.transform.localScale = Vector3.one;
					}
				}
				else if (!_isChargeWeapon)
				{
					_setChargeUpVisibleAndProgressMethod?.Invoke(GuiManager.CrosshairLayer, new object[2] { false, 0f });
					_showChargeMethod?.Invoke(_circleTarget, new object[1] { false });
					_setChargeMethod?.Invoke(_circleTarget, new object[1] { 0f });
					GameObject gameObject5 = _circleTarget.Cast<Component>().gameObject;
					if ((Object)(object)gameObject5 != (Object)null)
					{
						gameObject5.transform.localScale = Vector3.one;
					}
					_setChargeColorMethod?.Invoke(_circleTarget, new object[1] { _originalChargeColor });
					_chargeUpColOrgField?.SetValue(_circleTarget, _originalChargeColor);
					_chargeShown = false;
				}
			}
		}

		private void ClearGlitchLayers()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_glitchTextMesh2 != (Object)null)
			{
				((TMP_Text)_glitchTextMesh2).text = "";
				((Graphic)_glitchTextMesh2).color = new Color(0f, 0f, 0f, 0f);
			}
		}

		private void PlayReloadCue()
		{
			try
			{
				ConfigEntry<ReloadSoundOption>? configReloadSoundCue = EntryPoint.ConfigReloadSoundCue;
				if (configReloadSoundCue != null && configReloadSoundCue.Value == ReloadSoundOption.CustomLocalFile)
				{
					if ((Object)(object)_customClip != (Object)null && (Object)(object)_audioSource != (Object)null)
					{
						_audioSource.PlayOneShot(_customClip);
					}
					else
					{
						Logger.Warn("Custom audio clip is not loaded yet or file is missing.");
					}
					return;
				}
				string text = EntryPoint.ConfigReloadSoundCue?.Value.ToString() ?? "";
				if (!string.IsNullOrEmpty(text) && !text.Equals("None", StringComparison.OrdinalIgnoreCase) && !((Object)(object)_localPlayer == (Object)null) && _localPlayer.Sound != null)
				{
					uint soundEventId = SoundHelper.GetSoundEventId(text);
					if (soundEventId != 0)
					{
						_localPlayer.Sound.Post(soundEventId, true);
					}
					else
					{
						Logger.Warn("Sound event '" + text + "' not found in AK.EVENTS, skipping cue.");
					}
				}
			}
			catch (Exception ex)
			{
				Logger.Error("PlayReloadCue failed: " + ex.Message);
			}
		}

		private string GetGlitchedText(string original, float intensity)
		{
			if (string.IsNullOrEmpty(original) || Random.value > intensity)
			{
				return original;
			}
			char[] array = original.ToCharArray();
			int num = Random.Range(0, array.Length);
			if (array[num] != ' ' && array[num] != '[' && array[num] != ']' && array[num] != '[' && array[num] != ']')
			{
				array[num] = "#@&!$%01X?"[Random.Range(0, "#@&!$%01X?".Length)];
			}
			return new string(array);
		}

		private void ResetReloadState()
		{
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			_isReloading = false;
			_isAnimatingReady = false;
			_hasTriggeredReadyEffect = false;
			_readyEffectStartTime = -1f;
			((TMP_Text)_textMesh).text = string.Empty;
			_currGlitchedText = string.Empty;
			_lastClipCount = -1;
			_waitingForNativeReloadToEnd = (Object)(object)_cachedBulletWeapon != (Object)null && ((ItemEquippable)_cachedBulletWeapon).IsReloading;
			if (_circleTarget != null)
			{
				_showChargeMethod?.Invoke(_circleTarget, new object[1] { false });
				_setChargeMethod?.Invoke(_circleTarget, new object[1] { 0f });
				_setChargeUpVisibleAndProgressMethod?.Invoke(GuiManager.CrosshairLayer, new object[2] { false, 0f });
				if (_chargeShown)
				{
					_setChargeColorMethod?.Invoke(_circleTarget, new object[1] { _originalChargeColor });
					_chargeUpColOrgField?.SetValue(_circleTarget, _originalChargeColor);
					GameObject gameObject = _circleTarget.Cast<Component>().gameObject;
					if ((Object)(object)gameObject != (Object)null)
					{
						gameObject.transform.localScale = Vector3.one;
					}
					_chargeShown = false;
				}
			}
			ClearGlitchLayers();
		}

		private void ApplyHUDSway()
		{
			//IL_0025: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//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_005d: 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_0064: 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_0039: 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)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			FPSCamera fPSCamera = _localPlayer.FPSCamera;
			if ((Object)(object)fPSCamera == (Object)null)
			{
				return;
			}
			Vector3 forward = ((Component)fPSCamera).transform.forward;
			if (_isFirstSwayFrame)
			{
				_lastCamForward = forward;
				_isFirstSwayFrame = false;
				return;
			}
			Vector3 val = ((Component)fPSCamera).transform.InverseTransformDirection(forward - _lastCamForward);
			_lastCamForward = forward;
			float num = 1800.0001f;
			bool flag = false;
			try
			{
				if (_isAimingField != null)
				{
					flag = (bool)_isAimingField.GetValue(_cachedBulletWeapon);
				}
			}
			catch
			{
			}
			if ((Object)(object)_cachedBulletWeapon != (Object)null && flag)
			{
				num *= 0.25f;
			}
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor((0f - val.x) * num, val.y * num);
			if (((Vector2)(ref val2)).magnitude > 12f)
			{
				val2 = ((Vector2)(ref val2)).normalized * 12f;
			}
			_currentSwayOffset = Vector2.SmoothDamp(_currentSwayOffset, val2, ref _swayVelocity, 0.12f);
			_currentSwayOffset.x = Mathf.Clamp(_currentSwayOffset.x, -12f, 12f);
			_currentSwayOffset.y = Mathf.Clamp(_currentSwayOffset.y, -12f, 12f);
			float num2 = EntryPoint.ConfigOffset?.Value ?? 85f;
			_uiRoot.transform.localPosition = new Vector3(_currentSwayOffset.x, 0f - num2 + _currentSwayOffset.y, 0f);
		}

		public void UpdateUIPosition()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_uiRoot == (Object)null))
			{
				float num = EntryPoint.ConfigOffset?.Value ?? 85f;
				_uiRoot.transform.localPosition = new Vector3(0f, 0f - num, 0f);
			}
		}

		private float GetWeaponMultiplier(BulletWeapon weapon)
		{
			try
			{
				GearIDRange gearIDRange = ((ItemEquippable)weapon).GearIDRange;
				if (gearIDRange == null)
				{
					return 1f;
				}
				if (_getIdentifierMethod == null)
				{
					_getIdentifierMethod = ((object)gearIDRange).GetType().GetMethod("GetIdentifier");
				}
				if (_getIdentifierMethod == null)
				{
					return 1f;
				}
				for (int i = 0; i < 64; i++)
				{
					try
					{
						uint num = (uint)_getIdentifierMethod.Invoke(gearIDRange, new object[1] { (object)(InventorySlot)(byte)i });
						if (num != 0)
						{
							GearMagPartDataBlock block = GameDataBlockBase<GearMagPartDataBlock>.GetBlock(num);
							if (block != null)
							{
								return block.ReloadTimeMultiplier;
							}
						}
					}
					catch
					{
					}
				}
			}
			catch
			{
			}
			return 1f;
		}

		private void InitializeReflection()
		{
			_reflectionChecked = true;
			if (GuiManager.CrosshairLayer != null)
			{
				Type type = ((object)GuiManager.CrosshairLayer).GetType();
				_setChargeUpVisibleAndProgressMethod = type.GetMethod("SetChargeUpVisibleAndProgress");
				CircleCrosshair circleCrosshair = GuiManager.CrosshairLayer.m_circleCrosshair;
				if ((Object)(object)circleCrosshair != (Object)null)
				{
					_circleTarget = (Il2CppObjectBase?)(object)circleCrosshair;
					Type type2 = ((object)circleCrosshair).GetType();
					_setChargeMethod = type2.GetMethod("SetCharge");
					_showChargeMethod = type2.GetMethod("ShowCharge");
					_setChargeColorMethod = type2.GetMethod("SetChargeUpColor");
					_chargeUpColOrgField = type2.GetField("m_chargeUpColOrg", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				Type typeFromHandle = typeof(ItemEquippable);
				if ((object)_isAimingField == null)
				{
					_isAimingField = typeFromHandle.GetField("m_isAiming", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
		}

		private bool DetectIsChargeWeapon(BulletWeapon weapon)
		{
			if (((weapon != null) ? ((ItemEquippable)weapon).ArchetypeData : null) == null)
			{
				return false;
			}
			try
			{
				ArchetypeDataBlock archetypeData = ((ItemEquippable)weapon).ArchetypeData;
				Type type = ((object)archetypeData).GetType();
				BindingFlags bindingAttr = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
				PropertyInfo[] properties = type.GetProperties(bindingAttr);
				foreach (PropertyInfo propertyInfo in properties)
				{
					if (propertyInfo.PropertyType == typeof(float) && propertyInfo.Name.IndexOf("charge", StringComparison.OrdinalIgnoreCase) >= 0 && ((float?)propertyInfo.GetValue(archetypeData)).GetValueOrDefault() > 0.001f)
					{
						return true;
					}
				}
				FieldInfo[] fields = type.GetFields(bindingAttr);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (fieldInfo.FieldType == typeof(float) && fieldInfo.Name.IndexOf("charge", StringComparison.OrdinalIgnoreCase) >= 0 && ((float?)fieldInfo.GetValue(archetypeData)).GetValueOrDefault() > 0.001f)
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerInventoryLocal), "DoReload")]
	internal static class ReloadDonePatch
	{
		public static void Postfix()
		{
			if ((Object)(object)Zose_ReloadTimerPlus.Instance != (Object)null)
			{
				Zose_ReloadTimerPlus.Instance.OnAmmoRefreshed();
			}
		}
	}
	internal static class SoundHelper
	{
		private static Dictionary<string, uint>? _eventCache;

		private static bool _initDone;

		public static void InvalidateCache()
		{
			_eventCache = null;
			_initDone = false;
		}

		public static uint GetSoundEventId(string eventName)
		{
			if (!_initDone)
			{
				BuildCache();
			}
			if (_eventCache != null && _eventCache.TryGetValue(eventName, out var value))
			{
				return value;
			}
			return 0u;
		}

		private static void BuildCache()
		{
			_initDone = true;
			_eventCache = new Dictionary<string, uint>(StringComparer.OrdinalIgnoreCase);
			try
			{
				Type typeFromHandle = typeof(EVENTS);
				IEnumerable<PropertyInfo> enumerable = from p in typeFromHandle.GetProperties(BindingFlags.Static | BindingFlags.Public)
					where p.PropertyType == typeof(uint) && p.GetMethod != null
					select p;
				foreach (PropertyInfo item in enumerable)
				{
					try
					{
						uint value = (uint)item.GetValue(null);
						_eventCache[item.Name] = value;
					}
					catch
					{
					}
				}
				IEnumerable<FieldInfo> enumerable2 = from f in typeFromHandle.GetFields(BindingFlags.Static | BindingFlags.Public)
					where f.FieldType == typeof(uint)
					select f;
				foreach (FieldInfo item2 in enumerable2)
				{
					try
					{
						uint value2 = (uint)item2.GetValue(null);
						if (!_eventCache.ContainsKey(item2.Name))
						{
							_eventCache[item2.Name] = value2;
						}
					}
					catch
					{
					}
				}
				Logger.Info($"SoundHelper: cached {_eventCache.Count} sound events from AK.EVENTS.");
			}
			catch (Exception ex)
			{
				Logger.Error("SoundHelper init failed: " + ex.Message);
			}
		}
	}
	public static class WavUtility
	{
		public static AudioClip? ToAudioClip(string filePath, string clipName = "CustomWav")
		{
			if (!File.Exists(filePath))
			{
				return null;
			}
			byte[] buffer = File.ReadAllBytes(filePath);
			using MemoryStream memoryStream = new MemoryStream(buffer);
			using BinaryReader binaryReader = new BinaryReader(memoryStream);
			if (new string(binaryReader.ReadChars(4)) != "RIFF")
			{
				return null;
			}
			binaryReader.ReadInt32();
			if (new string(binaryReader.ReadChars(4)) != "WAVE")
			{
				return null;
			}
			short num = 1;
			int num2 = 44100;
			short num3 = 16;
			int num4 = 0;
			while (memoryStream.Position < memoryStream.Length)
			{
				string text = new string(binaryReader.ReadChars(4));
				int num5 = binaryReader.ReadInt32();
				if (text == "fmt ")
				{
					binaryReader.ReadInt16();
					num = binaryReader.ReadInt16();
					num2 = binaryReader.ReadInt32();
					binaryReader.ReadInt32();
					binaryReader.ReadInt16();
					num3 = binaryReader.ReadInt16();
					if (num5 > 16)
					{
						memoryStream.Position += num5 - 16;
					}
				}
				else
				{
					if (text == "data")
					{
						num4 = num5;
						break;
					}
					memoryStream.Position += num5;
				}
			}
			if (num4 <= 0)
			{
				return null;
			}
			int num6 = num3 / 8;
			int num7 = num4 / num6;
			float[] array = new float[num7];
			for (int i = 0; i < num7; i++)
			{
				switch (num3)
				{
				case 16:
					array[i] = (float)binaryReader.ReadInt16() / 32768f;
					break;
				case 8:
					array[i] = (float)(binaryReader.ReadByte() - 128) / 128f;
					break;
				case 32:
					array[i] = binaryReader.ReadSingle();
					break;
				}
			}
			AudioClip val = AudioClip.Create(clipName, num7 / num, (int)num, num2, false);
			if ((Object)(object)val != (Object)null)
			{
				val.SetData(new Il2CppStructArray<float>(array), 0);
				return val;
			}
			return null;
		}
	}
}
namespace Zose_ReloadTimerPlus.Patches
{
	[HarmonyPatch(typeof(CM_PageRundown_New), "PlaceRundown")]
	internal static class CM_PageRundown_New_PlaceRundown
	{
		private static bool _injected;

		private static void Postfix()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!_injected)
			{
				_injected = true;
				GameObject val = new GameObject("RT_CompInject");
				val.AddComponent<Zose_ReloadTimerPlus>();
				Object.DontDestroyOnLoad((Object)(object)val);
			}
		}
	}
}