Decompiled source of FairAI v1.5.8

FairAI.dll

Decompiled 21 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using FairAI;
using FairAI.Component;
using FairAI.Patches;
using GameNetcodeStuff;
using HarmonyLib;
using LethalThings;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("FairAI")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FairAI")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("42deea12-f73e-4d63-81e9-5359e98c8d53")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal class TurretAIPatch
{
	private readonly struct TurretTarget
	{
		public readonly PlayerControllerB Player;

		public readonly EnemyAI Enemy;

		public static readonly TurretTarget None = default(TurretTarget);

		public bool IsPlayer => (Object)(object)Player != (Object)null;

		public bool IsEnemy => (Object)(object)Enemy != (Object)null;

		public bool IsValid => IsPlayer || IsEnemy;

		public bool IsDead => (IsPlayer && Player.isPlayerDead) || (IsEnemy && (Enemy.isEnemyDead || Enemy.enemyHP <= 0));

		public Vector3 AimPosition => IsPlayer ? ((Component)Player.gameplayCamera).transform.position : (((Component)Enemy).transform.position + Vector3.up * 0.5f);

		public Transform AimTransform => IsPlayer ? ((Component)Player.gameplayCamera).transform : ((Component)Enemy).transform;

		public TurretTarget(PlayerControllerB p)
		{
			Player = p;
			Enemy = null;
		}

		public TurretTarget(EnemyAI e)
		{
			Player = null;
			Enemy = e;
		}
	}

	private const float DetectRange = 30f;

	private const int SweepRays = 7;

	private static readonly Type TurretType = typeof(Turret);

	private static bool HasCustomSettings => Plugin.turretSettings.Count > 7;

	private static float FireInterval => HasCustomSettings ? Setting(1) : 0.21f;

	private static float SwitchInterval => HasCustomSettings ? Setting(3) : 7f;

	private static float DetectSpeed => HasCustomSettings ? Setting(5) : 28f;

	private static float ChargeSpeed => HasCustomSettings ? Setting(6) : 95f;

	private static float BerserkSpeed => HasCustomSettings ? Setting(7) : 77f;

	private static int PlayerDamage => HasCustomSettings ? ((int)Setting(0)) : Plugin.GetInt("TurretConfig", "Player Damage");

	private static T GetField<T>(Turret t, string name)
	{
		return (T)TurretType.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(t);
	}

	private static void SetField(Turret t, string name, object value)
	{
		TurretType.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic).SetValue(t, value);
	}

	private static void CallMethod(Turret t, string name, params object[] args)
	{
		TurretType.GetMethod(name, BindingFlags.Instance | BindingFlags.NonPublic).Invoke(t, args);
	}

	private static float Setting(int index)
	{
		return Plugin.turretSettings[index];
	}

	private static FAIR_AI GetAI(Turret turret)
	{
		return ((Component)turret).gameObject.GetComponent<FAIR_AI>() ?? ((Component)turret).gameObject.AddComponent<FAIR_AI>();
	}

	private static TurretTarget GetCurrentTarget(Turret turret, FAIR_AI ai)
	{
		if ((Object)(object)ai.targetWithRotation != (Object)null && !ai.targetWithRotation.isEnemyDead)
		{
			return new TurretTarget(ai.targetWithRotation);
		}
		if ((Object)(object)turret.targetPlayerWithRotation != (Object)null && !turret.targetPlayerWithRotation.isPlayerDead)
		{
			return new TurretTarget(turret.targetPlayerWithRotation);
		}
		return TurretTarget.None;
	}

	private static void SetCurrentTarget(Turret turret, FAIR_AI ai, TurretTarget target)
	{
		turret.targetPlayerWithRotation = null;
		ai.targetWithRotation = null;
		if (target.IsPlayer)
		{
			turret.targetPlayerWithRotation = target.Player;
		}
		else if (target.IsEnemy)
		{
			ai.targetWithRotation = target.Enemy;
			turret.targetTransform = ((Component)target.Enemy).transform;
		}
	}

	private static void ClearTarget(Turret turret, FAIR_AI ai)
	{
		turret.targetPlayerWithRotation = null;
		ai.targetWithRotation = null;
		turret.targetTransform = null;
		ai.targetWithRotation = null;
		if (((NetworkBehaviour)turret).IsServer)
		{
			turret.RemoveTargetedPlayerClientRpc();
			ai.RemoveTargetedEnemyClientRpc();
		}
	}

	public static bool PatchUpdate(ref Turret __instance)
	{
		//IL_0012: 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_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Invalid comparison between Unknown and I4
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Expected I4, but got Unknown
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)__instance == (Object)null || !Plugin.AllowFairness(((Component)__instance).transform.position))
		{
			return false;
		}
		Turret val = __instance;
		FAIR_AI aI = GetAI(val);
		if (!val.turretActive)
		{
			SetField(val, "wasTargetingPlayerLastFrame", false);
			val.turretMode = (TurretMode)0;
			ClearTarget(val, aI);
			return false;
		}
		TurretTarget currentTarget = GetCurrentTarget(val, aI);
		if (currentTarget.IsValid && !currentTarget.IsDead)
		{
			if (!GetField<bool>(val, "wasTargetingPlayerLastFrame"))
			{
				SetField(val, "wasTargetingPlayerLastFrame", true);
				if ((int)val.turretMode == 0)
				{
					val.turretMode = (TurretMode)1;
				}
			}
			SyncTargetTransform(val, aI, currentTarget);
		}
		else if (currentTarget.IsDead)
		{
			ClearTarget(val, aI);
			SetField(val, "wasTargetingPlayerLastFrame", false);
			val.turretMode = (TurretMode)0;
		}
		else if (GetField<bool>(val, "wasTargetingPlayerLastFrame"))
		{
			SetField(val, "wasTargetingPlayerLastFrame", false);
			val.turretMode = (TurretMode)0;
		}
		TurretMode turretMode = val.turretMode;
		TurretMode val2 = turretMode;
		switch ((int)val2)
		{
		case 0:
			DetectionFunction(val, aI);
			break;
		case 1:
			ChargingFunction(val, aI);
			break;
		case 2:
			FiringFunction(val, aI);
			break;
		case 3:
			BerserkFunction(val);
			break;
		}
		if (GetField<bool>(val, "rotatingClockwise"))
		{
			val.turnTowardsObjectCompass.localEulerAngles = new Vector3(-180f, val.turretRod.localEulerAngles.y - Time.deltaTime * 20f, 180f);
		}
		else if (GetField<bool>(val, "rotatingSmoothly"))
		{
			val.turnTowardsObjectCompass.localEulerAngles = new Vector3(-180f, Mathf.Clamp(val.targetRotation, 0f - val.rotationRange, val.rotationRange), 180f);
		}
		val.turretRod.rotation = Quaternion.RotateTowards(val.turretRod.rotation, val.turnTowardsObjectCompass.rotation, val.rotationSpeed * Time.deltaTime);
		return false;
	}

	private static void DetectionFunction(Turret turret, FAIR_AI ai)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Invalid comparison between Unknown and I4
		//IL_028d: Unknown result type (might be due to invalid IL or missing references)
		if ((int)GetField<TurretMode>(turret, "turretModeLastFrame") > 0)
		{
			SetField(turret, "turretModeLastFrame", (object)(TurretMode)0);
			SetField(turret, "rotatingClockwise", false);
			SetField(turret, "rotatingSmoothly", true);
			SetField(turret, "turretInterval", Random.Range(0f, 0.15f));
			turret.mainAudio.Stop();
			turret.farAudio.Stop();
			turret.berserkAudio.Stop();
			StopAndStartFadeBulletAudio(turret);
			turret.bulletParticles.Stop(true, (ParticleSystemStopBehavior)0);
			turret.rotationSpeed = DetectSpeed;
			turret.turretAnimator.SetInteger("TurretMode", 0);
		}
		if (!((NetworkBehaviour)turret).IsServer)
		{
			return;
		}
		float field = GetField<float>(turret, "switchRotationTimer");
		if (field >= SwitchInterval)
		{
			SetField(turret, "switchRotationTimer", 0f);
			bool flag = !GetField<bool>(turret, "rotatingRight");
			turret.SwitchRotationClientRpc(flag);
			turret.SwitchRotationOnInterval(flag);
		}
		else
		{
			SetField(turret, "switchRotationTimer", field + Time.deltaTime);
		}
		float field2 = GetField<float>(turret, "turretInterval");
		if (field2 < 0.25f)
		{
			SetField(turret, "turretInterval", field2 + Time.deltaTime);
			return;
		}
		SetField(turret, "turretInterval", 0f);
		TurretTarget target = FindBestTarget(turret, angleRangeCheck: true);
		if (target.IsValid && (!target.IsEnemy || Plugin.CanMob("TurretTargetAllMobs", ".Turret Target", target.Enemy.enemyType.enemyName)))
		{
			SetCurrentTarget(turret, ai, target);
			if (target.IsEnemy)
			{
				ai.SwitchedTargetedEnemyClientRpc(turret, target.Enemy);
				Plugin.logger.LogInfo((object)("Turret: Detected enemy '" + target.Enemy.enemyType.enemyName + "', entering charging mode."));
			}
			else
			{
				turret.SwitchTargetedPlayerClientRpc((int)target.Player.playerClientId, true);
				Plugin.logger.LogInfo((object)"Turret: Detected player, entering charging mode.");
			}
			CallMethod(turret, "SwitchTurretMode", (object)(TurretMode)1);
			turret.SetToModeClientRpc(1);
			turret.turretMode = (TurretMode)1;
		}
	}

	private static void ChargingFunction(Turret turret, FAIR_AI ai)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Invalid comparison between Unknown and I4
		if ((int)GetField<TurretMode>(turret, "turretModeLastFrame") != 1)
		{
			SetField(turret, "turretModeLastFrame", (object)(TurretMode)1);
			SetField(turret, "rotatingClockwise", false);
			SetField(turret, "rotatingSmoothly", false);
			SetField(turret, "lostLOSTimer", 0f);
			turret.mainAudio.PlayOneShot(turret.detectPlayerSFX);
			WalkieTalkie.TransmitOneShotAudio(turret.mainAudio, turret.detectPlayerSFX, 1f);
			turret.berserkAudio.Stop();
			turret.rotationSpeed = ChargeSpeed;
			turret.turretAnimator.SetInteger("TurretMode", 1);
		}
		TurnTowardsTarget(turret, ai);
		if (!((NetworkBehaviour)turret).IsServer)
		{
			return;
		}
		float field = GetField<float>(turret, "turretInterval");
		if (field < 1.5f)
		{
			SetField(turret, "turretInterval", field + Time.deltaTime);
			return;
		}
		SetField(turret, "turretInterval", 0f);
		TurretTarget target = FindBestTarget(turret, angleRangeCheck: false);
		if (!target.IsValid)
		{
			Plugin.logger.LogInfo((object)"Turret: Lost LOS during charge wind-up, returning to detection.");
			ClearTarget(turret, ai);
			return;
		}
		if (target.IsEnemy && !Plugin.CanMob("TurretTargetAllMobs", ".Turret Target", target.Enemy.enemyType.enemyName))
		{
			ClearTarget(turret, ai);
			return;
		}
		SetCurrentTarget(turret, ai, target);
		Plugin.logger.LogInfo((object)"Turret: Charge complete, opening fire.");
		CallMethod(turret, "SwitchTurretMode", (object)(TurretMode)2);
		turret.SetToModeClientRpc(2);
	}

	private static void FiringFunction(Turret turret, FAIR_AI ai)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Invalid comparison between Unknown and I4
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		if ((int)GetField<TurretMode>(turret, "turretModeLastFrame") != 2)
		{
			SetField(turret, "turretModeLastFrame", (object)(TurretMode)2);
			SetField(turret, "rotatingSmoothly", false);
			SetField(turret, "lostLOSTimer", 0f);
			turret.berserkAudio.Stop();
			RoundManager.Instance.PlayAudibleNoise(((Component)turret.berserkAudio).transform.position, 15f, 0.9f, 0, false, 0);
			turret.mainAudio.clip = turret.firingSFX;
			turret.mainAudio.Play();
			turret.farAudio.clip = turret.firingFarSFX;
			turret.farAudio.Play();
			turret.bulletParticles.Play(true);
			turret.bulletCollisionAudio.Play();
			StopAndStartFadeBulletAudio(turret);
			turret.bulletCollisionAudio.volume = 1f;
			turret.turretAnimator.SetInteger("TurretMode", 2);
		}
		TurnTowardsTarget(turret, ai);
		if (!GetField<bool>(turret, "hasLineOfSight"))
		{
			if (!((NetworkBehaviour)turret).IsServer)
			{
				return;
			}
			float num = GetField<float>(turret, "lostLOSTimer") + Time.deltaTime;
			SetField(turret, "lostLOSTimer", num);
			if (num >= 2f)
			{
				SetField(turret, "lostLOSTimer", 0f);
				TurretTarget target = FindBestTarget(turret, angleRangeCheck: false);
				if (target.IsValid && (!target.IsEnemy || Plugin.CanMob("TurretTargetAllMobs", ".Turret Target", target.Enemy.enemyType.enemyName)))
				{
					Plugin.logger.LogInfo((object)"Turret: Re-acquired target after LOS loss.");
					SetCurrentTarget(turret, ai, target);
					SetField(turret, "turretInterval", 0f);
				}
				else
				{
					Plugin.logger.LogInfo((object)"Turret: LOS lost for 2 s, no replacement — returning to detection.");
					ReturnToDetection(turret, ai);
				}
			}
			return;
		}
		SetField(turret, "lostLOSTimer", 0f);
		float field = GetField<float>(turret, "turretInterval");
		if (field < FireInterval)
		{
			SetField(turret, "turretInterval", field + Time.deltaTime);
			return;
		}
		SetField(turret, "turretInterval", 0f);
		ApplyDamageToLocalPlayer(turret);
		PerformShootRaycast(turret, useCenterPoint: false);
		TurretTarget currentTarget = GetCurrentTarget(turret, ai);
		if (!currentTarget.IsValid || currentTarget.IsDead)
		{
			TurretTarget target2 = FindBestTarget(turret, angleRangeCheck: false);
			if (target2.IsValid && (!target2.IsEnemy || Plugin.CanMob("TurretTargetAllMobs", ".Turret Target", target2.Enemy.enemyType.enemyName)))
			{
				Plugin.logger.LogInfo((object)"Turret: Target died, acquired new target.");
				SetCurrentTarget(turret, ai, target2);
			}
			else
			{
				Plugin.logger.LogInfo((object)"Turret: Target died, no new targets — returning to detection.");
				ReturnToDetection(turret, ai);
			}
		}
	}

	private static void BerserkFunction(Turret turret)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Invalid comparison between Unknown and I4
		if ((int)GetField<TurretMode>(turret, "turretModeLastFrame") != 3)
		{
			SetField(turret, "turretModeLastFrame", (object)(TurretMode)3);
			SetField(turret, "rotatingClockwise", false);
			SetField(turret, "rotatingSmoothly", true);
			SetField(turret, "lostLOSTimer", 0f);
			SetField(turret, "wasTargetingPlayerLastFrame", false);
			SetField(turret, "berserkTimer", 1.3f);
			SetField(turret, "enteringBerserkMode", true);
			turret.targetPlayerWithRotation = null;
			turret.rotationSpeed = BerserkSpeed;
			turret.berserkAudio.Play();
			turret.turretAnimator.SetInteger("TurretMode", 1);
		}
		if (GetField<bool>(turret, "enteringBerserkMode"))
		{
			float num = GetField<float>(turret, "berserkTimer") - Time.deltaTime;
			SetField(turret, "berserkTimer", num);
			if (num <= 0f)
			{
				SetField(turret, "enteringBerserkMode", false);
				SetField(turret, "rotatingClockwise", true);
				SetField(turret, "berserkTimer", 9f);
				turret.turretAnimator.SetInteger("TurretMode", 2);
				turret.mainAudio.clip = turret.firingSFX;
				turret.mainAudio.Play();
				turret.farAudio.clip = turret.firingFarSFX;
				turret.farAudio.Play();
				turret.bulletParticles.Play(true);
				turret.bulletCollisionAudio.Play();
				StopAndStartFadeBulletAudio(turret);
				turret.bulletCollisionAudio.volume = 1f;
			}
			return;
		}
		float field = GetField<float>(turret, "turretInterval");
		if (field >= FireInterval)
		{
			SetField(turret, "turretInterval", 0f);
			ApplyDamageToLocalPlayer(turret);
			PerformShootRaycast(turret, useCenterPoint: true);
		}
		else
		{
			SetField(turret, "turretInterval", field + Time.deltaTime);
		}
		if (((NetworkBehaviour)turret).IsServer)
		{
			float num2 = GetField<float>(turret, "berserkTimer") - Time.deltaTime;
			SetField(turret, "berserkTimer", num2);
			if (num2 <= 0f)
			{
				CallMethod(turret, "SwitchTurretMode", 0);
				turret.SetToModeClientRpc(0);
			}
		}
	}

	private static TurretTarget FindBestTarget(Turret turret, bool angleRangeCheck)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		EnemyAI val = SweepForEnemy(turret);
		if ((Object)(object)val != (Object)null && !val.isEnemyDead && (!angleRangeCheck || WithinAngleRange(turret, ((Component)val).transform.position + Vector3.up * 0.5f)))
		{
			return new TurretTarget(val);
		}
		PlayerControllerB val2 = SweepForPlayer(turret, angleRangeCheck);
		if ((Object)(object)val2 != (Object)null && !val2.isPlayerDead)
		{
			return new TurretTarget(val2);
		}
		return TurretTarget.None;
	}

	private static EnemyAI SweepForEnemy(Turret turret)
	{
		//IL_0014: 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_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: 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_004d: 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_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		float rotationRange = turret.rotationRange;
		Vector3 val = Quaternion.Euler(0f, 0f - rotationRange, 0f) * turret.aimPoint.forward;
		float num = rotationRange * 2f / 6f;
		Ray val2 = default(Ray);
		for (int i = 0; i < 7; i++)
		{
			((Ray)(ref val2))..ctor(turret.centerPoint.position, val);
			RaycastHit[] array = Physics.RaycastAll(val2, 30f, -5, (QueryTriggerInteraction)2);
			Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
			RaycastHit[] array2 = array;
			for (int j = 0; j < array2.Length; j++)
			{
				RaycastHit val3 = array2[j];
				if (Physics.Linecast(turret.centerPoint.position, ((RaycastHit)(ref val3)).point, StartOfRound.Instance.collidersAndRoomMask, (QueryTriggerInteraction)1))
				{
					break;
				}
				EnemyAI val4 = ((Component)((RaycastHit)(ref val3)).transform).GetComponent<EnemyAI>() ?? ((Component)((RaycastHit)(ref val3)).transform).GetComponent<EnemyAICollisionDetect>()?.mainScript;
				if ((Object)(object)val4 != (Object)null && !val4.isEnemyDead && val4.enemyHP > 0)
				{
					return val4;
				}
			}
			val = Quaternion.Euler(0f, num, 0f) * val;
		}
		return null;
	}

	private static PlayerControllerB SweepForPlayer(Turret turret, bool angleRangeCheck)
	{
		//IL_0014: 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_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: 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_004d: 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_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: 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)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Invalid comparison between Unknown and I4
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Invalid comparison between Unknown and I4
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		float rotationRange = turret.rotationRange;
		Vector3 val = Quaternion.Euler(0f, 0f - rotationRange, 0f) * turret.aimPoint.forward;
		float num = rotationRange * 2f / 6f;
		Ray val2 = default(Ray);
		RaycastHit val3 = default(RaycastHit);
		for (int i = 0; i < 7; i++)
		{
			((Ray)(ref val2))..ctor(turret.centerPoint.position, val);
			if (Physics.Raycast(val2, ref val3, 30f, 1051400, (QueryTriggerInteraction)1))
			{
				if (((Component)((RaycastHit)(ref val3)).transform).CompareTag("Player"))
				{
					PlayerControllerB component = ((Component)((RaycastHit)(ref val3)).transform).GetComponent<PlayerControllerB>();
					if ((Object)(object)component != (Object)null)
					{
						if (angleRangeCheck && !WithinAngleRange(turret, ((Component)component).transform.position + Vector3.up * 1.75f))
						{
							return null;
						}
						return component;
					}
				}
				else if (((int)turret.turretMode == 2 || (int)turret.turretMode == 3) && !GetField<bool>(turret, "enteringBerserkMode") && ((Component)((RaycastHit)(ref val3)).transform).tag.StartsWith("PlayerRagdoll"))
				{
					Rigidbody component2 = ((Component)((RaycastHit)(ref val3)).transform).GetComponent<Rigidbody>();
					if (component2 != null)
					{
						component2.AddForce(((Vector3)(ref val)).normalized * 42f, (ForceMode)1);
					}
				}
			}
			val = Quaternion.Euler(0f, num, 0f) * val;
		}
		return null;
	}

	private static bool WithinAngleRange(Turret turret, Vector3 worldPos)
	{
		//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_0017: Unknown result type (might be due to invalid IL or missing references)
		return Vector3.Angle(worldPos - turret.centerPoint.position, turret.forwardFacingPos.forward) <= turret.rotationRange;
	}

	private static void TurnTowardsTarget(Turret turret, FAIR_AI ai)
	{
		//IL_0043: 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_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		TurretTarget currentTarget = GetCurrentTarget(turret, ai);
		if (currentTarget.IsValid && !currentTarget.IsDead)
		{
			SyncTargetTransform(turret, ai, currentTarget);
			bool flag = (Object)(object)turret.targetTransform != (Object)null && WithinAngleRange(turret, turret.targetTransform.position) && !Physics.Linecast(turret.aimPoint.position, currentTarget.AimPosition, StartOfRound.Instance.collidersAndRoomMask, (QueryTriggerInteraction)1);
			SetField(turret, "hasLineOfSight", flag);
			if (flag)
			{
				turret.tempTransform.position = currentTarget.AimPosition - Vector3.up * 0.15f;
				turret.turnTowardsObjectCompass.LookAt(turret.tempTransform);
			}
		}
	}

	private static void SyncTargetTransform(Turret turret, FAIR_AI ai, TurretTarget target)
	{
		if (target.IsPlayer)
		{
			turret.targetTransform = ((target.Player.isPlayerDead && (Object)(object)target.Player.deadBody != (Object)null) ? ((Component)target.Player.deadBody.bodyParts[5]).transform : ((Component)target.Player.gameplayCamera).transform);
		}
		else if (target.IsEnemy)
		{
			turret.targetTransform = ((Component)target.Enemy).transform;
		}
	}

	private static void ApplyDamageToLocalPlayer(Turret turret)
	{
		//IL_0031: 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_0046: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: 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_012d: 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: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
		if ((Object)(object)localPlayerController == (Object)null || localPlayerController.isPlayerDead)
		{
			return;
		}
		Ray val = default(Ray);
		((Ray)(ref val))..ctor(turret.centerPoint.position, turret.aimPoint.forward);
		RaycastHit val2 = default(RaycastHit);
		if (Physics.Raycast(val, ref val2, 30f, 1051400, (QueryTriggerInteraction)1) && ((Component)((RaycastHit)(ref val2)).transform).CompareTag("Player") && !((Object)(object)((Component)((RaycastHit)(ref val2)).transform).GetComponent<PlayerControllerB>() != (Object)(object)localPlayerController))
		{
			int playerDamage = PlayerDamage;
			if (playerDamage <= 0)
			{
				localPlayerController.MakeCriticallyInjured(false);
				localPlayerController.DamagePlayer(playerDamage, false, true, (CauseOfDeath)0, 0, false, default(Vector3));
				localPlayerController.MakeCriticallyInjured(false);
			}
			else if (localPlayerController.health > playerDamage)
			{
				localPlayerController.DamagePlayer(playerDamage, true, true, (CauseOfDeath)7, 0, false, default(Vector3));
			}
			else
			{
				localPlayerController.KillPlayer(turret.aimPoint.forward * 40f, true, (CauseOfDeath)7, 0, default(Vector3), false);
			}
		}
	}

	private static void PerformShootRaycast(Turret turret, bool useCenterPoint)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: 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_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		Ray val = default(Ray);
		((Ray)(ref val))..ctor(turret.aimPoint.position, turret.aimPoint.forward);
		SetField(turret, "shootRay", val);
		RaycastHit val2 = default(RaycastHit);
		if (Physics.Raycast(val, ref val2, 30f, StartOfRound.Instance.collidersAndRoomMask, (QueryTriggerInteraction)1))
		{
			SetField(turret, "hit", val2);
			((Component)turret.bulletCollisionAudio).transform.position = ((Ray)(ref val)).GetPoint(((RaycastHit)(ref val2)).distance - 0.5f);
		}
		Vector3 aimPoint = (useCenterPoint ? turret.centerPoint.position : turret.aimPoint.position);
		Vector3 forward = Quaternion.Euler(0f, (float)(-(int)turret.rotationRange) / 3f, 0f) * turret.aimPoint.forward;
		Plugin.AttackTargets(((Component)turret).GetComponent<FAIR_AI>(), aimPoint, forward, 30f);
	}

	private static void ReturnToDetection(Turret turret, FAIR_AI ai)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		ClearTarget(turret, ai);
		turret.turretMode = (TurretMode)0;
		turret.SetToModeClientRpc(0);
		SetField(turret, "wasTargetingPlayerLastFrame", false);
		SetField(turret, "targetingDeadPlayer", true);
		turret.turretAnimator.SetInteger("TurretMode", 0);
		CallMethod(turret, "SwitchTurretMode", (object)(TurretMode)0);
	}

	public static bool CheckForTargetsInLOS(ref Turret __instance, float radius = 2f, bool angleRangeCheck = false)
	{
		FAIR_AI aI = GetAI(__instance);
		TurretTarget turretTarget = FindBestTarget(__instance, angleRangeCheck);
		if (!turretTarget.IsValid)
		{
			return false;
		}
		aI.targets = new Dictionary<int, GameObject> { 
		{
			0,
			turretTarget.IsPlayer ? ((Component)turretTarget.Player).gameObject : ((Component)turretTarget.Enemy).gameObject
		} };
		return true;
	}

	public static bool SetTargetToEnemyBody(ref Turret __instance)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return false;
		}
		FAIR_AI aI = GetAI(__instance);
		SyncTargetTransform(__instance, aI, GetCurrentTarget(__instance, aI));
		return false;
	}

	public static bool TurnTowardsTargetEnemyIfHasLOS(ref Turret __instance)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return false;
		}
		TurnTowardsTarget(__instance, GetAI(__instance));
		return false;
	}

	private static void StopAndStartFadeBulletAudio(Turret turret)
	{
		FieldInfo field = TurretType.GetField("fadeBulletAudioCoroutine", BindingFlags.Instance | BindingFlags.NonPublic);
		object? obj = field?.GetValue(turret);
		Coroutine val = (Coroutine)((obj is Coroutine) ? obj : null);
		if (val != null)
		{
			((MonoBehaviour)turret).StopCoroutine(val);
		}
		MethodInfo method = TurretType.GetMethod("FadeBulletAudio", BindingFlags.Instance | BindingFlags.NonPublic);
		field?.SetValue(turret, ((MonoBehaviour)turret).StartCoroutine((IEnumerator)method.Invoke(turret, null)));
	}
}
namespace FairAI
{
	public class FAIR_AI : NetworkBehaviour
	{
		public EnemyAI targetWithRotation;

