Decompiled source of PocketCartTurret v0.1.1

BepInEx/plugins/PocketCartTurret/PocketCartTurret.dll

Decompiled 12 hours ago
using System;
using System.Collections;
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.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("artrointel")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Turn pocket carts with mounted cannons or lasers into automatic turrets. Only the host needs the mod; vanilla clients are supported.")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1+584d0c089206d8094eaa3b938425123171a8df27")]
[assembly: AssemblyProduct("PocketCartTurret")]
[assembly: AssemblyTitle("PocketCartTurret")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
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;
		}
	}
	[CompilerGenerated]
	[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 PocketCartTurret
{
	internal sealed class DetectionWarning
	{
		internal const float Delay = 2f;

		internal const float LossGrace = 0.5f;

		private bool _active;

		private bool _visible;

		private float _fireAt;

		private float _lostAt;

		internal bool FirstShotPending { get; private set; }

		internal bool KeepItem
		{
			get
			{
				if (_active)
				{
					return FirstShotPending;
				}
				return false;
			}
		}

		internal bool Observe(bool eligible, bool visible, float now)
		{
			if (!eligible)
			{
				Reset();
				return false;
			}
			if (!visible)
			{
				if (_visible)
				{
					_lostAt = now;
				}
				_visible = false;
				_fireAt = float.PositiveInfinity;
				if (_active && now - _lostAt >= 0.5f)
				{
					Reset();
				}
				return false;
			}
			if (_active && !_visible && now - _lostAt >= 0.5f)
			{
				Reset();
			}
			if (_active && !_visible)
			{
				_visible = true;
				_fireAt = now + 2f;
				bool result = !FirstShotPending;
				FirstShotPending = true;
				return result;
			}
			_visible = true;
			if (_active)
			{
				return false;
			}
			_active = true;
			FirstShotPending = true;
			_fireAt = now + 2f;
			return true;
		}

		internal bool CanFire(float now)
		{
			if (_active && _visible)
			{
				return now >= _fireAt;
			}
			return false;
		}

		internal bool CanFire(float now, float cycleReadyAt, bool aligned)
		{
			return CanFire(now) && now >= cycleReadyAt && aligned;
		}

		internal void MarkFired()
		{
			FirstShotPending = false;
		}

		internal void Reset()
		{
			_active = false;
			_visible = false;
			FirstShotPending = false;
			_fireAt = float.PositiveInfinity;
			_lostAt = 0f;
		}
	}
	internal sealed class MineWarningCarrier : MonoBehaviour
	{
		private static Item? _mineItem;

		private Transform _mount;

		private PhysGrabObject _physical;

		private Rigidbody _body;

		private float _leaseExpiresAt;

		private bool _disposing;

		private Collider[] _colliders = Array.Empty<Collider>();

		private ItemMine _mine;

		private bool _armingStarted;

		internal static bool IsWarning(Component component)
		{
			return (Object)(object)component.GetComponent<MineWarningCarrier>() != (Object)null;
		}

		internal void RenewLease()
		{
			_leaseExpiresAt = Time.time + 5f;
		}

		internal static MineWarningCarrier Create(Transform mount)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			Item val = FindMine();
			Vector3 position = mount.position;
			GameObject val2 = (SemiFunc.IsMultiplayer() ? PhotonNetwork.InstantiateRoomObject(((PrefabRef<GameObject>)(object)val.prefab).ResourcePath, position, mount.rotation, (byte)0, (object[])null) : Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)val.prefab).Prefab, position, mount.rotation));
			MineWarningCarrier mineWarningCarrier = null;
			try
			{
				mineWarningCarrier = val2.AddComponent<MineWarningCarrier>();
				mineWarningCarrier._mount = mount;
				mineWarningCarrier._physical = val2.GetComponent<PhysGrabObject>();
				mineWarningCarrier._body = val2.GetComponent<Rigidbody>();
				mineWarningCarrier._mine = val2.GetComponent<ItemMine>();
				mineWarningCarrier.RenewLease();
				mineWarningCarrier._colliders = val2.GetComponentsInChildren<Collider>(true);
				mineWarningCarrier.PinToMount();
				mineWarningCarrier._mine.triggeredByEnemies = false;
				mineWarningCarrier._mine.triggeredByPlayers = false;
				mineWarningCarrier._mine.triggeredByRigidBodies = false;
				mineWarningCarrier._mine.triggeredByForces = false;
				val2.GetComponent<PhysGrabObjectImpactDetector>().destroyDisable = true;
				ItemMineTrigger[] componentsInChildren = val2.GetComponentsInChildren<ItemMineTrigger>(true);
				foreach (ItemMineTrigger val3 in componentsInChildren)
				{
					((Behaviour)val3).enabled = false;
				}
				PhotonView component = val2.GetComponent<PhotonView>();
				if (SemiFunc.IsMultiplayer())
				{
					component.RPC("ToggleDisableRPC", (RpcTarget)3, new object[1] { true });
					component.RPC("StateSetRPC", (RpcTarget)3, new object[1] { 1 });
				}
				else
				{
					mineWarningCarrier._mine.StateSetRPC(1, default(PhotonMessageInfo));
				}
				val2.SetActive(true);
				return mineWarningCarrier;
			}
			catch
			{
				if ((Object)(object)mineWarningCarrier != (Object)null)
				{
					mineWarningCarrier.Dispose();
				}
				else if (SemiFunc.IsMultiplayer())
				{
					PhotonNetwork.Destroy(val2);
				}
				else
				{
					Object.Destroy((Object)(object)val2);
				}
				throw;
			}
		}

		private IEnumerator Start()
		{
			yield return null;
			if (!_disposing && !((Object)(object)_mount == (Object)null))
			{
				PinToMount();
				_physical.Teleport(((Component)this).transform.position, ((Component)this).transform.rotation);
				StartArming();
			}
		}

		private void StartArming()
		{
			if (!_armingStarted && SemiFunc.IsMasterClientOrSingleplayer())
			{
				_armingStarted = true;
				VanillaMineArming.Tick(_mine);
			}
		}

		private void Update()
		{
			if (_armingStarted && !_disposing && SemiFunc.IsMasterClientOrSingleplayer())
			{
				VanillaMineArming.Tick(_mine);
			}
		}

		private static Item FindMine()
		{
			if ((Object)(object)_mineItem != (Object)null)
			{
				return _mineItem;
			}
			foreach (Item value in StatsManager.instance.itemDictionary.Values)
			{
				if ((Object)(object)value != (Object)null && value.prefab != null && ((PrefabRef<GameObject>)(object)value.prefab).IsValid() && (Object)(object)((PrefabRef<GameObject>)(object)value.prefab).Prefab != (Object)null && (Object)(object)((PrefabRef<GameObject>)(object)value.prefab).Prefab.GetComponent<ItemMineExplosive>() != (Object)null)
				{
					Sound soundArmingBeep = ((PrefabRef<GameObject>)(object)value.prefab).Prefab.GetComponent<ItemMine>().soundArmingBeep;
					if (soundArmingBeep == null || soundArmingBeep.Sounds == null || soundArmingBeep.Sounds.Length == 0)
					{
						throw new InvalidOperationException("The vanilla Explosive Mine has no arming sound.");
					}
					_mineItem = value;
					return value;
				}
			}
			throw new InvalidOperationException("The vanilla Explosive Mine prefab (ItemMine) was not found.");
		}

		private void LateUpdate()
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			if ((Object)(object)_mount == (Object)null || Time.time >= _leaseExpiresAt)
			{
				Dispose();
				return;
			}
			Collider[] colliders = _colliders;
			foreach (Collider val in colliders)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.enabled = false;
				}
			}
			PinToMount();
		}

		private void PinToMount()
		{
			//IL_004e: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			_physical.OverrideKinematic(0.2f);
			_physical.OverrideGrabDisable(0.2f);
			_physical.OverrideIndestructible(0.2f);
			_body.detectCollisions = false;
			_body.interpolation = (RigidbodyInterpolation)0;
			Vector3 position = _mount.position;
			((Component)this).transform.SetPositionAndRotation(position, _mount.rotation);
			_body.position = position;
			_body.rotation = _mount.rotation;
		}

		internal void Dispose()
		{
			if (_disposing)
			{
				return;
			}
			bool flag = (Object)(object)GameManager.instance != (Object)null && SemiFunc.IsMultiplayer();
			if (!flag || !PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
			{
				_disposing = true;
				if (flag && PhotonNetwork.InRoom)
				{
					PhotonNetwork.Destroy(((Component)this).gameObject);
				}
				else
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager), "ItemFetchName")]
	internal static class WarningItemStatsPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemAttributes itemAttributes)
		{
			if (!((Object)(object)itemAttributes == (Object)null))
			{
				return !MineWarningCarrier.IsWarning((Component)(object)itemAttributes);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ItemManager), "AddSpawnedItem")]
	internal static class WarningItemListPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemAttributes item)
		{
			if (!((Object)(object)item == (Object)null))
			{
				return !MineWarningCarrier.IsWarning((Component)(object)item);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject), "GrabStartedRPC")]
	internal static class WarningItemGrabPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(PhysGrabObject __instance)
		{
			return !MineWarningCarrier.IsWarning((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(ItemEquippable), "RPC_RequestEquip")]
	internal static class WarningItemEquipPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemEquippable __instance)
		{
			return !MineWarningCarrier.IsWarning((Component)(object)__instance);
		}
	}
	[BepInPlugin("artrointel.PocketCartTurret", "PocketCartTurret", "0.1.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "artrointel.PocketCartTurret";

		public const string PluginName = "PocketCartTurret";

		public const string PluginVersion = "0.1.1";

		private Harmony? _harmony;

		internal static ManualLogSource ModLogger { get; private set; }

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			ModLogger = ((BaseUnityPlugin)this).Logger;
			_harmony = new Harmony("artrointel.PocketCartTurret");
			_harmony.PatchAll();
			ModLogger.LogInfo((object)"PocketCartTurret v0.1.1 loaded.");
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal sealed class TurretController : MonoBehaviour
	{
		private ItemCartCannonMain _weapon;

		private ItemBattery _battery;

		private PhysGrabObject _physical;

		private PhysGrabObjectImpactDetector _impact;

		private Transform _muzzle;

		private float _range;

		private EnemyParent? _target;

		private bool _automaticCycle;

		private bool _failed;

		private readonly DetectionWarning _warningState = new DetectionWarning();

		private MineWarningCarrier? _warningItem;

		private float _cycleReadyAt;

		internal bool OwnsAim
		{
			get
			{
				if (_failed || (Object)(object)GameManager.instance == (Object)null || (Object)(object)RunManager.instance == (Object)null)
				{
					return false;
				}
				PhysGrabCart val = VanillaWeapon.Cart.Invoke(_impact);
				return TurretRules.CanAutomate(SemiFunc.IsMasterClientOrSingleplayer(), (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated && SemiFunc.RunIsLevel(), (Object)(object)val != (Object)null && val.isSmallCart, _impact.inCart && (Object)(object)val != (Object)null, VanillaWeapon.BatteryBars.Invoke(_battery) > 0 && VanillaWeapon.BatteryLife.Invoke(_battery) > 0f, _physical.playerGrabbing.Count > 0);
			}
		}

		internal void Initialize(ItemCartCannonMain weapon)
		{
			_weapon = weapon;
			_battery = ((Component)this).GetComponent<ItemBattery>();
			_physical = ((Component)this).GetComponent<PhysGrabObject>();
			_impact = ((Component)this).GetComponent<PhysGrabObjectImpactDetector>();
			Rigidbody component = ((Component)this).GetComponent<Rigidbody>();
			ItemCartLaser component2 = ((Component)this).GetComponent<ItemCartLaser>();
			_muzzle = (((Object)(object)component2 != (Object)null) ? component2.muzzleTransform : weapon.muzzle);
			_range = (((Object)(object)component2 != (Object)null) ? 15f : 25f);
			_failed = (Object)(object)_battery == (Object)null || (Object)(object)_physical == (Object)null || (Object)(object)_impact == (Object)null || (Object)(object)component == (Object)null || (Object)(object)_muzzle == (Object)null;
			if (_failed)
			{
				Plugin.ModLogger.LogError((object)("Cannot initialize turret on " + ((Object)this).name + ": a required vanilla component is missing."));
			}
		}

		internal void BeforeWeaponUpdate()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Invalid comparison between Unknown and I4
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Invalid comparison between Unknown and I4
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected I4, but got Unknown
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Invalid comparison between Unknown and I4
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Invalid comparison between Unknown and I4
			if (_failed || !SemiFunc.IsMasterClientOrSingleplayer())
			{
				RemoveWarningItem();
				_target = null;
				_automaticCycle = false;
				_warningState.Reset();
				return;
			}
			try
			{
				bool ownsAim = OwnsAim;
				_target = (ownsAim ? FindNearestTarget() : null);
				state val = VanillaWeapon.State.Invoke(_weapon);
				if (_warningState.Observe(ownsAim, (Object)(object)_target != (Object)null, Time.time))
				{
					RemoveWarningItem();
					_warningItem = MineWarningCarrier.Create(((Component)_weapon).transform);
				}
				if (!ownsAim || !_warningState.KeepItem)
				{
					RemoveWarningItem();
				}
				else
				{
					_warningItem?.RenewLease();
				}
				if (_automaticCycle)
				{
					if ((int)val == 1 || (int)val == 0)
					{
						_automaticCycle = false;
					}
					else
					{
						if (!ownsAim || (Object)(object)_target == (Object)null || ((int)val == 3 && !CurrentRayHits(_target)))
						{
							int? num = TurretRules.StopState((int)val);
							if (num.HasValue)
							{
								VanillaWeaponState.Set(_weapon, num.Value);
							}
							return;
						}
						if ((int)val == 2)
						{
							if (PrepareAutomaticShot())
							{
								VanillaWeaponState.Set(_weapon, 3);
							}
							return;
						}
					}
				}
				if (ownsAim && (int)val == 1 && (Object)(object)_target != (Object)null)
				{
					_automaticCycle = true;
					_cycleReadyAt = (_warningState.FirstShotPending ? Time.time : (Time.time + _weapon.shootBuildUpTime));
					VanillaWeaponState.Set(_weapon, 2);
				}
			}
			catch (Exception exception)
			{
				DisableAutomation(exception);
			}
		}

		internal bool PrepareAutomaticShot()
		{
			if (!_automaticCycle)
			{
				return true;
			}
			if (!OwnsAim || (Object)(object)_target == (Object)null || !_warningState.CanFire(Time.time, _cycleReadyAt, CurrentRayHits(_target)))
			{
				return false;
			}
			RemoveWarningItem();
			_warningState.MarkFired();
			return true;
		}

		private void RemoveWarningItem()
		{
			if ((Object)(object)_warningItem != (Object)null)
			{
				_warningItem.Dispose();
				_warningItem = null;
			}
		}

		internal void DisableAutomation(Exception exception)
		{
			_failed = true;
			Plugin.ModLogger.LogError((object)$"Turret disabled on {((Object)this).name}; vanilla behavior retained: {exception}");
			try
			{
				StopAutomaticCycle();
			}
			catch (Exception arg)
			{
				_automaticCycle = false;
				_target = null;
				Plugin.ModLogger.LogError((object)$"Could not cancel the automatic firing cycle: {arg}");
			}
		}

		internal void BeforeVanillaGrab()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			if (!OwnsAim || (Object)(object)_target == (Object)null || (Object)(object)_weapon.currentCorrector == (Object)null)
			{
				return;
			}
			Enemy val = VanillaWeapon.Enemy.Invoke(_target);
			if (!((Object)(object)val == (Object)null) && IsLive(_target, val))
			{
				Transform transform = _weapon.currentCorrector.transform;
				Quaternion rotation = transform.rotation;
				if (TryAimYaw(AimPoint(val), _muzzle.position, _muzzle.forward, out var yaw))
				{
					float num = ((Component)this).transform.eulerAngles.y + yaw;
					float num2 = Mathf.Clamp(Mathf.DeltaAngle(((Quaternion)(ref rotation)).eulerAngles.y, num), -180f * Time.fixedDeltaTime, 180f * Time.fixedDeltaTime);
					transform.rotation = Quaternion.AngleAxis(num2, Vector3.up) * rotation;
				}
			}
		}

		private EnemyParent? FindNearestTarget()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0070: 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)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)EnemyDirector.instance == (Object)null)
			{
				return null;
			}
			EnemyParent result = null;
			float bestDistanceSquared = float.PositiveInfinity;
			int bestId = int.MaxValue;
			foreach (EnemyParent item in EnemyDirector.instance.enemiesSpawned)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				Enemy enemy = VanillaWeapon.Enemy.Invoke(item);
				if (IsLive(item, enemy))
				{
					Vector3 val = AimPoint(enemy);
					Vector3 val2 = val - _muzzle.position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					int instanceID = ((Object)item).GetInstanceID();
					if (TurretRules.InRange(sqrMagnitude, _range) && TurretRules.PreferCandidate(sqrMagnitude, instanceID, bestDistanceSquared, bestId) && SweptRayHits(item, val))
					{
						result = item;
						bestDistanceSquared = sqrMagnitude;
						bestId = instanceID;
					}
				}
			}
			return result;
		}

		private static bool IsLive(EnemyParent parent, Enemy enemy)
		{
			if ((Object)(object)enemy == (Object)null || !VanillaWeapon.Spawned.Invoke(parent) || !((Behaviour)enemy).isActiveAndEnabled)
			{
				return false;
			}
			EnemyHealth component = ((Component)enemy).GetComponent<EnemyHealth>();
			if (!((Object)(object)component == (Object)null))
			{
				return !VanillaWeapon.Dead.Invoke(component);
			}
			return true;
		}

		private static Vector3 AimPoint(Enemy enemy)
		{
			//IL_0020: 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)
			if (!((Object)(object)enemy.CenterTransform != (Object)null))
			{
				return ((Component)enemy).transform.position;
			}
			return enemy.CenterTransform.position;
		}

		private bool SweptRayHits(EnemyParent target, Vector3 point)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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)
			Vector3 position = _muzzle.position;
			Vector3 forward = _muzzle.forward;
			if (!TryAimYaw(point, position, forward, out var yaw))
			{
				return false;
			}
			Quaternion val = Quaternion.AngleAxis(yaw, Vector3.up);
			Vector3 origin = ((Component)this).transform.position + val * (position - ((Component)this).transform.position);
			return RayHits(target, origin, val * forward);
		}

		private bool TryAimYaw(Vector3 point, Vector3 origin, Vector3 forward, out float yaw)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = point - ((Component)this).transform.position;
			Vector3 val2 = origin - ((Component)this).transform.position;
			return TurretRules.TryAimYaw(forward.x, forward.z, val2.x, val2.z, val.x, val.z, out yaw);
		}

		private bool CurrentRayHits(EnemyParent target)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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)
			if (IsLive(target, VanillaWeapon.Enemy.Invoke(target)))
			{
				Vector3 val = AimPoint(VanillaWeapon.Enemy.Invoke(target)) - _muzzle.position;
				if (TurretRules.InRange(((Vector3)(ref val)).sqrMagnitude, _range))
				{
					return RayHits(target, _muzzle.position, _muzzle.forward);
				}
			}
			return false;
		}

		private bool RayHits(EnemyParent target, Vector3 origin, Vector3 direction)
		{
			//IL_0000: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			int num = LayerMask.op_Implicit(SemiFunc.LayerMaskGetVisionObstruct()) | LayerMask.GetMask(new string[1] { "Enemy" });
			RaycastHit[] array = Physics.RaycastAll(origin, direction, _range * 0.7f, num, (QueryTriggerInteraction)2);
			float num2 = float.PositiveInfinity;
			Collider val = null;
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val2 = array2[i];
				if (!((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<PhysGrabObject>() == (Object)(object)_physical) && !(((RaycastHit)(ref val2)).distance >= num2) && !((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<MineWarningCarrier>() != (Object)null) && (!((RaycastHit)(ref val2)).collider.isTrigger || ((Component)((RaycastHit)(ref val2)).collider).gameObject.layer == LayerMask.NameToLayer("Enemy")))
				{
					num2 = ((RaycastHit)(ref val2)).distance;
					val = ((RaycastHit)(ref val2)).collider;
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				return (Object)(object)((Component)val).GetComponentInParent<EnemyParent>() == (Object)(object)target;
			}
			return false;
		}

		private void StopAutomaticCycle()
		{
			RemoveWarningItem();
			_warningState.Reset();
			if (_automaticCycle && (Object)(object)_weapon != (Object)null && (Object)(object)GameManager.instance != (Object)null && SemiFunc.IsMasterClientOrSingleplayer())
			{
				int? num = TurretRules.StopState((int)VanillaWeapon.State.Invoke(_weapon));
				if (num.HasValue)
				{
					VanillaWeaponState.Set(_weapon, num.Value);
				}
			}
			_automaticCycle = false;
			_target = null;
		}

		private void OnDisable()
		{
			StopAutomaticCycle();
		}
	}
	internal static class TurretRules
	{
		internal const float CannonRange = 25f;

		internal const float LaserRange = 15f;

		internal const float DetectionRatio = 0.7f;

		internal const float TurnSpeedDegrees = 180f;

		internal static bool CanAutomate(bool host, bool missionReady, bool smallCart, bool mounted, bool powered, bool weaponHeld)
		{
			if (host && missionReady && smallCart && mounted && powered)
			{
				return !weaponHeld;
			}
			return false;
		}

		internal static bool InRange(float distanceSquared, float weaponRange)
		{
			if (distanceSquared >= 0f)
			{
				return distanceSquared <= weaponRange * weaponRange * 0.7f * 0.7f;
			}
			return false;
		}

		internal static bool PreferCandidate(float distanceSquared, int id, float bestDistanceSquared, int bestId)
		{
			if (!(distanceSquared < bestDistanceSquared))
			{
				if (distanceSquared == bestDistanceSquared)
				{
					return id < bestId;
				}
				return false;
			}
			return true;
		}

		internal static float YawDelta(float forwardX, float forwardZ, float offsetX, float offsetZ)
		{
			double y = forwardZ * offsetX - forwardX * offsetZ;
			double x = forwardX * offsetX + forwardZ * offsetZ;
			return (float)(Math.Atan2(y, x) * (180.0 / Math.PI));
		}

		internal static bool TryAimYaw(float forwardX, float forwardZ, float muzzleX, float muzzleZ, float targetX, float targetZ, out float yaw)
		{
			yaw = 0f;
			double num = Math.Sqrt(forwardX * forwardX + forwardZ * forwardZ);
			double num2 = Math.Sqrt(targetX * targetX + targetZ * targetZ);
			if (num < 0.0001 || num2 < 0.0001)
			{
				return false;
			}
			double num3 = (double)(forwardZ * muzzleX - forwardX * muzzleZ) / num;
			if (Math.Abs(num3) >= num2)
			{
				return false;
			}
			yaw = YawDelta(forwardX, forwardZ, targetX, targetZ) - (float)(Math.Asin(num3 / num2) * (180.0 / Math.PI));
			double num4 = (double)(forwardX * muzzleX + forwardZ * muzzleZ) / num;
			return Math.Sqrt(num2 * num2 - num3 * num3) > num4;
		}

		internal static int? StopState(int state)
		{
			return state switch
			{
				3 => 4, 
				2 => 1, 
				_ => null, 
			};
		}
	}
	internal static class VanillaWeapon
	{
		internal static readonly FieldRef<ItemCartCannonMain, state> State = AccessTools.FieldRefAccess<ItemCartCannonMain, state>("stateCurrent");

		internal static readonly FieldRef<PhysGrabObjectImpactDetector, PhysGrabCart> Cart = AccessTools.FieldRefAccess<PhysGrabObjectImpactDetector, PhysGrabCart>("currentCart");

		internal static readonly FieldRef<ItemBattery, int> BatteryBars = AccessTools.FieldRefAccess<ItemBattery, int>("batteryLifeInt");

		internal static readonly FieldRef<ItemBattery, float> BatteryLife = AccessTools.FieldRefAccess<ItemBattery, float>("batteryLife");

		internal static readonly FieldRef<EnemyParent, Enemy> Enemy = AccessTools.FieldRefAccess<EnemyParent, Enemy>("Enemy");

		internal static readonly FieldRef<EnemyParent, bool> Spawned = AccessTools.FieldRefAccess<EnemyParent, bool>("Spawned");

		internal static readonly FieldRef<EnemyHealth, bool> Dead = AccessTools.FieldRefAccess<EnemyHealth, bool>("dead");
	}
	[HarmonyPatch(typeof(ItemCartCannonMain), "StateSet")]
	internal static class VanillaWeaponState
	{
		[MethodImpl(MethodImplOptions.NoInlining)]
		[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
		internal static void Set(ItemCartCannonMain instance, int state)
		{
			throw new NotSupportedException("Harmony reverse patch was not installed.");
		}
	}
	[HarmonyPatch(typeof(ItemMine), "Start")]
	internal static class WarningMineStartPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ItemMine __instance)
		{
			if ((Object)(object)((Component)__instance).GetComponent<MineWarningCarrier>() != (Object)null)
			{
				((Behaviour)__instance).enabled = false;
			}
		}
	}
	[HarmonyPatch(typeof(ItemMine), "StateSetRPC")]
	internal static class WarningMineStatePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemMine __instance, int newState)
		{
			if (MineWarningCarrier.IsWarning((Component)(object)__instance))
			{
				return newState == 1;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ItemMine), "StateSet")]
	internal static class WarningMineTransitionPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemMine __instance)
		{
			return !MineWarningCarrier.IsWarning((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(ItemMine), "DestroyMine")]
	internal static class WarningMineDestroyPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemMine __instance)
		{
			return !MineWarningCarrier.IsWarning((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(ItemMine), "TriggeredRPC")]
	internal static class WarningMineTriggerPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemMine __instance)
		{
			return !MineWarningCarrier.IsWarning((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(ItemMineExplosive), "OnTriggered")]
	internal static class WarningMineExplosionPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemMineExplosive __instance)
		{
			return !MineWarningCarrier.IsWarning((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(ItemMine), "StateArming")]
	internal static class VanillaMineArming
	{
		[MethodImpl(MethodImplOptions.NoInlining)]
		[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
		internal static void Tick(ItemMine instance)
		{
			throw new NotSupportedException("Harmony reverse patch was not installed.");
		}
	}
	[HarmonyPatch(typeof(ItemCartCannonMain), "Start")]
	internal static class WeaponStartPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ItemCartCannonMain __instance)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && ((Object)(object)((Component)__instance).GetComponent<ItemCartCannon>() != (Object)null || (Object)(object)((Component)__instance).GetComponent<ItemCartLaser>() != (Object)null) && (Object)(object)((Component)__instance).GetComponent<TurretController>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<TurretController>().Initialize(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(ItemCartCannonMain), "Update")]
	internal static class WeaponUpdatePatch
	{
		[HarmonyPrefix]
		private static void Prefix(ItemCartCannonMain __instance)
		{
			((Component)__instance).GetComponent<TurretController>()?.BeforeWeaponUpdate();
		}
	}
	[HarmonyPatch(typeof(ItemCartCannonMain), "GrabLogic")]
	internal static class WeaponGrabPatch
	{
		[HarmonyPrefix]
		private static void Prefix(ItemCartCannonMain __instance)
		{
			TurretController component = ((Component)__instance).GetComponent<TurretController>();
			try
			{
				component?.BeforeVanillaGrab();
			}
			catch (Exception exception)
			{
				component?.DisableAutomation(exception);
			}
		}
	}
	[HarmonyPatch(typeof(ItemCartCannonMain), "StateSet")]
	internal static class WeaponShotGatePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemCartCannonMain __instance, int state)
		{
			if (state != 3 || !SemiFunc.IsMasterClientOrSingleplayer())
			{
				return true;
			}
			TurretController component = ((Component)__instance).GetComponent<TurretController>();
			if (!((Object)(object)component == (Object)null))
			{
				return component.PrepareAutomaticShot();
			}
			return true;
		}
	}
}