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

FREE AbandonedBases : 2.0.2 2.0.2

Нет прав для скачивания
C#:
using Facepunch;
using Facepunch.Math;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Plugins.AbandonedBasesExtensionMethods;
using Rust;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("Abandoned Bases", "https://discord.gg/NUXhMfyc", "2.0.2")]
    [Description("Allows bases to become raidable when the owner becomes inactive")]
    public class AbandonedBases : RustPlugin {
#region Variables
        private new const string Name = "Abandoned Bases";
        [PluginReference]
        Plugin Economics, ServerRewards, IQEconomic, RaidableBases, Clans, Friends, Notify, AdvancedAlerts, ZoneManager, SkillTree;
        private void OnNewSave(string filename) {
            newSave = true;
        }
        private void Init() {
            Instance = this;
            TryInvokeMethod(Unsubscribe);
        }
        private void OnServerInitialized(bool isStartup) {
            TryInvokeMethod(RegisterPermissions);
            TryInvokeMethod(RegisterCommands);
            TryInvokeMethod(LoadData);
            TryInvokeMethod(config.Validate);
            TryInvokeMethod(UpdateLastSeen);
            TryInvokeMethod(StartNotificationTimer);
            TryInvokeMethod(BlockZoneManagerZones);
            SetupAbandonedRoutine();
        }
        private void Unload() {
            TryInvokeMethod(StopAbandonedCoroutine);
            TryInvokeMethod(SaveData);
            TryInvokeMethod(DestroyAll);
            TryInvokeMethod(DelaySettings.Clear);
            data = null;
            config = null;
            Instance = null;
            AbandonedBasesExtensionMethods.ExtensionMethods.p = null;
        }
        private List<string> ID_FLOORS = new List<string> {
            "floor", "floor.frame", "floor.grill", "floor.ladder.hatch", "floor.triangle", "floor.triangle.frame", "floor.triangle.grill", "floor.triangle.ladder.hatch"
        }
        ;
        private List<string> ID_DQD = new List<string> {
            "foundation", "foundation.triangle", "roof.triangle", "roof"
        }
        ;
        private enum Response {
            Delete, Success, Skipped, Unknown
        }
        private Coroutine reportCoroutine;
        private bool DebugMode {
            get;
            set;
        }
        private bool newSave {
            get;
            set;
        }
        private bool purgeDay {
            get;
            set;
        }
        private StoredData data {
            get;
            set;
        }
        private StringBuilder _sb {
            get;
            set;
        }
        = new StringBuilder();
        private static AbandonedBases Instance {
            get;
            set;
        }
        private Coroutine abandonedCoroutine {
            get;
            set;
        }
        private List<ulong> AbandonedSleepers {
            get;
            set;
        }
        = new List<ulong>();
        private List<string> _waitingList {
            get;
            set;
        }
        = new List<string>();
        private List<AbandonedBuilding> AbandonedBuildings {
            get;
            set;
        }
        = new List<AbandonedBuilding>();
        private Dictionary<uint, AbandonedBuilding> AbandonedReferences {
            get;
            set;
        }
        = new Dictionary<uint, AbandonedBuilding>();
        private Dictionary<BuildingPrivlidge, List<BaseEntity>> _buildings {
            get;
            set;
        }
        = new Dictionary<BuildingPrivlidge, List<BaseEntity>>();
        private Dictionary<ulong, List<Notification>> _notifications = new Dictionary<ulong, List<Notification>>();
        public class Notification {
            public BasePlayer player;
            public string messageEx;
        }
        private class StoredData {
            [JsonProperty("Last Seen", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<ulong, int> LastSeen {
                get;
                set;
            }
            = new Dictionary<ulong, int>();
            [JsonProperty("Cooldown", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<ulong, float> Cooldowns {
                get;
                set;
            }
            = new Dictionary<ulong, float>();
            [JsonProperty("Activities", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<ActivityInfo> Activity {
                get;
                set;
            }
            = new List<ActivityInfo>();
            public string LastRunTime {
                get;
                set;
            }
            = DateTime.MinValue.ToString();
            public StoredData() {
            }
        }
        public class Payment {
            public Payment(List<CustomCostOptions> options, BasePlayer player) {
                userId = player.userID;
                this.player = player;
                this.options = options;
            }
            public Payment(double cost, BasePlayer player) {
                userId = player.userID;
                this.player = player;
                this.cost = cost;
            }
            public double cost {
                get;
                set;
            }
            public ulong userId {
                get;
                set;
            }
            public List<CustomCostOptions> options {
                get;
                set;
            }
            public BasePlayer player {
                get;
                set;
            }
        }
        private class ActivityInfo {
            [JsonProperty(PropertyName = "owners", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<ulong> owners {
                get;
                set;
            }
            = new List<ulong>();
            [JsonProperty(PropertyName = "permission")]
            public string aipermission {
                get;
                set;
            }
            = string.Empty;
            public int total {
                get;
                set;
            }
            public ActivityInfo() {
            }
            public ActivityInfo(List<ulong> owners) {
                if (!owners.IsNullOrEmpty()) {
                    this.owners = owners;
                    int limit = int.MinValue;
                    foreach (ulong ownerId in this.owners) {
                        var purge = PurgeSettings.Find(ownerId.ToString());
                        if (purge?.Limit > limit) {
                            aipermission = string.IsNullOrEmpty(purge.Permission) ? string.Empty : purge.Permission.ToLower();
                            limit = purge.Limit;
                        }
                    }
                }
                else this.owners = new List<ulong>();
            }
            public bool IsExpired() {
                if (string.IsNullOrEmpty(aipermission)) {
                    return true;
                }
                foreach (var purge in config.Purges) {
                    if (aipermission.Equals(purge.Permission, StringComparison.OrdinalIgnoreCase)) {
                        return total >= purge?.Limit;
                    }
                }
                return true;
            }
            public bool Equals(List<ulong> owners) {
                if (owners.IsNullOrEmpty()) return false;
                //this.owners.IsNullOrEmpty();
                foreach (ulong ownerId in this.owners) {
                    if (ownerId.HasPermission("abandonedbases.exclude")) {
                        continue;
                    }
                    if (!owners.Contains(ownerId)) {
                        return false;
                    }
                }
                return true;
            }
            public static ActivityInfo Find(List<ulong> owners, List<ActivityInfo> source) {
                foreach (var ai in source) {
                    if (ai.Equals(owners)) {
                        return ai;
                    }
                }
                return new ActivityInfo(owners);
            }
        }
        private class DelaySettings {
            private static Dictionary<ulong, DelaySettings> PvpDelay {
                get;
                set;
            }
            = new Dictionary<ulong, DelaySettings>();
            public AbandonedBuilding Building {
                get;
                set;
            }
            public Timer Timer {
                get;
                set;
            }
            public static bool TryGetValue(ulong userid, out DelaySettings delaySettings) {
                return PvpDelay.TryGetValue(userid, out delaySettings);
            }
            public static bool Has(ulong userid) {
                return PvpDelay.ContainsKey(userid);
            }
            public static void Remove(BasePlayer player) {
                DelaySettings ds;
                if (PvpDelay.TryGetValue(player.userID, out ds)) {
                    if (ds.Timer != null && !ds.Timer.Destroyed) {
                        ds.Timer.Callback.Invoke();
                        ds.Timer.Destroy();
                    }
                    PvpDelay.Remove(player.userID);
                }
            }
            public static void Add(AbandonedBuilding abandonedBuilding, BasePlayer player) {
                if (config.Abandoned.PVPDelay <= 0f) {
                    Message(player, abandonedBuilding.AllowPVP ? "OnPlayerExit" : "OnPlayerExitPVE");
                    return;
                }
                DelaySettings ds;
                if (!PvpDelay.TryGetValue(player.userID, out ds)) {
                    ulong userid = player.userID;
                    PvpDelay[userid] = ds = new DelaySettings {
                        Timer = Instance.timer.Once(config.Abandoned.PVPDelay, () => {
                            Interface.CallHook("OnPlayerPvpDelayExpiredII", player, userid, abandonedBuilding.center, abandonedBuilding.intruders, abandonedBuilding.entities);
                            PvpDelay.Remove(userid);
                        }
                        ), Building = abandonedBuilding
                    }
                    ;
                    Message(player, "DoomAndGloom", _("PVPFlag", player.UserIDString), config.Abandoned.PVPDelay);
                    return;
                }
                ds.Timer.Reset();
            }
            public static void Clear() => PvpDelay.Clear();
        }
        private class AbandonedBuilding : FacepunchBehaviour {
            public HashSet<uint> buildingIDs {
                get;
                set;
            }
            = new HashSet<uint>();
            public List<BaseEntity> entities {
                get;
                set;
            }
            = new List<BaseEntity>();
            private List<SphereEntity> spheres {
                get;
                set;
            }
            = new List<SphereEntity>();
            private List<Vector3> foundations {
                get;
                set;
            }
            = new List<Vector3>();
            public List<BasePlayer> intruders {
                get;
                set;
            }
            = new List<BasePlayer>();
            private List<StorageContainer> containers {
                get;
                set;
            }
            = new List<StorageContainer>();
            private Dictionary<BaseEntity, ulong> _entityOwners {
                get;
                set;
            }
            = new Dictionary<BaseEntity, ulong>();
            private MapMarkerGenericRadius genericMarker {
                get;
                set;
            }
            = null;
            private VendingMachineMapMarker vendingMarker {
                get;
                set;
            }
            = null;
            private PluginTimers timer {
                get;
                set;
            }
            public Vector3 center {
                get;
                set;
            }
            private float DespawnTime {
                get;
                set;
            }
            private float radius {
                get;
                set;
            }
            private bool markerCreated {
                get;
                set;
            }
            public bool killed {
                get;
                set;
            }
            public bool AllowPVP {
                get;
                set;
            }
            public bool IsExpired {
                get;
                set;
            }
            private SphereCollider _collider {
                get;
                set;
            }
            private Payment payment {
                get;
                set;
            }
            private List<string> groups = new List<string>();
            private GameObject go {
                get;
                set;
            }
            private float cancelCooldownTime {
                get;
                set;
            }
            private bool isCanceled {
                get;
                set;
            }
            public bool InRange(Vector3 target) => AbandonedBases.InRange(target, center, radius);
            public static bool AddRange(List<BaseEntity> entities, List<StorageContainer> containers, List<Vector3> foundations, List<Vector3> walls) {
                var floors = new List<Vector3>();
                foreach (var e in entities) {
                    if (e.ShortPrefabName == "foundation" || e.ShortPrefabName == "foundation.triangle") {
                        if (config.Abandoned.Twig || (e as BuildingBlock).grade != BuildingGrade.Enum.Twigs) {
                            foundations.Add(e.transform.position);
                        }
                    }
                    else if (e.ShortPrefabName == "wall" || e.ShortPrefabName == "wall.half" || e.ShortPrefabName == "wall.window") {
                        if (config.Abandoned.Twig || (e as BuildingBlock)?.grade != BuildingGrade.Enum.Twigs) {
                            walls.Add(e.transform.position);
                        }
                    }
                    else if (Instance.ID_FLOORS.Contains(e.ShortPrefabName)) {
                        floors.Add(e.transform.position);
                    }
                    else if (IsBox(e) || e is BuildingPrivlidge) {
                        containers.Add(e as StorageContainer);
                    }
                }
                if (foundations.Count == 0)  // support for WaterBases plugin
                {
                    foundations = floors;
                }
                if (foundations.Count == 0 || foundations.Count < config.Abandoned.FoundationLimit || walls.Count < config.Abandoned.WallLimit) {
                    return false;
                }
                return true;
            }
            public void Setup(PluginTimers timer, List<Vector3> foundations, List<BaseEntity> entities, List<StorageContainer> containers, List<ulong> ownerIds, Vector3 center, Payment payment, float radius) {
                Instance.AbandonedBuildings.Add(this);
                AllowPVP = config.Abandoned.AllowPVP;
                this.foundations = foundations;
                this.containers = containers;
                this.entities = entities;
                this.payment = payment;
                this.center = center;
                this.radius = radius;
                this.timer = timer;
                Interface.Oxide.NextTick(() => {
                    TryInvokeMethod(SetupEntities);
                    TryInvokeMethod(SetupPosition);
                    TryInvokeMethod(SetupCollider);
                    TryInvokeMethod(CompleteConvertPayment);
                    TryInvokeMethod(Announce);
                    TryInvokeMethod(Refresh);
                    TryInvokeMethod(SpawnNpcs);
                    TryInvokeMethod(SetupSleepers);
                    UpdateActivity(ownerIds);
                    Puts("Opened abandoned player base at {0} with {1} entities", center, entities.Count);
                    cancelCooldownTime = Time.time + config.Abandoned.CancelCooldown;
                }
                );
            }
            private void Awake() {
                go = gameObject;
                go.name = "AbandonedBase";
            }
            private void OnDestroy() {
                if (groups.Count > 0) {
                    Plugin BotReSpawn = Interface.Oxide.RootPluginManager.GetPlugin("BotReSpawn");
                    groups.ForEach(group => BotReSpawn?.Call("RemoveGroupSpawn", group));
                }
            }
            private void OnTriggerEnter(Collider collider) {
                if (collider == null) {
                    return;
                }
                var entity = collider.ToBaseEntity();
                if (entity is BasePlayer) {
                    var player = entity as BasePlayer;
                    if (!intruders.Contains(player)) {
                        intruders.Add(player);
                        Message(player, AllowPVP ? "OnPlayerEntered" : "OnPlayerEnteredPVE");
                    }
                    Interface.CallHook("OnPlayerEnteredAbandonedBase", player, transform.position, AllowPVP, center, intruders, entities);
                }
                else if (entity is BaseMountable) {
                    var m = entity as BaseMountable;
                    GetMountedPlayers(m).ForEach(player => {
                        if (!intruders.Contains(player)) {
                            intruders.Add(player);
                            Message(player, AllowPVP ? "OnPlayerEntered" : "OnPlayerEnteredPVE");
                        }
                        Interface.CallHook("OnPlayerEnteredAbandonedBase", player, center, AllowPVP, intruders, entities);
                    }
                    );
                }
            }
            private void OnTriggerExit(Collider collider) {
                if (collider == null) {
                    return;
                }
                var entity = collider.ToBaseEntity();
                if (entity is BasePlayer) {
                    var player = entity as BasePlayer;
                    OnPlayerExit(player, player.IsDead());
                }
                else if (entity is BaseMountable) {
                    var m = entity as BaseMountable;
                    GetMountedPlayers(m).ForEach(player => OnPlayerExit(player, player.IsDead()));
                }
            }
            public void DestroyMe() {
                if (killed) {
                    return;
                }
                Interface.CallHook("OnAbandonedBaseEnded", center, AllowPVP, intruders, entities);
                killed = true;
                TryInvokeMethod(RewardPlayers);
                TryInvokeMethod(RestoreEntityOwners);
                TryInvokeMethod(RemoveReferences);
                TryInvokeMethod(CancelInvokes);
                TryInvokeMethod(KillMarkers);
                TryInvokeMethod(KillSpheres);
                Destroy(go);
                Destroy(this);
            }
            private void SetupSleepers() {
                if (!config.KillInactiveSleepers || !config.MoveInventory || payment == null) {
                    return;
                }
                var boxes = containers.Where(x => !x.IsKilled() && IsBox(x) && !x.inventory.IsFull());
                if (boxes.Count == 0) {
                    return;
                }
                var sleepers = entities.OfType<BasePlayer>().Where(x => x.IsSleeping() && !x.IsConnected && x.inventory != null);
                if (sleepers.Count == 0) {
                    return;
                }
                foreach (var sleeper in sleepers) {
                    var items = sleeper.inventory.AllItems().ToList();
                    if (items.Count == 0) continue;
                    var box = boxes.GetRandom();
                    while (!box.inventory.IsFull() && items.Count > 0) {
                        Item item = items[0];
                        if (item == null) continue;
                        if (config.MoveInventoryBlacklist.Contains(item.info.shortname)) {
                            item.RemoveFromContainer();
                            item.Remove(0f);
                        }
                        else item.MoveToContainer(box.inventory);
                        items.Remove(item);
                    }
                    if (box.inventory.IsFull()) boxes.Remove(box);
                    if (boxes.Count == 0) break;
                }
            }
            private void RewardPlayers() {
                foreach (var player in intruders) {
                    if (player != null) {
                        Rewards.Give(player, intruders.Count);
                    }
                }
            }
            private void RestoreEntityOwners() {
                if (IsExpired || _entityOwners.Count == 0) {
                    return;
                }
                foreach (var element in _entityOwners.ToList()) {
                    if (element.Key.IsKilled()) continue;
                    element.Key.OwnerID = element.Value;
                }
            }
            private void RemoveReferences() => Instance?.RemoveReferences(this, entities);
            private void CancelInvokes() {
                try {
                    CancelInvoke();
                }
                catch {
                }
            }
            public void KillMarkers() {
                vendingMarker.SafelyKill();
                genericMarker.SafelyKill();
            }
            public void KillSpheres() {
                spheres.ToList().ForEach(sphere => sphere.SafelyKill());
            }
            public void KillCollider() {
                if (_collider != null) {
                    DestroyImmediate(_collider);
                }
            }
            private void CompleteConvertPayment() => CompletePayment(payment, false);
            public void CompleteCancelPayment(Payment payment) => CompletePayment(payment, true);
            private void CompletePayment(Payment payment, bool cancel) {
                if (payment == null || payment.cost == 0 && !payment.options.IsValid()) {
                    return;
                }
                var eco = cancel ? config.Abandoned.EconomicsCancel : config.Abandoned.Economics;
                if (eco > 0 && Instance.Economics.CanCall()) {
                    if (Convert.ToBoolean(Instance.Economics?.Call("Withdraw", payment.userId.ToString(), payment.cost))) {
                        if (payment.player.IsValid()) {
                            Message(payment.player, cancel ? "EconomicsWithdrawCancel" : "EconomicsWithdraw", payment.cost);
                        }
                    }
                }
                var rp = cancel ? config.Abandoned.ServerRewardsCancel : config.Abandoned.ServerRewards;
                if (rp > 0 && Instance.ServerRewards.CanCall()) {
                    if (Convert.ToBoolean(Instance.ServerRewards?.Call("TakePoints", payment.userId, (int)payment.cost))) {
                        if (payment.player.IsValid()) {
                            Message(payment.player, cancel ? "ServerRewardPointsTakenCancel" : "ServerRewardPointsTaken", (int)payment.cost);
                        }
                    }
                }
                if (payment.options.IsValid()) {
                    TakeCustomCost(payment.player, payment.options, cancel);
                }
                if (cancel) {
                    isCanceled = config.Abandoned.Rewards.Cancel;
                }
            }
            private void TakeCustomCost(BasePlayer player, List<CustomCostOptions> options, bool cancel) {
                var sb = new StringBuilder();
                foreach (var option in options) {
                    if (option.Amount <= 0) continue;
                    var slots = player.inventory.FindItemIDs(option.Definition.itemid);
                    var amountLeft = option.Amount;
                    foreach (var slot in slots) {
                        if (slot == null || option.Skin != 0 && slot.skin != option.Skin) {
                            continue;
                        }
                        var taken = slot.amount > amountLeft ? slot.SplitItem(amountLeft) : slot;
                        taken.RemoveFromContainer();
                        taken.Remove(0f);
                        amountLeft -= taken.amount;
                        if (amountLeft <= 0) {
                            string name = string.IsNullOrEmpty(option.Name) ? slot.info.displayName.english : option.Name;
                            sb.Append(string.Format("{0} {1}", option.Amount, name)).Append(", ");
                            break;
                        }
                    }
                }
                if (sb.Length > 2) {
                    sb.Length -= 2;
                    Message(player, cancel ? "CustomCostTakenCancel" : "CustomCostTaken", sb.ToString());
                }
            }
            public void Announce() {
                if (Instance.purgeDay) {
                    return;
                }
                var grid = PositionToGrid(center);
                foreach (var target in BasePlayer.activePlayerList) {
                    if (target.HasPermission("abandonedbases.notices")) {
                        Message(target, "Abandoned", grid);
                    }
                }
            }
            private bool NearFoundation(Vector3 a) {
                for (int i = 0; i < foundations.Count; i++) {
                    if (AbandonedBases.InRange(foundations[i], a, 3f)) {
                        return true;
                    }
                }
                return false;
            }
            public bool IsAttached(BaseEntity entity) {
                if (entity is DecayEntity) {
                    var decayEntity = entity as DecayEntity;
                    return buildingIDs.Contains(decayEntity.buildingID);
                }
                var priv = entity.GetBuildingPrivilege();
                if (priv == null) {
                    return NearFoundation(entity.transform.position);
                }
                return buildingIDs.Contains(priv.buildingID);
            }
            public void RememberOwner(BaseEntity entity) {
                Instance.AbandonedReferences[entity.net.ID] = this;
                _entityOwners[entity] = entity.OwnerID;
            }
            private void SetupEntities() {
                float invokeTime = 0f;
                foreach (var e in entities) {
                    if (e.IsKilled() || e.net == null) continue;
                    //if (e is BaseCombatEntity) TryInvokeMethod(() => SetupHealth(e as BaseCombatEntity));
                    RememberOwner(e);
                    if (e is DecayEntity) SetupDecayEntity(e as DecayEntity);
                    if (e is AutoTurret) Instance.timer.Once(invokeTime += 0.1f, () => SetupTurret(e as AutoTurret));
                    if (config.Abandoned.DespawnTime <= 0f) continue;
                    if (config.RemoveOwnership || config.RemoveOwnershipFromContainers && e is StorageContainer) e.OwnerID = 0;
                }
                Instance.Subscribe();
            }
            private void SetupDecayEntity(DecayEntity e) {
                buildingIDs.Add(e.buildingID);
            }
            /*private void SetupHealth(BaseCombatEntity e)
            {
                BuildingBlockOptions bbo;
                if (config.Abandoned.Blocks.TryGetValue(e.ShortPrefabName, out bbo))
                {
                    var block = e as BuildingBlock;
                    if (block.IsKilled()) return;
                    switch (block.grade)
                    {
                        case BuildingGrade.Enum.Twigs: block.health = bbo.Twigs; break;
                        case BuildingGrade.Enum.Wood: block.health = bbo.Wooden; break;
                        case BuildingGrade.Enum.Stone: block.health = bbo.Stone; break;
                        case BuildingGrade.Enum.Metal: block.health = bbo.Metal; break;
                        case BuildingGrade.Enum.TopTier: block.health = bbo.HQM; break;
                    }
                }
                else
                {
                    float value;
                    if (config.Abandoned.Other.TryGetValue(e.ShortPrefabName, out value))
                    {
                        e.health = value;
                    }
                }
            }*/
            private void SetupTurret(AutoTurret turret) {
                if (!config.Abandoned.AutoTurret.Enabled) {
                    return;
                }
                SetupIO(turret);
                if (payment == null && config.RemoveOwnership) turret.authorizedPlayers.Clear();
                turret.InitializeHealth(config.Abandoned.AutoTurret.Health, config.Abandoned.AutoTurret.Health);
                turret.sightRange = config.Abandoned.AutoTurret.SightRange;
                turret.aimCone = config.Abandoned.AutoTurret.AimCone;
                if (config.Abandoned.AutoTurret.RemoveWeapon) {
                    turret.AttachedWeapon = null;
                    Item slot = turret.inventory.GetSlot(0);
                    if (slot != null && (slot.info.category == ItemCategory.Weapon || slot.info.category == ItemCategory.Fun)) {
                        slot.RemoveFromContainer();
                        slot.Remove();
                    }
                }
                if (config.Abandoned.AutoTurret.Shortnames.Count > 0) {
                    if (turret.AttachedWeapon == null) {
                        var shortname = config.Abandoned.AutoTurret.Shortnames.GetRandom();
                        var itemToCreate = ItemManager.FindItemDefinition(shortname);
                        if (itemToCreate != null) {
                            Item item = ItemManager.Create(itemToCreate, 1, (ulong)itemToCreate.skins.GetRandom().id);
                            if (!item.MoveToContainer(turret.inventory, 0, false)) {
                                item.Remove();
                            }
                        }
                    }
                }
                InvokeEx(turret.UpdateAttachedWeapon, 0.1f);
                InvokeEx(() => FillAmmoTurret(turret), 0.2f);
                if (config.Abandoned.AutoTurret.Hostile) {
                    turret.SetPeacekeepermode(false);
                }
                if (!config.Abandoned.AutoTurret.RequiresPower) {
                    InvokeEx(turret.InitiateStartup, 0.3f);
                }
                if (config.Abandoned.AutoTurret.InfiniteAmmo) {
                    turret.inventory.onPreItemRemove += new Action<Item>(OnWeaponItemPreRemove);
                }
            }
            private void InvokeEx(Action action, float time) {
                timer.Once(time, () => {
                    try {
                        action.Invoke();
                    }
                    catch {
                    }
                }
                );
            }
            private void OnWeaponItemPreRemove(Item item) {
                var weapon = item.parent?.entityOwner;
                if (weapon is AutoTurret) {
                    var turret = weapon as AutoTurret;
                    InvokeEx(() => FillAmmoTurret(turret), 0.1f);
                }
            }
            private void FillAmmoTurret(AutoTurret turret) {
                if (turret.IsDestroyed) {
                    return;
                }
                if (turret.authorizedPlayers.Exists(x => x.userid.IsSteamId())) {
                    return;
                }
                var attachedWeapon = turret.GetAttachedWeapon();
                if (attachedWeapon == null) {
                    return;
                }
                int p = Math.Max(config.Abandoned.AutoTurret.Ammo, attachedWeapon.primaryMagazine.capacity);
                turret.inventory.AddItem(attachedWeapon.primaryMagazine.ammoType, p, 0uL);
                attachedWeapon.primaryMagazine.contents = attachedWeapon.primaryMagazine.capacity;
                attachedWeapon.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
                InvokeEx(turret.UpdateTotalAmmo, 0.25f);
            }
            private void SetupIO(ContainerIOEntity io) {
                io.dropsLoot = false;
                io.inventory.SetFlag(ItemContainer.Flag.NoItemInput, true);
                if (config.Abandoned.AutoTurret.HasPower) {
                    io.SetFlag(BaseEntity.Flags.Reserved8, true, false, true);
                }
            }
            private void SetupPosition() {
                if (radius <= 0 || radius < config.Abandoned.MinCustomSphereRadius) {
                    if (config.Abandoned.Dynamic) {
                        radius = Mathf.Min(config.Abandoned.MaxDynamicRadius, Mathf.Max(config.Abandoned.SphereRadius, GetRadiusFromMultiplePoints(GetPositions(), center)));
                    }
                    else radius = config.Abandoned.SphereRadius;
                }
                go.transform.position = center;
            }
            private void SetupCollider() {
                _collider = gameObject.GetComponent<SphereCollider>() ?? gameObject.AddComponent<SphereCollider>();
                _collider.radius = radius;
                _collider.isTrigger = true;
                _collider.center = Vector3.zero;
                gameObject.layer = (int)Layer.Trigger;
            }
            public void Refresh() {
                if (config.Abandoned.DespawnTime > 0f) {
                    CancelInvoke(DestroyAll);
                    Invoke(DestroyAll, config.Abandoned.DespawnTime);
                    DespawnTime = Time.realtimeSinceStartup + config.Abandoned.DespawnTime;
                }
                if (config.Abandoned.Markers) CreateMarkers();
                else markerCreated = true;
            }
            public void UpdateActivity(List<ulong> ownerIds) {
                if (config.Abandoned.DoNotDestroyManual && payment != null) {
                    IsExpired = false;
                    return;
                }
                if (!config.Abandoned.DoNotDestroy) {
                    var activity = ActivityInfo.Find(ownerIds, Instance.data.Activity);
                    if (!Instance.data.Activity.Contains(activity)) {
                        Instance.data.Activity.Add(activity);
                    }
                    activity.total++;
                    if (IsExpired = activity.IsExpired()) {
                        Instance.data.Activity.Remove(activity);
                    }
                }
            }
            private void SpawnNpcs() {
                var profiles = config.Abandoned.BotSpawnProfileNames;
                profiles.Remove("profile_name_1");
                profiles.Remove("profile_name_2");
                if (profiles.Count == 0) {
                    return;
                }
                string group = Guid.NewGuid().ToString();
                Plugin BotReSpawn = Interface.Oxide.RootPluginManager.GetPlugin("BotReSpawn");
                if (BotReSpawn == null) {
                    return;
                }
                groups.Add(group);
                BotReSpawn?.Call("AddGroupSpawn", center, profiles.GetRandom(), group, 0);
            }
            private List<Vector3> GetPositions() {
                var positions = new List<Vector3>();
                entities.RemoveAll(e => e.IsKilled());
                foreach (var e in entities) {
                    if (e.prefabID == 3234260181 || e.prefabID == 72949757 || e is SimpleBuildingBlock) {
                        positions.Add(e.transform.position);
                    }
                }
                return positions;
            }
            private void CreateMarkers() {
                if (markerCreated) {
                    return;
                }
                genericMarker = GameManager.server.CreateEntity(StringPool.Get(2849728229), center) as MapMarkerGenericRadius;
                genericMarker.alpha = 0.75f;
                genericMarker.color1 = Color.magenta;
                genericMarker.color2 = Color.magenta;
                genericMarker.radius = 0.25f;
                genericMarker.Spawn();
                vendingMarker = GameManager.server.CreateEntity(StringPool.Get(3459945130), center) as VendingMachineMapMarker;
                vendingMarker.enabled = false;
                vendingMarker.Spawn();
                if (config.Abandoned.SphereAmount > 0) {
                    for (int i = 0; i < config.Abandoned.SphereAmount; i++) {
                        var sphere = GameManager.server.CreateEntity(StringPool.Get(3211242734), center) as SphereEntity;
                        sphere.currentRadius = 1f;
                        sphere.Spawn();
                        sphere.LerpRadiusTo(radius * 2f, radius * 0.75f);
                        spheres.Add(sphere);
                    }
                }
                UpdateMarkers();
                markerCreated = true;
            }
            private void UpdateMarkers() {
                if (genericMarker != null) {
                    genericMarker.SendUpdate();
                }
                if (vendingMarker != null) {
                    if (DespawnTime == 0f) {
                        vendingMarker.markerShopName = config.Abandoned.MarkerNameSeconds.Replace(" [{time}m]", string.Empty);
                        vendingMarker.SendNetworkUpdate();
                        Invoke(UpdateMarkers, 10f);
                        return;
                    }
                    var ts = TimeSpan.FromSeconds(DespawnTime - Time.realtimeSinceStartup);
                    if (ts.TotalMinutes >= 1) {
                        string despawnText = Math.Floor(ts.TotalMinutes).ToString();
                        vendingMarker.markerShopName = config.Abandoned.MarkerName.Replace("{time}", despawnText);
                        Invoke(UpdateMarkers, 10f);
                    }
                    else {
                        string despawnText = Math.Floor(ts.TotalSeconds).ToString();
                        vendingMarker.markerShopName = config.Abandoned.MarkerNameSeconds.Replace("{time}", despawnText);
                        Invoke(UpdateMarkers, 1f);
                    }
                    vendingMarker.SendNetworkUpdate();
                }
            }
            private void DestroyAll() {
                if (IsExpired) {
                    UndoLoop(entities, hookObjects);
                }
                DestroyMe();
            }
            public static void UndoLoop(ListHashSet<DecayEntity> decayEntities, object[] hookObjects, int count = 0) {
                var entities = new List<BaseEntity>();
                foreach (DecayEntity decayEntity in decayEntities) {
                    entities.Add(decayEntity);
                }
                UndoLoop(entities, hookObjects, count);
            }
            public static void UndoLoop(List<BaseEntity> entities, object[] hookObjects, int count = 0) {
                entities.RemoveAll(e => e.IsKilled() || e.HasParent());
                entities.Sort((x, y) => (x is BuildingBlock).CompareTo(y is BuildingBlock));
                entities.Take(10).ToList().ForEach(entity => {
                    entities.Remove(entity);
                    if (entity is IOEntity) {
                        var io = entity as IOEntity;
                        io.ClearConnections();
                        if (entity is SamSite) {
                            (io as SamSite).staticRespawn = false;
                        }
                    }
                    if (entity is IItemContainerEntity) {
                        (entity as IItemContainerEntity)?.inventory?.Clear();
                    }
                    entity.SafelyKill();
                }
                );
                if (count != 0 && entities.Count != 0 && entities.Count == count) {
                    goto done;
                }
                if (entities.Count > 0) {
                    Interface.Oxide.NextTick(() => UndoLoop(entities, hookObjects, entities.Count));
                    return;
                }
                done : if (hookObjects != null) {
                    Interface.CallHook("OnAbandonedBaseDespawned", hookObjects);
                }
            }
            internal object[] hookObjects => new object[] {
                center, AllowPVP, intruders, entities
            }
            ;
            public void OnPlayerExit(BasePlayer player, bool skipDelay) {
                if (player == null || !player.IsHuman()) {
                    return;
                }
                intruders.Remove(player);
                Interface.CallHook("OnPlayerExitAbandonedBase", player, center, AllowPVP, intruders, entities);
                if (skipDelay || !AllowPVP) {
                    return;
                }
                DelaySettings.Add(this, player);
            }
            public static List<BasePlayer> GetMountedPlayers(BaseMountable m) {
                BaseVehicle vehicle = m.HasParent() ? m.VehicleParent() : m as BaseVehicle;
                if (!vehicle.IsRealNull()) {
                    return GetMountedPlayers(vehicle);
                }
                var players = new List<BasePlayer>();
                var player = m.GetMounted();
                if (!player.IsRealNull() && player.IsHuman()) {
                    players.Add(player);
                }
                return players;
            }
            private static List<BasePlayer> GetMountedPlayers(BaseVehicle vehicle) {
                var players = new HashSet<BasePlayer>();
                if (!vehicle.HasMountPoints()) {
                    var player = vehicle.GetMounted();
                    if (player?.IsHuman() == true) {
                        players.Add(player);
                    }
                    return players.ToList();
                }
                foreach (var mountPoint in vehicle.allMountPoints) {
                    var player = mountPoint.mountable?.GetMounted();
                    if (player?.IsHuman() == true) {
                        players.Add(player);
                    }
                }
                return players.ToList();
            }
            public static bool IsBox(BaseEntity entity) {
                return entity.ShortPrefabName == "box.wooden.large" || entity.ShortPrefabName == "woodbox_deployed" || entity.ShortPrefabName == "coffinstorage";
            }
            public bool HasCancelCooldown(IPlayer user) {
                if (cancelCooldownTime > Time.time) {
                    user.Reply(_("CancelCooldown", user.Id, Math.Round(cancelCooldownTime - Time.time, 2)));
                    return true;
                }
                return false;
            }
            public bool IsCompleted() {
                foreach (var container in containers) {
                    if (!container.IsKilled() && !container.inventory.IsEmpty()) {
                        return false;
                    }
                }
                return true;
            }
            public static AbandonedBuilding Get(BasePlayer victim, HitInfo hitInfo) {
                DelaySettings ds;
                if (DelaySettings.TryGetValue(victim.userID, out ds) && ds.Building != null) {
                    return CompareTo(ds.Building, Get(hitInfo));
                }
                return CompareTo(Get(victim.transform.position), Get(hitInfo));
            }
            public static AbandonedBuilding Get(BaseEntity victim, HitInfo hitInfo) {
                return CompareTo(Get(victim.transform.position), Get(hitInfo));
            }
            public static AbandonedBuilding CompareTo(AbandonedBuilding v, AbandonedBuilding a) {
                if (v == null) return a;
                if (a == null) return v;
                if (v == a) return v;
                return null;
            }
            private static AbandonedBuilding Get(HitInfo hitInfo) {
                if (hitInfo?.Initiator?.IsDestroyed == false) {
                    var abandonedBuilding = Get(hitInfo.Initiator.ServerPosition);
                    if (abandonedBuilding != null) return abandonedBuilding;
                }
                if (hitInfo?.WeaponPrefab?.IsDestroyed == false) {
                    var abandonedBuilding = Get(hitInfo.WeaponPrefab.ServerPosition);
                    if (abandonedBuilding != null) return abandonedBuilding;
                }
                if (hitInfo?.Weapon?.IsDestroyed == false) {
                    return Get(hitInfo.Weapon.ServerPosition);
                }
                return null;
            }
            public static AbandonedBuilding Get(Vector3 target) {
                foreach (var abandonedBuilding in Instance.AbandonedBuildings) {
                    if (abandonedBuilding.InRange(target)) {
                        return abandonedBuilding;
                    }
                }
                return null;
            }
        }
#endregion
#region Hooks
        private void OnPlayerConnected(BasePlayer player) {
            UpdateLastSeen(player);
            UpdateInvoke(player);
        }
        private void OnPlayerSleep(BasePlayer player) {
            UpdateLastSeen(player);
        }
        private void OnPlayerSleepEnded(BasePlayer player) {
            DelaySettings.Remove(player);
        }
        private void OnPlayerDeath(BasePlayer player, HitInfo hitInfo) {
            if (player == null || !player.IsHuman()) {
                return;
            }
            if (player.IsConnected) {
                UpdateLastSeen(player);
            }
            var abandonedBuilding = AbandonedBuilding.Get(player, hitInfo);
            if (abandonedBuilding == null) {
                return;
            }
            abandonedBuilding.OnPlayerExit(player, true);
        }
        private void OnEntitySpawned(DroppedItemContainer backpack) {
            if (!config.Abandoned.BackpacksLooted) {
                return;
            }
            NextTick(() => {
                if (backpack.IsKilled()) {
                    return;
                }
                if (DelaySettings.Has(backpack.playerSteamID) || EventTerritory(backpack.transform.position)) {
                    backpack.playerSteamID = 0;
                }
            }
            );
      
// ... [Code preview truncated due to length. Full source in attached file] ...

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