		public Dictionary<int, GameObject> targets;

		private void Awake()
		{
			targetWithRotation = null;
		}

		[ClientRpc]
		public void SwitchedTargetedEnemyClientRpc(Turret turret, EnemyAI enemy, bool setModeToCharging = false)
		{
			targetWithRotation = enemy;
			if (setModeToCharging)
			{
				Type typeFromHandle = typeof(Turret);
				MethodInfo method = typeFromHandle.GetMethod("SwitchTurretMode", BindingFlags.Instance | BindingFlags.NonPublic);
				method.Invoke(turret, new object[1] { 2 });
			}
		}

		[ClientRpc]
		public void RemoveTargetedEnemyClientRpc()
		{
			targetWithRotation = null;
		}
	}
	[BepInPlugin("GoldenKitten.FairAI", "Fair AI", "1.5.8")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private const string modGUID = "GoldenKitten.FairAI";

		private const string modName = "Fair AI";

		private const string modVersion = "1.5.8";

		private Harmony harmony = new Harmony("GoldenKitten.FairAI");

		private static readonly float onMeshThreshold = 3f;

		public static Plugin Instance = null;

		public static ManualLogSource logger;

		public static List<EnemyType> allEnemies;

		public static List<EnemyType> enemies;

		public static List<Item> items;

		public static List<EnemyType> enemyList;

		public static List<Item> itemList;

		public static List<float> turretSettings;

		public static Dictionary<string, float[]> speeds;

		public static Dictionary<int, Vector3> positions;

		public static Dictionary<int, float> sinkingValues;

		public static Dictionary<int, float> sinkingProgress;

		public static Assembly codeRebirthAssembly;

		public static Assembly lethalConfigAssembly;

		public static Assembly lguAssembly;

		public static Assembly surfacedAssembly;

		public static Assembly turretSettingsAssembly;

		public static Type rubberBootsType;

		public static PropertyInfo tsBoundConfig;

		public const string ltModID = "evaisa.lethalthings";

		public const string surfacedModID = "Surfaced";

		public static bool codeRebirthEnabled = false;

		public static bool lethalConfigEnabled = false;

		public static bool lethalThingsEnabled = false;

		public static bool lguEnabled = false;

		public static bool playersEnteredInside = false;

		public static bool roundHasStarted = false;

		public static bool surfacedEnabled = false;

		public static bool turretSettingsEnabled = false;

		public static int wallsAndEnemyLayerMask = 524288;

		public static int enemyMask = 524288;

		public static int allHittablesMask;

		private async void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			logger = Logger.CreateLogSource("GoldenKitten.FairAI");
			allEnemies = new List<EnemyType>();
			enemies = new List<EnemyType>();
			items = new List<Item>();
			itemList = new List<Item>();
			enemyList = new List<EnemyType>();
			speeds = new Dictionary<string, float[]>();
			positions = new Dictionary<int, Vector3>();
			sinkingProgress = new Dictionary<int, float>();
			turretSettings = new List<float>();
			sinkingValues = new Dictionary<int, float>();
			harmony = new Harmony("GoldenKitten.FairAI");
			harmony.PatchAll(typeof(Plugin));
			Patch(typeof(RoundManager), "Start", null, typeof(RoundManagerPatch), "PatchStart", isPrefix: false);
			Patch(typeof(StartOfRound), "Awake", null, typeof(LevelGenManPatch), "PatchAwake", isPrefix: false);
			Patch(typeof(StartOfRound), "Start", null, typeof(StartOfRoundPatch), "PatchStart", isPrefix: false);
			Patch(typeof(StartOfRound), "Update", null, typeof(StartOfRoundPatch), "PatchUpdate", isPrefix: false);
			Patch(typeof(FlowermanAI), "HitEnemy", new Type[4]
			{
				typeof(int),
				typeof(PlayerControllerB),
				typeof(bool),
				typeof(int)
			}, typeof(EnemyAIPatch), "BrackenHitEnemyPatch", isPrefix: true);
			Patch(typeof(HoarderBugAI), "HitEnemy", new Type[4]
			{
				typeof(int),
				typeof(PlayerControllerB),
				typeof(bool),
				typeof(int)
			}, typeof(EnemyAIPatch), "HoardingBugHitEnemyPatch", isPrefix: true);
			Patch(typeof(EnemyAI), "KillEnemyOnOwnerClient", new Type[1] { typeof(bool) }, typeof(EnemyAIPatch), "KillEnemyOnOwnerClientPatch", isPrefix: false);
			Patch(typeof(QuicksandTrigger), "OnTriggerStay", new Type[1] { typeof(Collider) }, typeof(QuickSandPatch), "OnTriggerStayPatch", isPrefix: true);
			Patch(typeof(QuicksandTrigger), "StopSinkingLocalPlayer", new Type[1] { typeof(PlayerControllerB) }, typeof(QuickSandPatch), "StopSinkingLocalPlayerPatch", isPrefix: true);
			Patch(typeof(QuicksandTrigger), "OnTriggerExit", new Type[1] { typeof(Collider) }, typeof(QuickSandPatch), "OnTriggerExitPatch", isPrefix: true);
			Patch(typeof(Turret), "Update", null, typeof(TurretAIPatch), "PatchUpdate", isPrefix: true);
			Patch(typeof(Turret), "CheckForPlayersInLineOfSight", new Type[2]
			{
				typeof(float),
				typeof(bool)
			}, typeof(TurretAIPatch), "CheckForTargetsInLOS", isPrefix: true);
			Patch(typeof(Turret), "SetTargetToPlayerBody", null, typeof(TurretAIPatch), "SetTargetToEnemyBody", isPrefix: true);
			Patch(typeof(Turret), "TurnTowardsTargetIfHasLOS", null, typeof(TurretAIPatch), "TurnTowardsTargetEnemyIfHasLOS", isPrefix: true);
			Patch(typeof(Landmine), "SpawnExplosion", new Type[8]
			{
				typeof(Vector3),
				typeof(bool),
				typeof(float),
				typeof(float),
				typeof(int),
				typeof(float),
				typeof(GameObject),
				typeof(bool)
			}, typeof(MineAIPatch), "PatchSpawnExplosion", isPrefix: false);
			Patch(typeof(Landmine), "OnTriggerEnter", null, typeof(MineAIPatch), "PatchOnTriggerEnter", isPrefix: false);
			Patch(typeof(Landmine), "OnTriggerExit", null, typeof(MineAIPatch), "PatchOnTriggerExit", isPrefix: false);
			Patch(typeof(Landmine), "Detonate", null, typeof(MineAIPatch), "DetonatePatch", isPrefix: false);
			await WaitForProcess(1);
			GetTurretSettings();
			logger.LogInfo((object)"Fair AI initiated!");
		}

