Decompiled source of Bullet Control v1.0.0

BulletControl.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Omniscye")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BulletControl")]
[assembly: AssemblyTitle("BulletControl")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Empress.RepoMods.GuidedBulletCam
{
	[BepInPlugin("empress.repogame.guidedbulletcam", "Guided Bullet Camera", "2.1.0")]
	public class GuidedBulletCamPlugin : BaseUnityPlugin
	{
		private sealed class TimeGuard : MonoBehaviour
		{
			private float _deadline = -1f;

			private Action _quitHandler;

			private UnityAction<Scene, Scene> _sceneChangedHandler;

			private void OnEnable()
			{
				_quitHandler = OnAppQuitting;
				_sceneChangedHandler = OnSceneChanged;
				Application.quitting += _quitHandler;
				SceneManager.activeSceneChanged += _sceneChangedHandler;
			}

			private void OnDisable()
			{
				if (_quitHandler != null)
				{
					Application.quitting -= _quitHandler;
				}
				if (_sceneChangedHandler != null)
				{
					SceneManager.activeSceneChanged -= _sceneChangedHandler;
				}
			}

			public static void Arm(float seconds)
			{
				TimeGuard timeGuard = Object.FindObjectOfType<TimeGuard>();
				if (Object.op_Implicit((Object)(object)timeGuard))
				{
					timeGuard._deadline = Time.realtimeSinceStartup + Mathf.Max(0.25f, seconds);
				}
			}

			public static void Disarm()
			{
				TimeGuard timeGuard = Object.FindObjectOfType<TimeGuard>();
				if (Object.op_Implicit((Object)(object)timeGuard))
				{
					timeGuard._deadline = -1f;
				}
			}

			private void Update()
			{
				if (_deadline >= 0f && Time.realtimeSinceStartup >= _deadline)
				{
					ForceRestore();
				}
			}

			private void OnAppQuitting()
			{
				ForceRestore();
			}

			private void OnSceneChanged(Scene a, Scene b)
			{
				ForceRestore();
			}

			private void ForceRestore()
			{
				try
				{
					IsGuiding = false;
					Time.timeScale = BaselineTimeScale;
					Time.fixedDeltaTime = BaselineFixedDelta;
				}
				catch
				{
				}
				_deadline = -1f;
			}
		}

		public class GuidedCamHandshakeRouter : MonoBehaviourPunCallbacks, IOnEventCallback
		{
			[CompilerGenerated]
			private sealed class <WaitForLevelThenHandshake>d__18 : IEnumerator<object>, IEnumerator, IDisposable
			{
				private int <>1__state;

				private object <>2__current;

				public GuidedCamHandshakeRouter <>4__this;

				private float <t>5__1;

				private float <elapsed>5__2;

				object IEnumerator<object>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <WaitForLevelThenHandshake>d__18(int <>1__state)
				{
					this.<>1__state = <>1__state;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					//IL_0106: Unknown result type (might be due to invalid IL or missing references)
					//IL_010b: 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_0112: Unknown result type (might be due to invalid IL or missing references)
					//IL_011c: Expected O, but got Unknown
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<t>5__1 = 0f;
						goto IL_0066;
					case 1:
						<>1__state = -1;
						goto IL_0066;
					case 2:
						{
							<>1__state = -1;
							goto IL_0155;
						}
						IL_0066:
						if (((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated) && <t>5__1 < 20f)
						{
							<t>5__1 += Time.deltaTime;
							<>2__current = null;
							<>1__state = 1;
							return true;
						}
						_levelReady = true;
						if (!PhotonNetwork.InRoom || !PhotonNetwork.IsConnectedAndReady)
						{
							_handshakeComplete = true;
							_hostHasMod = true;
							return false;
						}
						if (PhotonNetwork.IsMasterClient)
						{
							_handshakeComplete = true;
							_hostHasMod = true;
							return false;
						}
						if (_requestSent)
						{
							break;
						}
						_requestSent = true;
						PhotonNetwork.RaiseEvent((byte)73, (object)new object[2] { "empress.repogame.guidedbulletcam", "2.1.0" }, new RaiseEventOptions
						{
							Receivers = (ReceiverGroup)2
						}, SendOptions.SendReliable);
						<elapsed>5__2 = 0f;
						goto IL_0155;
						IL_0155:
						if (!_handshakeComplete && <elapsed>5__2 < 4f)
						{
							<elapsed>5__2 += Time.deltaTime;
							<>2__current = null;
							<>1__state = 2;
							return true;
						}
						if (!_handshakeComplete)
						{
							_hostHasMod = false;
							_handshakeComplete = true;
						}
						break;
					}
					return false;
				}

				bool IEnumerator.MoveNext()
				{
					//ILSpy generated this explicit interface implementation from .override directive in MoveNext
					return this.MoveNext();
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}
			}

			private const byte EVENT_HANDSHAKE_REQUEST = 73;

			private const byte EVENT_HANDSHAKE_RESPONSE = 74;

			private static bool _levelReady;

			private static bool _handshakeComplete;

			private static bool _hostHasMod;

			private static bool _requestSent;

			private static string _loadedSceneName;

			private bool _callbackHooked;

			public static bool CanUseModNow()
			{
				if (!CfgEnabled.Value)
				{
					return false;
				}
				if (!PhotonNetwork.InRoom)
				{
					return _levelReady;
				}
				if (PhotonNetwork.IsMasterClient)
				{
					return _levelReady;
				}
				return _levelReady && _handshakeComplete && _hostHasMod;
			}

			private void OnEnable()
			{
				SceneManager.sceneLoaded += OnSceneLoaded;
			}

			private void OnDisable()
			{
				SceneManager.sceneLoaded -= OnSceneLoaded;
				if (_callbackHooked)
				{
					PhotonNetwork.RemoveCallbackTarget((object)this);
				}
				_callbackHooked = false;
			}

			public override void OnJoinedRoom()
			{
				//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)
				EnsureCallbackHooked();
				ResetStatesOnRoomChange();
				Scene activeScene = SceneManager.GetActiveScene();
				if (IsRealLevel(((Scene)(ref activeScene)).name))
				{
					((MonoBehaviour)this).StartCoroutine(WaitForLevelThenHandshake());
				}
			}

			public override void OnLeftRoom()
			{
				if (_callbackHooked)
				{
					PhotonNetwork.RemoveCallbackTarget((object)this);
					_callbackHooked = false;
				}
				_levelReady = false;
				_handshakeComplete = false;
				_hostHasMod = false;
				_requestSent = false;
			}

			private void EnsureCallbackHooked()
			{
				if (!_callbackHooked)
				{
					PhotonNetwork.AddCallbackTarget((object)this);
					_callbackHooked = true;
				}
			}

			private void OnSceneLoaded(Scene s, LoadSceneMode m)
			{
				_loadedSceneName = ((Scene)(ref s)).name ?? string.Empty;
				ResetStatesOnSceneChange();
				EnsureCallbackHooked();
				if (IsRealLevel(_loadedSceneName))
				{
					((MonoBehaviour)this).StartCoroutine(WaitForLevelThenHandshake());
				}
			}

			private static void ResetStatesOnSceneChange()
			{
				_levelReady = false;
				_handshakeComplete = false;
				_hostHasMod = false;
				_requestSent = false;
			}

			private static void ResetStatesOnRoomChange()
			{
				_levelReady = false;
				_handshakeComplete = false;
				_hostHasMod = false;
				_requestSent = false;
			}

			private bool IsRealLevel(string sceneName)
			{
				if (string.IsNullOrEmpty(sceneName))
				{
					return false;
				}
				if (sceneName.IndexOf("Lobby", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return false;
				}
				return true;
			}

			[IteratorStateMachine(typeof(<WaitForLevelThenHandshake>d__18))]
			private IEnumerator WaitForLevelThenHandshake()
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <WaitForLevelThenHandshake>d__18(0)
				{
					<>4__this = this
				};
			}

			public void OnEvent(EventData photonEvent)
			{
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Expected O, but got Unknown
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (photonEvent.Code == 73)
					{
						if (PhotonNetwork.IsMasterClient)
						{
							int sender = photonEvent.Sender;
							object[] array = new object[3] { "empress.repogame.guidedbulletcam", "2.1.0", true };
							RaiseEventOptions val = new RaiseEventOptions();
							val.TargetActors = new int[1] { sender };
							PhotonNetwork.RaiseEvent((byte)74, (object)array, val, SendOptions.SendReliable);
						}
					}
					else if (photonEvent.Code == 74 && photonEvent.CustomData is object[] array2 && array2.Length >= 3)
					{
						string text = array2[0] as string;
						object obj = array2[2];
						bool flag = default(bool);
						int num;
						if (obj is bool)
						{
							flag = (bool)obj;
							num = 1;
						}
						else
						{
							num = 0;
						}
						bool flag2 = (byte)((uint)num & (flag ? 1u : 0u)) != 0;
						if (!string.IsNullOrEmpty(text) && text == "empress.repogame.guidedbulletcam" && flag2)
						{
							_hostHasMod = true;
						}
						else
						{
							_hostHasMod = false;
						}
						_handshakeComplete = true;
					}
				}
				catch
				{
				}
			}
		}

		[HarmonyPatch]
		private static class ItemGunStartInjector
		{
			private static MethodBase TargetMethod()
			{
				Type type = AccessTools.TypeByName("ItemGun");
				return (type != null) ? AccessTools.Method(type, "Start", (Type[])null, (Type[])null) : null;
			}

			private static void Postfix(MonoBehaviour __instance)
			{
				GameObject gameObject = ((Component)__instance).gameObject;
				if (!Object.op_Implicit((Object)(object)gameObject.GetComponent<EmpressGunProxy>()))
				{
					gameObject.AddComponent<EmpressGunProxy>();
				}
			}
		}

		[HarmonyPatch]
		private static class ItemToggleHooks
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(AccessTools.TypeByName("ItemToggle"), "ToggleItem", new Type[2]
				{
					typeof(bool),
					typeof(int)
				}, (Type[])null);
			}

			private static bool Prefix(MonoBehaviour __instance, bool toggle, int player)
			{
				//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_0181: Unknown result type (might be due to invalid IL or missing references)
				//IL_0400: Unknown result type (might be due to invalid IL or missing references)
				//IL_0414: Unknown result type (might be due to invalid IL or missing references)
				//IL_0293: Unknown result type (might be due to invalid IL or missing references)
				//IL_0298: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_04dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_04ed: Unknown result type (might be due to invalid IL or missing references)
				if (!CfgEnabled.Value)
				{
					return true;
				}
				if (!IsLevelReady())
				{
					return true;
				}
				Type type = AccessTools.TypeByName("SemiFunc");
				MethodInfo methodInfo = AccessTools.Method(type, "PhotonViewIDPlayerAvatarLocal", (Type[])null, (Type[])null);
				int num = -1;
				try
				{
					num = (int)(methodInfo?.Invoke(null, null) ?? ((object)(-1)));
				}
				catch
				{
				}
				if (player != num)
				{
					return true;
				}
				Type type2 = AccessTools.TypeByName("ItemGun");
				Component component = ((Component)__instance).GetComponent(type2);
				if (!Object.op_Implicit((Object)(object)component) || !toggle)
				{
					return true;
				}
				if (!HasAmmo(component))
				{
					object obj2 = AccessTools.Field(((object)component).GetType(), "soundNoAmmoClick")?.GetValue(component);
					Vector3 position = ((Component)__instance).transform.position;
					if (obj2 != null)
					{
						MethodInfo methodInfo2 = AccessTools.Method(obj2.GetType(), "Play", new Type[5]
						{
							typeof(Vector3),
							typeof(float),
							typeof(float),
							typeof(float),
							typeof(float)
						}, (Type[])null);
						if (methodInfo2 != null)
						{
							methodInfo2.Invoke(obj2, new object[5] { position, 1f, 1f, 1f, 1f });
						}
					}
					SafeCall(component, "StartTriggerAnimation");
					object field = GetField(component, "gunMuzzle");
					Transform val = (Transform)((field is Transform) ? field : null);
					if (Object.op_Implicit((Object)(object)val))
					{
						AccessTools.Method(type, "CameraShakeImpact", new Type[2]
						{
							typeof(float),
							typeof(float)
						}, (Type[])null)?.Invoke(null, new object[2] { 1f, 0.1f });
						object? obj3 = AccessTools.Field(((object)component).GetType(), "physGrabObject")?.GetValue(component);
						Component val2 = (Component)((obj3 is Component) ? obj3 : null);
						Rigidbody val3 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent<Rigidbody>() : null);
						if (val3 != null)
						{
							val3.AddForceAtPosition(-val.forward * 1f, val.position, (ForceMode)1);
						}
					}
					return false;
				}
				PhotonView val4 = ResolvePV((Component)(object)__instance);
				if (!Object.op_Implicit((Object)(object)val4))
				{
					return true;
				}
				object field2 = GetField(component, "gunMuzzle");
				Transform val5 = (Transform)((field2 is Transform) ? field2 : null);
				if (!Object.op_Implicit((Object)(object)val5))
				{
					return true;
				}
				float num2 = (float)(GetField(component, "batteryDrain") ?? ((object)0f));
				bool flag = (bool)(GetField(component, "batteryDrainFullBar") ?? ((object)false));
				int num3 = (int)(GetField(component, "batteryDrainFullBars") ?? ((object)1));
				if (PhotonNetwork.IsConnected && val4.ViewID != 0)
				{
					val4.RPC("Empress_StartGuide", (RpcTarget)2, new object[4] { num, flag, num3, num2 });
					val4.RPC("ToggleItemRPC", (RpcTarget)1, new object[2] { toggle, player });
				}
				else
				{
					EmpressGunProxy.SetPendingLocal(val4, component, flag, num3, num2, val5);
				}
				SafeInvokeSound(component, "soundShoot", val5.position);
				SafeInvokeSound(component, "soundShootGlobal", val5.position);
				SafeCall(component, "MuzzleFlash");
				SafeCall(component, "StartTriggerAnimation");
				AccessTools.Method(type, "CameraShakeImpact", new Type[2]
				{
					typeof(float),
					typeof(float)
				}, (Type[])null)?.Invoke(null, new object[2] { 1f, 0.1f });
				object? obj4 = AccessTools.Field(((object)component).GetType(), "physGrabObject")?.GetValue(component);
				Component val6 = (Component)((obj4 is Component) ? obj4 : null);
				Rigidbody val7 = (Object.op_Implicit((Object)(object)val6) ? val6.GetComponent<Rigidbody>() : null);
				if (val7 != null)
				{
					val7.AddForceAtPosition(-val5.forward * 1f, val5.position, (ForceMode)1);
				}
				StartLocalOverlay(component, val4, val5);
				return false;
			}

			private static void StartLocalOverlay(object gun, PhotonView pv, Transform muzzle)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Expected O, but got Unknown
				//IL_001f: 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)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					GameObject val = new GameObject("Empress_GuidedBulletHost");
					Object.DontDestroyOnLoad((Object)(object)val);
					GuidedBulletController guidedBulletController = val.AddComponent<GuidedBulletController>();
					guidedBulletController.Init(gun, pv, muzzle.position, muzzle.forward, Mathf.Max(0.1f, CfgBulletSpeed.Value), Mathf.Clamp(CfgTurnRateDeg.Value, 10f, 1440f), Mathf.Clamp(CfgFov.Value, 20f, 110f), CfgCancelKey.Value, Mathf.Clamp(CfgTimeScale.Value, 0.02f, 0.5f), Mathf.Clamp(CfgMaxGuideSeconds.Value, 0.25f, 30f), Mathf.Clamp(CfgHitRadius.Value, 0f, 0.5f), Mathf.Clamp(CfgMaxDistance.Value, 5f, 5000f));
				}
				catch (Exception arg)
				{
					ManualLogSource logS = LogS;
					if (logS != null)
					{
						logS.LogError((object)$"StartLocalOverlay failed: {arg}");
					}
				}
			}
		}

		[HarmonyPatch]
		private static class ShootRpcMasterSkipper
		{
			private static MethodBase TargetMethod()
			{
				Type type = AccessTools.TypeByName("ItemGun");
				return (type != null) ? AccessTools.Method(type, "ShootRPC", new Type[1] { typeof(PhotonMessageInfo) }, (Type[])null) : null;
			}

			private static bool Prefix(MonoBehaviour __instance)
			{
				if (!CfgEnabled.Value)
				{
					return true;
				}
				if (!PhotonNetwork.IsConnected || !PhotonNetwork.IsMasterClient)
				{
					return true;
				}
				PhotonView val = ResolvePV((Component)(object)__instance);
				if (Object.op_Implicit((Object)(object)val) && IsPendingGuided(val))
				{
					return false;
				}
				return true;
			}
		}

		private sealed class EmpressGunProxy : MonoBehaviour
		{
			[PunRPC]
			public void Empress_StartGuide(int shooterViewID, bool fullBar, int bars, float drain, PhotonMessageInfo info)
			{
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
				if (!PhotonNetwork.IsMasterClient)
				{
					return;
				}
				PhotonView val = ResolvePV((Component)(object)this);
				if (!Object.op_Implicit((Object)(object)val))
				{
					return;
				}
				Type type = AccessTools.TypeByName("ItemGun");
				Component val2 = ((type != null) ? ((Component)this).GetComponent(type) : null);
				if ((Object)(object)val2 == (Object)null)
				{
					return;
				}
				if (!HasAmmo(val2))
				{
					val.RPC("Empress_CancelGuideClient", info.Sender, Array.Empty<object>());
					return;
				}
				MarkPendingGuided(val);
				object field = GetField(val2, "itemBattery");
				ApplyBatteryDrain(field, fullBar, bars, drain);
				object field2 = GetField(val2, "gunMuzzle");
				Transform val3 = (Transform)((field2 is Transform) ? field2 : null);
				if (Object.op_Implicit((Object)(object)val3))
				{
					SafeInvokeSound(val2, "soundShoot", val3.position);
					SafeInvokeSound(val2, "soundShootGlobal", val3.position);
					SafeCall(val2, "MuzzleFlash");
					SafeCall(val2, "StartTriggerAnimation");
				}
			}

			[PunRPC]
			public void Empress_BulletResult(Vector3 endPos, bool hit, PhotonMessageInfo info)
			{
				//IL_0099: Unknown result type (might be due to invalid IL or missing references)
				if (!PhotonNetwork.IsMasterClient)
				{
					return;
				}
				PhotonView val = ResolvePV((Component)(object)this);
				if (Object.op_Implicit((Object)(object)val))
				{
					ClearPending(val);
				}
				Type type = AccessTools.TypeByName("ItemGun");
				Component val2 = ((type != null) ? ((Component)this).GetComponent(type) : null);
				if ((Object)(object)val2 == (Object)null)
				{
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "ShootBullet", new Type[2]
				{
					typeof(Vector3),
					typeof(bool)
				}, (Type[])null);
				try
				{
					methodInfo?.Invoke(val2, new object[2] { endPos, hit });
				}
				catch (Exception arg)
				{
					ManualLogSource logS = LogS;
					if (logS != null)
					{
						logS.LogError((object)$"ShootBullet invoke failed: {arg}");
					}
				}
			}

			[PunRPC]
			public void Empress_CancelGuideClient(PhotonMessageInfo _)
			{
				GuidedBulletController[] array = Object.FindObjectsOfType<GuidedBulletController>();
				foreach (GuidedBulletController guidedBulletController in array)
				{
					guidedBulletController.CancelFromMaster();
				}
			}

			public static void SetPendingLocal(PhotonView pv, object gun, bool fullBar, int bars, float drain, Transform muzzle)
			{
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				if (Object.op_Implicit((Object)(object)pv) && gun != null)
				{
					MarkPendingGuided(pv);
					object field = GetField(gun, "itemBattery");
					ApplyBatteryDrain(field, fullBar, bars, drain);
					if (Object.op_Implicit((Object)(object)muzzle))
					{
						SafeInvokeSound(gun, "soundShoot", muzzle.position);
						SafeInvokeSound(gun, "soundShootGlobal", muzzle.position);
						SafeCall(gun, "MuzzleFlash");
						SafeCall(gun, "StartTriggerAnimation");
					}
				}
			}
		}

		private sealed class GuidedBulletController : MonoBehaviour
		{
			private object _gun;

			private PhotonView _gunPV;

			private GameObject _projGo;

			private Vector3 _startPos;

			private float _speed;

			private float _turnDegPerSec;

			private float _hitRadius;

			private float _maxDistance;

			private int _hitMask = -5;

			private Camera _mainCam;

			private Camera _guidedCam;

			private RenderTexture _rt;

			private GameObject _uiCanvasGo;

			private RawImage _uiImage;

			private float _deadlineRealtime;

			private KeyCode _cancelKey;

			private bool _active;

			private bool _suppressSend;

			public void Init(object ownerGun, PhotonView ownerPV, Vector3 startPos, Vector3 startDir, float speed, float turnDegPerSec, float fov, KeyCode cancelKey, float timeScaleTarget, float maxGuideSeconds, float hitSphereRadius, float maxDistanceUnits)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: 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_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_011a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0124: Expected O, but got Unknown
				//IL_012f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0130: Unknown result type (might be due to invalid IL or missing references)
				//IL_0132: Unknown result type (might be due to invalid IL or missing references)
				//IL_0137: Unknown result type (might be due to invalid IL or missing references)
				_gun = ownerGun;
				_gunPV = ownerPV;
				_startPos = startPos;
				_speed = speed;
				_turnDegPerSec = turnDegPerSec;
				_hitRadius = hitSphereRadius;
				_maxDistance = maxDistanceUnits;
				_cancelKey = cancelKey;
				_mainCam = ResolveMainCam();
				if ((Object)(object)_mainCam == (Object)null)
				{
					ManualLogSource logS = LogS;
					if (logS != null)
					{
						logS.LogError((object)"[GuidedBulletCam] No main camera; abort.");
					}
					Object.Destroy((Object)(object)((Component)this).gameObject);
					return;
				}
				Type type = AccessTools.TypeByName("SemiFunc");
				if (type != null)
				{
					MethodInfo methodInfo = AccessTools.Method(type, "LayerMaskGetVisionObstruct", (Type[])null, (Type[])null);
					if (methodInfo != null && methodInfo.GetParameters().Length == 0)
					{
						try
						{
							_hitMask = (int)methodInfo.Invoke(null, null);
						}
						catch
						{
						}
					}
				}
				try
				{
					_hitMask |= LayerMask.GetMask(new string[1] { "Enemy" });
				}
				catch
				{
				}
				_projGo = new GameObject("Empress_GuidedProjectile");
				_projGo.transform.SetPositionAndRotation(startPos, Quaternion.LookRotation(startDir, Vector3.up));
				Rigidbody val = _projGo.AddComponent<Rigidbody>();
				val.isKinematic = true;
				CapsuleCollider val2 = _projGo.AddComponent<CapsuleCollider>();
				((Collider)val2).isTrigger = true;
				val2.radius = Mathf.Max(0.01f, hitSphereRadius);
				val2.height = val2.radius * 2f;
				val2.direction = 2;
				TrailRenderer val3 = _projGo.AddComponent<TrailRenderer>();
				val3.time = 0.25f;
				val3.minVertexDistance = 0.01f;
				val3.startWidth = 0.02f;
				val3.endWidth = 0f;
				SetupOverlayCameraAndUI(fov);
				Time.timeScale = timeScaleTarget;
				Time.fixedDeltaTime = BaselineFixedDelta * Time.timeScale;
				_deadlineRealtime = Time.realtimeSinceStartup + maxGuideSeconds;
				SceneManager.activeSceneChanged += OnSceneChanged;
				TimeGuard.Arm(maxGuideSeconds + 0.5f);
				IsGuiding = true;
				_active = true;
			}

			private Camera ResolveMainCam()
			{
				if (Object.op_Implicit((Object)(object)Camera.main))
				{
					return Camera.main;
				}
				Type type = AccessTools.TypeByName("CameraUtils");
				if (type != null)
				{
					object obj = AccessTools.Field(type, "Instance")?.GetValue(null);
					if (obj != null)
					{
						object? obj2 = AccessTools.Field(type, "MainCamera")?.GetValue(obj);
						Camera val = (Camera)((obj2 is Camera) ? obj2 : null);
						if (Object.op_Implicit((Object)(object)val))
						{
							return val;
						}
					}
				}
				Camera[] array = Object.FindObjectsOfType<Camera>();
				foreach (Camera val2 in array)
				{
					if (((Behaviour)val2).enabled)
					{
						return val2;
					}
				}
				return null;
			}

			private void SetupOverlayCameraAndUI(float fov)
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Expected O, but got Unknown
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Expected O, but got Unknown
				//IL_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00be: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_017f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0189: Expected O, but got Unknown
				//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fe: Expected O, but got Unknown
				//IL_0252: Unknown result type (might be due to invalid IL or missing references)
				//IL_025f: Unknown result type (might be due to invalid IL or missing references)
				//IL_026c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0279: Unknown result type (might be due to invalid IL or missing references)
				int num = Mathf.Max(16, Screen.width);
				int num2 = Mathf.Max(16, Screen.height);
				_rt = new RenderTexture(num, num2, 24, (RenderTextureFormat)7)
				{
					useMipMap = false,
					autoGenerateMips = false
				};
				_rt.Create();
				GameObject val = new GameObject("Empress_GuidedCam");
				_guidedCam = val.AddComponent<Camera>();
				Object.DontDestroyOnLoad((Object)(object)val);
				_guidedCam.CopyFrom(_mainCam);
				_guidedCam.fieldOfView = fov;
				((Component)_guidedCam).transform.position = _projGo.transform.position - _projGo.transform.forward * 0.25f + Vector3.up * 0.02f;
				((Component)_guidedCam).transform.rotation = Quaternion.LookRotation(_projGo.transform.forward, Vector3.up);
				AudioListener component = val.GetComponent<AudioListener>();
				if (Object.op_Implicit((Object)(object)component))
				{
					Object.Destroy((Object)(object)component);
				}
				_guidedCam.targetTexture = _rt;
				_guidedCam.depth = _mainCam.depth + 1000f;
				_uiCanvasGo = new GameObject("Empress_GuidedCanvas", new Type[3]
				{
					typeof(Canvas),
					typeof(CanvasScaler),
					typeof(GraphicRaycaster)
				});
				Object.DontDestroyOnLoad((Object)(object)_uiCanvasGo);
				Canvas component2 = _uiCanvasGo.GetComponent<Canvas>();
				component2.renderMode = (RenderMode)0;
				component2.sortingOrder = 32767;
				CanvasScaler component3 = _uiCanvasGo.GetComponent<CanvasScaler>();
				component3.uiScaleMode = (ScaleMode)1;
				component3.referenceResolution = new Vector2((float)num, (float)num2);
				GameObject val2 = new GameObject("Empress_GuidedImage", new Type[1] { typeof(RawImage) });
				val2.transform.SetParent(_uiCanvasGo.transform, false);
				_uiImage = val2.GetComponent<RawImage>();
				_uiImage.texture = (Texture)(object)_rt;
				((Graphic)_uiImage).raycastTarget = false;
				RectTransform rectTransform = ((Graphic)_uiImage).rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.offsetMin = Vector2.zero;
				rectTransform.offsetMax = Vector2.zero;
			}

			private void LateUpdate()
			{
				//IL_004a: 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_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fd: 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_010b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0110: Unknown result type (might be due to invalid IL or missing references)
				//IL_0115: Unknown result type (might be due to invalid IL or missing references)
				//IL_011a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0127: Unknown result type (might be due to invalid IL or missing references)
				//IL_0134: Unknown result type (might be due to invalid IL or missing references)
				//IL_0139: Unknown result type (might be due to invalid IL or missing references)
				//IL_014f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0154: Unknown result type (might be due to invalid IL or missing references)
				//IL_0156: Unknown result type (might be due to invalid IL or missing references)
				//IL_015e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0168: Unknown result type (might be due to invalid IL or missing references)
				//IL_016d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0193: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_0203: Unknown result type (might be due to invalid IL or missing references)
				//IL_0208: Unknown result type (might be due to invalid IL or missing references)
				//IL_020a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0220: Unknown result type (might be due to invalid IL or missing references)
				//IL_0226: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
				//IL_024f: Unknown result type (might be due to invalid IL or missing references)
				//IL_027f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0284: Unknown result type (might be due to invalid IL or missing references)
				//IL_028b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0290: Unknown result type (might be due to invalid IL or missing references)
				//IL_0295: Unknown result type (might be due to invalid IL or missing references)
				//IL_029f: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
				//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_0304: Unknown result type (might be due to invalid IL or missing references)
				if (!_active)
				{
					return;
				}
				if (Time.realtimeSinceStartup >= _deadlineRealtime)
				{
					FinishAndSend(hit: false, _projGo.transform.position);
					return;
				}
				if (Input.GetKeyDown(_cancelKey))
				{
					FinishAndSend(hit: false, _projGo.transform.position);
					return;
				}
				float axisRaw = Input.GetAxisRaw("Mouse X");
				float axisRaw2 = Input.GetAxisRaw("Mouse Y");
				float num = axisRaw + (Input.GetKey((KeyCode)100) ? 0.5f : 0f) - (Input.GetKey((KeyCode)97) ? 0.5f : 0f);
				float num2 = 0f - axisRaw2 + (Input.GetKey((KeyCode)119) ? 0.5f : 0f) - (Input.GetKey((KeyCode)115) ? 0.5f : 0f);
				float num3 = _turnDegPerSec * Time.unscaledDeltaTime;
				Quaternion val = Quaternion.AngleAxis(num * num3, Vector3.up) * Quaternion.AngleAxis(num2 * num3, Vector3.right);
				_projGo.transform.rotation = val * _projGo.transform.rotation;
				Vector3 forward = _projGo.transform.forward;
				Vector3 val2 = forward * _speed * Time.deltaTime;
				float num4 = Mathf.Max(0.001f, ((Vector3)(ref val2)).magnitude + 0.05f);
				RaycastHit val3 = default(RaycastHit);
				if (Physics.SphereCast(_projGo.transform.position, (_hitRadius > 0.001f) ? _hitRadius : 0.01f, forward, ref val3, num4, _hitMask, (QueryTriggerInteraction)1))
				{
					_projGo.transform.position = ((RaycastHit)(ref val3)).point;
					FinishAndSend(hit: true, ((RaycastHit)(ref val3)).point);
					return;
				}
				Transform transform = _projGo.transform;
				transform.position += val2;
				if (Vector3.Distance(_projGo.transform.position, _startPos) >= _maxDistance)
				{
					FinishAndSend(hit: false, _projGo.transform.position);
				}
				else if (Object.op_Implicit((Object)(object)_guidedCam))
				{
					Vector3 val4 = _projGo.transform.position - forward * 0.25f + Vector3.up * 0.02f;
					((Component)_guidedCam).transform.position = Vector3.Lerp(((Component)_guidedCam).transform.position, val4, 0.6f);
					((Component)_guidedCam).transform.rotation = Quaternion.Slerp(((Component)_guidedCam).transform.rotation, Quaternion.LookRotation(forward, Vector3.up), 0.6f);
				}
			}

			public void CancelFromMaster()
			{
				_suppressSend = true;
				try
				{
					Time.timeScale = BaselineTimeScale;
					Time.fixedDeltaTime = BaselineFixedDelta;
				}
				catch
				{
				}
				Cleanup();
			}

			private void FinishAndSend(bool hit, Vector3 finalPos)
			{
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					Time.timeScale = BaselineTimeScale;
					Time.fixedDeltaTime = BaselineFixedDelta;
				}
				catch
				{
				}
				try
				{
					if (!_suppressSend)
					{
						if ((Object)(object)_gunPV != (Object)null && _gunPV.ViewID != 0 && PhotonNetwork.IsConnected)
						{
							_gunPV.RPC("Empress_BulletResult", (RpcTarget)2, new object[2] { finalPos, hit });
						}
						else
						{
							Type type = _gun.GetType();
							AccessTools.Method(type, "ShootBullet", new Type[2]
							{
								typeof(Vector3),
								typeof(bool)
							}, (Type[])null)?.Invoke(_gun, new object[2] { finalPos, hit });
						}
					}
				}
				catch (Exception arg)
				{
					ManualLogSource logS = LogS;
					if (logS != null)
					{
						logS.LogError((object)$"Finish send failed: {arg}");
					}
				}
				Cleanup();
			}

			private void OnSceneChanged(Scene a, Scene b)
			{
				Cleanup();
			}

			private void OnDisable()
			{
				Cleanup();
			}

			private void OnDestroy()
			{
				Cleanup();
			}

			private void Cleanup()
			{
				if (!_active)
				{
					return;
				}
				_active = false;
				SceneManager.activeSceneChanged -= OnSceneChanged;
				TimeGuard.Disarm();
				IsGuiding = false;
				try
				{
					if (Object.op_Implicit((Object)(object)_guidedCam))
					{
						_guidedCam.targetTexture = null;
						Object.Destroy((Object)(object)((Component)_guidedCam).gameObject);
					}
				}
				catch
				{
				}
				try
				{
					if (Object.op_Implicit((Object)(object)_uiImage))
					{
						_uiImage.texture = null;
					}
					if (Object.op_Implicit((Object)(object)_uiCanvasGo))
					{
						Object.Destroy((Object)(object)_uiCanvasGo);
					}
				}
				catch
				{
				}
				try
				{
					if (Object.op_Implicit((Object)(object)_rt))
					{
						_rt.Release();
						Object.Destroy((Object)(object)_rt);
					}
				}
				catch
				{
				}
				if (Object.op_Implicit((Object)(object)_projGo))
				{
					Object.Destroy((Object)(object)_projGo);
				}
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		public const string PluginGuid = "empress.repogame.guidedbulletcam";

		public const string PluginName = "Guided Bullet Camera";

		public const string PluginVersion = "2.1.0";

		internal static ManualLogSource LogS;

		internal static ConfigEntry<bool> CfgEnabled;

		internal static ConfigEntry<KeyCode> CfgCancelKey;

		internal static ConfigEntry<float> CfgTimeScale;

		internal static ConfigEntry<float> CfgFov;

		internal static ConfigEntry<float> CfgBulletSpeed;

		internal static ConfigEntry<float> CfgTurnRateDeg;

		internal static ConfigEntry<float> CfgHitRadius;

		internal static ConfigEntry<float> CfgMaxGuideSeconds;

		internal static ConfigEntry<float> CfgMaxDistance;

		internal static float BaselineTimeScale = 1f;

		internal static float BaselineFixedDelta = 0.02f;

		internal static volatile bool IsGuiding;

		private static readonly HashSet<int> PendingGuided = new HashSet<int>();

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Expected O, but got Unknown
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Expected O, but got Unknown
			LogS = ((BaseUnityPlugin)this).Logger;
			BaselineTimeScale = Time.timeScale;
			BaselineFixedDelta = Time.fixedDeltaTime;
			CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master toggle.");
			CfgCancelKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "CancelKey", (KeyCode)27, "Abort guiding.");
			CfgTimeScale = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "TimeScaleDuringGuide", 0.08f, "Local Time.timeScale during guide.");
			CfgFov = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraFOV", 45f, "Overlay camera FOV.");
			CfgBulletSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Projectile", "SpeedUnitsPerSec", 70f, "Projectile speed (u/s).");
			CfgTurnRateDeg = ((BaseUnityPlugin)this).Config.Bind<float>("Projectile", "TurnRateDegPerSec", 240f, "Turn rate (deg/s).");
			CfgHitRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Projectile", "HitSphereRadius", 0.05f, "Spherecast radius.");
			CfgMaxGuideSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "MaxGuideSeconds", 3f, "Realtime hard cap for a guided shot.");
			CfgMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "MaxDistanceUnits", 500f, "Auto-restore after projectile travels this far.");
			_harmony = new Harmony("empress.repogame.guidedbulletcam");
			_harmony.PatchAll(typeof(ItemGunStartInjector));
			_harmony.PatchAll(typeof(ItemToggleHooks));
			_harmony.PatchAll(typeof(ShootRpcMasterSkipper));
			GameObject val = new GameObject("Empress_TimeGuard");
			Object.DontDestroyOnLoad((Object)(object)val);
			val.AddComponent<TimeGuard>();
			GameObject val2 = new GameObject("Empress_GuidedCam_Handshake");
			Object.DontDestroyOnLoad((Object)(object)val2);
			((Object)val2).hideFlags = (HideFlags)52;
			val2.AddComponent<GuidedCamHandshakeRouter>();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Guided Bullet Camera v2.1.0 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		internal static bool IsLevelReady()
		{
			return GuidedCamHandshakeRouter.CanUseModNow();
		}

		private static PhotonView ResolvePV(Component c)
		{
			if (!Object.op_Implicit((Object)(object)c))
			{
				return null;
			}
			PhotonView component = c.GetComponent<PhotonView>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return component;
			}
			component = c.GetComponentInParent<PhotonView>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return component;
			}
			return c.GetComponentInChildren<PhotonView>();
		}

		private static bool IsPendingGuided(PhotonView pv)
		{
			return Object.op_Implicit((Object)(object)pv) && PendingGuided.Contains(pv.ViewID);
		}

		private static void MarkPendingGuided(PhotonView pv)
		{
			if (Object.op_Implicit((Object)(object)pv))
			{
				PendingGuided.Add(pv.ViewID);
			}
		}

		private static void ClearPending(PhotonView pv)
		{
			if (Object.op_Implicit((Object)(object)pv))
			{
				PendingGuided.Remove(pv.ViewID);
			}
		}

		private static object GetField(object obj, string name)
		{
			if (obj == null)
			{
				return null;
			}
			return AccessTools.Field(obj.GetType(), name)?.GetValue(obj);
		}

		private static void SafeInvokeSound(object gun, string fieldName, Vector3 pos)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				object obj = AccessTools.Field(gun.GetType(), fieldName)?.GetValue(gun);
				if (obj == null)
				{
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(obj.GetType(), "Play", new Type[5]
				{
					typeof(Vector3),
					typeof(float),
					typeof(float),
					typeof(float),
					typeof(float)
				}, (Type[])null);
				if (methodInfo != null)
				{
					methodInfo.Invoke(obj, new object[5] { pos, 1f, 1f, 1f, 1f });
					return;
				}
				foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(obj.GetType()))
				{
					if (declaredMethod.Name != "Play")
					{
						continue;
					}
					ParameterInfo[] parameters = declaredMethod.GetParameters();
					if (parameters.Length < 1 || !(parameters[0].ParameterType == typeof(Vector3)))
					{
						continue;
					}
					object[] array = new object[parameters.Length];
					array[0] = pos;
					for (int i = 1; i < parameters.Length; i++)
					{
						array[i] = ((parameters[i].ParameterType == typeof(float)) ? ((object)1f) : Type.Missing);
					}
					declaredMethod.Invoke(obj, array);
					break;
				}
			}
			catch
			{
			}
		}

		private static void SafeCall(object obj, string method)
		{
			MethodInfo methodInfo = AccessTools.Method(obj.GetType(), method, (Type[])null, (Type[])null);
			try
			{
				methodInfo?.Invoke(obj, null);
			}
			catch
			{
			}
		}

		private static bool HasAmmo(object gun)
		{
			object field = GetField(gun, "itemBattery");
			if (field == null)
			{
				return false;
			}
			FieldInfo fieldInfo = AccessTools.Field(field.GetType(), "batteryLifeInt");
			if (fieldInfo == null)
			{
				return false;
			}
			int num = (int)fieldInfo.GetValue(field);
			return num > 0;
		}

		internal static void ApplyBatteryDrain(object itemBattery, bool fullBar, int bars, float drain)
		{
			if (itemBattery == null)
			{
				return;
			}
			try
			{
				if (!fullBar)
				{
					FieldInfo fieldInfo = AccessTools.Field(itemBattery.GetType(), "batteryLife");
					if (fieldInfo != null)
					{
						float num = (float)fieldInfo.GetValue(itemBattery);
						fieldInfo.SetValue(itemBattery, Mathf.Max(0f, num - drain));
						FieldInfo fieldInfo2 = AccessTools.Field(itemBattery.GetType(), "batteryLifeInt");
						if (fieldInfo2 != null)
						{
							FieldInfo fieldInfo3 = AccessTools.Field(itemBattery.GetType(), "batteryBars");
							int num2 = ((fieldInfo3 != null) ? ((int)fieldInfo3.GetValue(itemBattery)) : 6);
							int num3 = Mathf.Clamp(Mathf.RoundToInt((float)fieldInfo.GetValue(itemBattery) / (100f / (float)Mathf.Max(1, num2))), 0, num2);
							fieldInfo2.SetValue(itemBattery, num3);
						}
						MethodInfo methodInfo = AccessTools.Method(itemBattery.GetType(), "BatteryFullPercentChange", new Type[2]
						{
							typeof(int),
							typeof(bool)
						}, (Type[])null);
						FieldInfo fieldInfo4 = AccessTools.Field(itemBattery.GetType(), "batteryLifeInt");
						if (methodInfo != null && fieldInfo4 != null)
						{
							methodInfo.Invoke(itemBattery, new object[2]
							{
								(int)fieldInfo4.GetValue(itemBattery),
								false
							});
						}
					}
				}
				else
				{
					AccessTools.Method(itemBattery.GetType(), "RemoveFullBar", new Type[1] { typeof(int) }, (Type[])null)?.Invoke(itemBattery, new object[1] { bars });
				}
			}
			catch (Exception arg)
			{
				ManualLogSource logS = LogS;
				if (logS != null)
				{
					logS.LogWarning((object)$"Battery drain apply failed: {arg}");
				}
			}
		}
	}
}
namespace BulletControl
{
	[BepInPlugin("Omniscye.BulletControl", "BulletControl", "1.0")]
	public class BulletControl : BaseUnityPlugin
	{
		internal static BulletControl Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		private void Awake()
		{
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Patch();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		internal void Patch()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0026: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
		}
	}
}