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

FREE AbandonedBases : 2.0.8 2.0.8

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6

/*
*  <----- End-User License Agreement ----->
*  
*  You may not copy, modify, merge, publish, distribute, sublicense, or sell copies of This Software without the Developer’s consent
*  
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
*  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
*  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*
*  Developer: nivex (mswenson82@yahoo.com)
*
*  Copyright © 2022-2023 nivex
*/
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", "nivex", "2.0.8")]
    [Description("Allows bases to become raidable when the owner becomes inactive")]
    public class AbandonedBases : RustPlugin {
#region Variables
        [PluginReference]
        Plugin Backpacks, Economics, ServerRewards, IQEconomic, RaidableBases, Clans, Friends, Notify, AdvancedAlerts, ZoneManager, SkillTree;
        private new const string Name = "Abandoned Bases";
        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 List<string> TrueDamage = new List<string> {
            "Barricade", "SimpleBuildingBlock", "IceFence", "TeslaCoil", "BaseTrap", "GunTrap", "FlameTurret", "FogMachine", "SamSite", "AutoTurret"
        }
        ;
        private Coroutine reportCoroutine;
        private bool DebugMode {
            get;
            set;
        }
        private bool newSave {
            get;
            set;
        }
        private bool purgeDay {
            get;
            set;
        }
        private StoredData data {
            get;
            set;
        }
        = new StoredData();
        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<UserConversion> _conversions {
            get;
            set;
        }
        = new List<UserConversion>();
        private List<AbandonedBuilding> AbandonedBuildings {
            get;
            set;
        }
        = new List<AbandonedBuilding>();
        private Dictionary<ulong, List<Notification>> _notifications {
            get;
            set;
        }
        = new Dictionary<ulong, List<Notification>>();
        private Dictionary<ulong, AbandonedBuilding> AbandonedReferences {
            get;
            set;
        }
        = new Dictionary<ulong, AbandonedBuilding>();
        private Dictionary<BuildingPrivlidge, List<BaseEntity>> _buildings {
            get;
            set;
        }
        = new Dictionary<BuildingPrivlidge, List<BaseEntity>>();
        public class UserConversion {
            public string userid;
            public Coroutine co;
            public List<ulong> owners;
            public UserConversion(string userid, List<ulong> owners, Coroutine co) {
                this.owners = owners;
                this.userid = userid;
                this.co = co;
            }
            public bool Exists(IPlayer user, List<ulong> owners) {
                if (co == null) {
                    return false;
                }
                return userid == user.Id || this.owners.Exists(owners.Contains);
            }
        }
        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 Between Conversion", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<ulong, DateTime> CooldownBetweenConversion {
                get;
                set;
            }
            = new Dictionary<ulong, DateTime>();
            [JsonProperty("Cooldown Between Cancel", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<ulong, DateTime> CooldownBetweenCancel {
                get;
                set;
            }
            = new Dictionary<ulong, DateTime>();
            [JsonProperty("Cooldown Between Events", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<ulong, DateTime> CooldownBetweenEvents {
                get;
                set;
            }
            = new Dictionary<ulong, DateTime>();
            [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(BasePlayer player, double cost = 0, List<CustomCostOptions> options = null) {
                userId = player.userID;
                this.options = options;
                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 perm {
                get;
                set;
            }
            = string.Empty;
            [JsonProperty(PropertyName = "total")]
            public int total {
                get;
                set;
            }
            public ActivityInfo() {
            }
            public ActivityInfo(List<ulong> owners) {
                this.owners = owners;
                SetPermission();
            }
            public int GetLimit() {
                if (string.IsNullOrEmpty(perm) || !perm.PermissionExists()) {
                    SetPermission();
                }
                foreach (var purge in config.Purges) {
                    if (purge.Permission.Equals(perm, StringComparison.OrdinalIgnoreCase)) {
                        if (purge.NoPurge) {
                            return 0;
                        }
                        return purge.Limit;
                    }
                }
                return 0;
            }
            private void SetPermission() {
                var limit = int.MinValue;
                foreach (var owner in this.owners) {
                    var purge = PurgeSettings.Find(owner);
                    if (purge?.Permission == null) {
                        continue;
                    }
                    if (purge.Limit > limit) {
                        perm = purge.Permission;
                        limit = purge.Limit;
                    }
                    if (purge.Limit <= 0) {
                        perm = purge.Permission;
                        break;
                    }
                }
            }
            public bool SameOwners(List<ulong> owners) {
                foreach (var owner in this.owners) {
                    if (!owners.Contains(owner)) {
                        return false;
                    }
                }
                return true;
            }
            public static ActivityInfo Find(List<ulong> owners, List<ActivityInfo> activity) {
                ActivityInfo result = null;
                int j = int.MinValue;
                foreach (var other in activity) {
                    if (other.SameOwners(owners)) {
                        int k = other.GetLimit();
                        if (k > j) {
                            result = other;
                            j = k;
                        }
                    }
                }
                if (result == null) {
                    result = new ActivityInfo(owners);
                }
                return result;
            }
        }
        private class DelaySettings {
            public static Dictionary<ulong, DelaySettings> PvpDelay {
                get;
                set;
            }
            = new Dictionary<ulong, DelaySettings>();
            public AbandonedBuilding Building {
                get;
                set;
            }
            public Timer Timer {
                get;
                set;
            }
            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;
                    Interface.CallHook("OnPlayerPvpDelayStart", player, userid, abandonedBuilding.center, abandonedBuilding.intruders, abandonedBuilding.entities);
                    PvpDelay[userid] = ds = new DelaySettings {
                        Timer = abandonedBuilding.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);
                }
                else ds.Timer.Reset();
            }
        }
        private class AbandonedBuilding : FacepunchBehaviour {
            internal class EntityOwner {
                public BaseEntity Entity;
                public ulong OwnerID;
                public EntityOwner(BaseEntity entity) {
                    Entity = entity;
                    OwnerID = entity.OwnerID;
                }
            }
            internal List<ulong> IsAllowed {
                get;
                set;
            }
            = new List<ulong>();
            internal List<ulong> Messages {
                get;
                set;
            }
            = new List<ulong>();
            internal HashSet<uint> buildingIDs {
                get;
                set;
            }
            = new HashSet<uint>();
            internal List<BuildingPrivlidge> privs {
                get;
                set;
            }
            = new List<BuildingPrivlidge>();
            internal List<ulong> owners {
                get;
                set;
            }
            = new List<ulong>();
            internal List<BaseEntity> entities {
                get;
                set;
            }
            = new List<BaseEntity>();
            internal List<SphereEntity> spheres {
                get;
                set;
            }
            = new List<SphereEntity>();
            internal List<Vector3> compound {
                get;
                set;
            }
            = new List<Vector3>();
            internal List<Vector3> foundations {
                get;
                set;
            }
            = new List<Vector3>();
            internal List<BasePlayer> intruders {
                get;
                set;
            }
            = new List<BasePlayer>();
            internal List<StorageContainer> containers {
                get;
                set;
            }
            = new List<StorageContainer>();
            internal Dictionary<ulong, EntityOwner> EntityOwners {
                get;
                set;
            }
            = new Dictionary<ulong, EntityOwner>();
            internal MapMarkerGenericRadius genericMarker {
                get;
                set;
            }
            = null;
            internal VendingMachineMapMarker vendingMarker {
                get;
                set;
            }
            = null;
            internal bool IsOwnerLocked {
                get;
                set;
            }
            internal bool DisableEventCooldown {
                get;
                set;
            }
            internal PluginTimers timer {
                get;
                set;
            }
            internal BaseEntity anchor {
                get;
                set;
            }
            internal DateTime DespawnDateTime {
                get;
                set;
            }
            internal float radius {
                get;
                set;
            }
            internal bool markerCreated {
                get;
                set;
            }
            internal bool isDestroyed {
                get;
                set;
            }
            internal bool IsClaimed {
                get;
                set;
            }
            internal bool AllowPVP {
                get;
                set;
            }
            internal bool IsExpired {
                get;
                set;
            }
            internal SphereCollider _collider {
                get;
                set;
            }
            internal Payment payment {
                get;
                set;
            }
            internal List<string> groups {
                get;
                set;
            }
            = new List<string>();
            internal GameObject go {
                get;
                set;
            }
            internal float cancelCooldownTime {
                get;
                set;
            }
            internal bool isCanceled {
                get;
                set;
            }
            internal string currentName {
                get;
                set;
            }
            internal ulong currentId {
                get;
                set;
            }
            internal string previousName {
                get;
                set;
            }
            internal ulong previousId {
                get;
                set;
            }
            internal bool canReassign {
                get;
                set;
            }
            = true;
            internal ActivityInfo activity {
                get;
                set;
            }
            internal int lootAmount {
                get;
                set;
            }
            internal Coroutine _coroutine {
                get;
                set;
            }
            internal AbandonedBases MyInstance {
                get;
                set;
            }
            internal bool LockBaseToFirstAttacker => AllowPVP ? config.Abandoned.LockBaseToFirstAttackerPVP : config.Abandoned.LockBaseToFirstAttackerPVE;
            internal bool EjectFromLockedBase => AllowPVP ? config.Abandoned.EjectLockedPVP : config.Abandoned.EjectLockedPVE;
            internal string GetGrid() => PhoneController.PositionToGridCoord(center);
            internal Vector3 _center {
                get;
                set;
            }
            internal Vector3 center {
                get {
                    if (!anchor.IsKilled()) {
                        _center = anchor.transform.position;
                    }
                    return _center;
                }
                set {
                    _center = value;
                }
            }
            public bool InRange(Vector3 from) => AbandonedBases.InRange(from, center, radius);
            public bool NearCompound(Vector3 from) => compound.Exists(to => AbandonedBases.InRange(from, to, 3f));
            public bool NearFoundation(Vector3 from) => foundations.Exists(to => AbandonedBases.InRange(from, to, 3f));
            public static bool AddRange(List<BaseEntity> entities, List<StorageContainer> containers, List<Vector3> foundations, List<Vector3> compound, List<Vector3> walls) {
                var floors = new List<Vector3>();
                foreach (var e in entities.ToList()) {
                    if (e.IsKilled()) {
                        entities.Remove(e);
                        continue;
                    }
                    if (e.ShortPrefabName == "foundation" || e.ShortPrefabName == "foundation.triangle" || e.skinID == 1337424001 && e is CollectibleEntity) {
                        if (config.Abandoned.Twig || (e as BuildingBlock).grade != BuildingGrade.Enum.Twigs) {
                            foundations.Add(e.transform.position);
                            compound.Add(e.transform.position);
                        }
                    }
                    else if (e.ShortPrefabName.Contains("external.high")) {
                        compound.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 || foundations.Count < config.Abandoned.FoundationLimit || walls.Count < config.Abandoned.WallLimit) {
                    return false;
                }
                return true;
            }
            public static bool AddRange(List<BaseEntity> entities, List<StorageContainer> containers, List<Vector3> compound, ref int loot) {
                List<BaseEntity.Slot> _checkSlots = new List<BaseEntity.Slot> {
                    BaseEntity.Slot.Lock, BaseEntity.Slot.UpperModifier, BaseEntity.Slot.MiddleModifier, BaseEntity.Slot.LowerModifier
                }
                ;
                foreach (var e in entities.ToList()) {
                    if (e.IsKilled()) {
                        entities.Remove(e);
                        continue;
                    }
                    if (IsBox(e) || e is BuildingPrivlidge) {
                        containers.Add(e as StorageContainer);
                    }
                    foreach (var checkSlot in _checkSlots) {
                        var slot = e.GetSlot(checkSlot);
                        if (slot == null) continue;
                        if (entities.Contains(slot)) continue;
                        entities.Add(slot);
                    }
                    var container = e as IItemContainerEntity;
                    if (container?.inventory?.itemList != null) {
                        loot += container.inventory.itemList.Count;
                    }
                    compound.Add(e.transform.position);
                }
                return config.Abandoned.Tugboats.Loot <= 0 || loot >= config.Abandoned.Tugboats.Loot;
            }
            public void TrySetOwner(IPlayer user) {
                if (user == null || user.IsServer) {
                    return;
                }
                var player = user.Object as BasePlayer;
                if (player == null || player.IsFlying || player.limitNetworking) {
                    return;
                }
                SetOwner(player.userID, player.displayName, player.userID, player.displayName);
            }
            public void TrySetOwnerLock(BasePlayer attacker) {
                if (IsOwnerLocked && !CanBypass(attacker) && !IsAlly(attacker)) {
                    TryEjectFromLockedBase(attacker);
                    return;
                }
                if (!canReassign || !LockBaseToFirstAttacker || !attacker.IsHuman() || owners.Contains(attacker.userID) || MyInstance.HasEventCooldown(attacker, this) || IsAlly(attacker)) {
                    return;
                }
                IsOwnerLocked = true;
                canReassign = false;
                SetOwner(attacker.userID, attacker.displayName, currentId, currentName);
                Invoke(UpdateMarkers, 0f);
            }
            public bool CanBypass(BasePlayer player) {
                return !player.IsHuman() || player.IsFlying || player.limitNetworking || player.HasPermission("abandonedbases.canbypass");
            }
            public bool CanDoActions(BasePlayer player) {
                return owners.Contains(player.userID) || CanBypass(player) || IsAlly(player);
            }
            public void SetOwner(ulong newid, string newname, ulong currid, string currname) {
                previousName = currname;
                previousId = currid;
                currentName = newname;
                currentId = newid;
            }
            public void TryEjectFromLockedBase(BasePlayer player) {
                if (!EjectFromLockedBase || owners.Contains(player.userID)) {
                    return;
                }
                if (anchor == null && !NearFoundation(player.transform.position)) {
                    return;
                }
                if (anchor is Tugboat && !(player.GetParentEntity() is Tugboat)) {
                    return;
                }
                RemovePlayer(player);
            }
            public void RemovePlayer(BasePlayer player) {
                var m = player.GetMounted();
                if (m != null) {
                    m.DismountPlayer(player, true);
                }
                if (player.HasParent()) {
                    player.SetParent(null);
                }
                var position = GetEjectLocation(player.transform.position, 10f, center, radius);
                player.Teleport(player.IsFlying ? position.WithY(player.transform.position.y) : position);
                player.SendNetworkUpdateImmediate();
                intruders.Remove(player);
            }
            public static Vector3 GetEjectLocation(Vector3 a, float distance, Vector3 target, float radius) {
                var position = ((a.XZ3D() - target.XZ3D()).normalized * (radius + distance)) + target;
                // credits ZoneManager
                float y = TerrainMeta.HighestPoint.y + 250f;
                RaycastHit hit;
                if (Physics.Raycast(position + new Vector3(0f, y, 0f), Vector3.down, out hit, Mathf.Infinity, 10551313, QueryTriggerInteraction.Ignore)) {
                    position.y = hit.point.y + 0.75f;
                }
                else position.y = Mathf.Max(TerrainMeta.HeightMap.GetHeight(position), TerrainMeta.WaterMap.GetHeight(position)) + 0.75f;
                return position;
            }
            public void TryMessage(BasePlayer player, string key, params object[] args) {
                if (Messages.Contains(player.userID)) return;
                ulong userid = player.userID;
                Messages.Add(userid);
                timer.Once(10f, () => Messages.Remove(userid));
                Message(player, key, args);
            }
            public void Setup(AbandonedBases instance, IPlayer user, PluginTimers timer, List<Vector3> compound, List<Vector3> foundations, List<BaseEntity> entities, List<StorageContainer> containers, List<ulong> owners, Vector3 center, Payment payment, float radius, bool allowPVP) {
                MyInstance = instance;
                if (EjectFromLockedBase) {
                    timer.Every(1f, Protector);
                }
                TrySetOwner(user);
                markerCreated = user == null && !config.Abandoned.AutoMarkers || user != null && !config.Abandoned.ManualMarkers;
                canReassign = currentId == 0 || string.IsNullOrEmpty(currentName);
                MyInstance.AbandonedBuildings.Add(this);
                this.AllowPVP = allowPVP;
                this.compound = compound;
                this.foundations = foundations;
                this.containers = containers;
                this.entities = entities;
                this.payment = payment;
                this.owners = owners;
                this.radius = radius;
                this.timer = timer;
                this.center = center;
                Interface.Oxide.NextTick(() => {
                    TryInvokeMethod(SetupEntities);
                    TryInvokeMethod(SetupCollider);
                    TryInvokeMethod(CompleteConvertPayment);
                    TryInvokeMethod(Announce);
                    TryInvokeMethod(Refresh);
                    TryInvokeMethod(SpawnNpcs);
                    TryInvokeMethod(SetupSleepers);
                    UpdateActivity(owners);
                    cancelCooldownTime = Time.time + config.Abandoned.CancelCooldown;
                }
                );
                Interface.CallHook("OnAbandonedBaseStarted", center, AllowPVP, intruders, entities);
            }
            private void Awake() {
                go = gameObject;
            }
            private void OnDestroy() {
                if (groups.Count > 0) {
                    Plugin BotReSpawn = Interface.Oxide.RootPluginManager.GetPlugin("BotReSpawn");
                    groups.ForEach(group => BotReSpawn?.Call("RemoveGroupSpawn", group));
                }
            }
            private bool IsAlly(BasePlayer player) => MyInstance.IsAlly(player.userID, currentId);
            private void Protector() {
                if (isDestroyed || !IsOwnerLocked || intruders.Count == 0) {
                    return;
                }
                foreach (var intruder in intruders.ToList()) {
                    if (intruder.IsKilled()) {
                        intruders.Remove(intruder);
                        continue;
                    }
                    if (IsAllowed.Contains(intruder.userID)) {
                        continue;
                    }
                    if (CanDoActions(intruder)) {
                        IsAllowed.Add(intruder.userID);
                        continue;
                    }
                    TryEjectFromLockedBase(intruder);
                }
            }
            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() {
                isDestroyed = true;
                TryInvokeMethod(CancelEntitySetup);
                TryInvokeMethod(KillMarkers);
                TryInvokeMethod(KillSpheres);
                TryInvokeMethod(RewardPlayers);
                TryInvokeMethod(PowerDownAutoTurrets);
                TryInvokeMethod(RestoreEntityOwners);
                TryInvokeMethod(RemoveReferences);
                TryInvokeMethod(CancelInvokes);
                if (anchor.IsKilled()) Destroy(go);
                Destroy(this);
            }
            private void SetupSleepers() {
                if (!config.KillInactiveSleepers || !config.MoveInventory) {
                    return;
                }
                var boxes = containers.Where(x => !x.IsKilled() && IsBox(x) && !x.inventory.IsFull());
                if (boxes.Count == 0) {
                    return;
                }
                foreach (var entity in entities) {
                    if (entity.IsKilled() || !(entity is BasePlayer)) continue;
                    var target = entity as BasePlayer;
                    if (!target.IsSleeping() || target.IsConnected || target.inventory == null) continue;
                    var items = target.inventory.AllItems().ToList();
                    while (items.Count > 0 && boxes.Count > 0) {
                        var box = boxes.GetRandom();
                        if (box.inventory.IsFull()) {
                            boxes.Remove(box);
                            continue;
                        }
                        Item item = items[0];
                        items.Remove(item);
                        if (item == null) {
                            continue;
                        }
                        if (config.MoveInventoryBlacklist.Contains(item.info.shortname) || !item.MoveToContainer(box.inventory)) {
                            item.RemoveFromContainer();
                            item.Remove(0f);
                        }
                    }
                }
            }
            private void RewardPlayers() {
                var raiders = intruders.Where(player => !IsPlayerIneligible(player));
                foreach (var player in raiders) {
                    if (!isCanceled) {
                        MyInstance.GiveRewards(player, raiders.Count);
                    }
                    if (!DisableEventCooldown) {
                        SetEventCooldown(player.userID);
                    }
                }
                if (isCanceled) {
                    return;
                }
                var players = string.Join(", ", raiders.Select(x => x.displayName));
                var text = $"{currentName} ({currentId}) has raided the base with {players} at {center} ({GetGrid()}) owned by {previousName} ({previousId})";
                if (raiders.Count == 0) text = $"{currentName} ({currentId}) base has been abandoned at {center} ({GetGrid()}) by {previousName} ({previousId})";
                if (config.UseLogFile && previousId != 0uL && previousId != currentId) {
                    MyInstance.LogToFile("sar", text, MyInstance, false, true);
                }
                Puts(text);
            }
            private bool IsPlayerIneligible(BasePlayer player) {
                return player == null || player.IsFlying || player.limitNetworking || config.Abandoned.RemoveAdminRaiders && player.IsAdmin;
            }
            private void RestoreEntityOwners() {
                if (IsExpired || IsClaimed || EntityOwners.Count == 0) {
                    return;
                }
                foreach (var pair in EntityOwners.ToList()) {
                    if (pair.Value.Entity.IsKilled()) continue;
                    pair.Value.Entity.OwnerID = pair.Value.OwnerID;
                }
            }
            private void RemoveReferences() => MyInstance.RemoveReferences(this, entities);
            private void CancelInvokes() {
                try {
                    CancelInvoke(DestroyAll);
                }
                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);
            public void SetConversionCooldown(ulong userid) {
                if (config?.Abandoned.CooldownBetweenConversion > 0 && !userid.HasPermission("abandonedbases.convert.nocooldown")) {
                    MyInstance.data.CooldownBetweenConversion[userid] = DateTime.Now.AddSeconds(config.Abandoned.CooldownBetweenConversion);
                }
            }
            public void SetCancelCooldown(ulong userid) {
                if (config?.Abandoned.CooldownBetweenCancel > 0 && !userid.HasPermission("abandonedbases.convert.cancel.nocooldown")) {
                    MyInstance.data.CooldownBetweenCancel[userid] = DateTime.Now.AddSeconds(config.Abandoned.CooldownBetweenCancel);
                }
            }
            public void SetEventCooldown(ulong userid) {
                if (config?.Abandoned.CooldownBetweenEvents > 0 && !userid.HasPermission("abandonedbases.noeventcooldown")) {
                    MyInstance.data.CooldownBetweenEvents[userid] = DateTime.Now.AddSeconds(config.Abandoned.CooldownBetweenEvents);
                }
            }
            private void CompletePayment(Payment payment, bool cancel) {
                if (cancel) {
                    isCanceled = config.Abandoned.Rewards.Cancel;
                }
                if (payment == null || payment.cost == 0 && !payment.options.IsValid()) {
                    return;
                }
                var eco = cancel ? config.Abandoned.EconomicsCancel : config.Abandoned.Economics;
                if (eco > 0 && MyInstance.Economics.CanCall()) {
                    if (Convert.ToBoolean(MyInstance.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 && MyInstance.ServerRewards.CanCall()) {
                    if (Convert.ToBoolean(MyInstance.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);
                }
            }
            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.FindItemsByItemID(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;
                        if (taken == null) {
                            continue;
                        }
                        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 (MyInstance.purgeDay) {
                    return;
                }
                var grid = GetGrid();
                foreach (var target in BasePlayer.activePlayerList) {
                    if (target.HasPermission("abandonedbases.notices")) {
                        Message(target, "Abandoned", grid);
                    }
                }
            }
            public bool IsAttached(BaseEntity entity) {
                if (entity is DecayEntity) {
                    var decayEntity = entity as DecayEntity;
                    if (buildingIDs.Contains(decayEntity.buildingID)) {
                        return true;
                    }
                }
                var priv = entity.GetBuildingPrivilege();
                if (priv == null) {
                    return NearCompound(entity.transform.position);
                }
                return buildingIDs.Contains(priv.buildingID);
            }
            public void RememberOwner(BaseEntity entity) {
                if (entity.OwnerID == 0 || owners.Contains(entity.OwnerID)) {
                    MyInstance.AbandonedReferences[entity.net.ID.Value] = this;
                    EntityOwners[entity.net.ID.Value] = new EntityOwner(entity);
                    var ice = entity as IItemContainerEntity;
                    if (ice == null || ice.inventory == null) return;
                    lootAmount += ice.inventory.itemList.Count;
                }
            }
            private void CancelEntitySetup() {
                Interface.CallHook("OnAbandonedBaseEnded", center, AllowPVP, intruders, entities);
                if (_coroutine != null) {
                    ServerMgr.Instance.StopCoroutine(_coroutine);
                    _coroutine = null;
                }
            }
            private IEnumerator EntitySetup() {
                float invokeTime = 0f;
                int checks = 0;
                foreach (var e in entities.ToList()) {
                    if (++checks % 100 == 0) {
                        yield return CoroutineEx.waitForSeconds(0.025f);
                    }
                    if (e.IsKilled() || e.net == null || e.OwnerID == 0 && e is StorageContainer || e.OwnerID != 0 && !owners.Contains(e.OwnerID)) {
                        entities.Remove(e);
                        continue;
                    }
                    RememberOwner(e);
                    //if (e is BaseCombatEntity) TryInvokeMethod(() => SetupHealth(e as BaseCombatEntity));
                    if (e is BuildingPrivlidge) SetCurrentNameFromBuilding(e);
                    if (e is Tugboat) SetCurrentNameFromVehicle(e);
                    if (e is DecayEntity) SetupDecayEntity(e as DecayEntity);
                    if (e is AutoTurret) MyInstance.timer.Once(invokeTime += 0.1f, () => SetupTurret(e as AutoTurret));
                    if (config.Abandoned.DespawnTime <= 0f && !config.RemoveOwnershipZero) continue;
                    if (config.RemoveOwnership || config.RemoveOwnershipFromContainers && e is StorageContainer) e.OwnerID = 0;
                }
                var type = anchor.IsKilled() ? "BUILDING" : $"{anchor.GetType().Name.ToUpper()}";
                if (!string.IsNullOrEmpty(previousName)) {
                    Puts("{0} - {1} ({2}) at {3} with {4} entities and {5} items", type, previousName, previousId, center, entities.Count, lootAmount);
                }
                else Puts("{0} - {1} with {2} entities and {3} items", type, center, entities.Count, lootAmount);
                _coroutine = null;
            }
            private void SetCurrentNameFromBuilding(BaseEntity entity) {
                if (!string.IsNullOrEmpty(currentName)) return;
                if (entity.OwnerID.IsSteamId() && owners.Contains(entity.OwnerID)) {
                    var username = GetUserName(entity.OwnerID);
                    SetOwner(entity.OwnerID, username, entity.OwnerID, username);
                }
                privs.Add(entity as BuildingPrivlidge);
            }
            private void SetCurrentNameFromVehicle(BaseEntity entity) {
                if (!string.IsNullOrEmpty(currentName)) return;
                var priv = MyInstance.GetVehiclePrivilege(entity.children);
                if (priv == null || !priv.AnyAuthed()) return;
                foreach (var auth in priv.authorizedPlayers) {
                    var username = GetUserName(auth.userid);
                    if (string.IsNullOrEmpty(username)) continue;
                    SetOwner(auth.userid, username, auth.userid, username);
                    break;
                }
            }
            private void SetupEntities() {
                _coroutine = ServerMgr.Instance.StartCoroutine(EntitySetup());
                MyInstance.Subscribe();
            }
            private void SetupDecayEntity(DecayEntity e) {
                buildingIDs.Add(e.buildingID);
            }
            /*private void SetupHealth(BaseCombatEntity e)
            {
                if (e is BuildingBlock)
                {
                    BuildingBlockOptions bbo;
                    if (config.Abandoned.Blocks.TryGetValue(e.ShortPrefabName, out bbo))
                    {
                        var block = e as BuildingBlock;
                        if (block.IsKilled()) return;
                        block.currentGrade.construction.healthMultiplier = 1f;
                        block.SetHealthToMax();
                        System.Reflection.MethodInfo MemberwiseCloneMethod = typeof(object).GetMethod("MemberwiseClone", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                        Construction construction = (Construction)MemberwiseCloneMethod.Invoke(block.blockDefinition, null);
                        ConstructionGrade[] grades = (ConstructionGrade[])MemberwiseCloneMethod.Invoke(block.blockDefinition.grades, null);
                        block.blockDefinition = construction;
                        block.blockDefinition.grades = grades;
                        switch (block.grade)
                        {
                            case BuildingGrade.Enum.Twigs: block.currentGrade.gradeBase.baseHealth = bbo.Twigs; break;
                            case BuildingGrade.Enum.Wood: block.currentGrade.gradeBase.baseHealth = bbo.Wooden; break;
                            case BuildingGrade.Enum.Stone: block.currentGrade.gradeBase.baseHealth = bbo.Stone; break;
                            case BuildingGrade.Enum.Metal: block.currentGrade.gradeBase.baseHealth = bbo.Metal; break;
                            case BuildingGrade.Enum.TopTier: block.currentGrade.gradeBase.baseHealth = bbo.HQM; break;
                        }
                        float multiplier;
                        if (config.Abandoned.BlocksMultiplier.TryGetValue(block.grade, out multiplier))
                        {
                            block.currentGrade.construction = (Construction)MemberwiseCloneMethod.Invoke(block.currentGrade.construction, null);
                            block.currentGrade.construction
// ... [Code preview truncated due to length. Full source in attached file] ...

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