		private void Patch(Type type, string method, Type[] parameters, Type patchType, string patchMethod, bool isPrefix)
		{
			CreateHarmonyPatch(harmony, type, method, parameters, patchType, patchMethod, isPrefix);
		}

		public static void ImmortalAffected()
		{
			if (!GetBool("General", "ImmortalAffected"))
			{
				enemies = (from EnemyType e in Resources.FindObjectsOfTypeAll(typeof(EnemyType))
					where (Object)(object)e != (Object)null && e.canDie
					select e).ToList();
			}
			allEnemies = (from EnemyType e in Resources.FindObjectsOfTypeAll(typeof(EnemyType))
				where (Object)(object)e != (Object)null
				select e).ToList();
		}

		public static float[] SpeedAndAccelerationEnemyList(EnemyAICollisionDetect enemy)
		{
			if ((Object)(object)enemy?.mainScript?.enemyType == (Object)null)
			{
				logger.LogWarning((object)"No valid enemy to get speeds!");
				return new float[2] { 1f, 1f };
			}
			string key = RemoveInvalidCharacters(enemy.mainScript.enemyType.enemyName);
			if (speeds.TryGetValue(key, out var value))
			{
				return value;
			}
			NavMeshAgent componentInChildren = ((Component)enemy.mainScript).GetComponentInChildren<NavMeshAgent>();
			float[] array = ((!((Object)(object)componentInChildren != (Object)null)) ? new float[2] { 1f, 1f } : new float[2] { componentInChildren.speed, componentInChildren.acceleration });
			speeds[key] = array;
			return array;
		}

