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 TurretsShootEverything v1.0.0
TurretsShootEverything.dll
Decompiled 11 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("TurretsShootEverything")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("TurretsShootEverything")] [assembly: AssemblyTitle("TurretsShootEverything")] [assembly: AssemblyVersion("1.0.0.0")] [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 TurretsShootEverything { internal static class ModInfo { public const string GUID = "yourname.TurretsShootEverything"; public const string NAME = "TurretsShootEverything"; public const string VERSION = "1.0.0"; } [BepInPlugin("yourname.TurretsShootEverything", "TurretsShootEverything", "1.0.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static Settings Cfg; private void Awake() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Cfg = new Settings(((BaseUnityPlugin)this).Config); new Harmony("yourname.TurretsShootEverything").PatchAll(typeof(Plugin).Assembly); Log.LogInfo((object)"TurretsShootEverything 1.0.0 loaded."); } private void Start() { foreach (PluginInfo value in Chainloader.PluginInfos.Values) { string obj = value.Metadata.Name ?? ""; if (obj.IndexOf("ToilHead", StringComparison.OrdinalIgnoreCase) >= 0) { Log.LogInfo((object)("Detected ToilHead (" + value.Metadata.GUID + ") - turret-head enemies will be treated like any other enemy.")); } if (obj.IndexOf("FairAI", StringComparison.OrdinalIgnoreCase) >= 0) { Log.LogInfo((object)("Detected FairAI (" + value.Metadata.GUID + ") - no AI methods are patched by this mod, so there is no overlap.")); } } } } internal class Settings { public readonly ConfigEntry<bool> Enabled; public readonly ConfigEntry<float> Range; public readonly ConfigEntry<int> Damage; public readonly ConfigEntry<float> FireInterval; public readonly ConfigEntry<float> ChargeTime; public readonly ConfigEntry<bool> SpareEnemiesWithOwnTurret; public readonly ConfigEntry<string> IgnoredEnemies; private HashSet<string> _ignored = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public Settings(ConfigFile cfg) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Expected O, but got Unknown Enabled = cfg.Bind<bool>("General", "Enabled", true, "Turrets also shoot enemies/monsters (players are still handled by the vanilla turret logic)."); Range = cfg.Bind<float>("Targeting", "Range", 30f, new ConfigDescription("Maximum distance at which turrets pick enemy targets.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); Damage = cfg.Bind<int>("Targeting", "DamagePerShot", 1, new ConfigDescription("Damage dealt to an enemy per bullet.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>())); FireInterval = cfg.Bind<float>("Targeting", "FireInterval", 0.21f, new ConfigDescription("Seconds between bullets (vanilla turret = 0.21).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2f), Array.Empty<object>())); ChargeTime = cfg.Bind<float>("Targeting", "ChargeTime", 1f, new ConfigDescription("Seconds a turret tracks an enemy before it starts firing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); SpareEnemiesWithOwnTurret = cfg.Bind<bool>("Compatibility", "SpareEnemiesWithOwnTurret", false, "If true, enemies that carry their own Turret component (e.g. ToilHead's turret-heads) are NOT targeted by other turrets."); IgnoredEnemies = cfg.Bind<string>("Compatibility", "IgnoredEnemies", "", "Comma-separated enemy names (EnemyType.enemyName) that turrets should never shoot. Example: Docile Locust Bees,Manticoil"); IgnoredEnemies.SettingChanged += delegate { Rebuild(); }; Rebuild(); } private void Rebuild() { _ignored = new HashSet<string>(StringComparer.OrdinalIgnoreCase); string[] array = IgnoredEnemies.Value.Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { _ignored.Add(text); } } } public bool IsIgnored(string enemyName) { return _ignored.Contains(enemyName ?? ""); } } [HarmonyPatch(typeof(Turret), "Update")] internal static class TurretUpdatePatch { [HarmonyPostfix] private static void Postfix(Turret __instance) { TurretEnemyTargeting turretEnemyTargeting = default(TurretEnemyTargeting); if (!((Component)__instance).TryGetComponent<TurretEnemyTargeting>(ref turretEnemyTargeting)) { ((Component)__instance).gameObject.AddComponent<TurretEnemyTargeting>(); } } } internal class TurretEnemyTargeting : MonoBehaviour { private Turret _turret; private EnemyAI _target; private float _scanTimer; private float _chargeTimer; private float _fireTimer; private float _lostTimer; private void Awake() { _turret = ((Component)this).GetComponent<Turret>(); } private void LateUpdate() { //IL_004b: 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_00cb: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_turret == (Object)null || !Plugin.Cfg.Enabled.Value) { return; } NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } if (!_turret.turretActive || (int)_turret.turretMode != 0) { ResetTarget(); return; } _scanTimer -= Time.deltaTime; if ((Object)(object)_target == (Object)null || !IsValid(_target)) { ResetTarget(); if (_scanTimer <= 0f) { _scanTimer = 0.25f; _target = FindTarget(); } if ((Object)(object)_target == (Object)null) { return; } } Vector3 point = AimPoint(_target); if (!HasLineOfSight(point)) { _lostTimer += Time.deltaTime; if (_lostTimer > 0.5f) { ResetTarget(); } return; } _lostTimer = 0f; RotateTowards(point); _chargeTimer += Time.deltaTime; if (!(_chargeTimer < Plugin.Cfg.ChargeTime.Value)) { _fireTimer -= Time.deltaTime; if (_fireTimer <= 0f) { _fireTimer = Plugin.Cfg.FireInterval.Value; Shoot(point); } } } private void ResetTarget() { _target = null; _chargeTimer = 0f; _fireTimer = 0f; _lostTimer = 0f; } private static Vector3 AimPoint(EnemyAI e) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) return ((Component)e).transform.position + Vector3.up * 1f; } private Vector3 Origin() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_turret.aimPoint != (Object)null)) { return ((Component)_turret).transform.position + Vector3.up * 1.5f; } return _turret.aimPoint.position; } private bool IsValid(EnemyAI e) { //IL_0092: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)e == (Object)null || e.isEnemyDead || !((Component)e).gameObject.activeInHierarchy) { return false; } if ((Object)(object)e.enemyType == (Object)null || !e.enemyType.canDie) { return false; } if (Plugin.Cfg.IsIgnored(e.enemyType.enemyName)) { return false; } if ((Object)(object)((Component)_turret).GetComponentInParent<EnemyAI>() == (Object)(object)e) { return false; } if (Plugin.Cfg.SpareEnemiesWithOwnTurret.Value && (Object)(object)((Component)e).GetComponentInChildren<Turret>() != (Object)null) { return false; } Vector3 val = ((Component)e).transform.position - ((Component)_turret).transform.position; return ((Vector3)(ref val)).sqrMagnitude <= Plugin.Cfg.Range.Value * Plugin.Cfg.Range.Value; } private EnemyAI FindTarget() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) RoundManager instance = RoundManager.Instance; if ((Object)(object)instance == (Object)null || instance.SpawnedEnemies == null) { return null; } EnemyAI result = null; float num = float.MaxValue; foreach (EnemyAI spawnedEnemy in instance.SpawnedEnemies) { if (IsValid(spawnedEnemy)) { Vector3 val = ((Component)spawnedEnemy).transform.position - ((Component)_turret).transform.position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (!(sqrMagnitude >= num) && HasLineOfSight(AimPoint(spawnedEnemy))) { result = spawnedEnemy; num = sqrMagnitude; } } } return result; } private bool HasLineOfSight(Vector3 point) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Origin(); int num = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-5)); return !Physics.Linecast(val, point, num, (QueryTriggerInteraction)1); } private void RotateTowards(Vector3 point) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //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_0022: 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_0056: Unknown result type (might be due to invalid IL or missing references) Transform turretRod = _turret.turretRod; if (!((Object)(object)turretRod == (Object)null)) { Vector3 val = point - turretRod.position; val.y = 0f; if (!(((Vector3)(ref val)).sqrMagnitude < 0.01f)) { turretRod.rotation = Quaternion.RotateTowards(turretRod.rotation, Quaternion.LookRotation(val), 360f * Time.deltaTime); } } } private void Shoot(Vector3 point) { //IL_0000: 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_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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = point - Origin(); Vector3 normalized = ((Vector3)(ref val)).normalized; if ((Object)(object)_turret.bulletParticles != (Object)null) { _turret.bulletParticles.Play(); } if ((Object)(object)_turret.mainAudio != (Object)null && (Object)(object)_turret.firingSFX != (Object)null) { _turret.mainAudio.PlayOneShot(_turret.firingSFX); } try { _target.HitEnemyOnLocalClient(Plugin.Cfg.Damage.Value, normalized, (PlayerControllerB)null, true, -1); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Hit on " + _target.enemyType.enemyName + " failed: " + ex.Message)); ResetTarget(); } } } }