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

FREE LootDefender : 2.2.4 2.2.4

Нет прав для скачивания
C#:
using Facepunch;
using Facepunch.Math;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("Loot Defender", "Author Egor Blagov, Maintainer nivex", "2.2.4")]
    [Description("Defends loot from other players who dealt less damage than you.")]
    internal class LootDefender : RustPlugin {
        [PluginReference]
        Plugin PersonalHeli, Friends, Clans, RustRewards, HeliSignals, BradleyDrops, HelpfulSupply, ShoppyStock, XLevels, XPerience, SkillTree;
        private static LootDefender Instance;
        private static StringBuilder sb;
        private const ulong supplyDropSkinID = 234501;
        private const string bypassLootPerm = "lootdefender.bypass.loot";
        private const string bypassDamagePerm = "lootdefender.bypass.damage";
        private const string bypassLockoutsPerm = "lootdefender.bypass.lockouts";
        private Dictionary<ulong, List<DamageKey>> _apcAttackers = new();
        private Dictionary<ulong, List<DamageKey>> _heliAttackers = new();
        private Dictionary<ulong, ulong> _locked {
            get;
            set;
        }
        = new();
        private List<ulong> _personal {
            get;
            set;
        }
        = new();
        private List<ulong> _boss {
            get;
            set;
        }
        = new();
        private List<string> _sent {
            get;
            set;
        }
        = new();
        private static StoredData data {
            get;
            set;
        }
        = new();
        private MonumentInfo launchSite {
            get;
            set;
        }
        private List<MonumentInfo> harbors {
            get;
            set;
        }
        = new();
        private List<ulong> ownerids = new() {
            0, 1337422, 3566257, 123425345634634
        }
        ;
        public enum DamageEntryType {
            Bradley, Corpse, Heli, NPC, None
        }
        public class Lockout {
            public double Bradley {
                get;
                set;
            }
            public double Heli {
                get;
                set;
            }
            public bool Any() => Bradley > 0 || Heli > 0;
        }
        private class StoredData {
            public Dictionary<string, Lockout> Lockouts {
                get;
            }
            = new();
            public Dictionary<string, UI.Info> UI {
                get;
                set;
            }
            = new();
            [JsonProperty(PropertyName = "DamageInfo")]
            public Dictionary<ulong, DamageInfo> Damage {
                get;
                set;
            }
            = new();
            [JsonProperty(PropertyName = "LockInfo")]
            public Dictionary<ulong, LockInfo> Lock {
                get;
                set;
            }
            = new();
            public void Sanitize() {
                foreach (var (uid, damageInfo) in Damage.ToList()) {
                    damageInfo._entity = BaseNetworkable.serverEntities.Find(new(uid)) as BaseEntity;
                    if (damageInfo.damageEntryType == DamageEntryType.NPC && !config.Npc.Enabled) {
                        if (damageInfo._entity.IsValid()) {
                            damageInfo._entity.OwnerID = 0uL;
                        }
                        Damage.Remove(uid);
                    }
                    else if (damageInfo._entity == null) {
                        Damage.Remove(uid);
                    }
                    else {
                        foreach (var x in damageInfo.damageKeys) {
                            x.attacker = BasePlayer.FindByID(x.userid);
                        }
                        damageInfo.Start();
                    }
                }
                foreach (var (uid, lockInfo) in Lock.ToList()) {
                    var entity = BaseNetworkable.serverEntities.Find(new(uid)) as BaseEntity;
                    if (lockInfo.damageInfo.damageEntryType == DamageEntryType.NPC && !config.Npc.Enabled) {
                        if (entity.IsValid()) {
                            entity.OwnerID = 0uL;
                        }
                        Lock.Remove(uid);
                    }
                    else if (entity == null) {
                        Lock.Remove(uid);
                    }
                }
            }
        }
        private class DamageEntry {
            public float DamageDealt {
                get;
                set;
            }
            public DateTime Timestamp {
                get;
                set;
            }
            public string TeamID {
                get;
                set;
            }
            public DamageEntry() {
            }
            public DamageEntry(ulong teamID) {
                Timestamp = DateTime.Now;
                TeamID = teamID.ToString();
            }
            public bool IsOutdated(int timeout) => timeout > 0 && DateTime.Now.Subtract(Timestamp).TotalSeconds >= timeout;
        }
        private class DamageKey {
            public ulong userid {
                get;
                set;
            }
            public string name {
                get;
                set;
            }
            public DamageEntry damageEntry {
                get;
                set;
            }
            internal BasePlayer attacker {
                get;
                set;
            }
            public DamageKey() {
            }
            public DamageKey(BasePlayer attacker) {
                this.attacker = attacker;
                userid = attacker.userID;
                name = attacker.displayName;
            }
        }
        private class DamageInfo {
            public List<DamageKey> damageKeys {
                get;
                set;
            }
            = new();
            [JsonIgnore]
            public Dictionary<ulong, BasePlayer> interact {
                get;
                set;
            }
            = new();
            private List<ulong> participants {
                get;
                set;
            }
            = new();
            public DamageEntryType damageEntryType {
                get;
                set;
            }
            = DamageEntryType.None;
            public string NPCName {
                get;
                set;
            }
            public ulong OwnerID {
                get;
                set;
            }
            public ulong SkinID {
                get;
                set;
            }
            public DateTime start {
                get;
                set;
            }
            internal int _lockTime {
                get;
                set;
            }
            [JsonIgnore]
            internal BaseEntity _entity {
                get;
                set;
            }
            internal Vector3 _position {
                get;
                set;
            }
            internal Vector3 lastAttackedPosition {
                get;
                set;
            }
            internal ulong _uid {
                get;
                set;
            }
            [JsonIgnore]
            internal Timer _timer {
                get;
                set;
            }
            internal List<DamageKey> keys {
                get;
                set;
            }
            = new();
            List<DamageGroup> damageGroups;
            internal float FullDamage {
                get {
                    return damageKeys.Sum(x => x.damageEntry.DamageDealt);
                }
            }
            public DamageInfo() {
            }
            public DamageInfo(DamageEntryType damageEntryType, string NPCName, BaseEntity entity, DateTime start) {
                SkinID = entity.skinID;
                _entity = entity;
                _uid = entity.net.ID.Value;
                this.damageEntryType = damageEntryType;
                this.NPCName = NPCName;
                this.start = start;
                Start();
            }
            public void Start() {
                _lockTime = GetLockTime(damageEntryType);
                _timer = Instance.timer.Every(1f, CheckExpiration);
            }
            public void DestroyTimer() {
                _timer?.Destroy();
            }
            private void CheckExpiration() {
                damageKeys.ForEach(x => {
                    if (x.damageEntry.IsOutdated(_lockTime)) {
                        if (x.userid == OwnerID) {
                            Unlock();
                        }
                        keys.Add(x);
                    }
                }
                );
                keys.ForEach(x => damageKeys.Remove(x));
                keys.Clear();
            }
            public void Unlock() {
                OwnerID = 0;
                if (_entity != null) {
                    _entity.OwnerID = 0;
                }
                if (!Instance._locked.Remove(_uid)) {
                    return;
                }
                if (damageEntryType == DamageEntryType.Bradley && config.Bradley.Messages.NotifyChat) {
                    foreach (var target in BasePlayer.activePlayerList) {
                        CreateMessage(target, "BradleyUnlocked", PositionToGrid(_position));
                    }
                }
                if (damageEntryType == DamageEntryType.Heli && config.Helicopter.Messages.NotifyChat) {
                    foreach (var target in BasePlayer.activePlayerList) {
                        CreateMessage(target, "HeliUnlocked", PositionToGrid(_position));
                    }
                }
                if (damageEntryType == DamageEntryType.NPC && config.Npc.Messages.NotifyChat) {
                    foreach (var target in BasePlayer.activePlayerList) {
                        CreateMessage(target, "NpcUnlocked", NPCName, PositionToGrid(_position));
                    }
                }
            }
            private void Lock(BaseEntity entity, ulong id) {
                Instance._locked[_uid] = entity.OwnerID = OwnerID = id;
                _position = entity.transform.position;
            }
            public void AddDamage(BaseCombatEntity entity, BasePlayer attacker, DamageEntry entry, float amount) {
                entry.DamageDealt += amount;
                entry.Timestamp = DateTime.Now;
                _position = entity.transform.position;
                lastAttackedPosition = attacker.transform.position;
                if (SkinID == 0) {
                    SkinID = entity.skinID;
                }
                if (damageEntryType == DamageEntryType.NPC && !Instance.CanLockNpc(entity)) {
                    return;
                }
                if (damageEntryType == DamageEntryType.Bradley && !Instance.CanLockBradley(entity)) {
                    return;
                }
                if (entity.OwnerID.IsSteamId()) {
                    OwnerID = entity.OwnerID;
                }
                if (OwnerID != 0uL) {
                    return;
                }
                float damage = 0f;
                var grid = PositionToGrid(entity.transform.position);
                if (entry.TeamID != "0") {
                    foreach (var x in damageKeys) {
                        if (x.damageEntry.TeamID == entry.TeamID) {
                            damage += x.damageEntry.DamageDealt;
                        }
                    }
                }
                else damage = entry.DamageDealt;
                if (config.Helicopter.Threshold > 0f && entity is PatrolHelicopter) {
                    if (damage >= entity.MaxHealth() * config.Helicopter.Threshold && !Instance.HasPermission(attacker, "lootdefender.bypasshelilock")) {
                        if (config.Helicopter.Messages.NotifyLocked == true) {
                            foreach (var target in BasePlayer.activePlayerList) {
                                CreateMessage(target, "Locked Heli", grid, attacker.displayName);
                            }
                        }
                        Lock(entity, attacker.userID);
                    }
                }
                else if (config.Bradley.Threshold > 0f && entity is BradleyAPC && Instance.CanLockBradley(entity)) {
                    if (damage >= entity.MaxHealth() * config.Bradley.Threshold && !Instance.HasPermission(attacker, "lootdefender.bypassbradleylock")) {
                        if (config.Bradley.Messages.NotifyLocked == true) {
                            foreach (var target in BasePlayer.activePlayerList) {
                                CreateMessage(target, "Locked Bradley", grid, attacker.displayName);
                            }
                        }
                        Lock(entity, attacker.userID);
                    }
                }
                else if (config.Npc.Threshold > 0f && entity is BasePlayer npc && Instance.CanLockNpc(npc)) {
                    if (!npc.userID.IsSteamId() && damage >= entity.MaxHealth() * config.Npc.Threshold && !Instance.HasPermission(attacker, "lootdefender.bypassnpclock")) {
                        if (config.Npc.Messages.NotifyLocked == true) {
                            foreach (var target in BasePlayer.activePlayerList) {
                                CreateMessage(target, "Locked Npc", grid, npc.displayName, attacker.displayName);
                            }
                        }
                        Lock(entity, attacker.userID);
                    }
                }
            }
            public DamageEntry TryGet(ulong id) {
                foreach (var x in damageKeys) {
                    if (x.userid == id) {
                        return x.damageEntry;
                    }
                }
                return null;
            }
            public DamageEntry Get(BasePlayer attacker) {
                DamageEntry entry = TryGet(attacker.userID);
                if (entry == null) {
                    damageKeys.Add(new(attacker) {
                        damageEntry = entry = new(attacker.currentTeam),
                    }
                    );
                }
                return entry;
            }
            public bool isKilled;
            public void OnKilled(Vector3 position, HitInfo hitInfo, float distance) {
                if (isKilled) return;
                isKilled = true;
                SetCanInteract();
                DisplayDamageReport();
                FindLooters(position, hitInfo, distance);
            }
            private void FindLooters(Vector3 position, HitInfo hitInfo, float distance) {
                var weapon = hitInfo?.Weapon?.GetItem()?.info?.shortname ?? hitInfo?.WeaponPrefab?.ShortPrefabName ?? "";
                HashSet<ulong> looters = new();
                HashSet<ulong> users = new();
                foreach (var x in damageKeys) {
                    if (CanInteract(x.userid, x.attacker)) {
                        if (TryGet(x.userid)?.DamageDealt > 0) {
                            users.Add(x.userid);
                        }
                        looters.Add(x.userid);
                    }
                }
                foreach (var userid in users) {
                    Instance.GiveXpReward(_entity, this, userid, weapon, distance, users.Count);
                    Instance.GiveRustReward(_entity, this, userid, weapon, users.Count);
                    Instance.GiveShopReward(_entity, this, userid, weapon, distance, users.Count);
                }
                if (damageEntryType == DamageEntryType.Bradley || damageEntryType == DamageEntryType.Heli) {
                    Instance.LockoutLooters(looters, position, damageEntryType, SkinID);
                }
            }
            public void DisplayDamageReport() {
                if (damageEntryType == DamageEntryType.Bradley || damageEntryType == DamageEntryType.Heli) {
                    foreach (var target in BasePlayer.activePlayerList) {
                        if (CanDisplayReport(target)) {
                            Message(target, GetDamageReport(target.userID));
                        }
                    }
                }
                else if (damageEntryType == DamageEntryType.NPC) {
                    foreach (var x in damageKeys) {
                        if (CanDisplayReport(x.attacker)) {
                            Message(x.attacker, GetDamageReport(x.userid));
                        }
                    }
                }
            }
            private bool CanDisplayReport(BasePlayer target) {
                if (target == null || !target.IsConnected || damageEntryType == DamageEntryType.None) {
                    return false;
                }
                if (damageEntryType == DamageEntryType.Bradley) {
                    if (config.Bradley.Messages.NotifyKiller && IsParticipant(target.userID, target)) {
                        return true;
                    }
                    return config.Bradley.Messages.NotifyChat;
                }
                if (damageEntryType == DamageEntryType.Heli) {
                    if (config.Helicopter.Messages.NotifyKiller && IsParticipant(target.userID, target)) {
                        return true;
                    }
                    return config.Helicopter.Messages.NotifyChat;
                }
                if (damageEntryType == DamageEntryType.NPC) {
                    if (config.Npc.Messages.NotifyKiller && IsParticipant(target.userID, target)) {
                        return true;
                    }
                    return config.Npc.Messages.NotifyChat;
                }
                return false;
            }
            public void SetCanInteract() {
                var damageGroups = GetDamageGroups();
                var topDamageGroups = GetTopDamageGroups(damageGroups, damageEntryType);
                if (damageGroups.Count > 0) {
                    foreach (var damageGroup in damageGroups) {
                        if (topDamageGroups.Contains(damageGroup) || Instance.IsAlly(OwnerID, damageGroup.FirstDamagerDealer.userid)) {
                            interact[damageGroup.FirstDamagerDealer.userid] = damageGroup.FirstDamagerDealer.attacker;
                        }
                        else {
                            var damage = TryGet(damageGroup.FirstDamagerDealer.userid)?.DamageDealt ?? 0f;
                            var dmgRatio = damage > 0 && FullDamage > 0 ? damage / FullDamage : 0;
                            float threshold = config.Npc.Threshold;
                            if (damageEntryType == DamageEntryType.Bradley) {
                                threshold = config.Bradley.Threshold;
                            }
                            else if (damageEntryType == DamageEntryType.Heli) {
                                threshold = config.Helicopter.Threshold;
                            }
                            if (OwnerID == 0 && dmgRatio >= threshold) {
                                OwnerID = damageGroup.FirstDamagerDealer.userid;
                                interact[damageGroup.FirstDamagerDealer.userid] = damageGroup.FirstDamagerDealer.attacker;
                            }
                            else {
                                participants.Add(damageGroup.FirstDamagerDealer.userid);
                            }
                        }
                    }
                }
                this.damageGroups = damageGroups;
            }
            public string GetDamageReport(ulong targetId) {
                var userid = targetId.ToString();
                var nameKey = damageEntryType == DamageEntryType.Bradley ? _("BradleyAPC", userid) : damageEntryType == DamageEntryType.Heli ? _("Helicopter", userid) : NPCName;
                var firstDamageDealer = string.Empty;
                sb.Length = 0;
                sb.AppendLine($"{_("DamageReport", userid, $"<color= {
                    config.Report.Ok
                }
                > {
                    nameKey
                }
                </color>")}:");
                if (damageEntryType == DamageEntryType.Bradley || damageEntryType == DamageEntryType.Heli) {
                    var seconds = Math.Ceiling((DateTime.Now - start).TotalSeconds);
                    sb.AppendLine($"{_("DamageTime", userid, nameKey, seconds)}");
                }
                if (damageGroups.Count > 0) {
                    foreach (var damageGroup in damageGroups) {
                        if (interact.ContainsKey(damageGroup.FirstDamagerDealer.userid)) {
                            sb.Append($"<color={config.Report.Ok}>√</color> ");
                            firstDamageDealer = damageGroup.FirstDamagerDealer.name;
                        }
                        else {
                            sb.Append($"<color={config.Report.NotOk}>X</color> ");
                        }
                        sb.Append($"{damageGroup.ToReport(damageGroup.FirstDamagerDealer, this)}\n");
                    }
                    if (damageEntryType == DamageEntryType.NPC && !string.IsNullOrEmpty(firstDamageDealer) && damageGroups.Count > 1) {
                        sb.Append($" {_("FirstLock", userid, firstDamageDealer, config.Npc.Threshold * 100f)}");
                    }
                }
                return sb.ToString();
            }
            public bool IsParticipant(ulong userid, BasePlayer player) {
                return participants.Contains(userid) || CanInteract(userid, player);
            }
            public bool CanInteract(ulong userid, BasePlayer player) {
                if (damageEntryType == DamageEntryType.NPC && !config.Npc.Enabled) {
                    return true;
                }
                if (damageGroups == null) {
                    interact.Clear();
                    participants.Clear();
                    SetCanInteract();
                }
                if (interact.Count == 0 || interact.ContainsKey(userid)) {
                    return true;
                }
                if (Instance.IsAlly(userid, OwnerID)) {
                    interact.Add(userid, player);
                    return true;
                }
                return false;
            }
            private List<DamageGroup> GetTopDamageGroups(List<DamageGroup> damageGroups, DamageEntryType damageEntryType) {
                List<DamageGroup> topDamageGroups = new();
                if (damageGroups.Count == 0) {
                    return topDamageGroups;
                }
                var topDamageGroup = damageGroups.OrderByDescending(x => x.TotalDamage).First();
                foreach (var damageGroup in damageGroups) {
                    foreach (var playerId in damageGroup.Players) {
                        if (Instance.IsAlly(playerId, OwnerID)) {
                            topDamageGroups.Add(damageGroup);
                            break;
                        }
                    }
                }
                return topDamageGroups;
            }
            private List<DamageGroup> GetDamageGroups() {
                List<DamageGroup> damageGroups = new();
                foreach (var x in damageKeys) {
                    damageGroups.Add(new(x));
                }
                damageGroups.Sort((x, y) => y.TotalDamage.CompareTo(x.TotalDamage));
                return damageGroups;
            }
        }
        private class LockInfo {
            public DamageInfo damageInfo {
                get;
                set;
            }
            private DateTime LockTimestamp {
                get;
                set;
            }
            private int LockTimeout {
                get;
                set;
            }
            internal bool IsLockOutdated => LockTimeout > 0 && DateTime.Now.Subtract(LockTimestamp).TotalSeconds >= LockTimeout;
            public LockInfo() {
            }
            public LockInfo(DamageInfo damageInfo, int lockTimeout) {
                LockTimestamp = DateTime.Now;
                LockTimeout = lockTimeout;
                this.damageInfo = damageInfo;
            }
            public bool CanInteract(ulong userId, BasePlayer target) => damageInfo.CanInteract(userId, target);
            public string GetDamageReport(ulong userId) => damageInfo.GetDamageReport(userId);
        }
        private class DamageGroup {
            public float TotalDamage {
                get;
                set;
            }
            public DamageKey FirstDamagerDealer {
                get;
                set;
            }
            private List<ulong> additionalPlayers {
                get;
                set;
            }
            = new();
            [JsonIgnore]
            public List<ulong> Players {
                get {
                    List<ulong> players = new() {
                        FirstDamagerDealer.userid
                    }
                    ;
                    foreach (var targetId in additionalPlayers) {
                        if (!players.Contains(targetId)) {
                            players.Add(targetId);
                        }
                    }
                    return players;
                }
            }
            public DamageGroup() {
            }
            public DamageGroup(DamageKey x) {
                TotalDamage = x.damageEntry.DamageDealt;
                FirstDamagerDealer = x;
                if (RelationshipManager.ServerInstance.playerToTeam.TryGetValue(x.userid, out var team)) {
                    for (int i = 0; i < team.members.Count; i++) {
                        ulong member = team.members[i];
                        if (member == x.userid || additionalPlayers.Contains(member)) {
                            continue;
                        }
                        additionalPlayers.Add(member);
                    }
                }
                // add clan
            }
            public string ToReport(DamageKey damageKey, DamageInfo damageInfo) {
                var damage = damageInfo.TryGet(damageKey.userid)?.DamageDealt ?? 0f;
                var percent = damage > 0 && damageInfo.FullDamage > 0 ? damage / damageInfo.FullDamage * 100 : 0;
                var color = additionalPlayers.Count == 0 ? config.Report.SinglePlayer : config.Report.Team;
                var damageLine = _("Format", damageKey.userid.ToString(), damage, percent);
                return $"<color={color}>{damageKey.name}</color> {damageLine}";
            }
        }
#region Hooks
        private void OnServerSave() {
            timer.Once(15f, SaveData);
        }
        private void Init() {
            Unsubscribe(nameof(OnEventTrigger));
            Unsubscribe();
            Instance = this;
            sb = new();
            if (!string.IsNullOrEmpty(config.Lockout.Command)) AddCovalenceCommand(config.Lockout.Command, nameof(CommandLockouts));
            if (!string.IsNullOrEmpty(config.UI.Command)) AddCovalenceCommand(config.UI.Command, nameof(CommandUI));
            AddCovalenceCommand("lo", nameof(CommandLootDefender));
            RegisterPermissions();
            LoadData();
        }
        private void OnServerInitialized(bool serverinit) {
            if (config.Hackable.Enabled) {
                Subscribe(nameof(CanHackCrate));
                Subscribe(nameof(OnGuardedCrateEventEnded));
            }
            if (config.SupplyDrop.Lock) {
                if (config.SupplyDrop.LockTime > 0) {
                    if (config.SupplyDrop.NpcRandomRaids) {
                        Subscribe(nameof(OnRandomRaidWin));
                    }
                    Subscribe(nameof(OnSupplyDropLanded));
                }
                if (config.SupplyDrop.Excavator) {
                    Subscribe(nameof(OnExcavatorSuppliesRequested));
                }
                if (config.SupplyDrop.HelpfulSupply && HelpfulSupply != null) {
                    Subscribe(nameof(OnEntitySpawned));
                }
                Subscribe(nameof(OnExplosiveDropped));
                Subscribe(nameof(OnExplosiveThrown));
                Subscribe(nameof(OnSupplyDropDropped));
                Subscribe(nameof(OnCargoPlaneSignaled));
            }
            if (config.SupplyDrop.DestroyTime > 0f || config.CH47Gibs) {
                Subscribe(nameof(OnEntitySpawned));
            }
            if (config.Npc.BossMonster) {
                Unsubscribe(nameof(OnBossSpawn));
                Unsubscribe(nameof(OnBossKilled));
            }
            if (!config.Bradley.LockPersonal) {
                Subscribe(nameof(OnPersonalApcSpawned));
            }
            if (!config.Helicopter.LockPersonal) {
                Subscribe(nameof(OnPersonalHeliSpawned));
            }
            if (config.UI.Bradley.Enabled || config.UI.Heli.Enabled) {
                foreach (var player in BasePlayer.activePlayerList) {
                    UI.ShowLockouts(player);
                }
                Subscribe(nameof(OnPlayerSleepEnded));
            }
            if (config.Bradley.Threshold != 0f || config.Helicopter.Threshold != 0f || config.Hackable.Laptop) {
                Subscribe(nameof(OnPlayerAttack));
            }
            if (!config.SupplyDrop.Skins.Contains(0uL)) {
                config.SupplyDrop.Skins.Add(0uL);
            }
            if (config.Lockout.F15) {
                Subscribe(nameof(OnEventTrigger));
            }
            Subscribe(nameof(OnEntityTakeDamage));
            Subscribe(nameof(OnEntityDeath));
            Subscribe(nameof(OnEntityKill));
            Subscribe(nameof(CanLootEntity));
            Subscribe(nameof(CanBradleyTakeDamage));
            SetupLaunchSite();
        }
        private bool IsF15EventActive;
        private void OnEventTrigger(TriggeredEventPrefab prefab) {
            if (config.Lockout.F15 && !IsF15EventActive && prefab.name == "assets/bundled/prefabs/world/event_f15e.prefab") {
                Puts("F15 event has started; bypassing player lockouts!");
                IsF15EventActive = true;
            }
        }
        private void Unload() {
            UI.DestroyAllLockoutUI();
            SaveData();
            Instance = null;
            data = null;
            sb = null;
        }
        private void OnPlayerSleepEnded(BasePlayer player) {
            UI.DestroyLockoutUI(player);
            UI.ShowLockouts(player);
        }
        private object OnTeamLeave(RelationshipManager.PlayerTeam team, BasePlayer player) => HandleTeam(team, player.userID);
        private object OnTeamKick(RelationshipManager.PlayerTeam team, BasePlayer player, ulong targetId) => HandleTeam(team, targetId);
        private object OnPlayerAttack(BasePlayer attacker, HitInfo hitInfo) {
            if (attacker == null || HasPermission(attacker, bypassDamagePerm) || hitInfo == null) {
                return null;
            }
            if (config.Hackable.Laptop && hitInfo.HitBone == 242862488 && hitInfo.HitEntity is HackableLockedCrate crate && IsDefended(crate))  // laptopcollision
            {
                hitInfo.HitBone = 0;
                return null;
            }
            if (config.Bradley.Threshold != 0f || config.Helicopter.Threshold != 0f) {
                if (hitInfo.HitEntity is ServerGib gibs && gibs.IsValid() && data.Lock.TryGetValue(gibs.net.ID.Value, out var lockInfo)) {
                    if (gibs.OwnerID != 0 && !lockInfo.IsLockOutdated) {
                        if (!lockInfo.CanInteract(attacker.userID, attacker)) {
                            if (CanMessage(attacker)) {
                                CreateMessage(attacker, "CannotMine");
                                Message(attacker, lockInfo.GetDamageReport(attacker.userID));
                            }
                            CancelDamage(hitInfo);
                            return false;
                        }
                    }
                    else {
                        data.Lock.Remove(gibs.net.ID.Value);
                        gibs.OwnerID = 0;
                    }
                }
            }
            return null;
        }
        private object OnEntityTakeDamage(PatrolHelicopter heli, HitInfo hitInfo) {
            if (config.Helicopter.Threshold == 0f || !heli.IsValid() || _personal.Contains(heli.net.ID.Value) || hitInfo == null || heli.myAI == null || heli.myAI.isDead || CanHeliTakeDamage(heli, hitInfo) != null) {
                return null;
            }
            return OnEntityTakeDamageHandler(heli, hitInfo, DamageEntryType.Heli, string.Empty);
        }
        private object OnEntityTakeDamage(BradleyAPC apc, HitInfo hitInfo) {
            if (config.Bradley.Threshold == 0f || !apc.IsValid() || hitInfo == null || CanBradleyTakeDamage(apc, hitInfo) != null) {
                return null;
            }
            return OnEntityTakeDamageHandler(apc, hitInfo, DamageEntryType.Bradley, string.Empty);
        }
        private object OnEntityTakeDamage(BasePlayer player, HitInfo hitInfo) {
            if (!config.Npc.Enabled || !player.IsValid() || player.userID.IsSteamId() || hitInfo == null) {
                return null;
            }
            if (config.Npc.Min > 0 && player.startHealth < config.Npc.Min) {
                return null;
            }
            return OnEntityTakeDamageHandler(player, hitInfo, DamageEntryType.NPC, player.displayName);
        }
        private object OnEntityTakeDamageHandler(BaseCombatEntity entity, HitInfo hitInfo, DamageEntryType damageEntryType, string npcName) {
            if (!config.Bradley.LockConvoy && entity.skinID == 755446 && entity is BradleyAPC) {
                return null;
            }
            if (!config.Helicopter.LockConvoy && entity.skinID == 755446 && entity is PatrolHelicopter) {
                return null;
            }
            if (!(hitInfo.Initiator is BasePlayer attacker) || !attacker.userID.IsSteamId()) {
                return null;
            }
            if (_locked.TryGetValue(entity.net.ID.Value, out var ownerId) && !HasPermission(attacker, bypassDamagePerm) && !IsAlly(attacker.userID, ownerId)) {
                if (!BlockDamage(damageEntryType)) {
                    return null;
                }
                if (CanMessage(attacker)) {
                    CreateMessage(attacker, "CannotDamageThis");
                }
                CancelDamage(hitInfo);
                return true;
            }
            if (!data.Damage.TryGetValue(entity.net.ID.Value, out var damageInfo)) {
                data.Damage[entity.net.ID.Value] = damageInfo = new(damageEntryType, npcName, entity, DateTime.Now);
            }
            DamageEntry entry = damageInfo.Get(attacker);
            float total = hitInfo.damageTypes.Total();
            if (hitInfo.isHeadshot) total *= 2f;
            damageInfo.AddDamage(entity, attacker, entry, total);
            if (damageEntryType == DamageEntryType.Heli) {
                float prevHealth = entity.health;
                NextTick(() => {
                    if (entity == null) {
                        return;
                    }
                    damageInfo.AddDamage(entity, attacker, entry, Mathf.Abs(prevHealth - entity.health));
                }
                );
            }
            return null;
        }
        public static bool IsKilled(BaseNetworkable a) => a == null || a.IsDestroyed || !a.isSpawned;
        private bool BlockDamage(DamageEntryType damageEntryType) {
            if (damageEntryType == DamageEntryType.NPC && config.Npc.LootingOnly) {
                return false;
            }
            else if (damageEntryType == DamageEntryType.Heli && config.Helicopter.LootingOnly) {
                return false;
            }
            else if (damageEntryType == DamageEntryType.Bradley && config.Bradley.LootingOnly) {
                return false;
            }
            return true;
        }
        private object CanBradleyTakeDamage(BradleyAPC apc, HitInfo hitInfo) {
            if (config.Lockout.Bradley <= 0 || !apc.IsValid() || !(hitInfo.Initiator is BasePlayer attacker)) {
                return null;
            }
            if (HasLockout(attacker, DamageEntryType.Bradley, apc.skinID)) {
                CancelDamage(hitInfo);
                return false;
            }
            if (!data.Lockouts.ContainsKey(attacker.UserIDString)) {
                if (!_apcAttackers.TryGetValue(apc.net.ID.Value, out var attackers)) {
                    _apcAttackers[apc.net.ID.Value] = attackers = new();
                }
                if (!attackers.Exists(x => x.userid == attacker.userID)) {
                    attackers.Add(new(attacker));
                }
            }
            return null;
        }
        private object CanHeliTakeDamage(PatrolHelicopter heli, HitInfo hitInfo) {
            if (config.Lockout.Heli <= 0 || !heli.IsValid() || !(hitInfo.Initiator is BasePlayer attacker)) {
                return null;
            }
            if (HasLockout(attacker, DamageEntryType.Heli, heli.skinID)) {
                CancelDamage(hitInfo);
                return false;
            }
            if (!data.Lockouts.ContainsKey(attacker.UserIDString)) {
                if (!_heliAttackers.TryGetValue(heli.net.ID.Value, out var attackers)) {
                    _heliAttackers[heli.net.ID.Value] = attackers = new();
                }
                if (!attackers.Exists(x => x.userid == attacker.userID)) {
                    attackers.Add(new(attacker));
                }
            }
            return null;
        }
        private void OnEntityDeath(PatrolHelicopter heli, HitInfo hitInfo) {
            if (!heli.IsValid()) {
                return;
            }
            _personal.Remove(heli.net.ID.Value);
            _heliAttackers.Remove(heli.net.ID.Value);
            OnEntityDeathHandler(heli, DamageEntryType.Heli, hitInfo);
        }
        private void OnEntityKill(PatrolHelicopter heli) => OnEntityDeath(heli, null);
        private void OnEntityDeath(BradleyAPC apc, HitInfo hitInfo) {
            if (!apc.IsValid()) {
                return;
            }
            _apcAttackers.Remove(apc.net.ID.Value);
            OnEntityDeathHandler(apc, DamageEntryType.Bradley, hitInfo);
        }
        private void OnEntityDeath(BasePlayer player, HitInfo hitInfo) {
            if (!config.Npc.Enabled || !player.IsValid() || player.userID.IsSteamId()) {
                return;
            }
            OnEntityDeathHandler(player, DamageEntryType.NPC, hitInfo);
        }
        private void OnEntityDeath(NPCPlayerCorpse corpse, HitInfo hitInfo) {
            if (!config.Npc.Enabled || !corpse.IsValid()) {
                return;
            }
            OnEntityDeathHandler(corpse, DamageEntryType.Corpse, hitInfo);
        }
        private void OnEntityKill(NPCPlayerCorpse corpse) => OnEntityDeath(corpse, null);
        private bool IsInBounds(MonumentInfo monument, Vector3 target) {
            return monument.IsInBounds(target) || new OBB(monument.transform.position, monument.transform.rotation, new Bounds(monument.Bounds.center, new Vector3(300f, 300f, 300f))).Contains(target);
        }
        private bool CanLockBradley(BaseEntity entity) {
            if (config.Bradley.Threshold <= 0f || _personal.Contains(entity.net.ID.Value)) {
                return false;
            }
            if (BradleyDrops && BradleyDrops.CallHook("IsBradleyDrop", entity.skinID) != null) {
                return false;
            }
            if (entity.name.Contains($"BradleyApc[{entity.net.ID}]")) {
                return config.Bradley.LockBradleyTiers;
            }
            if (entity.skinID != 0) {
                if (entity.skinID == 755446) {
                    return config.Bradley.LockConvoy;
                }
                if (entity.skinID == 81182151852251420) {
                    return config.Bradley.LockHarbor;
                }
                if (entity.skinID == 8675309) {
                    return config.Bradley.LockMonument;
                }
                return false;
            }
            if (launchSite != null && IsInBounds(launchSite, entity.ServerPosition)) {
                return config.Bradley.LockLaunchSite;
            }
            if (harbors.Exists(mi => IsInBounds(mi, entity.ServerPosition))) {
                return config.Bradley.LockHarbor;
            }
            return config.Bradley.LockWorldly;
        }
        private bool CanLockHeli(BaseCombatEntity entity) {
            if (HeliSignals && HeliSignals.CallHook("IsHeliSignalObject", entity.skinID) != null) {
                return false;
            }
            if (entity.skinID != 0) {
                if (entity.skinID == 755446) {
                    return config.Helicopter.LockConvoy;
                }
                if (entity.skinID == 81182151852251420) {
                    return config.Helicopter.LockHarbor == true;
                }
                return false;
            }
            return config.Helicopter.Threshold > 0f;
        }
        private bool CanLockNpc(BaseEntity entity) {
            if (entity.OwnerID.ToString().Length == 5) {
                return false;
            }
            return config.Npc.Threshold > 0f && !_boss.Contains(entity.net.ID.Value);
        }
        private void OnEntityDeathHandler(BaseCombatEntity entity, DamageEntryType damageEntryType, HitInfo hitInfo) {
            if (data.Damage.TryGetValue(entity.net.ID.Value, out var damageInfo) && !damageInfo.isKilled) {
                if (damageEntryType == DamageEntryType.Bradley && !CanLockBradley(entity)) return;
                if (damageEntryType == DamageEntryType.Heli && !CanLockHeli(entity)) return;
                if (damageEntryType == DamageEntryType.NPC && !CanLockNpc(entity)) return;
                if (damageEntryType == DamageEntryType.Bradley || damageEntryType == DamageEntryType.Heli) {
                    var lockInfo = new LockInfo(damageInfo, damageEntryType == DamageEntryType.Heli ? config.Helicopter.LockTime : config.Bradley.LockTime);
                    var position = entity.transform.position;
                    if (entity is PatrolHelicopter && (position - Vector3.zero).magnitude > World.Size / 1.25f) {
                        return;
                    }
                    damageInfo.OnKilled(position, hitInfo, hitInfo?.ProjectileDistance ?? Vector3.Distance(position, damageInfo.lastAttackedPosition));
                    timer.Once(0.1f, () => {
                        LockInRadius<LockedByEntCrate>(position, lockInfo, damageEntryType);
                        LockInRadius<HelicopterDebris>(position, lockInfo, damageEntryType);
                        RemoveFireFromCrates(position, damageEntryType);
                    }
                    );
                    damageInfo.DestroyTimer();
                }
                else if (damageEntryType == DamageEntryType.NPC && config.Npc.Enabled && entity is BasePlayer npc) {
                    var position = entity.transform.position;
                    var npcId = npc.userID;
                    var damageKey = npc.net.ID.Value;
                    damageInfo.OnKilled(position, hitInfo, hitInfo?.ProjectileDistance ?? Vector3.Distance(position, damageInfo.lastAttackedPosition));
                    damageInfo.DestroyTimer();
                    timer.Once(0.1f, () => LockInRadius(position, damageKey, damageInfo, npcId));
                }
                else if (damageEntryType == DamageEntryType.NPC && config.Npc.Enabled && entity is LootableCorpse corpse) {
                    var position = entity.transform.position;
                    var npcId = corpse.playerSteamID;
                    var damageKey = corpse.net.ID.Value;
                    damageInfo.OnKilled(position, hitInfo, hitInfo?.ProjectileDistance ?? Vector3.Distance(position, damageInfo.lastAttackedPosition));
                    damageInfo.DestroyTimer();
                    timer.Once(0.1f, () => LockInRadius(position, damageKey, damageInfo, npcId));
                }
            }
            if (data.Lock.Remove(entity.net.ID.Value, out var lockInfo2) && damageEntryType == DamageEntryType.Corpse && config.Npc.Enabled && entity is LootableCorpse corpse2) {
                var corpsePos = corpse2.transform.position;
                var corpseId = corpse2.playerSteamID;
                timer.Once(0.1f, () => LockInRadius(corpsePos, lockInfo2, corpseId));
            }
        }
        //void OnEntitySpawned(DroppedItemContainer container)
        //{
        //    if (!config.Npc.Enabled || !container.IsValid() || container.playerSteamID.IsSteamId() || data.Lock.ContainsKey(container.net.ID.Value))
        //    {
        //        return;
        //    }
        //    foreach (var damageInfo in data.Damage.Values)
        //    {
        //        if (damageInfo.damageEntryType == DamageEntryType.NPC && container.Distance(damageInfo._position) <= 3f)
        //        {
        //            if (config.Npc.LockTime > 0f)
        //            {
        //                var uid = container.net.ID.Value;
        //                timer.Once(config.Npc.LockTime, () => data.Lock.Remove(uid));
        //                container.Invoke(() => container.OwnerID = 0, config.Npc.LockTime);
        //            }
        //            ulong ownerid = damageInfo.OwnerID;
        //            container.OwnerID = ownerid;
        //            container.Invoke(() => container.OwnerID = ownerid, 1f);
        //            data.Lock[container.net.ID.Value] = new(damageInfo, config.Npc.LockTime);
        //        }
        //    }
        //}
        void GiveRustReward(BaseEntity entity, DamageInfo damageInfo, ulong userid, string weapon, int total) {
            if (RustRewards == null) {
                return;
            }
            BasePlayer attacker = BasePlayer.FindByID(userid);
            if (attacker == null || !attacker.userID.IsSteamId()) {
                return;
            }
            var amount = damageInfo.damageEntryType == DamageEntryType.Bradley ? config.Bradley.RRP : damageInfo.damageEntryType == DamageEntryType.Heli ? config.Helicopter.RRP : config.Npc.RRP;
            if (amount <= 0.0) {
                return;
            }
            var distance = Vector3.Distance(attacker.transform.position, entity.transform.position);
         
// ... [Code preview truncated due to length. Full source in attached file] ...

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

Другие ресурсы пользователя 15FPS

Сверху