		public static float[] GetSpeeds(string name)
		{
			if (speeds.TryGetValue(name, out var value))
			{
				return value;
			}
			logger.LogWarning((object)("Speeds missing on: " + name));
			return null;
		}

		public static void GetTurretSettings()
		{
			if (!turretSettingsEnabled)
			{
				turretSettings = new List<float>(8) { 50f, 0.21f, 0f, 7f, 0f, 28f, 95f, 77f };
				return;
			}
			object value = tsBoundConfig.GetValue(null);
			if (value == null)
			{
				logger.LogInfo((object)"Unable to get BoundConfig");
				return;
			}
			Type type = value.GetType();
			turretSettings.Clear();
			string[] array = new string[8] { "turretDamage", "turretFireRate", "turretWarmupTime", "turretRotateTimer", "turretRotationRange", "turretIdleRotationSpeed", "turretFiringRotationSpeed", "turretBerzerkRotationSpeed" };
			string[] array2 = array;
			foreach (string name in array2)
			{
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public);
				if (!(field == null))
				{
					object value2 = field.GetValue(value);
					PropertyInfo propertyInfo = value2?.GetType().GetProperty("Value");
					if (!(propertyInfo == null))
					{
						object value3 = propertyInfo.GetValue(value2);
						turretSettings.Add((value3 is int num) ? ((float)num) : ((float)value3));
					}
				}
			}
			logger.LogInfo((object)$"Got Turret Settings: {turretSettings.Count}");
		}

		public static async Task<IEnumerable<int>> WaitForProcess(int waitTime)
		{
			await Task.Delay(waitTime);
			await Instance.DelayedInitialization();
			return Array.Empty<int>();
		}

		private async Task DelayedInitialization()
		{
			await Task.Run(delegate
			{
				TryLoadCodeRebirth();
				TryLoadLategameUpgrades();
				TryLoadLethalConfig();
				TryLoadLethalThings();
				TryLoadSurfaced();
				TryLoadTurretSettings();
				logger.LogInfo((object)"Optional Components initiated!");
			});
		}

		private void TryLoadLethalThings()
		{
			TryLoadAssembly("LethalThings", ref lethalThingsEnabled, delegate(Assembly assembly)
			{
				Type type = assembly.GetType("LethalThings.RoombaAI");
				if (!(type == null) && BoombaPatch.enabled)
				{
					Patch(type, "Start", null, typeof(BoombaPatch), "PatchStart", isPrefix: false);
					Patch(type, "DoAIInterval", null, typeof(BoombaPatch), "PatchDoAIInterval", isPrefix: false);
					lethalThingsEnabled = true;
				}
			});
		}

		private void TryLoadSurfaced()
		{
			TryLoadAssembly("Surfaced", ref surfacedEnabled, delegate(Assembly assembly)
			{
				surfacedAssembly = assembly;
				if (SurfacedMinePatch.enabled)
				{
					Type type = assembly.GetType("Seamine");
					if (type != null)
					{
						Patch(type, "OnTriggerEnter", new Type[1] { typeof(Collider) }, typeof(SurfacedMinePatch), "PatchOnTriggerEnter", isPrefix: false);
						surfacedEnabled = true;
						logger.LogInfo((object)"Surfaced Component Seamine Initiated!");
					}
					Type type2 = assembly.GetType("Bertha");
					if (type2 != null)
					{
						Patch(type2, "OnTriggerEnter", new Type[1] { typeof(Collider) }, typeof(SurfacedMinePatch), "PatchBerthaOnTriggerEnter", isPrefix: false);
						surfacedEnabled = true;
						logger.LogInfo((object)"Surfaced Component Bertha Initiated!");
					}
				}
			});
		}

		private void TryLoadTurretSettings()
		{
			try
			{
				Assembly assembly = Assembly.Load("TheNameIsTyler.TurretSettings");
				if (!(assembly == null))
				{
					turretSettingsAssembly = assembly;
					PropertyInfo propertyInfo = assembly.GetType("TurretSettings.TurretSettings")?.GetProperty("BoundConfig", BindingFlags.Static | BindingFlags.NonPublic);
					if (propertyInfo != null)
					{
						tsBoundConfig = propertyInfo;
						turretSettingsEnabled = true;
						logger.LogInfo((object)"TurretSettings Component Initiated!");
					}
				}
			}
			catch (Exception e)
			{
				LogOptionalError("TurretSettings", e);
			}
		}

		private void TryLoadLategameUpgrades()
		{
			try
			{
				Assembly assembly = Assembly.Load("MoreShipUpgrades");
				if (!(assembly == null))
				{
					lguAssembly = assembly;
					Type type = assembly.GetType("MoreShipUpgrades.UpgradeComponents.TierUpgrades.Player.RubberBoots");
					if (type?.GetMethod("ReduceMovementHinderance") != null)
					{
						rubberBootsType = type;
						lguEnabled = true;
						logger.LogInfo((object)"LategameUpgrades Component Initiated!");
					}
				}
			}
			catch (Exception e)
			{
				LogOptionalError("LategameUpgrades", e);
			}
		}

		private void TryLoadLethalConfig()
		{
			TryLoadAssembly("LethalConfig", ref lethalConfigEnabled, delegate(Assembly assembly)
			{
				lethalConfigAssembly = assembly;
				if (assembly.GetType("LethalConfig.LethalConfigManager") != null)
				{
					lethalConfigEnabled = true;
					logger.LogInfo((object)"LethalConfig Component Initiated!");
				}
			});
		}

		private void TryLoadCodeRebirth()
		{
			TryLoadAssembly("CodeRebirth", ref codeRebirthEnabled, delegate(Assembly assembly)
			{
				codeRebirthAssembly = assembly;
				if (assembly.GetType("CodeRebirth.CodeRebirthEnemyKeys.CutieFly") != null)
				{
					codeRebirthEnabled = true;
					logger.LogInfo((object)"CodeRebirth Component Initiated!");
				}
			});
		}

		private void TryLoadAssembly(string assemblyName, ref bool enabledFlag, Action<Assembly> onFound)
		{
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == assemblyName);
				if (assembly != null)
				{
					onFound(assembly);
				}
				else
				{
					logger.LogWarning((object)(assemblyName + " assembly not found. Skipping optional patch."));
				}
			}
			catch (Exception e)
			{
				LogOptionalError(assemblyName, e);
			}
		}

		private static void LogOptionalError(string name, Exception e)
		{
			if (!e.Message.Contains("Could not load the file"))
			{
				logger.LogError((object)("An error occurred while trying to apply patches for " + name + ": " + e.Message));
			}
		}

		public static List<PlayerControllerB> GetActivePlayers()
		{
			return StartOfRound.Instance.allPlayerScripts.Where((PlayerControllerB p) => (Object)(object)p != (Object)null && !p.isPlayerDead && ((Behaviour)p).isActiveAndEnabled && p.isPlayerControlled).ToList();
		}

		public static bool AllowFairness(Vector3 position)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)StartOfRound.Instance == (Object)null)
			{
				return true;
			}
			if (!Can("CheckForPlayersInside"))
			{
				return true;
			}
			if (!StartOfRound.Instance.shipHasLanded)
			{
				return true;
			}
			if (!IsAPlayersOutside())
			{
				goto IL_006d;
			}
			if (!(position.y > -80f))
			{
				Bounds bounds = StartOfRound.Instance.shipInnerRoomBounds.bounds;
				if (!((Bounds)(ref bounds)).Contains(position))
				{
					goto IL_006d;
				}
			}
			int result = 1;
			goto IL_0075;
			IL_006d:
			result = (playersEnteredInside ? 1 : 0);
			goto IL_0075;
			IL_0075:
			return (byte)result != 0;
		}

		public static bool IsAPlayersOutside()
		{
			if (!StartOfRound.Instance.shipHasLanded)
			{
				return false;
			}
			return GetActivePlayers().Any((PlayerControllerB p) => !p.isInsideFactory);
		}

		public static bool IsAPlayerInsideShip()
		{
			if (!StartOfRound.Instance.shipHasLanded)
			{
				return false;
			}
			return GetActivePlayers().Any((PlayerControllerB p) => p.isInHangarShipRoom);
		}

		public static bool IsAPlayerInsideDungeon()
		{
			if (!StartOfRound.Instance.shipHasLanded)
			{
				return false;
			}
			return GetActivePlayers().Any((PlayerControllerB p) => p.isInsideFactory);
		}

		public static bool CanMob(string parentIdentifier, string identifier, string mobName)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			if (!((BaseUnityPlugin)Instance).Config[new ConfigDefinition("Mobs", parentIdentifier)].BoxedValue.ToString().Equals("TRUE", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			string text = RemoveInvalidCharacters(mobName).ToUpper();
			string target = RemoveInvalidCharacters(text + identifier).ToUpper();
			return ((BaseUnityPlugin)Instance).Config.Keys.Where((ConfigDefinition e) => RemoveInvalidCharacters(e.Key.ToUpper()) == target).Any((ConfigDefinition e) => ((BaseUnityPlugin)Instance).Config[e].BoxedValue.ToString().Equals("TRUE", StringComparison.OrdinalIgnoreCase));
		}

		public static bool Can(string identifier)
		{
			string target = RemoveInvalidCharacters(identifier.ToUpper());
			return ((BaseUnityPlugin)Instance).Config.Keys.Where((ConfigDefinition e) => RemoveInvalidCharacters(e.Key.ToUpper()) == target).Any((ConfigDefinition e) => ((BaseUnityPlugin)Instance).Config[e].BoxedValue.ToString().Equals("TRUE", StringComparison.OrdinalIgnoreCase));
		}

		public static int GetInt(string parentIdentifier, string identifier)
		{
			try
			{
				int.TryParse(((BaseUnityPlugin)Instance).Config[parentIdentifier, identifier].BoxedValue.ToString(), out var result);
				return result;
			}
			catch
			{
				return 1;
			}
		}

		public static float GetFloat(string parentIdentifier, string identifier)
		{
			try
			{
				float.TryParse(((BaseUnityPlugin)Instance).Config[parentIdentifier, identifier].BoxedValue.ToString(), out var result);
				return result;
			}
			catch
			{
				return 1f;
			}
		}

		public static bool GetBool(string parentIdentifier, string identifier)
		{
			return ((BaseUnityPlugin)Instance).Config[parentIdentifier, identifier].BoxedValue.ToString().Equals("TRUE", StringComparison.OrdinalIgnoreCase);
		}

		public static string RemoveWhitespaces(string source)
		{
			return string.Join("", source.Split((string[]?)null, StringSplitOptions.RemoveEmptyEntries));
		}

		public static string RemoveSpecialCharacters(string source)
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (char c in source)
			{
				if (char.IsLetterOrDigit(c))
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString();
		}

		public static string RemoveInvalidCharacters(string source)
		{
			return RemoveWhitespaces(RemoveSpecialCharacters(source));
		}

		public static Type FindType(string fullName)
		{
			try
			{
				return (from a in AppDomain.CurrentDomain.GetAssemblies()
					where !a.IsDynamic
					select a).SelectMany((Assembly a) => a.GetTypes()).FirstOrDefault((Type t) => t.FullName.Equals(fullName));
			}
			catch
			{
				return null;
			}
		}

		public static void CreateHarmonyPatch(Harmony harmony, Type typeToPatch, string methodToPatch, Type[] parameters, Type patchType, string patchMethod, bool isPrefix, bool isTranspiler = false)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			if (typeToPatch == null || patchType == null)
			{
				logger.LogInfo((object)"Type is either incorrect or does not exist!");
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(typeToPatch, methodToPatch, parameters, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(patchType, patchMethod, (Type[])null, (Type[])null);
			if (isTranspiler)
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else if (isPrefix)
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		public static bool IsAgentOnNavMesh(GameObject agentObject)
		{
			//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_000d: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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)
			Vector3 position = agentObject.transform.position;
			NavMeshHit val = default(NavMeshHit);
			if (!NavMesh.SamplePosition(position, ref val, onMeshThreshold, -1))
			{
				return false;
			}
			return Mathf.Approximately(position.x, ((NavMeshHit)(ref val)).position.x) && Mathf.Approximately(position.z, ((NavMeshHit)(ref val)).position.z) && position.y >= ((NavMeshHit)(ref val)).position.y;
		}

		public static List<GameObject> GetTargets(FAIR_AI turret_ai, Vector3 aimPoint, Vector3 forward, float range)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0043: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: 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_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			List<GameObject> list = new List<GameObject>();
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			float num = ((Component)turret_ai).GetComponent<Turret>()?.rotationRange ?? 45f;
			int num2 = 7;
			Vector3 val = Quaternion.Euler(0f, (0f - num) / 3f, 0f) * forward;
			float num3 = num / 3f * 2f / (float)(num2 - 1);
			Ray val2 = default(Ray);
			IHittable val5 = default(IHittable);
			EnemyAI val7 = default(EnemyAI);
			for (int i = 0; i < num2; i++)
			{
				((Ray)(ref val2))..ctor(aimPoint, val);
				RaycastHit[] array = Physics.RaycastAll(val2, range, -5, (QueryTriggerInteraction)2);
				Array.Sort(array, (RaycastHit x, RaycastHit y) => ((RaycastHit)(ref x)).distance.CompareTo(((RaycastHit)(ref y)).distance));
				Vector3 val3 = aimPoint + val * range;
				RaycastHit[] array2 = array;
				for (int j = 0; j < array2.Length; j++)
				{
					RaycastHit val4 = array2[j];
					Transform transform = ((RaycastHit)(ref val4)).transform;
					if (((Component)transform).TryGetComponent<IHittable>(ref val5))
					{
						EnemyAICollisionDetect val6 = (EnemyAICollisionDetect)(object)((val5 is EnemyAICollisionDetect) ? val5 : null);
						if (val6 != null)
						{
							EnemyAI mainScript = val6.mainScript;
							if ((Object)(object)mainScript != (Object)null && !mainScript.isEnemyDead && mainScript.enemyHP > 0 && hashSet.Add(((Component)transform).gameObject))
							{
								list.Add(((Component)transform).gameObject);
							}
						}
						else if (!(val5 is PlayerControllerB) && !(val5 is SandSpiderWebTrap) && (!(val5 is Turret) || GetBool("TurretConfig", "HitOtherTurrets")))
						{
							val5.Hit(1, val3, (PlayerControllerB)null, false, -1);
						}
						val3 = ((RaycastHit)(ref val4)).point;
					}
					else
					{
						if (((Component)transform).TryGetComponent<EnemyAI>(ref val7) && !val7.isEnemyDead && val7.enemyHP > 0 && hashSet.Add(((Component)transform).gameObject))
						{
							list.Add(((Component)transform).gameObject);
						}
						val3 = ((RaycastHit)(ref val4)).point;
					}
				}
				val = Quaternion.Euler(0f, num3, 0f) * val;
			}
			return list;
		}

		public static List<EnemyAICollisionDetect> GetEnemyTargets(List<GameObject> originalTargets)
		{
			List<EnemyAICollisionDetect> list = new List<EnemyAICollisionDetect>();
			EnemyAICollisionDetect item = default(EnemyAICollisionDetect);
			foreach (GameObject originalTarget in originalTargets)
			{
				if ((Object)(object)originalTarget == (Object)null)
				{
					continue;
				}
				if (originalTarget.TryGetComponent<EnemyAICollisionDetect>(ref item))
				{
					list.Add(item);
					continue;
				}
				EnemyAICollisionDetect componentInChildren = originalTarget.GetComponentInChildren<EnemyAICollisionDetect>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					list.Add(componentInChildren);
				}
			}
			return list;
		}

		public static bool AttackTargets(FAIR_AI turret_ai, Vector3 aimPoint, Vector3 forward, float range)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return HitTargets(GetTargets(turret_ai, aimPoint, forward, range), forward);
		}

		public static bool HitTargets(List<GameObject> targets, Vector3 forward)
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			if (!targets.Any())
			{
				return false;
			}
			bool result = false;
			IHittable val3 = default(IHittable);
			foreach (GameObject target in targets)
			{
				if ((Object)(object)target == (Object)null)
				{
					continue;
				}
				EnemyAI val = target.GetComponent<EnemyAI>() ?? target.GetComponent<EnemyAICollisionDetect>()?.mainScript;
				if ((Object)(object)val != (Object)null)
				{
					if (CanMob("TurretDamageAllMobs", ".Turret Damage", val.enemyType.enemyName))
					{
						int @int = GetInt("TurretConfig", "Enemy Damage");
						NutcrackerEnemyAI val2 = (NutcrackerEnemyAI)(object)((val is NutcrackerEnemyAI) ? val : null);
						if (val2 == null || ((EnemyAI)val2).currentBehaviourStateIndex > 0)
						{
							val.HitEnemyOnLocalClient(@int, default(Vector3), (PlayerControllerB)null, false, -1);
							result = true;
						}
					}
				}
				else if (target.TryGetComponent<IHittable>(ref val3) && !(val3 is PlayerControllerB) && (!(val3 is Turret) || GetBool("TurretConfig", "HitOtherTurrets")))
				{
					val3.Hit(1, forward, (PlayerControllerB)null, true, -1);
					result = true;
				}
			}
			return result;
		}
	}
	public class Utils
	{
		[CompilerGenerated]
		private sealed class <WaitForTime>d__2 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Action onComplete;

			public float timeToWait;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(timeToWait);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					onComplete?.Invoke();
					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();
			}
		}

		public static void AddLethalConfigBoolItem(ConfigEntry<bool> tempEntry)
		{
			Type type = Plugin.lethalConfigAssembly.GetType("LethalConfig.ConfigItems.BoolCheckBoxConfigItem");
			ConstructorInfo constructor = type.GetConstructor(new Type[1] { typeof(ConfigEntry<bool>) });
			object obj = constructor.Invoke(new object[1] { tempEntry });
			Type type2 = Plugin.lethalConfigAssembly.GetType("LethalConfig.LethalConfigManager");
			MethodInfo method = type2.GetMethod("AddConfigItem", new Type[1] { type.BaseType });
			method.Invoke(null, new object[1] { obj });
		}

		public static void AddLethalConfigFloatItem(ConfigEntry<float> tempEntry)
		{
			Type type = Plugin.lethalConfigAssembly.GetType("LethalConfig.ConfigItems.FloatInputFieldConfigItem");
			ConstructorInfo constructor = type.GetConstructor(new Type[1] { typeof(ConfigEntry<float>) });
			object obj = constructor.Invoke(new object[1] { tempEntry });
			Type type2 = Plugin.lethalConfigAssembly.GetType("LethalConfig.LethalConfigManager");
			MethodInfo method = type2.GetMethod("AddConfigItem", new Type[1] { type.BaseType });
			method.Invoke(null, new object[1] { obj });
		}

		[IteratorStateMachine(typeof(<WaitForTime>d__2))]
		public static IEnumerator WaitForTime(Action onComplete, float timeToWait)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForTime>d__2(0)
			{
				onComplete = onComplete,
				timeToWait = timeToWait
			};
		}

		public static bool WaitInSeconds(float timeToWait, MonoBehaviour objectToTime = null)
		{
			if ((Object)(object)objectToTime == (Object)null)
			{
				objectToTime = (MonoBehaviour)(object)Plugin.Instance;
			}
			bool done = false;
			objectToTime.StartCoroutine(WaitForTime(delegate
			{
				done = true;
			}, timeToWait));
			return done;
		}

		public static void SetupConfig()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Expected O, but got Unknown
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Expected O, but got Unknown
			//IL_040c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0416: Expected O, but got Unknown
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Expected O, but got Unknown
			//IL_04ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d8: Expected O, but got Unknown
			//IL_052f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0539: Expected O, but got Unknown
			//IL_058c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0596: Expected O, but got Unknown
			//IL_05e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f3: Expected O, but got Unknown
			//IL_0646: Unknown result type (might be due to invalid IL or missing references)
			//IL_0650: Expected O, but got Unknown
			//IL_06a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ad: Expected O, but got Unknown
			//IL_0700: Unknown result type (might be due to invalid IL or missing references)
			//IL_070a: Expected O, but got Unknown
			//IL_075d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0767: Expected O, but got Unknown
			//IL_07ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c4: Expected O, but got Unknown
			//IL_0817: Unknown result type (might be due to invalid IL or missing references)
			//IL_0821: Expected O, but got Unknown
			//IL_08a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_08af: Expected O, but got Unknown
			//IL_09d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_09dc: Expected O, but got Unknown
			//IL_0a43: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a4d: Expected O, but got Unknown
			//IL_0ab4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0abe: Expected O, but got Unknown
			//IL_0b25: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b2f: Expected O, but got Unknown
			//IL_0b96: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba0: Expected O, but got Unknown
			//IL_0c07: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c11: Expected O, but got Unknown
			if (!Plugin.itemList.SequenceEqual(Plugin.items) || Plugin.items.Count == 0)
			{
				Plugin.items = Resources.FindObjectsOfTypeAll<Item>().ToList();
				Plugin.itemList = Plugin.items;
			}
			Plugin.allHittablesMask = StartOfRound.Instance.collidersRoomMaskDefaultAndPlayers | 0x280008 | Plugin.enemyMask;
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("General", "ImmortalAffected")))
			{
				ConfigEntry<bool> tempEntry = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("General", "ImmortalAffected", false, "If set to on/true immortal enemies will be targeted and trip off traps.");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigBoolItem(tempEntry);
				}
				if (Plugin.enemies.Count == 0)
				{
					if (!Plugin.GetBool("General", "ImmortalAffected"))
					{
						Plugin.enemies = (from e in Resources.FindObjectsOfTypeAll<EnemyType>()
							where e.canDie
							select e).ToList();
						Plugin.allEnemies = (from EnemyType e in Resources.FindObjectsOfTypeAll(typeof(EnemyType))
							where (Object)(object)e != (Object)null
							select e).ToList();
						Plugin.enemyList = Plugin.enemies;
					}
					else
					{
						Plugin.enemies = (from e in Resources.FindObjectsOfTypeAll<EnemyType>()
							where (Object)(object)e != (Object)null
							select e).ToList();
						Plugin.allEnemies = (from EnemyType e in Resources.FindObjectsOfTypeAll(typeof(EnemyType))
							where (Object)(object)e != (Object)null
							select e).ToList();
						Plugin.enemyList = Plugin.enemies;
					}
				}
				else if (!Plugin.enemyList.SequenceEqual(Plugin.enemies))
				{
					if (!Plugin.GetBool("General", "ImmortalAffected"))
					{
						Plugin.enemies = (from e in Resources.FindObjectsOfTypeAll<EnemyType>()
							where (Object)(object)e != (Object)null && e.canDie
							select e).ToList();
						Plugin.allEnemies = (from EnemyType e in Resources.FindObjectsOfTypeAll(typeof(EnemyType))
							where (Object)(object)e != (Object)null
							select e).ToList();
						Plugin.enemyList = Plugin.enemies;
					}
					else
					{
						Plugin.enemies = (from e in Resources.FindObjectsOfTypeAll<EnemyType>()
							where (Object)(object)e != (Object)null
							select e).ToList();
						Plugin.allEnemies = (from EnemyType e in Resources.FindObjectsOfTypeAll(typeof(EnemyType))
							where (Object)(object)e != (Object)null
							select e).ToList();
						Plugin.enemyList = Plugin.enemies;
					}
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("ExplosionConfig", "Damage")))
			{
				ConfigEntry<float> tempEntry2 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<float>("ExplosionConfig", "Damage", 1f, "Damage explosions will do outside the kill radius");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigFloatItem(tempEntry2);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Quick Sand Config", "Sink Time")))
			{
				ConfigEntry<float> tempEntry3 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<float>("Quick Sand Config", "Sink Time", 5f, "Time Until A Enemy Is Considered Sunk And Will Be Killed");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigFloatItem(tempEntry3);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Quick Sand Config", "Slowing Speed")))
			{
				ConfigEntry<float> tempEntry4 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<float>("Quick Sand Config", "Slowing Speed", 33f, "Percentage of Original Speed Enemies Move In Quick Sand");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigFloatItem(tempEntry4);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("TurretConfig", "Enemy Damage")))
			{
				ConfigEntry<float> tempEntry5 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<float>("TurretConfig", "Enemy Damage", 1f, "Damage Turrets will Do To Enemies");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigFloatItem(tempEntry5);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("TurretConfig", "Player Damage")))
			{
				ConfigEntry<float> tempEntry6 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<float>("TurretConfig", "Player Damage", 50f, "Damage Turrets will Do To Players");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigFloatItem(tempEntry6);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("TurretConfig", "HitOtherTurrets")))
			{
				ConfigEntry<bool> tempEntry7 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("TurretConfig", "HitOtherTurrets", false, "If turrets can hit other turrets when firing.(Does not make them target other turrets)");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigBoolItem(tempEntry7);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "QuicksandAllMobs")))
			{
				ConfigEntry<bool> tempEntry8 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "QuicksandAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Set Off Quicksand interactions.");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigBoolItem(tempEntry8);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "ExplodeAllMobs")))
			{
				ConfigEntry<bool> tempEntry9 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "ExplodeAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Set Off Mines.");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigBoolItem(tempEntry9);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "BoombaAllMobs")))
			{
				ConfigEntry<bool> tempEntry10 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "BoombaAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Set Off Boombas.");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigBoolItem(tempEntry10);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "SeamineAllMobs")))
			{
				ConfigEntry<bool> tempEntry11 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "SeamineAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Set Off Seamines.");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigBoolItem(tempEntry11);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "BerthaAllMobs")))
			{
				ConfigEntry<bool> tempEntry12 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "BerthaAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Set Off Big Berthas.");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigBoolItem(tempEntry12);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "TurretTargetAllMobs")))
			{
				ConfigEntry<bool> tempEntry13 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "TurretTargetAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Be Targeted By Turrets.");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigBoolItem(tempEntry13);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "TurretDamageAllMobs")))
			{
				ConfigEntry<bool> tempEntry14 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "TurretDamageAllMobs", true, "Leave On To Customise Mobs Below Or Turn Off To Make All Mobs Unable To Be Killed By Turrets.");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigBoolItem(tempEntry14);
				}
			}
			if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", "CheckForPlayersInside")))
			{
				ConfigEntry<bool> tempEntry15 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", "CheckForPlayersInside", false, "Whether to check for players inside the dungeon before anything else occurs.");
				if (Plugin.lethalConfigEnabled)
				{
					AddLethalConfigBoolItem(tempEntry15);
				}
			}
			foreach (EnemyType allEnemy in Plugin.allEnemies)
			{
				string text = Plugin.RemoveInvalidCharacters(allEnemy.enemyName);
				if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Quicksand Kill")))
				{
					if (allEnemy.canDie)
					{
						ConfigEntry<bool> tempEntry16 = ((!text.ToLower().Equals("cutieflyai") && !text.ToLower().Equals("cutieflyobj") && !text.ToLower().Equals("cutiefly")) ? ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Quicksand Kill", true, "Is it killable by quicksand?") : ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Quicksand Kill", false, "Is it killable by quicksand?"));
						if (Plugin.lethalConfigEnabled)
						{
							AddLethalConfigBoolItem(tempEntry16);
						}
					}
					else
					{
						ConfigEntry<bool> tempEntry16 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Quicksand Kill", false, "Is it killable by quicksand?");
						if (Plugin.lethalConfigEnabled)
						{
							AddLethalConfigBoolItem(tempEntry16);
						}
					}
				}
				if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Mine")))
				{
					ConfigEntry<bool> tempEntry17 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Mine", allEnemy.canDie, "Does it set off the landmine or not?");
					if (Plugin.lethalConfigEnabled)
					{
						AddLethalConfigBoolItem(tempEntry17);
					}
				}
				if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Seamine")))
				{
					ConfigEntry<bool> tempEntry18 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Seamine", allEnemy.canDie, "Does it set off the Surfaced Seamine or not?");
					if (Plugin.lethalConfigEnabled)
					{
						AddLethalConfigBoolItem(tempEntry18);
					}
				}
				if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Bertha")))
				{
					ConfigEntry<bool> tempEntry19 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Bertha", allEnemy.canDie, "Does it set off the Surfaced Big Bertha or not?");
					if (Plugin.lethalConfigEnabled)
					{
						AddLethalConfigBoolItem(tempEntry19);
					}
				}
				if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Boomba")))
				{
					ConfigEntry<bool> tempEntry20 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Boomba", allEnemy.canDie, "Does it set off the LethalThings Boomba or not?");
					if (Plugin.lethalConfigEnabled)
					{
						AddLethalConfigBoolItem(tempEntry20);
					}
				}
				if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Turret Target")))
				{
					ConfigEntry<bool> tempEntry21 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Turret Target", allEnemy.canDie, "Is it targetable by turrets?");
					if (Plugin.lethalConfigEnabled)
					{
						AddLethalConfigBoolItem(tempEntry21);
					}
				}
				if (!((BaseUnityPlugin)Plugin.Instance).Config.ContainsKey(new ConfigDefinition("Mobs", text + ".Turret Damage")))
				{
					ConfigEntry<bool> tempEntry22 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mobs", text + ".Turret Damage", allEnemy.canDie, "Is it damageable by turrets?");
					if (Plugin.lethalConfigEnabled)
					{
						AddLethalConfigBoolItem(tempEntry22);
					}
				}
			}
		}

		public static int[] GetLateGameUpgradeTier(string upgradeName)
		{
			try
			{
				Type type = Plugin.lguAssembly.GetType("MoreShipUpgrades.API.UpgradeApi");
				if (type == null)
				{
					Plugin.logger.LogError((object)"[FairAI] Could not find UpgradeApi type!");
					return Array.Empty<int>();
				}
				MethodInfo method = type.GetMethod("GetRankableUpgradeNodes", BindingFlags.Static | BindingFlags.Public);
				if (method == null)
				{
					Plugin.logger.LogError((object)"[FairAI] Could not find GetRankableUpgradeNodes() method!");
					return Array.Empty<int>();
				}
				object obj = method.Invoke(null, null);
				if (!(obj is IEnumerable enumerable))
				{
					Plugin.logger.LogError((object)"[FairAI] Result is not an IEnumerable!");
					return Array.Empty<int>();
				}
				foreach (object item in enumerable)
				{
					Type type2 = item.GetType();
					PropertyInfo property = type2.GetProperty("Name", BindingFlags.Instance | BindingFlags.Public);
					PropertyInfo property2 = type2.GetProperty("MaxUpgrade", BindingFlags.Instance | BindingFlags.Public);
					PropertyInfo property3 = type2.GetProperty("CurrentUpgrade", BindingFlags.Instance | BindingFlags.Public);
					string text = property?.GetValue(item)?.ToString() ?? "(unknown)";
					if (!text.Equals("(unknown)") && text.Equals(upgradeName, StringComparison.OrdinalIgnoreCase))
					{
						int num = (int)(property2?.GetValue(item) ?? ((object)0));
						int num2 = (int)(property3?.GetValue(item) ?? ((object)0));
						Plugin.logger.LogInfo((object)$"[FairAI] {text} — Current: {num2}, Max: {num}");
						return new int[2] { num2, num };
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"[FairAI] Error: {arg}");
			}
			return Array.Empty<int>();
		}

		public static bool ReadSyncedEntryBool(object syncedEntry)
		{
			if (syncedEntry == null)
			{
				return false;
			}
			PropertyInfo property = syncedEntry.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public);
			return property != null && (bool)property.GetValue(syncedEntry);
		}

		public static int ReadSyncedEntryInt(object syncedEntry)
		{
			if (syncedEntry == null)
			{
				return 0;
			}
			PropertyInfo property = syncedEntry.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public);
			return (property != null) ? ((int)property.GetValue(syncedEntry)) : 0;
		}

		public static float CalculateDecreaseMultiplier()
		{
			Type rubberBootsType = Plugin.rubberBootsType;
			try
			{
				Type type = rubberBootsType.Assembly.GetType("MoreShipUpgrades.Misc.Upgrades.BaseUpgrade");
				if (type == null)
				{
					return 0f;
				}
				object obj = type.GetMethod("GetConfiguration", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null);
				if (obj == null)
				{
					return 0f;
				}
				object obj2 = obj.GetType().GetProperty("RubberBootsConfiguration", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj);
				if (obj2 == null)
				{
					return 0f;
				}
				object syncedEntry = obj2.GetType().GetProperty("Enabled")?.GetValue(obj2);
				if (!ReadSyncedEntryBool(syncedEntry))
				{
					return 0f;
				}
				MethodInfo method = type.GetMethod("GetActiveUpgrade", BindingFlags.Static | BindingFlags.Public);
				if (!(bool)method.Invoke(null, new object[1] { "Rubber Boots" }))
				{
					return 0f;
				}
				object syncedEntry2 = obj2.GetType().GetProperty("InitialEffect")?.GetValue(obj2);
				object syncedEntry3 = obj2.GetType().GetProperty("IncrementalEffect")?.GetValue(obj2);
				int num = ReadSyncedEntryInt(syncedEntry2);
				int num2 = ReadSyncedEntryInt(syncedEntry3);
				MethodInfo method2 = type.GetMethod("GetUpgradeLevel", BindingFlags.Static | BindingFlags.Public);
				int num3 = (int)method2.Invoke(null, new object[1] { "Rubber Boots" }) + 1;
				Plugin.logger.LogWarning((object)("Decrease: " + (float)(num + num2 * num3) / 100f));
				return (float)(num + num2 * num3) / 100f;
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"CalculateDecreaseMultiplier reflection failed: {arg}");
				return 0f;
			}
		}

		public static int ClearMovementHinderance(int defaultValue)
		{
			if (CalculateDecreaseMultiplier() >= 1f)
			{
				return 0;
			}
			return defaultValue;
		}

		public static float ReduceMovementHinderance(float defaultValue)
		{
			float num = CalculateDecreaseMultiplier();
			return Mathf.Clamp(Mathf.Clamp(1f - num, 0f, 1f) * defaultValue, 1f, 100f);
		}
	}
}
namespace FairAI.Patches
{
	public static class BoombaPatch
	{
		private static bool? _enabled;

