Иконка ресурса

FREE RocketTurrets : 2.0.27 2.0.27

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Random = UnityEngine.Random;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("RocketTurrets", "https://discord.gg/TrJ7jnS233", "2.0.27")]
    [Description("Allow users to covert auto turrets to fire rockets")]
    class RocketTurrets : RustPlugin {
#region Fields
        private StoredData storedData;
        private DynamicConfigFile data;
        [PluginReference]
        Plugin Clans, Friends;
        private QueueUpdater queueUpdater;
        private static Core.Libraries.Permission Permission;
        private bool hasLoaded = false;
        private static bool isUnloading;
        private static bool isCallingTargetHook = false;
        private const string ROCKET_BASIC_ITEM = "ammo.rocket.basic";
        private const string ROCKET_HV_ITEM = "ammo.rocket.hv";
        private const string ROCKET_FIRE_ITEM = "ammo.rocket.fire";
        private const string ROCKET_LAUNCHER_ITEM = "rocket.launcher";
        private const string CAMERA_ITEM = "cctv.camera";
        private const string COMPUTER_ITEM = "targeting.computer";
        private const string ROCKET_BASIC_PREFAB = "assets/prefabs/ammo/rocket/rocket_basic.prefab";
        private const string ROCKET_HV_PREFAB = "assets/prefabs/ammo/rocket/rocket_hv.prefab";
        private const string ROCKET_FIRE_PREFAB = "assets/prefabs/ammo/rocket/rocket_fire.prefab";
        private const string FIREBALL_PREFAB = "assets/bundled/prefabs/oilfireballsmall.prefab";
        private const string ROCKET_FIRE_EFFECT = "assets/prefabs/npc/patrol helicopter/effects/rocket_fire.prefab";
        private const string WEAPON_SOCKET_BONE = "WeaponAttachmentPoint";
        private const string BASIC_PERMISSION = "rocketturrets.rocket";
        private const string AA_PERMISSION = "rocketturrets.antiair";
        private const string JAVELIN_PERMISSION = "rocketturrets.javelin";
        private const string NOLIMIT_PERMISSION = "rocketturrets.unlimited";
        private const string NOAMMO_PERMISSION = "rocketturrets.unlimitedammo";
#endregion
#region Oxide Hooks
        private void Loaded() {
            isUnloading = false;
            Permission = permission;
            lang.RegisterMessages(Messages, this);
            permission.RegisterPermission(BASIC_PERMISSION, this);
            permission.RegisterPermission(AA_PERMISSION, this);
            permission.RegisterPermission(JAVELIN_PERMISSION, this);
            permission.RegisterPermission(NOAMMO_PERMISSION, this);
            permission.RegisterPermission(NOLIMIT_PERMISSION, this);
            foreach (string key in configData.VIPLimits.Keys) permission.RegisterPermission(key, this);
            data = Core.Interface.Oxide.DataFileSystem.GetFile("rocketturrets_data");
            Physics.IgnoreLayerCollision(18, 13, false);
            LoadData();
        }
        private void OnServerInitialized() => timer.In(3f, RestoreTurrets);
        private void OnNewSave(string str) => storedData.launchers.Clear();
        private void OnServerSave() {
            if (!Interface.Oxide.IsShuttingDown) {
                if (hasLoaded) {
                    for (int i = RocketTurret.allTurrets.Count - 1; i >= 0; i--) RocketTurret.allTurrets[i]?.PrepareForGameSave();
                    SaveRestore.Instance.StartCoroutine(RestoreOnSaveFinished());
                }
            }
            SaveData();
        }
        private IEnumerator RestoreOnSaveFinished() {
            while (SaveRestore.IsSaving) yield return null;
            yield return CoroutineEx.waitForEndOfFrame;
            yield return CoroutineEx.waitForEndOfFrame;
            for (int i = RocketTurret.allTurrets.Count - 1; i >= 0; i--) RocketTurret.allTurrets[i]?.RestoreAfterGameSave();
        }
        private void CanPickupEntity(AutoTurret turret, BasePlayer player) {
            if (configData.Settings.ReturnOnPickup == 0) return;
            RocketTurret rocketTurret = turret.GetComponent<RocketTurret>();
            if (rocketTurret != null) {
                ReturnResources(player, rocketTurret.type, configData.Settings.ReturnOnPickup);
                UnityEngine.Object.Destroy(rocketTurret);
            }
        }
        private object OnTurretTarget(AutoTurret turret, BaseCombatEntity baseCombatEntity) {
            if (isCallingTargetHook || turret == null || baseCombatEntity == null) return null;
            RocketTurret rocketTurret = turret.GetComponent<RocketTurret>();
            if (rocketTurret == null) return null;
            if (Vector3.Distance(baseCombatEntity.transform.position, rocketTurret.transform.position) > rocketTurret.Config.MaxTargetingDistance) return true;
            return null;
        }
        private static object CallTargetingHook(AutoTurret turret, BaseCombatEntity baseCombatEntity) {
            isCallingTargetHook = true;
            object obj = Interface.Call("OnTurretTarget", turret, baseCombatEntity);
            isCallingTargetHook = false;
            return obj;
        }
        private void Unload() {
            if (queueUpdater != null) UnityEngine.Object.Destroy(queueUpdater.gameObject);
            Physics.IgnoreLayerCollision(18, 13, true);
            SaveData();
            isUnloading = true;
            for (int i = RocketTurret.allTurrets.Count - 1; i >= 0; i--) UnityEngine.Object.Destroy(RocketTurret.allTurrets[i]);
            RocketTurret.allTurrets.Clear();
            RocketTurret[] rocketTurrets = UnityEngine.Object.FindObjectsOfType<RocketTurret>();
            for (int i = 0; i < rocketTurrets.Length; i++) UnityEngine.Object.Destroy(rocketTurrets[i]);
            Permission = null;
            configData = null;
        }
#endregion
#region Functions
        private void RestoreTurrets() {
            if (storedData.launchers.Count > 0) {
                List<BaseNetworkable> entities = BaseNetworkable.serverEntities.Where(x => x is AutoTurret).ToList();
                foreach (BaseNetworkable entity in entities) {
                    StoredData.Turret t;
                    if (storedData.launchers.TryGetValue(entity.net.ID.Value, out t)) {
                        RocketTurret.Load(entity as AutoTurret, t);
                    }
                }
            }
            queueUpdater = QueueUpdater.Create();
            hasLoaded = true;
        }
        private bool ParseType<T>(string type, out T value) {
            value = default(T);
            try {
                value = (T)System.Enum.Parse(typeof(T), type, true);
                if (System.Enum.IsDefined(typeof(T), value)) return true;
            }
            catch {
                return false;
            }
            return false;
        }
        private T FindEntityFromRay<T>(BasePlayer player) where T : Component {
            RaycastHit hit;
            if (!Physics.Raycast(player.eyes.HeadRay(), out hit, 3f)) return null;
            return hit.collider?.GetComponentInParent<T>();
        }
        private int CountTurrets(ulong userId, TurretType type) {
            int count = 0;
            for (int i = 0; i < RocketTurret.allTurrets.Count; i++) {
                RocketTurret rocketTurret = RocketTurret.allTurrets[i];
                if (rocketTurret.Turret.OwnerID == userId && rocketTurret.type == type) count++;
            }
            return count;
        }
        private int CountTurretsForBuilding(AutoTurret autoTurret) {
            BuildingManager.Building building = autoTurret.GetBuilding();
            int count = 0;
            foreach (DecayEntity decayEntity in building.decayEntities) {
                if (!(decayEntity is AutoTurret)) continue;
                if (decayEntity.GetComponent<RocketTurret>() != null) count++;
            }
            return count;
        }
        private static List<ConfigData.TurretConfig.ItemCost> GetTurretCosts(TurretType type) => type == TurretType.AA ? configData.AntiAir.Cost : type == TurretType.Basic ? configData.Basic.Cost : configData.Javelin.Cost;
        private bool HasResources(BasePlayer player, TurretType type) {
            List<ConfigData.TurretConfig.ItemCost> costs = GetTurretCosts(type);
            for (int i = 0; i < costs.Count; i++) {
                ConfigData.TurretConfig.ItemCost cost = costs[i];
                if (player.inventory.GetAmount(ItemManager.itemDictionaryByName[cost.Shortname].itemid) < cost.Amount) return false;
            }
            return true;
        }
        private void TakeResources(BasePlayer player, TurretType type) {
            List<ConfigData.TurretConfig.ItemCost> costs = GetTurretCosts(type);
            for (int i = 0; i < costs.Count; i++) {
                ConfigData.TurretConfig.ItemCost cost = costs[i];
                player.inventory.Take(null, ItemManager.itemDictionaryByName[cost.Shortname].itemid, cost.Amount);
            }
        }
        private void ReturnResources(BasePlayer player, TurretType type, float percentage) {
            List<ConfigData.TurretConfig.ItemCost> costs = GetTurretCosts(type);
            for (int i = 0; i < costs.Count; i++) {
                ConfigData.TurretConfig.ItemCost cost = costs[i];
                int amount = Mathf.RoundToInt(cost.Amount * (percentage / 100));
                if (amount == 0) continue;
                Item item = ItemManager.CreateByName(cost.Shortname, amount);
                player.GiveItem(item, BaseEntity.GiveItemReason.PickedUp);
            }
        }
        private static void DropResources(AutoTurret turret, TurretType type, float percentage) {
            List<ConfigData.TurretConfig.ItemCost> costs = GetTurretCosts(type);
            for (int i = 0; i < costs.Count; i++) {
                ConfigData.TurretConfig.ItemCost cost = costs[i];
                int amount = Mathf.CeilToInt((float)cost.Amount * (percentage / 100f));
                if (amount == 0) continue;
                if (cost.Shortname == ROCKET_LAUNCHER_ITEM) continue;
                Vector3 random = Random.onUnitSphere;
                random.y = Mathf.Abs(random.y);
                Item item = ItemManager.CreateByName(cost.Shortname, amount);
                item.Drop(turret.transform.position + Vector3.up, (Vector3.up + random) * 2f);
            }
        }
        private int GetTurretLimit(string playerId, TurretType type) {
            int count = -1;
            foreach (KeyValuePair<string, Dictionary<TurretType, int>> kvp in configData.VIPLimits) {
                if (permission.UserHasPermission(playerId, kvp.Key)) {
                    int amount = kvp.Value[type];
                    if (amount > count) count = amount;
                }
            }
            if (count == -1) count = type == TurretType.Basic ? configData.Basic.MaxPerPlayer : type == TurretType.AA ? configData.AntiAir.MaxPerPlayer : configData.Javelin.MaxPerPlayer;
            return count;
        }
#endregion
#region API
        private void TryFireRocket(AutoTurret turret) {
            RocketTurret rocketTurret = turret.GetComponent<RocketTurret>();
            if (rocketTurret != null) {
                if (Time.time >= rocketTurret.nextShotTime && turret.targetVisible) {
                    if (rocketTurret.HasAmmo()) {
                        if (rocketTurret.FireStandardRocket(turret.muzzlePos.position + (turret.muzzlePos.forward * 10))) rocketTurret.OnRocketFired();
                    }
                }
            }
        }
        private bool IsRocketTurret(AutoTurret turret) => turret.GetComponent<RocketTurret>() != null;
        private void ToggleTurretAutomation(AutoTurret turret, bool isOn) {
            RocketTurret rocketTurret = turret.GetComponent<RocketTurret>();
            if (rocketTurret != null) turret.SetIsOnline(isOn);
        }
#endregion
#region Components
        private class QueueUpdater : MonoBehaviour {
            internal static QueueUpdater Create() => new GameObject("RocketTurret.QueueUpdater").AddComponent<QueueUpdater>();
            private void Update() {
                RocketTurret.updateTurretScanQueue.RunQueue(0.5);
            }
        }
        private class UpdateRocketTurretScanQueue : ObjectWorkQueue<RocketTurret> {
            protected override void RunJob(RocketTurret turret) {
                if (!ShouldAdd(turret)) return;
                turret.TargetScan();
            }
            protected override bool ShouldAdd(RocketTurret turret) {
                if (!base.ShouldAdd(turret)) return false;
                return turret != null && turret.Turret != null && turret.Turret.IsValid();
            }
        }
#region Turrets
        private class RocketTurret : MonoBehaviour {
            internal static List<RocketTurret> allTurrets = new List<RocketTurret>();
            internal static UpdateRocketTurretScanQueue updateTurretScanQueue;
            static RocketTurret() {
                updateTurretScanQueue = new UpdateRocketTurretScanQueue();
            }
            internal AutoTurret Turret {
                get;
                private set;
            }
            internal BaseLauncher BaseLauncher {
                get;
                private set;
            }
            internal Item LauncherItem {
                get;
                private set;
            }
            internal TurretType type;
            internal Transform tr;
            private List<BaseEntity> attachments;
            private Item lastAmmoItem = null;
            private float targetAcquiredTime;
            internal float nextShotTime = Time.time;
            private bool dropResources;
            private RealTimeSinceEx timeSinceLastServerTick;
            internal virtual ConfigData.TurretConfig Config {
                get {
                    return configData.Basic;
                }
            }
            public static void Load(AutoTurret autoTurret, StoredData.Turret storedTurret) {
                if (autoTurret.GetComponent<RocketTurret>()) return;
                switch (storedTurret.type) {
                    case TurretType.Basic : RocketTurret rocketTurret = autoTurret.gameObject.AddComponent<RocketTurret>();
                    Interface.Oxide.NextTick(() => rocketTurret.OnLoad(storedTurret));
                    break;
                    case TurretType.AA : AATurret aaTurret = autoTurret.gameObject.AddComponent<AATurret>();
                    Interface.Oxide.NextTick(() => aaTurret.OnLoad(storedTurret));
                    break;
                    case TurretType.Javelin : JavelinTurret javelinTurret = autoTurret.gameObject.AddComponent<JavelinTurret>();
                    Interface.Oxide.NextTick(() => javelinTurret.OnLoad(storedTurret));
                    break;
                }
            }
            protected virtual void Awake() {
                allTurrets.Add(this);
                Turret = GetComponent<AutoTurret>();
                type = TurretType.Basic;
                tr = Turret.transform;
                attachments = Facepunch.Pool.GetList<BaseEntity>();
                BuildCosmetics();
                Turret.CancelInvoke(Turret.ServerTick);
                Turret.CancelInvoke(Turret.ScheduleForTargetScan);
                AutoTurret.updateAutoTurretScanQueue.Remove(Turret);
                InvokeHandler.InvokeRepeating(this, ServerTick, Random.Range(0f, 1f), 0.015f);
                InvokeHandler.InvokeRandomized(this, ScheduleForTargetScan, Random.Range(0f, 1f), Turret.TargetScanRate(), 0.2f);
                Turret.targetTrigger.GetComponent<SphereCollider>().radius = Config.MaxTargetingDistance;
                Turret.SetTarget(null);
            }
            private void Start() {
                AutoTurret.updateAutoTurretScanQueue.Remove(Turret);
            }
            protected virtual void OnDestroy() {
                InvokeHandler.CancelInvoke(this, ServerTick);
                InvokeHandler.CancelInvoke(this, ScheduleForTargetScan);
                RemoveCosmetics();
                if (Turret != null && !Turret.IsDestroyed) {
                    if (dropResources) DropResources(Turret, type, configData.Settings.ReturnOnRemove);
                    Turret.inventory.canAcceptItem -= CanAcceptItem;
                    Turret.inventory.onItemAddedRemoved -= OnItemAddedOrRemoved;
                    if (LauncherItem != null) {
                        LauncherItem.RemoveFromWorld();
                        LauncherItem.RemoveFromContainer();
                        LauncherItem.Remove(0f);
                    }
                    Turret.inventory.onlyAllowedItems = null;
                    Turret.inventory.canAcceptItem += Turret.CanAcceptItem;
                    Turret.inventory.onItemAddedRemoved += Turret.OnItemAddedOrRemoved;
                    Turret.AttachedWeapon = null;
                    Turret.Invoke(Turret.UpdateAttachedWeapon, 0.5f);
                    if (Turret.IsOnline()) {
                        Turret.InvokeRepeating(Turret.ServerTick, Random.Range(0f, 1f), 0.015f);
                        Turret.InvokeRandomized(Turret.ScheduleForTargetScan, Random.Range(0f, 1f), Turret.TargetScanRate(), 0.2f);
                    }
                    Turret.targetTrigger.GetComponent<SphereCollider>().radius = Turret.sightRange;
                }
                Facepunch.Pool.FreeList(ref attachments);
                allTurrets.Remove(this);
            }
            public void OnLoad(StoredData.Turret storedTurret) {
                if (BaseLauncher == null) {
                    Debug.LogError("No launcher");
                    return;
                }
                if (!string.IsNullOrEmpty(storedTurret.loadedAmmo) && BaseLauncher.primaryMagazine.ammoType.shortname != storedTurret.loadedAmmo) BaseLauncher.primaryMagazine.ammoType = ItemManager.FindItemDefinition(storedTurret.loadedAmmo);
                BaseLauncher.primaryMagazine.contents = storedTurret.loadedCapacity;
            }
#region Save Hack
            public void PrepareForGameSave() {
                if (LauncherItem != null) LauncherItem.removeTime = 1f;
            }
            public void RestoreAfterGameSave() {
                if (LauncherItem != null) LauncherItem.removeTime = 0f;
            }
#endregion
#region Cosmetics
            protected virtual void BuildCosmetics() {
                Item currentWeapon = Turret.inventory.GetSlot(0);
                bool hasLauncher = false;
                if (currentWeapon != null) {
                    if (currentWeapon.info.shortname != ROCKET_LAUNCHER_ITEM) {
                        currentWeapon.RemoveFromContainer();
                        currentWeapon.Drop(Turret.transform.position + Vector3.up, Vector3.up * 3f);
                    }
                    else {
                        BaseLauncher = currentWeapon.GetHeldEntity() as BaseLauncher;
                        hasLauncher = true;
                    }
                }
                Turret.inventory.canAcceptItem -= Turret.CanAcceptItem;
                Turret.inventory.canAcceptItem += CanAcceptItem;
                Turret.inventory.onItemAddedRemoved -= Turret.OnItemAddedOrRemoved;
                Turret.inventory.onItemAddedRemoved += OnItemAddedOrRemoved;
                List<ItemDefinition> allowedRockets = Facepunch.Pool.GetList<ItemDefinition>();
                if (Config.AllowedRockets.Contains(ROCKET_BASIC_ITEM)) allowedRockets.Add(BasicRocketDefinition);
                if (Config.AllowedRockets.Contains(ROCKET_FIRE_ITEM)) allowedRockets.Add(IncendiaryRocketDefinition);
                if (Config.AllowedRockets.Contains(ROCKET_HV_ITEM)) allowedRockets.Add(HVRocketDefinition);
                Turret.inventory.onlyAllowedItems = allowedRockets.ToArray();
                Facepunch.Pool.FreeList(ref allowedRockets);
                if (!hasLauncher) {
                    LauncherItem = ItemManager.CreateByName(ROCKET_LAUNCHER_ITEM, 1, Config.LauncherSkin);
                    MoveItemToInventory(LauncherItem);
                    BaseLauncher = LauncherItem.GetHeldEntity() as BaseLauncher;
                }
                else {
                    LauncherItem = currentWeapon;
                    if (!Turret.IsInvoking(UpdateAttachedWeapon)) Turret.Invoke(UpdateAttachedWeapon, 0.5f);
                }
                AttachToTurret(ItemManager.CreateByName(ROCKET_BASIC_ITEM), new Vector3(0.2f, 0f, -0.1f), new Vector3(0, 90, 0));
                AttachToTurret(ItemManager.CreateByName(ROCKET_BASIC_ITEM), new Vector3(-0.2f, 0f, -0.1f), new Vector3(0, 90, 0));
            }
            protected void AttachToTurret(Item item, Vector3 localPosition, Vector3 localEuler, string bone = WEAPON_SOCKET_BONE) {
                BaseEntity worldEntity = GameManager.server.CreateEntity("assets/prefabs/misc/burlap sack/generic_world.prefab", tr.position, tr.rotation, true);
                WorldItem worldItem = worldEntity as WorldItem;
                worldItem.InitializeItem(item);
                worldItem.allowPickup = false;
                worldEntity.enableSaving = false;
                worldEntity.Spawn();
                worldItem.CancelInvoke((worldItem as DroppedItem).IdleDestroy);
                item.SetWorldEntity(worldEntity);
                Rigidbody rb = worldEntity.GetComponent<Rigidbody>();
                rb.isKinematic = true;
                rb.useGravity = false;
                worldEntity.SetParent(Turret, bone);
                worldEntity.transform.localPosition = localPosition;
                worldEntity.transform.localRotation = Quaternion.Euler(localEuler);
                attachments.Add(worldEntity);
            }
            private void RemoveCosmetics() {
                for (int i = 0; i < attachments?.Count; i++) {
                    BaseEntity worldEntity = attachments[i];
                    if (worldEntity != null && !worldEntity.IsDestroyed) {
                        (worldEntity as WorldItem).DestroyItem();
                        worldEntity.Kill();
                    }
                }
            }
#endregion
#region Item Management
            private void MoveItemToInventory(Item item) {
                item.RemoveFromContainer();
                item.RemoveFromWorld();
                item.position = 0;
                item.SetParent(Turret.inventory);
                Turret.inventory.MarkDirty();
                item.MarkDirty();
                if (!Turret.IsInvoking(UpdateAttachedWeapon)) Turret.Invoke(UpdateAttachedWeapon, 0.5f);
            }
            private void OnItemAddedOrRemoved(Item item, bool added) {
                if (isUnloading) return;
                if (!added && item != null && item.info.shortname == ROCKET_LAUNCHER_ITEM) {
                    dropResources = true;
                    Destroy(this, 0.5f);
                }
            }
            private bool CanAcceptItem(Item item, int targetSlot) {
                Item slot = Turret.inventory.GetSlot(0);
                if (item.info.shortname == ROCKET_LAUNCHER_ITEM && targetSlot == 0) return true;
                if (item.info.category != ItemCategory.Ammunition || slot == null || !Turret.GetAttachedWeapon() || targetSlot == 0) return false;
                return true;
            }
            private void UpdateAttachedWeapon() {
                Item slot = Turret.inventory.GetSlot(0);
                BaseLauncher baseLauncher = null;
                if (slot != null && slot.info.category == ItemCategory.Weapon) {
                    BaseEntity heldEntity = slot.GetHeldEntity();
                    if (heldEntity != null) {
                        baseLauncher = heldEntity.GetComponent<BaseLauncher>();
                    }
                }
                Turret.SetFlag(BaseEntity.Flags.Reserved3, baseLauncher != null, false, true);
                if (baseLauncher == null) {
                    if (Turret.AttachedWeapon != null) {
                        Turret.AttachedWeapon.SetGenericVisible(false);
                        Turret.AttachedWeapon.SetLightsOn(false);
                    }
                    Turret.AttachedWeapon = null;
                    return;
                }
                baseLauncher.SetLightsOn(true);
                baseLauncher.limitNetworking = false;
                baseLauncher.SetFlag(BaseEntity.Flags.Disabled, false, false, true);
                baseLauncher.SetParent(Turret, WEAPON_SOCKET_BONE);
                baseLauncher.transform.localPosition = new Vector3(-0.15f, 0.1f, 0f);
                baseLauncher.transform.localRotation = Quaternion.Euler(180f, 95f, -52f);
                baseLauncher.SetGenericVisible(true);
                BaseLauncher = baseLauncher;
                Turret.AttachedWeapon = baseLauncher;
                Turret.totalAmmoDirty = true;
                Turret.Reload();
                Turret.UpdateTotalAmmo();
                baseLauncher.SendNetworkUpdateImmediate();
                Turret.SendNetworkUpdateImmediate();
            }
#endregion
#region Think
            private void ServerTick() {
                if (Turret == null || Turret.IsDestroyed) return;
                float timeSince = (float) timeSinceLastServerTick;
                timeSinceLastServerTick = 0;
                if (!Turret.IsOnline()) Turret.OfflineTick();
                else if (!Turret.HasTarget()) Turret.IdleTick(timeSince);
                else TargetTick();
                Turret.UpdateFacingToTarget(timeSince);
                if (Turret.totalAmmoDirty && Time.time > Turret.nextAmmoCheckTime) {
                    Turret.UpdateTotalAmmo();
                    Turret.totalAmmoDirty = false;
                    Turret.nextAmmoCheckTime = Time.time + 0.5f;
                }
            }
            private void ScheduleForTargetScan() {
                updateTurretScanQueue.Add(this);
            }
            internal void TargetScan() {
                if (Turret.IsOffline()) return;
                if (Turret.HasTarget()) {
                    if (Vector3.Distance(Turret.muzzlePos.position, Turret.target.transform.position) < Config.MinTargetingDistance || ShouldForgetTarget(Turret.target)) Turret.SetTarget(null);
                    return;
                }
                if (Turret.targetTrigger.entityContents != null) {
                    foreach (BaseEntity baseEntity in Turret.targetTrigger.entityContents) {
                        if (baseEntity != null) {
                            BaseCombatEntity component = baseEntity as BaseCombatEntity;
                            if (component != null && component.IsAlive() && Turret.InFiringArc(component) && Turret.ObjectVisible(component)) {
                                if (!CanTargetEntity(component)) continue;
                                if (Vector3.Distance(Turret.muzzlePos.position, component.transform.position) < Config.MinTargetingDistance) continue;
                                if (Turret.PeacekeeperMode()) {
                                    if (!Turret.IsEntityHostile(component)) {
                                        continue;
                                    }
                                    if (Turret.target == null) {
                                        nextShotTime = Time.time + 1f;
                                    }
                                }
                                SetTarget(component);
                                break;
                            }
                        }
                    }
                }
            }
            protected virtual bool ShouldForgetTarget(BaseCombatEntity baseCombatEntity) {
                return false;
            }
            protected void SetTarget(BaseCombatEntity component) {
                if (component != Turret.target) targetAcquiredTime = Time.realtimeSinceStartup;
                isCallingTargetHook = true;
                Turret.SetTarget(component);
                isCallingTargetHook = false;
            }
            protected virtual bool CanTargetEntity(BaseCombatEntity component) {
                if (component is AutoTurret || component is RidableHorse) return false;
                BasePlayer basePlayer = component as BasePlayer;
                if (basePlayer) {
                    if (!Config.TargetNPCs && basePlayer.IsNpc) return false;
                    if (Turret.IsAuthed(basePlayer)) return false;
                }
                BaseVehicle vehicle = component as BaseVehicle;
                if (vehicle != null) {
                    for (int i = 0; i < vehicle.mountPoints?.Count; i++) {
                        basePlayer = vehicle?.mountPoints[i]?.mountable?.GetMounted();
                        if (basePlayer && Turret.IsAuthed(basePlayer)) return false;
                    }
                }
                object obj = CallTargetingHook(Turret, component);
                if (obj is bool) return (bool)obj;
                return true;
            }
            protected void TargetTick() {
                if (Time.realtimeSinceStartup >= Turret.nextVisCheck) {
                    Turret.nextVisCheck = Time.realtimeSinceStartup + Random.Range(0.2f, 0.3f);
                    Turret.targetVisible = Turret.ObjectVisible(Turret.target);
                    if (Turret.targetVisible) {
                        Turret.lastTargetSeenTime = Time.realtimeSinceStartup;
                    }
                }
                if (Time.time >= nextShotTime && Turret.targetVisible) {
                    if (!HasAmmo()) nextShotTime = Time.time + Config.FireRate;
                    else {
                        if (Time.realtimeSinceStartup < targetAcquiredTime + Config.LockDuration) return;
                        if (FireRocket(Turret.target.transform.position, Turret.target)) OnRocketFired();
                    }
                }
                if (Turret.target.IsDead() || Time.realtimeSinceStartup - Turret.lastTargetSeenTime > 3f || Vector3.Distance(transform.position, Turret.target.transform.position) > Turret.sightRange || (Turret.PeacekeeperMode() && !Turret.IsEntityHostile(Turret.target))) {
                    SetTarget(null);
                }
            }
            internal bool HasAmmo() {
                if (!Config.RequiresAmmo || Permission.UserHasPermission(Turret.OwnerID.ToString(), NOAMMO_PERMISSION)) return true;
                if (lastAmmoItem == null || lastAmmoItem.amount == 0) {
                    for (int i = 0; i < Turret.inventory.itemList.Count; i++) {
                        Item item = Turret.inventory.itemList[i];
                        if ((item.info.shortname == ROCKET_BASIC_ITEM || item.info.shortname == ROCKET_FIRE_ITEM || item.info.shortname == ROCKET_HV_ITEM) && item.amount > 0) {
                            BaseLauncher.primaryMagazine.ammoType = item.info;
                            lastAmmoItem = item;
                            return true;
                        }
                    }
                    return false;
                }
                return true;
            }
#endregion
#region Shoot
            internal virtual bool FireRocket(Vector3 targetPos, BaseCombatEntity target = null) {
                if (Turret.IsOffline()) return false;
                BaseEntity rocket = GameManager.server.CreateEntity(GetPrefabFromItem(), Turret.muzzlePos.position, Quaternion.Euler(targetPos - Turret.muzzlePos.position));
                rocket.enableSaving = false;
                rocket.Spawn();
                Effect.server.Run(ROCKET_FIRE_EFFECT, rocket.transform.position);
                if (Config.RocketTrail) AttachFireball(rocket);
                rocket.creatorEntity = (BasePlayer.FindAwakeOrSleeping(Turret.OwnerID.ToString()) as BaseEntity) ?? Turret;
                ConfigData.BasicTurret config = Config as ConfigData.BasicTurret;
                if (config.SeekTarget) {
                    HeatSeekerRocket heatSeeker = rocket.gameObject.AddComponent<HeatSeekerRocket>();
                    heatSeeker.Initialize(target, targetPos, config.RocketSpeed, true, config.ProximityDetonation, config.DamageMultiplier);
                }
                else {
                    StandardRocket standardRocket = rocket.gameObject.AddComponent<StandardRocket>();
                    standardRocket.Initialize(target, targetPos, config.RocketSpeed, false, config.ProximityDetonation, config.DamageMultiplier);
                }
                return true;
            }
            protected void AttachFireball(BaseEntity parent) {
                FireBall fireball = GameManager.server.CreateEntity(FIREBALL_PREFAB, parent.transform.position) as FireBall;
                fireball.enableSaving = false;
                fireball.Spawn();
                Rigidbody rb = fireball.GetComponent<Rigidbody>();
                rb.useGravity = false;
                rb.isKinematic = true;
                fireball.SetParent(parent, false);
                fireball.transform.localPosition = Vector3.zero;
            }
            internal bool FireStandardRocket(Vector3 targetPos) {
                if (Turret.IsOffline()) return false;
                BaseEntity rocket = GameManager.server.CreateEntity(GetPrefabFromItem(), Turret.muzzlePos.position, Quaternion.Euler(targetPos - Turret.muzzlePos.position));
                rocket.enableSaving = false;
                rocket.Spawn();
                Effect.server.Run(ROCKET_FIRE_EFFECT, rocket.transform.position);
                rocket.creatorEntity = (BasePlayer.FindAwakeOrSleeping(Turret.OwnerID.ToString()) as BaseEntity) ?? Turret;
                StandardRocket standardRocket = rocket.gameObject.AddComponent<StandardRocket>();
                standardRocket.Initialize(null, targetPos, Config.RocketSpeed, false, false, Config.DamageMultiplier);
                return true;
            }
            internal void OnRocketFired() {
                nextShotTime = Time.time + Config.FireRate;
                if (lastAmmoItem != null) {
                    lastAmmoItem.UseItem(1);
                    if (lastAmmoItem.amount <= 0) {
                        lastAmmoItem.RemoveFromContainer();
                        lastAmmoItem.Remove(0f);
                        lastAmmoItem = null;
                    }
                }
                Turret.totalAmmoDirty = true;
            }
            protected string GetPrefabFromItem() {
                if (lastAmmoItem == null) return ROCKET_BASIC_PREFAB;
                switch (lastAmmoItem.info.shortname) {
                    case ROCKET_FIRE_ITEM : return ROCKET_FIRE_PREFAB;
                    case ROCKET_HV_ITEM : return ROCKET_HV_PREFAB;
                    case ROCKET_BASIC_ITEM : default : return ROCKET_BASIC_PREFAB;
                }
            }
#endregion
#region Definitions
            private static ItemDefinition _basicRocketDefinition;
            private static ItemDefinition _incendiaryRocketDefinition;
            private static ItemDefinition _hvRocketDefinition;
            private static ItemDefinition BasicRocketDefinition {
                get {
                    if (_basicRocketDefinition == null) _basicRocketDefinition = ItemManager.FindItemDefinition(ROCKET_BASIC_ITEM);
                    return _basicRocketDefinition;
                }
            }
            private static ItemDefinition IncendiaryRocketDefinition {
                get {
                    if (_incendiaryRocketDefinition == null) _incendiaryRocketDefinition = ItemManager.FindItemDefinition(ROCKET_FIRE_ITEM);
                    return _incendiaryRocketDefinition;
                }
            }
            private static ItemDefinition HVRocketDefinition {
                get {
                    if (_hvRocketDefinition == null) _hvRocketDefinition = ItemManager.FindItemDefinition(ROCKET_HV_ITEM);
                    return _hvRocketDefinition;
                }
            }
#endregion
        }
        private class AATurret : RocketTurret {
            internal override ConfigData.TurretConfig Config => configData.AntiAir;
            protected override void Awake() {
                base.Awake();
                type = TurretType.AA;
                Turret.targetTrigger.interestLayers.value |= 1 << 0 | 1 << 13 | 1 << 15 | 1 << 27;
            }
            protected override void BuildCosmetics() {
                base.BuildCosmetics();
                AttachToTurret(ItemManager.CreateByName(COMPUTER_ITEM), new Vector3(0f, 0f, -0.52f), Vector3.zero, string.Empty);
                AttachToTurret(ItemManager.CreateByName(CAMERA_ITEM), new Vector3(0.2f, 0.1f, -0.1f), new Vector3(0, 90f, 0f));
                AttachToTurret(ItemManager.CreateByName(CAMERA_ITEM), new Vector3(-0.2f, 0.1f, -0.1f), new Vector3(0, 90f, 0f));
            }
            protected override bool CanTargetEntity(BaseCombatEntity component) {
                if (component.transform.position.y < tr.position.y || component is AutoTurret || component is RidableHorse) return false;
                if (component is PatrolHelicopter) return (Config as ConfigData.AntiAirTurret).Patrol;
                if (component is BaseHelicopter) {
                    if (component is CH47Helicopter) return (Config as ConfigData.AntiAirTurret).CH47;
                    if (!(component is CH47Helicopter) && !(Config as ConfigData.AntiAirTurret).Helicopters) return false;
                    BaseHelicopter baseVehicle = component as BaseHelicopter;
                    bool hasMounted = false;
                    for (int i = 0; i < baseVehicle?.mountPoints?.Count; i++) {
                        BaseMountable mountable = baseVehicle.mountPoints[i].mountable;
                        if (mountable.AnyMounted()) {
                            hasMounted = true;
                            BasePlayer basePlayer = mountable.GetMounted();
                            if (basePlayer != null) {
                                if (Turret.IsAuthed(basePlayer)) return false;
                                object obj = CallTargetingHook(Turret, basePlayer);
                                if (obj is bool) return (bool)obj;
                            }
                        }
                    }
                    return hasMounted;
                }
                if (component is HotAirBalloon && (Config as ConfigData.AntiAirTurret).HAB) {
                    HotAirBalloon hotAirBalloon = component as HotAirBalloon;
                    bool hasMounted = false;
                    for (int i = 0; i < hotAirBalloon.children?.Count; i++) {
                        BasePlayer basePlayer = hotAirBalloon.children[i] as BasePlayer;
                        if (basePlayer != null) {
                            hasMounted = true;
                            if (Turret.IsAuthed(basePlayer)) return false;
                            object obj = CallTargetingHook(Turret, basePlayer);
                            if (obj is bool) return (bool)obj;
                        }
                    }
                    return hasMounted;
                }
                if (component is BasePlayer && (component as BasePlayer).isMounted) {
                    BaseVehicle baseVehicle = (component as BasePlayer).GetMounted().GetComponentInParent<BaseVehicle>();
                    if (baseVehicle != null) {
                        for (int i = 0; i < baseVehicle?.mountPoints?.Count; i++) {
                            BaseMountable mountable = baseVehicle.mountPoints[i].mountable;
                            if (mountable.AnyMounted()) {
                                BasePlayer basePlayer = mountable.GetMounted();
                                if (basePlayer != null) {
                                    if (Turret.IsAuthed(basePlayer)) return false;
                                    object obj = CallTargetingHook(Turret, basePlayer);
                                    if (obj is bool) return (bool)obj;
                                }
                            }
                        }
                        if (Turret.IsAuthed(component as BasePlayer)) return false;
                        object obj1 = CallTargetingHook(Turret, component as BasePlayer);
                        if (obj1 is bool) return (bool)obj1;
                        return true;
                    }
                    return false;
                }
                return false;
            }
            protected override bool ShouldForgetTarget(BaseCombatEntity baseCombatEntity) {
                return baseCombatEntity.transform.position.y < tr.position.y;
            }
            internal override bool FireRocket(Vector3 targetPos, BaseCombatEntity target = null) {
                if (Turret.IsOffline()) return false;
                BaseEntity rocket = GameManager.server.CreateEntity(GetPrefabFromItem(), Turret.muzzlePos.position, Quaternion.Euler(targetPos - Turret.muzzlePos.position));
                rocket.enableSaving = false;
                rocket.Spawn();
                Effect.server.Run(ROCKET_FIRE_EFFECT, rocket.transform.position);
                if (Config.RocketTrail) AttachFireball(rocket);
                rocket.creatorEntity = (BasePlayer.FindAwakeOrSleeping(Turret.OwnerID.ToString()) as BaseEntity) ?? Turret;
                ConfigData.AntiAirTurret config = Config as ConfigData.AntiAirTurret;
                HeatSeekerRocket heatSeeker = rocket.gameObject.AddComponent<HeatSeekerRocket>();
                heatSeeker.Initialize(target, targetPos, config.RocketSpeed, true, true, config.DamageMultiplier);
                return true;
            }
        }
        private class JavelinTurret : RocketTurret {
            internal override ConfigData.TurretConfig Config => configData.Javelin;
            protected override void Awake() {
                base.Awake();
                type = TurretType.Javelin;
            }
            protected override void BuildCosmetics() {
                base.BuildCosmetics();
                AttachToTurret(ItemManager.CreateByName(COMPUTER_ITEM), new Vector3(0f, 0, -0.52f), Vector3.zero, string.Empty);
            }
            internal override bool FireRocket(Vector3 targetPos, BaseCombatEntity target = null) {
                if (Turret.IsOffline()) return false;
                BaseEntity rocket = GameManager.server.CreateEntity(GetPrefabFromItem(), Turret.muzzlePos.position, Quaternion.Euler(targetPos - Turret.muzzlePos.position));
                rocket.enableSaving = false;
                rocket.Spawn();
                Effect.server.Run(ROCKET_FIRE_EFFECT, rocket.transform.position);
                if (Config.RocketTrail) AttachFireball(rocket);
                rocket.creatorEntity = (BasePlayer.FindAwakeOrSleeping(Turret.OwnerID.ToString()) as BaseEntity) ?? Turret;
                ConfigData.BasicTurret config = Config as ConfigData.BasicTurret;
                JavelinRocket javelinRocket = rocket.gameObject.AddComponent<JavelinRocket>();
                javelinRocket.Initialize(target, targetPos, config.RocketSpeed, config.SeekTarget, config.ProximityDetonation, config.DamageMultiplier);
                return true;
            }
        }
#endregion
#region Rockets
        private class StandardRocket : MonoBehaviour {
            protected ServerProjectile projectile;
            protected TimedExplosive explosive;
            protected Transform tr;
            protected BaseCombatEntity target;
            internal List<Rust.DamageTypeEntry> damageTypes = Facepunch.Pool.GetList<Rust.DamageTypeEntry>();
            protected float speed;
            private const int DAMAGE_LAYERS = 1 << 8 | 1 << 11 | 1 << 13 | 1 << 15 | 1 << 17 | 1 << 21 | 1 << 27 | 1 << 30;
            private void Awake() {
                projectile = GetComponent<ServerProjectile>();
                explosive = GetComponent<TimedExplosive>();
                damageTypes.AddRange(explosive.damageTypes);
                explosive.damageTypes.Clear();
                projectile.gravityModifier = 0f;
                explosive.CancelInvoke(explosive.Explode);
                explosive.Invoke(explosive.Explode, 30f);
                tr = projectile.transform;
            }
            protected virtual void OnDestroy() {
                DamageUtil.RadiusDamage(explosive.creatorEntity, explosive.LookupPrefab(), explosive.CenterPoint(), explosive.minExplosionRadius, explosive.explosionRadius, damageTypes, DAMAGE_LAYERS, true);
                if (explosive.creatorEntity != null && damageTypes != null) {
                    float damageAmount = 0f;
                    foreach (Rust.DamageTypeEntry damageType in damageTypes) {
                        damageAmount += damageType.amount;
                    }
                }
                Facepunch.Pool.FreeList(ref damageTypes);
            }
            internal virtual void Initialize(BaseCombatEntity target, Vector3 targetPosition, float speed, bool seekTarget, bool proximityDetonation, float damageMultiplier) {
                this.target = target;
                this.speed = speed;
                ScaleDamage(damageMultiplier);
                tr.LookAt(targetPosition);
                projectile.InitializeVelocity(tr.forward * speed);
            }
            internal void ScaleDamage(float damageMultiplier) {
                foreach (Rust.DamageTypeEntry damageType in damageTypes) damageType.amount *= damageMultiplier;
            }
        }
        private class HeatSeekerRocket : StandardRocket {
            protected Vector3 lastTargetPosition;
            internal override void Initialize(BaseCombatEntity target, Vector3 targetPosition, float speed, bool seekTarget, bool proximityDetonation, float damageMultiplier) {
                this.target = target;
                this.speed = speed;
                ScaleDamage(damageMultiplier);
                tr.LookAt(targetPosition);
                InvokeHandler.InvokeRepeating(this, AimThink, 0f, 0.15f);
                if (proximityDetonation) InvokeHandler.InvokeRepeating(this, CheckProximity, 0.05f, 0.05f);
            }
            protected void AimThink() {
                if (target == null || target.IsDead()) return;
                if (target.transform.position == lastTargetPosition) return;
                tr.LookAt(target.transform.position);
                projectile.InitializeVelocity(tr.forward * speed);
                lastTargetPosition = target.transform.position;
            }
            protected void CheckProximity() {
                if (target == null || target.IsDead() || Vector3.Distance(tr.position, target.transform.position) < 0.5f) {
                    explosive.Explode();
                    return;
                }
            }
        }
        private class JavelinRocket : HeatSeekerRocket {
            private bool seekTarget = false;
 
// ... [Code preview truncated due to length. Full source in attached file] ...

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху