Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Turrets Redo v0.0.4
plugins\TurretsRedo\TurretsRedo.dll
Decompiled 2 days agousing 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); } } }