		public static bool enabled
		{
			get
			{
				if (!_enabled.HasValue)
				{
					_enabled = Chainloader.PluginInfos.ContainsKey("evaisa.lethalthings");
				}
				return _enabled.Value;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void PatchStart(ref RoombaAI __instance)
		{
			((Component)__instance).gameObject.AddComponent<BoombaTimer>();
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void PatchDoAIInterval(ref RoombaAI __instance)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_007e: 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)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.AllowFairness(((Component)__instance).transform.position) || !Plugin.IsAgentOnNavMesh(((Component)__instance).gameObject) || (((EnemyAI)__instance).currentSearch == null && !((EnemyAI)__instance).movingTowardsTargetPlayer) || (!__instance.mineAudio.isPlaying && !__instance.mineFarAudio.isPlaying) || !((Component)__instance).GetComponent<BoombaTimer>().IsActiveBomb())
			{
				return;
			}
			Vector3 val = ((Component)__instance).transform.position + Vector3.up;
			Collider[] array = Physics.OverlapSphere(val, 6f, 2621448, (QueryTriggerInteraction)2);
			for (int i = 0; i < array.Length; i++)
			{
				float num = Vector3.Distance(val, ((Component)array[i]).transform.position);
				if ((num > 4f && Physics.Linecast(val, ((Component)array[i]).transform.position + Vector3.up * 0.3f, 256, (QueryTriggerInteraction)1)) || !((Object)(object)((Component)array[i]).gameObject.GetComponent<EnemyAICollisionDetect>() != (Object)null))
				{
					continue;
				}
				EnemyAICollisionDetect component = ((Component)array[i]).gameObject.GetComponent<EnemyAICollisionDetect>();
				if (!((Object)(object)((Component)component.mainScript).gameObject != (Object)(object)((Component)__instance).gameObject) || !Plugin.CanMob("BoombaAllMobs", ".Boomba", component.mainScript.enemyType.enemyName))
				{
					continue;
				}
				if ((Object)(object)component != (Object)null && ((NetworkBehaviour)component.mainScript).IsOwner && !component.mainScript.isEnemyDead)
				{
					Object.Instantiate<GameObject>(StartOfRound.Instance.explosionPrefab, val, Quaternion.Euler(-90f, 0f, 0f), RoundManager.Instance.mapPropsContainer.transform).SetActive(true);
					if (num < 3f)
					{
						component.mainScript.KillEnemyOnOwnerClient(true);
					}
					else if (num < 6f)
					{
						component.mainScript.HitEnemyOnLocalClient(2, default(Vector3), (PlayerControllerB)null, false, -1);
					}
				}
				if (((NetworkBehaviour)__instance).IsServer)
				{
					((EnemyAI)__instance).KillEnemy(true);
				}
				else
				{
					((EnemyAI)__instance).KillEnemyServerRpc(true);
				}
			}
		}
	}
	internal class EnemyAIPatch
	{
		private static void BaseHitEnemy(EnemyAI ai, int force, PlayerControllerB playerWhoHit, bool playHitSFX, int hitID)
		{
			if (!((Object)(object)ai == (Object)null))
			{
				if (playHitSFX && (Object)(object)ai.enemyType.hitBodySFX != (Object)null && !ai.isEnemyDead)
				{
					ai.creatureSFX.PlayOneShot(ai.enemyType.hitBodySFX);
					WalkieTalkie.TransmitOneShotAudio(ai.creatureSFX, ai.enemyType.hitBodySFX, 1f);
				}
				if ((Object)(object)ai.creatureVoice != (Object)null)
				{
					ai.creatureVoice.PlayOneShot(ai.enemyType.hitEnemyVoiceSFX);
				}
				if (ai.debugEnemyAI)
				{
					Debug.Log((object)$"Enemy #{ai.thisEnemyIndex} was hit with force of {force}");
				}
				if ((Object)(object)playerWhoHit != (Object)null)
				{
					Debug.Log((object)$"Client #{playerWhoHit.playerClientId} hit enemy {((Object)((Component)ai.agent).transform).name} with force of {force}.");
				}
			}
		}

