Decompiled source of Turrets Redo v0.0.4

plugins\TurretsRedo\TurretsRedo.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ConditionalConfigSync;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TurretsRedo
{
	[BepInPlugin("MrGay.TurretsRedo", "Turrets Redo", "0.0.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class TurretsRedoPlugin : BaseUnityPlugin
	{
		public const string Guid = "MrGay.TurretsRedo";

		public const string Name = "Turrets Redo";

		public const string Version = "0.0.4";

		private static readonly Harmony Harmony = new Harmony("MrGay.TurretsRedo");

		internal static ManualLogSource Log;

		internal static TurretConfig Settings;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Settings = new TurretConfig((BaseUnityPlugin)(object)this);
			Harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Turrets Redo loaded. Modular turret changes and self-hit protection are active.");
		}
	}
	[HarmonyPatch(typeof(Turret), "ShootProjectile")]
	internal static class TurretCollisionPatch
	{
		private static readonly Dictionary<Projectile, HashSet<Collider>> IgnoredCollisions = new Dictionary<Projectile, HashSet<Collider>>();

		private static void Postfix(Turret __instance, GameObject ___m_lastProjectile)
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)___m_lastProjectile == (Object)null)
			{
				return;
			}
			Projectile component = ___m_lastProjectile.GetComponent<Projectile>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			Collider[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Collider>(true);
			Collider[] componentsInChildren2 = ___m_lastProjectile.GetComponentsInChildren<Collider>(true);
			IgnoredCollisions[component] = new HashSet<Collider>(componentsInChildren);
			Collider[] array = componentsInChildren2;
			foreach (Collider val in array)
			{
				Collider[] array2 = componentsInChildren;
				foreach (Collider val2 in array2)
				{
					Physics.IgnoreCollision(val, val2, true);
				}
			}
		}

		internal static HashSet<Collider> GetIgnoredCollisions(Projectile projectile)
		{
			IgnoredCollisions.TryGetValue(projectile, out var value);
			return value;
		}
	}
	[HarmonyPatch(typeof(Projectile), "OnHit")]
	internal static class ProjectileCollisionPatch
	{
		private static bool Prefix(Projectile __instance, Collider collider)
		{
			HashSet<Collider> ignoredCollisions = TurretCollisionPatch.GetIgnoredCollisions(__instance);
			if ((Object)(object)collider == (Object)null)
			{
				return true;
			}
			if (ignoredCollisions != null && ignoredCollisions.Contains(collider))
			{
				return false;
			}
			Character componentInParent = ((Component)collider).GetComponentInParent<Character>();
			if (ignoredCollisions != null && !((Object)(object)componentInParent == (Object)null))
			{
				return !TurretTargetPatch.IsProjectileImmune(componentInParent);
			}
			return true;
		}
	}
	internal sealed class TurretConfig
	{
		private readonly ConfigSync sync;

		internal readonly ConfigEntry<bool> Enabled;

		internal readonly ConfigEntry<bool> ServerAuthority;

		internal readonly SyncedConfigEntry<bool> TurnSpeedEnabled;

		internal readonly SyncedConfigEntry<float> TurnSpeedPercent;

		internal readonly SyncedConfigEntry<bool> ProjectileSpeedEnabled;

		internal readonly SyncedConfigEntry<float> ProjectileSpeedPercent;

		internal readonly SyncedConfigEntry<bool> LeadShotEnabled;

		internal readonly SyncedConfigEntry<bool> RemoveVanillaSpread;

		internal readonly SyncedConfigEntry<bool> ViewDistanceEnabled;

		internal readonly SyncedConfigEntry<float> ViewDistancePercent;

		internal readonly SyncedConfigEntry<bool> AttackCooldownEnabled;

		internal readonly SyncedConfigEntry<float> AttackCooldownPercent;

		internal readonly SyncedConfigEntry<float> HorizontalAngle;

		internal readonly SyncedConfigEntry<float> VerticalAngle;

		internal readonly SyncedConfigEntry<bool> InfiniteAmmo;

		internal readonly SyncedConfigEntry<bool> IgnorePlayers;

		internal readonly SyncedConfigEntry<bool> IgnoreTames;

		internal readonly SyncedConfigEntry<bool> IgnoreFriendlyDvergr;

		internal readonly SyncedConfigEntry<bool> IgnoredIdentitiesImmune;

		internal TurretConfig(BaseUnityPlugin plugin)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0080: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: 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_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			Enabled = plugin.Config.Bind<bool>("General", "Enable_mod", true, "Enables all Turrets Redo modules.");
			ServerAuthority = plugin.Config.Bind<bool>("General", "Server_authority", true, "When enabled, the server owns gameplay settings. Requires a restart after changing.");
			sync = new ConfigSync("MrGay.TurretsRedo")
			{
				DisplayName = "Turrets Redo",
				CurrentVersion = "0.0.4",
				MinimumRequiredVersion = "0.0.4",
				ModRequired = true
			};
			ConfigSyncMode mode = (ConfigSyncMode)(ServerAuthority.Value ? 1 : 2);
			TurnSpeedEnabled = Add(plugin, "Turn speed", "Enable_Turn_Speed", value: true, "Changes turret turn speed.", mode);
			TurnSpeedPercent = Add(plugin, "Turn speed", "Percentage_change", 0f, "Percentage change from vanilla. Positive values are faster.", mode);
			ProjectileSpeedEnabled = Add(plugin, "Projectile speed", "Enable_Projectile_Speed", value: true, "Changes turret projectile speed.", mode);
			ProjectileSpeedPercent = Add(plugin, "Projectile speed", "Percentage_change", 0f, "Percentage change from vanilla. Positive values are faster.", mode);
			LeadShotEnabled = Add(plugin, "Accuracy", "Enable_lead_shots", value: true, "Aims ahead of moving targets using target direction and speed.", mode);
			RemoveVanillaSpread = Add(plugin, "Accuracy", "Remove_vanilla_spread", value: false, "Removes the projectile spread defined by the ammunition.", mode);
			ViewDistanceEnabled = Add(plugin, "View distance", "Enable_View_Distance", value: true, "Changes turret target view distance.", mode);
			ViewDistancePercent = Add(plugin, "View distance", "Percentage_change", 0f, "Percentage change from vanilla. Positive values increase range.", mode);
			AttackCooldownEnabled = Add(plugin, "Attack cooldown", "Enable_Attack_Cooldown", value: true, "Changes turret attack cooldown.", mode);
			AttackCooldownPercent = Add(plugin, "Attack cooldown", "Percentage_change", 0f, "Percentage change to firing rate. 0 is vanilla, 100 is twice as fast.", mode);
			HorizontalAngle = Add(plugin, "Aim range", "Horizontal_angle", 25f, "Maximum horizontal aim angle on either side of the turret. Vanilla: 25 degrees.", mode);
			VerticalAngle = Add(plugin, "Aim range", "Vertical_angle", 20f, "Maximum vertical aim angle above and below the turret. Vanilla: 20 degrees.", mode);
			InfiniteAmmo = Add(plugin, "Ammo", "Infinite_ammo", value: false, "Turrets use one loaded missile forever and drop one missile when broken.", mode);
			IgnorePlayers = Add(plugin, "Targeting", "Ignore_players", value: false, "Turrets will not target players.", mode);
			IgnoreTames = Add(plugin, "Targeting", "Ignore_tames", value: false, "Turrets will not target tamed creatures.", mode);
			IgnoreFriendlyDvergr = Add(plugin, "Targeting", "Ignore_friendly_Dvergr", value: false, "Turrets will ignore Dvergr unless they are hostile to at least one player.", mode);
			IgnoredIdentitiesImmune = Add(plugin, "Targeting", "Ignored_identities_immune_to_projectiles", value: false, "Ignored players, tames, and friendly Dvergr cannot be damaged by Turret projectiles.", mode);
			((ConditionalConfigSync)sync).AddConfigEntry<bool>(Enabled, (ConfigSyncMode)0);
			((ConditionalConfigSync)sync).AddConfigEntry<bool>(ServerAuthority, (ConfigSyncMode)0);
		}

		private SyncedConfigEntry<T> Add<T>(BaseUnityPlugin plugin, string section, string key, T value, string description, ConfigSyncMode mode)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_0022: Invalid comparison between Unknown and I4
			//IL_0029: Expected O, but got Unknown
			return ((ConditionalConfigSync)sync).AddConfigEntry<T>(plugin.Config, section, key, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), mode, (int)mode == 1);
		}
	}
	[HarmonyPatch(typeof(Turret), "HasAmmo")]
	internal static class TurretHasAmmoPatch
	{
		private static void Postfix(Turret __instance, ref bool __result)
		{
			if (TurretsRedoPlugin.Settings.Enabled.Value && TurretsRedoPlugin.Settings.InfiniteAmmo.Value && ((AccessTools.Field(typeof(Turret), "m_maxAmmo").GetValue(__instance) is int num && num != 0) ? 1 : 0) > (false ? 1 : 0))
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(Turret), "ShootProjectile")]
	internal static class TurretProjectilePatch
	{
		private static readonly Dictionary<Turret, int> AmmoBeforeShot = new Dictionary<Turret, int>();

		private static void Prefix(Turret __instance)
		{
			if (!TurretsRedoPlugin.Settings.Enabled.Value || !TurretsRedoPlugin.Settings.InfiniteAmmo.Value)
			{
				return;
			}
			object? value = AccessTools.Field(typeof(Turret), "m_nview").GetValue(__instance);
			ZNetView val = (ZNetView)((value is ZNetView) ? value : null);
			int num = ((AccessTools.Field(typeof(Turret), "m_maxAmmo").GetValue(__instance) is int num2) ? num2 : 0);
			if (!((Object)(object)val == (Object)null) && val.IsOwner() && num > 0)
			{
				int num3 = val.GetZDO().GetInt(ZDOVars.s_ammo, 0);
				AmmoBeforeShot[__instance] = num3;
				if (num3 <= 0)
				{
					val.GetZDO().Set(ZDOVars.s_ammo, 1, false);
				}
			}
		}

		private static void Finalizer(Turret __instance)
		{
			RestoreAmmo(__instance);
		}

		private static void Postfix(Turret __instance)
		{
			RestoreAmmo(__instance);
			ApplyProjectileChanges(__instance);
		}

		private static void RestoreAmmo(Turret turret)
		{
			if (AmmoBeforeShot.TryGetValue(turret, out var value))
			{
				AmmoBeforeShot.Remove(turret);
				object? value2 = AccessTools.Field(typeof(Turret), "m_nview").GetValue(turret);
				ZNetView val = (ZNetView)((value2 is ZNetView) ? value2 : null);
				if ((Object)(object)val != (Object)null && val.IsOwner() && val.IsValid())
				{
					val.GetZDO().Set(ZDOVars.s_ammo, value, false);
				}
			}
		}

		private static void ApplyProjectileChanges(Turret __instance)
		{
			//IL_0082: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: 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_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: 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_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: 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)
			TurretConfig settings = TurretsRedoPlugin.Settings;
			object? value = AccessTools.Field(typeof(Turret), "m_lastProjectile").GetValue(__instance);
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			Projectile val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<Projectile>());
			if ((Object)(object)val2 == (Object)null || !settings.Enabled.Value)
			{
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(Projectile), "m_vel");
			Vector3 val3 = ((fieldInfo.GetValue(val2) is Vector3 val4) ? val4 : Vector3.zero);
			float num = ((Vector3)(ref val3)).magnitude;
			if (settings.ProjectileSpeedEnabled.Value)
			{
				num *= Mathf.Max(0f, 1f + settings.ProjectileSpeedPercent.Value / 100f);
			}
			object? value2 = AccessTools.Field(typeof(Turret), "m_eye").GetValue(__instance);
			GameObject val5 = (GameObject)((value2 is GameObject) ? value2 : null);
			if ((Object)(object)val5 == (Object)null || num <= 0f)
			{
				return;
			}
			Vector3 val6 = val5.transform.forward;
			object? value3 = AccessTools.Field(typeof(Turret), "m_target").GetValue(__instance);
			Character val7 = (Character)((value3 is Character) ? value3 : null);
			if (settings.LeadShotEnabled.Value && (Object)(object)val7 != (Object)null)
			{
				object? value4 = AccessTools.Field(typeof(Character), "m_collider").GetValue(val7);
				CapsuleCollider val8 = (CapsuleCollider)((value4 is CapsuleCollider) ? value4 : null);
				Vector3 val9;
				if (!((Object)(object)val8 == (Object)null))
				{
					Bounds bounds = ((Collider)val8).bounds;
					val9 = ((Bounds)(ref bounds)).center;
				}
				else
				{
					val9 = ((Component)val7).transform.position;
				}
				Vector3 val10 = val9;
				Vector3 targetVelocity = GetTargetVelocity(val7);
				float num2 = Vector3.Distance(val5.transform.position, val10) / num;
				for (int i = 0; i < 3; i++)
				{
					Vector3 val11 = val10 + targetVelocity * num2;
					num2 = Vector3.Distance(val5.transform.position, val11) / num;
				}
				Vector3 val12 = val10 + targetVelocity * num2 - val5.transform.position;
				val6 = ((Vector3)(ref val12)).normalized;
			}
			if (!settings.RemoveVanillaSpread.Value)
			{
				float vanillaSpread = GetVanillaSpread(__instance);
				float vanillaViewDistance = GetVanillaViewDistance(__instance);
				float configuredViewDistance = GetConfiguredViewDistance(__instance);
				float spread = CompensateSpread(vanillaSpread, vanillaViewDistance, configuredViewDistance);
				val6 = ApplySpread(val6, spread);
			}
			fieldInfo.SetValue(val2, val6 * num);
		}

		private static Vector3 GetTargetVelocity(Character target)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			object? value = AccessTools.Field(typeof(Character), "m_body").GetValue(target);
			Rigidbody val = (Rigidbody)((value is Rigidbody) ? value : null);
			if (!((Object)(object)val == (Object)null))
			{
				return val.linearVelocity;
			}
			return Vector3.zero;
		}

		private static float GetVanillaSpread(Turret turret)
		{
			object? value = AccessTools.Field(typeof(Turret), "m_lastAmmo").GetValue(turret);
			return ((ItemData)(((value is ItemData) ? value : null)?)).m_shared.m_attack.m_projectileAccuracy ?? 0f;
		}

		private static float GetVanillaViewDistance(Turret turret)
		{
			if (TurretUpdatePatch.Defaults.TryGetValue(turret, out var value))
			{
				return value.ViewDistance;
			}
			return GetFloat(turret, "m_viewDistance");
		}

		private static float GetConfiguredViewDistance(Turret turret)
		{
			return GetFloat(turret, "m_viewDistance");
		}

		private static float GetFloat(Turret turret, string fieldName)
		{
			object value = AccessTools.Field(typeof(Turret), fieldName).GetValue(turret);
			if (value is float)
			{
				return (float)value;
			}
			return 0f;
		}

		private static float CompensateSpread(float vanillaSpread, float vanillaViewDistance, float configuredViewDistance)
		{
			if (vanillaSpread <= 0f || vanillaViewDistance <= 0f || configuredViewDistance <= 0f)
			{
				return 0f;
			}
			float num = vanillaViewDistance / configuredViewDistance;
			return 57.29578f * Mathf.Atan(Mathf.Tan(vanillaSpread * ((float)Math.PI / 180f)) * num);
		}

		private static Vector3 ApplySpread(Vector3 direction, float spread)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_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)
			if (spread <= 0f)
			{
				return direction;
			}
			Vector3 val = Vector3.Cross(direction, Vector3.up);
			if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
			{
				val = Vector3.right;
			}
			float num = Random.Range(0f - spread, spread);
			float num2 = Random.Range(0f - spread, spread);
			direction = Quaternion.AngleAxis(num, Vector3.up) * direction;
			return Quaternion.AngleAxis(num2, val) * direction;
		}
	}
	[HarmonyPatch(typeof(Turret), "OnDestroyed")]
	internal static class TurretDestroyedPatch
	{
		private static readonly HashSet<Turret> ReturnedAmmo = new HashSet<Turret>();

		private static void Prefix(Turret __instance)
		{
			if (!TurretsRedoPlugin.Settings.Enabled.Value || !TurretsRedoPlugin.Settings.InfiniteAmmo.Value)
			{
				return;
			}
			object? value = AccessTools.Field(typeof(Turret), "m_nview").GetValue(__instance);
			ZNetView val = (ZNetView)((value is ZNetView) ? value : null);
			int num = ((AccessTools.Field(typeof(Turret), "m_maxAmmo").GetValue(__instance) is int num2) ? num2 : 0);
			if (!((Object)(object)val == (Object)null) && val.IsOwner() && num > 0 && !ReturnedAmmo.Contains(__instance))
			{
				ReturnedAmmo.Add(__instance);
				if (val.IsValid())
				{
					val.GetZDO().Set(ZDOVars.s_ammo, 1, false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(BaseAI), "CanSenseTarget", new Type[]
	{
		typeof(Transform),
		typeof(Vector3),
		typeof(float),
		typeof(float),
		typeof(float),
		typeof(bool),
		typeof(bool),
		typeof(Character),
		typeof(bool),
		typeof(bool)
	})]
	internal static class TurretTargetPatch
	{
		private static void Postfix(Transform me, Character target, ref bool __result)
		{
			if (TurretsRedoPlugin.Settings.Enabled.Value && __result && !((Object)(object)target == (Object)null) && !((Object)(object)me == (Object)null) && !((Object)(object)((Component)me).GetComponent<Turret>() == (Object)null) && IsIgnoredIdentity(target))
			{
				__result = false;
			}
		}

		internal static bool IsIgnoredIdentity(Character target)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Invalid comparison between Unknown and I4
			TurretConfig settings = TurretsRedoPlugin.Settings;
			if ((Object)(object)target == (Object)null)
			{
				return false;
			}
			if (settings.IgnorePlayers.Value && target.IsPlayer())
			{
				return true;
			}
			if (settings.IgnoreTames.Value && target.IsTamed())
			{
				return true;
			}
			if (settings.IgnoreFriendlyDvergr.Value && (int)target.GetFaction() == 10)
			{
				return !IsHostileToAnyPlayer(target);
			}
			return false;
		}

		internal static bool IsProjectileImmune(Character target)
		{
			if (TurretsRedoPlugin.Settings.IgnoredIdentitiesImmune.Value)
			{
				return IsIgnoredIdentity(target);
			}
			return false;
		}

		private static bool IsHostileToAnyPlayer(Character target)
		{
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if ((Object)(object)allPlayer != (Object)null && BaseAI.IsEnemy(target, (Character)(object)allPlayer))
				{
					return true;
				}
			}
			return false;
		}
	}
	internal sealed class TurretDefaults
	{
		internal readonly float TurnRate;

		internal readonly float ViewDistance;

		internal readonly float AttackCooldown;

		internal readonly float HorizontalAngle;

		internal readonly float VerticalAngle;

		internal readonly bool TargetPlayers;

		internal readonly bool TargetTamed;

		internal TurretDefaults(Turret turret)
		{
			TurnRate = GetFloat(turret, "m_turnRate");
			ViewDistance = GetFloat(turret, "m_viewDistance");
			AttackCooldown = GetFloat(turret, "m_attackCooldown");
			HorizontalAngle = GetFloat(turret, "m_horizontalAngle");
			VerticalAngle = GetFloat(turret, "m_verticalAngle");
			TargetPlayers = GetBool(turret, "m_targetPlayers");
			TargetTamed = GetBool(turret, "m_targetTamed");
		}

		private static float GetFloat(Turret turret, string name)
		{
			object value = AccessTools.Field(typeof(Turret), name).GetValue(turret);
			if (value is float)
			{
				return (float)value;
			}
			return 0f;
		}

		private static bool GetBool(Turret turret, string name)
		{
			object value = AccessTools.Field(typeof(Turret), name).GetValue(turret);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}
	}
	[HarmonyPatch(typeof(Turret), "FixedUpdate")]
	internal static class TurretUpdatePatch
	{
		internal static readonly Dictionary<Turret, TurretDefaults> Defaults = new Dictionary<Turret, TurretDefaults>();

		private static void Prefix(Turret __instance)
		{
			if (!Defaults.TryGetValue(__instance, out var value))
			{
				value = new TurretDefaults(__instance);
				Defaults[__instance] = value;
			}
			TurretConfig settings = TurretsRedoPlugin.Settings;
			if (!settings.Enabled.Value)
			{
				Restore(__instance, value);
				return;
			}
			SetFloat(__instance, "m_turnRate", value.TurnRate * (settings.TurnSpeedEnabled.Value ? PercentMultiplier(settings.TurnSpeedPercent.Value) : 1f));
			SetFloat(__instance, "m_viewDistance", value.ViewDistance * (settings.ViewDistanceEnabled.Value ? PercentMultiplier(settings.ViewDistancePercent.Value) : 1f));
			SetFloat(__instance, "m_attackCooldown", value.AttackCooldown / (settings.AttackCooldownEnabled.Value ? CooldownRateMultiplier(settings.AttackCooldownPercent.Value) : 1f));
			SetFloat(__instance, "m_horizontalAngle", settings.HorizontalAngle.Value);
			SetFloat(__instance, "m_verticalAngle", settings.VerticalAngle.Value);
			SetBool(__instance, "m_targetPlayers", value.TargetPlayers && !settings.IgnorePlayers.Value);
			SetBool(__instance, "m_targetTamed", value.TargetTamed && !settings.IgnoreTames.Value);
		}

		private static void Restore(Turret turret, TurretDefaults defaults)
		{
			SetFloat(turret, "m_turnRate", defaults.TurnRate);
			SetFloat(turret, "m_viewDistance", defaults.ViewDistance);
			SetFloat(turret, "m_attackCooldown", defaults.AttackCooldown);
			SetFloat(turret, "m_horizontalAngle", defaults.HorizontalAngle);
			SetFloat(turret, "m_verticalAngle", defaults.VerticalAngle);
			SetBool(turret, "m_targetPlayers", defaults.TargetPlayers);
			SetBool(turret, "m_targetTamed", defaults.TargetTamed);
		}

		private static void SetFloat(Turret turret, string name, float value)
		{
			AccessTools.Field(typeof(Turret), name).SetValue(turret, Mathf.Max(0f, value));
		}

		private static void SetBool(Turret turret, string name, bool value)
		{
			AccessTools.Field(typeof(Turret), name).SetValue(turret, value);
		}

		private static float PercentMultiplier(float percent)
		{
			return Mathf.Max(0f, 1f + percent / 100f);
		}

		private static float CooldownRateMultiplier(float percent)
		{
			return Mathf.Max(0.01f, 1f + percent / 100f);
		}
	}
}