		public static void KillEnemyOnOwnerClientPatch(EnemyAI __instance, bool overrideDestroy = false)
		{
			if (overrideDestroy)
			{
				return;
			}
			int id = ((Object)__instance).GetInstanceID();
			if (Plugin.sinkingProgress.ContainsKey(id))
			{
				((MonoBehaviour)__instance).StartCoroutine(Utils.WaitForTime(delegate
				{
					Plugin.sinkingProgress.Remove(id);
					Plugin.sinkingValues.Remove(id);
					Plugin.positions.Remove(id);
					__instance.KillEnemyOnOwnerClient(true);
				}, 1f));
			}
		}

		public static bool BrackenHitEnemyPatch(ref FlowermanAI __instance, int force = 1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false, int hitID = -1)
		{
			BaseHitEnemy((EnemyAI)(object)__instance, force, playerWhoHit, playHitSFX, hitID);
			if (((EnemyAI)__instance).isEnemyDead)
			{
				return false;
			}
			FlowermanAI obj = __instance;
			((EnemyAI)obj).enemyHP = ((EnemyAI)obj).enemyHP - force;
			if (((NetworkBehaviour)__instance).IsOwner)
			{
				if (((EnemyAI)__instance).enemyHP <= 0)
				{
					((EnemyAI)__instance).KillEnemyOnOwnerClient(false);
					return false;
				}
				if (!Object.op_Implicit((Object)(object)playerWhoHit))
				{
					Plugin.logger.LogDebug((object)"Bracken was hit by another enemy. Not changing its anger meter");
					return false;
				}
				__instance.angerMeter = 11f;
				__instance.angerCheckInterval = 1f;
				__instance.AddToAngerMeter(0.1f);
			}
			return false;
		}

		public static bool HoardingBugHitEnemyPatch(ref HoarderBugAI __instance, int force = 1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false, int hitID = -1)
		{
			BaseHitEnemy((EnemyAI)(object)__instance, force, playerWhoHit, playHitSFX, hitID);
			if (((EnemyAI)__instance).isEnemyDead)
			{
				return false;
			}
			((EnemyAI)__instance).creatureAnimator.SetTrigger("damage");
			if (!Object.op_Implicit((Object)(object)playerWhoHit))
			{
				Plugin.logger.LogDebug((object)"Hoarding bug was hit by another enemy. Not changing its anger meter");
			}
			else
			{
				__instance.angryAtPlayer = playerWhoHit;
				HoarderBugAI obj = __instance;
				obj.angryTimer += 18f;
			}
			HoarderBugAI obj2 = __instance;
			((EnemyAI)obj2).enemyHP = ((EnemyAI)obj2).enemyHP - force;
			if (((NetworkBehaviour)__instance).IsOwner && ((EnemyAI)__instance).enemyHP <= 0)
			{
				((EnemyAI)__instance).KillEnemyOnOwnerClient(false);
			}
			return false;
		}
	}
	internal class LevelGenManPatch
	{
		public static void PatchAwake(ref LevelGenerationManager __instance)
		{
			Utils.SetupConfig();
		}
	}
	internal class MineAIPatch
	{
		[CompilerGenerated]
		private sealed class <WaitForUpdate>d__3 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public float waitTime;

			public Landmine mine;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(waitTime);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (!((Object)(object)mine == (Object)null))
					{
						if ((Object)(object)((Component)mine).GetComponent<NetworkObject>() != (Object)null)
						{
							((Component)mine).GetComponent<NetworkObject>().Despawn(true);
						}
						else
						{
							Object.Destroy((Object)(object)((Component)mine).gameObject);
						}
					}
					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();
			}
		}

		public static void PatchOnTriggerEnter(ref Landmine __instance, Collider other, ref float ___pressMineDebounceTimer)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.AllowFairness(((Component)__instance).transform.position))
			{
				EnemyAICollisionDetect component = ((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>();
				if ((Object)(object)component != (Object)null && !component.mainScript.isEnemyDead && Plugin.CanMob("ExplodeAllMobs", ".Mine", component.mainScript.enemyType.enemyName.ToUpper()))
				{
					___pressMineDebounceTimer = 0.5f;
					__instance.PressMineServerRpc();
				}
			}
		}

		public static void PatchOnTriggerExit(ref Landmine __instance, Collider other, ref bool ___sendingExplosionRPC)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.AllowFairness(((Component)__instance).transform.position))
			{
				EnemyAICollisionDetect component = ((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>();
				if ((Object)(object)component != (Object)null && !component.mainScript.isEnemyDead && Plugin.CanMob("ExplodeAllMobs", ".Mine", component.mainScript.enemyType.enemyName.ToUpper()) && !__instance.hasExploded)
				{
					__instance.SetOffMineAnimation();
					___sendingExplosionRPC = true;
					__instance.ExplodeMineServerRpc();
				}
			}
		}

		public static void DetonatePatch(ref Landmine __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				((MonoBehaviour)__instance).StartCoroutine(WaitForUpdate(1.5f, __instance));
			}
		}

		[IteratorStateMachine(typeof(<WaitForUpdate>d__3))]
		public static IEnumerator WaitForUpdate(float waitTime, Landmine mine)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForUpdate>d__3(0)
			{
				waitTime = waitTime,
				mine = mine
			};
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void PatchSpawnExplosion(Vector3 explosionPosition, bool spawnExplosionEffect = false, float killRange = 1f, float damageRange = 1f, int nonLethalDamage = 50, float physicsForce = 0f, GameObject overridePrefab = null, bool goThroughCar = false)
		{
			//IL_0004: 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_0027: 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_0043: 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_0052: 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)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			bool flag = true;
			Collider[] array = Physics.OverlapSphere(explosionPosition, 6f, 2621448, (QueryTriggerInteraction)2);
			for (int i = 0; i < array.Length; i++)
			{
				float num = Vector3.Distance(explosionPosition, ((Component)array[i]).transform.position);
				if (num > 4f && Physics.Linecast(explosionPosition, ((Component)array[i]).transform.position + Vector3.up * 0.3f, 256, (QueryTriggerInteraction)1))
				{
					continue;
				}
				if (Plugin.surfacedEnabled && Plugin.surfacedAssembly != null)
				{
					Type type = Plugin.surfacedAssembly.GetType("Seamine");
					if (type != null && (Object)(object)((Component)array[i]).gameObject.GetComponent(type) != (Object)null)
					{
						Component component = ((Component)array[i]).gameObject.GetComponent(type);
						FieldInfo field = type.GetField("mineActivated", BindingFlags.Instance | BindingFlags.NonPublic);
						FieldInfo field2 = type.GetField("hasExploded", BindingFlags.Instance | BindingFlags.Public);
						if (!(bool)field2.GetValue(component) || !(bool)field.GetValue(component))
						{
							break;
						}
						if (Plugin.AllowFairness(component.transform.position))
						{
							MethodInfo method = type.GetMethod("TriggerMineOnLocalClientByExiting", BindingFlags.Instance | BindingFlags.NonPublic);
							method.Invoke(component, new object[0]);
						}
					}
				}
				if (!((Object)(object)((Component)array[i]).gameObject.GetComponent<EnemyAICollisionDetect>() != (Object)null))
				{
					continue;
				}
				EnemyAICollisionDetect component2 = ((Component)array[i]).gameObject.GetComponent<EnemyAICollisionDetect>();
				if ((Object)(object)component2 != (Object)null && ((NetworkBehaviour)component2.mainScript).IsOwner && !component2.mainScript.isEnemyDead)
				{
					if (num < killRange)
					{
						component2.mainScript.HitEnemyOnLocalClient(component2.mainScript.enemyHP, default(Vector3), (PlayerControllerB)null, false, -1);
					}
					else if (num < damageRange)
					{
						component2.mainScript.HitEnemyOnLocalClient(Mathf.RoundToInt(Plugin.GetFloat("ExplosionConfig", "Damage")), default(Vector3), (PlayerControllerB)null, false, -1);
					}
				}
			}
		}
	}
	internal class QuickSandPatch
	{
		public static bool OnTriggerStayPatch(ref QuicksandTrigger __instance, Collider other)
		{
			if (!__instance.isWater && (Object)(object)((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>() != (Object)null && Plugin.GetBool("Mobs", "QuicksandAllMobs"))
			{
				EnemyAICollisionDetect component = ((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>();
				if ((Object)(object)component != (Object)null)
				{
					EnemyAI mainScript = component.mainScript;
					if ((Object)(object)mainScript != (Object)null)
					{
						string enemyName = mainScript.enemyType.enemyName;
						if ((Object)(object)mainScript.agent != (Object)null && (Plugin.GetBool("Mobs", Plugin.RemoveInvalidCharacters(enemyName) + ".Quicksand Kill") || !enemyName.ToLower().Contains("cutiefly")))
						{
							NavMeshAgent agent = mainScript.agent;
							float[] array = Plugin.SpeedAndAccelerationEnemyList(component);
							float num = (float)Plugin.GetInt("Quick Sand Config", "Slowing Speed") * 0.01f;
							if (array.Length != 0)
							{
								if (array[0] * num != agent.speed)
								{
									agent.speed = array[0] * num;
								}
								if (array[1] * num != agent.acceleration)
								{
									agent.acceleration = array[1] * num;
								}
							}
						}
						if (Plugin.GetBool("Mobs", Plugin.RemoveInvalidCharacters(mainScript.enemyType.enemyName) + ".Quicksand Kill"))
						{
							SetSinking(component);
						}
					}
				}
			}
			QuicksandEventsForPlayer(__instance, other);
			return false;
		}

		public static bool OnTriggerExitPatch(ref QuicksandTrigger __instance, Collider other)
		{
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>() != (Object)null && Plugin.GetBool("Mobs", "QuicksandAllMobs"))
			{
				EnemyAICollisionDetect component = ((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>();
				EnemyAI mainScript = component.mainScript;
				int instanceID = ((Object)mainScript).GetInstanceID();
				string enemyName = mainScript.enemyType.enemyName;
				if (!Plugin.positions.TryGetValue(instanceID, out var value))
				{
					return false;
				}
				if (Plugin.GetBool("Mobs", Plugin.RemoveInvalidCharacters(enemyName) + ".Quicksand Kill") || !enemyName.ToLower().Contains("cutiefly"))
				{
					float[] array = Plugin.SpeedAndAccelerationEnemyList(component);
					if (array.Length != 0)
					{
						mainScript.agent.speed = array[0];
						mainScript.agent.acceleration = array[1];
					}
				}
				if (Plugin.GetBool("Mobs", Plugin.RemoveInvalidCharacters(enemyName) + ".Quicksand Kill"))
				{
					((Component)mainScript).transform.position = new Vector3(((Component)mainScript).transform.position.x, value.y, ((Component)mainScript).transform.position.z);
					mainScript.SyncPositionToClients();
					Plugin.sinkingValues[instanceID] = 0f;
					Plugin.sinkingProgress[instanceID] = 0f;
				}
			}
			else
			{
				__instance.OnExit(other);
			}
			return false;
		}

		public static bool StopSinkingLocalPlayerPatch(ref QuicksandTrigger __instance, PlayerControllerB playerScript)
		{
			if (__instance.sinkingLocalPlayer)
			{
				__instance.sinkingLocalPlayer = false;
				playerScript.sourcesCausingSinking = Mathf.Clamp(playerScript.sourc