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

FREE HeliSignals : 1.0.25 1.0.25

Нет прав для скачивания
C#:
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Rust;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using System.Text.RegularExpressions;
using System.Reflection;
/* Changelog 1.0.25

 - Fixed: Hackable locked crate not despawning at time specified in config
 - Fixed: Custom loot not populating after 1.0.22 update (sorry)
 - Fixed: Occasional NullReferenceException error on CanStackItem
 - Added: Hackable locked crate loot table options

 */
namespace Oxide.Plugins {
    /*ПЛАГИН БЫЛ ПОФИКШЕН С ПОМОЩЬЮ ПРОГРАММЫ СКАЧАНОЙ С https://discord.gg/dNGbxafuJn */
    [Info("Heli Signals", "https://discord.gg/dNGbxafuJn", "1.0.25")]
    [Description("Call Patrol Helicopters to your location with custom supply signals.")]
    public class HeliSignals : RustPlugin {
#region Plugin References
        [PluginReference]
        Plugin Friends, Clans, FancyDrop, RewardPlugin, Vanish, NoEscape, BotReSpawn;
#endregion Plugin References
#region Constants
        public static HeliSignals Instance;
        public const string permAdmin = "helisignals.admin";
        public const string permBuy = "helisignals.buy";
        public const string permBypasscooldown = "helisignals.bypasscooldown";
        public const string heliPrefab = "assets/prefabs/npc/patrol helicopter/patrolhelicopter.prefab";
        public const string heliExplosion = "assets/prefabs/npc/patrol helicopter/effects/heli_explosion.prefab";
        public const string hackableCrate = "assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate.prefab";
        public const string defaultWebhookUrl = "https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks";
        public const int supplySignalId = 1397052267;
        public const int scrapId = -932201673;
        // Default config item skins
        public const ulong easySkinID = 2920175997;
        public const ulong medSkinID = 2920176079;
        public const ulong hardSkinID = 2920176050;
        public const ulong eliteSkinID = 2920176024;
        // Default config item names
        public const string easyHeli = "Heli Signal (Easy)";
        public const string medHeli = "Heli Signal (Medium)";
        public const string hardHeli = "Heli Signal (Hard)";
        public const string eliteHeli = "Heli Signal (Elite)";
#endregion Constants
#region Language
        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string> {
                ["SyntaxPlayer"]
                = "<color=red>Invalid syntax</color>, use:\n\n<color=green>/hsgive <type> <SteamID/PlayerName> <amount></color>", ["Receive"] = "You received <color=orange>{0}</color> x <color=orange>{1}</color>!", ["PlayerReceive"] = "Player {0} ({1}) received {2} x {3}!", ["Permission"] = "You do not have permission to use <color=orange>{0}</color>!", ["RaidBlocked"] = "You cannot use <color=orange>{0}</color> while raid blocked!", ["CombatBlocked"] = "You cannot use <color=orange>{0}</color> while combat blocked!", ["CooldownTime"] = "Cooldown active! You can call another in {0}!", ["TeamCooldownTime"] = "Team cooldown active! You can call another in {0}!", ["GlobalLimit"] = "Global limit of {0} active helicopters is reached, please try again later", ["NotAdmin"] = "You do not have permission to use that command!", ["PlayerNotFound"] = "Can't find a player with the name or ID: {0}", ["InGameOnly"] = "Error: This command is only for use in game!", ["PlayerDead"] = "Player with name or ID {0} is dead, try again when they have respawned", ["InSafeZone"] = "<color=orange>{0}</color> was thrown in a <color=green>Safe Zone</color> and was refunded, check inventory.", ["SyntaxConsole"] = "Invalid syntax, use: hsgive <type> <SteamID/PlayerName> <amount>", ["InvalidDrop"] = "Signal type \"{0}\" not recognised, please check and try again!", ["CannotLoot"] = "You cannot loot this because it is not yours!", ["CannotHack"] = "You cannot hack this because it is not yours!", ["CannotHarvest"] = "You cannot harvest this because it is not yours!", ["BuySyntaxCmd"] = "Usage:\n\n/{0} {1}", ["NoBuy"] = "Buy Command for <color=orange>{0}</color> Is Not Enabled!", ["BuyPermission"] = "You do not have permission to buy Heli Signal \"<color=orange>{0}</color>\".", ["PriceList"] = "Heli Signal Prices:\n\n{0}", ["HeliKilledTime"] = "<color=orange>{0}</color> killed by <color=green>{1}</color> in grid <color=green>{2}</color> (Time Taken: {3})", ["HeliCalled"] = "<color=green>{0}</color> just called in a <color=orange>{1}</color> to their location in grid <color=green>{2}</color>", ["PointsGiven"] = "<color=green>{0} {1}</color> received for destroying <color=orange>{2}</color>!", ["ScrapGiven"] = "<color=green>{0}</color> Scrap received for destroying <color=orange>{1}</color>!", ["CannotDamage"] = "You <color=red>Cannot</color> damage this <color=orange>{0}</color>!", ["TooFarAway"] = "You are <color=red>Too Far</color> away to engage this <color=orange>{0}</color> ({1} m)", ["CantAfford"] = "You <color=red>Cannot</color> afford this! Cost: <color=orange>{0}</color> Required: <color=orange>{1}</color>", ["FullInventory"] = "<color=green>{0}</color> <color=red>NOT</color> purchased - no inventory space.You have not been charged.", ["PlayerFull"] = "<color=green>{0}</color> <color=red>NOT</color> given to {1} - No inventory space.", ["HeliReportTitle"] = "There are currently <color=orange>{0}</color> active Helicopters", ["HeliReportItem"] = "<size=9><color=orange>{0}/{1}</color> - <color=green>{2}</color> (Owner: <color=orange>{3}</color> Grid: <color=orange>{4}</color> Health: <color=orange>{5}</color> Rotors: <color=orange>{6}/{7}</color> State: <color=orange>{8}</color>)\n</size>", ["HeliReportTitleCon"] = "There are currently {0} active Helicopters", ["HeliReportItemCon"] = "{0}/{1} - {2} (Owner: {3} Grid: {4} Health: {5} Rotors: {6}/{7} State: {8})\n", ["HeliReportList"] = "{0}", ["RetireHeli"] = "<color=orange>{0}</color> is retiring, you were warned! <color=red>{1}</color>/<color=red>{2}</color>", ["RetireWarn"] = "<color=red>Damage Blocked!</color> You may only attack from a base with TC auth.If you continue, the <color=orange>{0}</color> will retire.Warning Level: <color=red>{1}</color>/<color=red>{2}</color>", ["DamageReport"] = "<color=orange>Damage Report</color> / <color=orange>Rotor Accuracy</color>\n\n{0}", ["DamageReportItem"] = "<size=11><color=green>{0}</color> -> {1} HP / {2}%\n</size>", ["DiscordCall"] = "**{0}** just called a **{1}** to their location in grid **{2}**", ["DiscordKill"] = "**{0}** just took down a **{1}** in grid **{2}**", ["DiscordRetire"] = "**{0}** called by **{1}** just retired from grid **{2}**", ["RetiredHelis"] = "You have retired ALL your (your teams) called Patrol Helicopters"
            }
            , this, "en");
        }
        private string Lang(string messageKey, params object[] args) {
            return string.Format(lang.GetMessage(messageKey, this), args);
        }
        public void Message(IPlayer player, string messageKey, params object[] args) {
            var message = Lang(messageKey, args);
            if (config.options.usePrefix && config.options.chatPrefix != string.Empty) {
                if (player.IsServer) {
                    Regex regex = new Regex(@"(\[.*?\])");
                    Match match = regex.Match(config.options.chatPrefix);
                    player.Reply($"{match}: {message}");
                }
                else {
                    player.Reply($"{config.options.chatPrefix}: {message}");
                }
            }
            else {
                player.Reply(message);
            }
        }
        public void Message(BasePlayer player, string messageKey, params object[] args) {
            if (player is NPCPlayer) return;
            var message = Lang(messageKey, args);
            if (config.options.usePrefix && config.options.chatPrefix != string.Empty) {
                player.ChatMessage($"{config.options.chatPrefix}: {message}");
            }
            else {
                player.ChatMessage(message);
            }
        }
#endregion Language
#region Oxide Hooks
        private void OnServerInitialized() {
            Instance = this;
            CheckRewardPlugin();
            if (!config.options.useStacking) {
                Unsubscribe(nameof(CanStackItem));
                Unsubscribe(nameof(CanCombineDroppedItem));
            }
            if (config.options.noVanillaHeli) Puts($"INFO: Vanilla patrol Helicopter server event is disabled");
        }
        private void Init() {
            permission.RegisterPermission(permAdmin, this);
            permission.RegisterPermission(permBuy, this);
            permission.RegisterPermission(permBypasscooldown, this);
            config.rewards.RegisterPermissions(permission, this);
            config.heli.RegisterPermissions(permission, this);
            foreach (var key in config.heli.heliConfig.Keys) {
                var permSuffix = config.heli.heliConfig[key].GiveItemCommand.ToLower();
                var perm = $"{Name.ToLower()}.{permSuffix}";
                permission.RegisterPermission(perm, this);
                HeliTypes.Add(config.heli.heliConfig[key].GiveItemCommand);
            }
            AddCovalenceCommand("hsreport", nameof(CmdReport));
            AddCovalenceCommand(config.purchasing.buyCommand, nameof(CmdBuySignal));
            AddCovalenceCommand(config.heli.retireCommand, nameof(CmdRetireHeli));
            AddCovalenceCommand("hsgive", nameof(CmdGiveSignal));
        }
        private void Unload() {
            foreach (var netId in HeliSignalData.Keys) {
                var heli = BaseNetworkable.serverEntities.Find(new NetworkableId(netId)) as PatrolHelicopter;
                if (heli != null) {
                    if (IsHeliSignal(heli.skinID)) {
                        heli.Kill();
                    }
                }
            }
            if (config.options.noVanillaHeli) Puts($"INFO: Vanilla patrol Helicopter server event has been re-enabled");
            HeliSignalData.Clear();
            PlayerCooldowns.Clear();
            LockedCrates.Clear();
            HeliTypes.Clear();
            RewardPlugin = null;
            Instance = null;
        }
        private object OnEventTrigger(TriggeredEventPrefab eventPrefab) {
            if (eventPrefab.name.Contains("event_helicopter") && config.options.noVanillaHeli) return true;
            return null;
        }
        // Re-Adds supply signal names to items added via kits/loadouts by plugins
        // which don't specify a custom item display name.private void OnItemAddedToContainer(ItemContainer container, Item item)
        {
            if (IsHeliSignal(item.skin)) NextTick(()=> FixSignalInfo(item));
        }
        private void OnExplosiveThrown(BasePlayer player, SupplySignal entity, ThrownWeapon item) {
            var signal = item.GetItem();
            if (signal == null) return;
            if (IsHeliSignal(signal.skin)) {
                entity.EntityToCreate = null;
                entity.CancelInvoke(entity.Explode);
                entity.skinID = signal.skin;
                NextTick(()=> HeliSignalThrown(player, entity, signal));
            }
        }
        private object CanStackItem(Item item, Item targetItem) {
            if ((item.info || targetItem.info) == null) return null;
            if (item.info.itemid == targetItem.info.itemid && item.skin != targetItem.skin) return false;
            return null;
        }
        private object CanCombineDroppedItem(DroppedItem item, DroppedItem targetItem) {
            if (item.item == null || targetItem.item == null) return null;
            return CanStackItem(item.item, targetItem.item);
        }
        private void OnExplosiveDropped(BasePlayer player, SupplySignal entity, ThrownWeapon item) => OnExplosiveThrown(player, entity, item);
        private void OnEntitySpawned(BaseNetworkable entity) {
            if (entity.ShortPrefabName.Contains("rocket_heli")) {
                var heliList = Facepunch.Pool.GetList<PatrolHelicopter>();
                var rocketEnt = entity as BaseEntity;
                Vis.Entities(rocketEnt.transform.position, 10f, heliList);
                foreach (var ent in heliList) {
                    if (ent.IsDestroyed) continue;
                    PatrolHelicopter heli = ent as PatrolHelicopter;
                    if (!IsHeliSignal(heli.skinID)) continue;
                    var heliProfile = heli._name;
                    if (heliProfile == null) continue;
                    rocketEnt.creatorEntity = heli;
                    rocketEnt.OwnerID = heli.OwnerID;
                    SetDamageScale((rocketEnt as TimedExplosive), config.heli.heliConfig[heliProfile].RocketDamageScale);
                    break;
                }
                Facepunch.Pool.FreeList(ref heliList);
            }
        }
        private object OnEntityTakeDamage(PatrolHelicopter heli, HitInfo info) {
            if (heli?._name == null) return null;
            if (IsHeliSignal(heli.skinID)) {
                HeliComponent heliComp = heli.GetComponent<HeliComponent>();
                if (heliComp == null) return null;
                if (heliComp.isRetiring) {
                    CancelHit(info);
                    return true;
                }
                var heliProfile = heli._name;
                if (!config.heli.heliConfig.ContainsKey(heliProfile)) return null;
                var attacker = info?.Initiator as BasePlayer;
                if (attacker != null) {
                    var heliAI = heli.GetComponent<PatrolHelicopterAI>();
                    if (heliAI == null) return null;
                    var heliDisplayName = config.heli.heliConfig[heliProfile].HeliName;
                    if (config.heli.heliConfig[heliProfile].OwnerDamage) {
                        if (!IsOwnerOrFriend(attacker.userID, heli.OwnerID)) {
                            Message(attacker, "CannotDamage", heliDisplayName);
                            CancelHit(info);
                            return true;
                        }
                    }
                    var dist = Vector3.Distance(heli.transform.position, attacker.transform.position);
                    var maxDist = config.heli.maxHitDistance;
                    if (maxDist > 0 && dist > maxDist) {
                        CancelHit(info);
                        Message(attacker, "TooFarAway", heliDisplayName, maxDist);
                        return true;
                    }
                    if (config.heli.RetireWarning && attacker.IsBuildingBlocked() && IsOwnerOrFriend(attacker.userID, heli.OwnerID)) {
                        HeliSignalData[heli.net.ID.Value].WarningLevel++;
                        if (!heliComp.isRetiring && HeliSignalData[heli.net.ID.Value].WarningLevel >= config.heli.WarningThreshold) {
                            heliComp.isRetiring = true;
                            RetireHeli(heliAI, heli.net.ID.Value);
                            CancelHit(info);
                            Message(attacker, "RetireHeli", heliDisplayName, HeliSignalData[heli.net.ID.Value].WarningLevel, config.heli.WarningThreshold);
                            return true;
                        }
                        CancelHit(info);
                        Message(attacker, "RetireWarn", heliDisplayName, HeliSignalData[heli.net.ID.Value].WarningLevel, config.heli.WarningThreshold);
                        return true;
                    }
                    var heliId = heli.net.ID.Value;
                    if (heliAI._currentState != PatrolHelicopterAI.aiState.DEATH) {
                        if (!HeliSignalData.ContainsKey(heliId)) HeliSignalData.Add(heliId, new HeliStats());
                        if (HeliSignalData[heliId].FirstHitTime == 0) HeliSignalData[heliId].FirstHitTime = UnityEngine.Time.realtimeSinceStartup;
                        if (!HeliSignalData[heliId].Attackers.ContainsKey(attacker.userID)) {
                            HeliSignalData[heliId].Attackers.Add(attacker.userID, new AttackersStats());
                            HeliSignalData[heliId].Attackers[attacker.userID].Name = attacker.displayName;
                        }
                        HeliSignalData[heliId].Attackers[attacker.userID].DamageDealt += info.damageTypes.Total();
                        HeliSignalData[heliId].Attackers[attacker.userID].TotalHits++;
                        if (info.HitMaterial == 2306822461) HeliSignalData[heliId].Attackers[attacker.userID].RotorHits++;
                        if (heliAI._currentState != PatrolHelicopterAI.aiState.DEATH) HeliSignalData[heliId].LastAttacker = attacker;
                    }
                }
            }
            return null;
        }
        private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
            if (info == null || entity == null) return null;
            if (info.Initiator == null) return null;
            if (info.Initiator is PatrolHelicopter) {
                PatrolHelicopter heli = info.Initiator as PatrolHelicopter;
                if (heli == null) return null;
                PatrolHelicopterAI heliAI = heli.myAI;
                if (heliAI == null) return null;
                if (IsHeliSignal(heli.skinID)) {
                    string heliProfile = heli._name;
                    if (heliProfile == null || heliProfile == string.Empty) return null;
                    if (config.heli.heliConfig.ContainsKey(heliProfile)) {
                        if (entity is BasePlayer) {
                            BasePlayer player = entity as BasePlayer;
                            if (player == null) return null;
                            if (config.heli.heliConfig[heliProfile].BlockPlayerDamage && !IsOwnerOrFriend(heli.OwnerID, player.userID)) {
                                CancelHit(info);
                                return true;
                            }
                        }
                        else if (entity.OwnerID.IsSteamId()) {
                            if (config.heli.heliConfig[heliProfile].BlockOtherDamage && !IsOwnerOrFriend(heli.OwnerID, entity.OwnerID)) {
                                CancelHit(info);
                                return true;
                            }
                            if (config.heli.heliConfig[heliProfile].BlockOwnerDamage && IsOwnerOrFriend(heli.OwnerID, entity.OwnerID)) {
                                CancelHit(info);
                                return true;
                            }
                        }
                    }
                }
            }
            else if (info.Initiator.ShortPrefabName.Equals("napalm") || info.Initiator.ShortPrefabName.Equals("oilfireballsmall"))  // If Heli destroyed
            {
                string heliProfile = info.Initiator.creatorEntity?._name;
                if (heliProfile == null || heliProfile == string.Empty) return null;
                if (IsHeliSignal(info.Initiator.creatorEntity.skinID)) {
                    var heliOwner = info.Initiator.creatorEntity.OwnerID;
                    if (heliOwner == null) return null;
                    if (entity is BasePlayer) {
                        BasePlayer player = entity as BasePlayer;
                        if (player == null) return null;
                        if (config.heli.heliConfig[heliProfile].BlockPlayerDamage && !IsOwnerOrFriend(heliOwner, player.userID)) {
                            CancelHit(info);
                            return true;
                        }
                    }
                    else if (entity.OwnerID.IsSteamId()) {
                        if (config.heli.heliConfig[heliProfile].BlockOtherDamage && !IsOwnerOrFriend(heliOwner, entity.OwnerID)) {
                            CancelHit(info);
                            return true;
                        }
                        else if (config.heli.heliConfig[heliProfile].BlockOwnerDamage && IsOwnerOrFriend(heliOwner, entity.OwnerID)) {
                            CancelHit(info);
                            return true;
                        }
                    }
                }
            }
            return null;
        }
        private object OnEntityDestroy(BaseEntity heli) {
            Puts($"DEBUG: OnEntityDestroy hooked! {heli}");
            return null;
        }
        private object OnEntityKill(PatrolHelicopter heli) {
            if (heli == null) return null;
            if (!HeliSignalData.ContainsKey(heli.net.ID.Value)) return null;
            HeliComponent heliComp = heli.GetComponent<HeliComponent>();
            if (heliComp == null) return null;
            if (heliComp.isRetiring) return null;
            var skinId = heli.skinID;
            if (IsHeliSignal(skinId)) {
                var position = heli.transform.position;
                var ownerId = heli.OwnerID;
                var heliProfile = heli._name;
                var heliId = heli.net.ID.Value;
                var gridPos = PositionToGrid(heli.transform.position);
                if (gridPos == null) gridPos = "Unknown";
                BasePlayer lastAttacker = HeliSignalData[heliId].LastAttacker;
                if (lastAttacker == null) return null;
                var totalReward = config.heli.heliConfig[heliProfile].RewardPoints;
                var totalScrap = config.heli.heliConfig[heliProfile].ScrapReward;
                float damageThreshold = config.heli.heliConfig[heliProfile].DamageThreshold;
                if (config.rewards.enableRewards && totalReward > 0) {
                    if (plugins.Find(config.rewards.rewardPlugin)) {
                        if (config.rewards.shareRewards) {
                            foreach (var playerId in HeliSignalData[heliId].Attackers.Keys) {
                                float damageDealt = HeliSignalData[heliId].Attackers[playerId].DamageDealt;
                                if (damageDealt >= damageThreshold) {
                                    var amount = totalReward / HeliSignalData[heliId].Attackers.Count(key => key.Value.DamageDealt >= damageThreshold);
                                    GiveReward(playerId, amount, heliProfile);
                                }
                            }
                        }
                        else {
                            GiveReward(ownerId, totalReward, heliProfile);
                        }
                    }
                }
                if (config.rewards.enableScrap && totalScrap > 0) {
                    if (config.rewards.shareScrap) {
                        foreach (var playerId in HeliSignalData[heliId].Attackers.Keys) {
                            float damageDealt = HeliSignalData[heliId].Attackers[playerId].DamageDealt;
                            if (damageDealt >= damageThreshold) {
                                var amount = totalScrap / HeliSignalData[heliId].Attackers.Count(key => key.Value.DamageDealt >= damageThreshold);
                                if (playerId.IsSteamId()) GiveScrap(playerId, amount, heliProfile);
                            }
                        }
                    }
                    else {
                        GiveScrap(ownerId, totalScrap, heliProfile);
                    }
                }
                if (config.announce.killGlobal && !heli.myAI.isRetiring) {
                    TimeSpan timeSpan = TimeSpan.FromSeconds(UnityEngine.Time.realtimeSinceStartup - HeliSignalData[heliId].FirstHitTime);
                    string time = timeSpan.ToString(@"hh\:mm\:ss");
                    var heliDisplayName = config.heli.heliConfig[heliProfile].HeliName;
                    var message = string.Format(lang.GetMessage("HeliKilledTime", this), heliDisplayName, lastAttacker.displayName, gridPos, time);
                    Server.Broadcast(message, config.options.usePrefix ? config.options.chatPrefix : null, 0);
                }
                if (config.announce.reportGlobal && !heli.myAI.isRetiring) {
                    string topReport = string.Empty;
                    int count = 0;
                    foreach (var key in HeliSignalData[heliId].Attackers.Keys.OrderByDescending(x => HeliSignalData[heliId].Attackers[x].DamageDealt)) {
                        if (count >= config.announce.maxReported) break;
                        string playerName = HeliSignalData[heliId].Attackers[key].Name;
                        float damageDealt = HeliSignalData[heliId].Attackers[key].DamageDealt;
                        int totalHits = HeliSignalData[heliId].Attackers[key].TotalHits;
                        int rotorHits = HeliSignalData[heliId].Attackers[key].RotorHits;
                        double rotorAccuracy = ((double)rotorHits / (double)totalHits) * 100;
                        topReport += string.Format(lang.GetMessage("DamageReportItem", this), playerName, Math.Round(damageDealt, 2), Math.Round(rotorAccuracy, 2));
                        count++;
                    }
                    var dmgReport = string.Format(lang.GetMessage("DamageReport", this), topReport);
                    Server.Broadcast(dmgReport, config.options.usePrefix ? config.options.chatPrefix : null, 0);
                }
                if (config.discord.sendHeliKill && !heli.myAI.isRetiring) {
                    string discordMsg = string.Format(lang.GetMessage("DiscordKill", this), lastAttacker.displayName, heliProfile, gridPos);
                    SendToDiscord(discordMsg);
                }
                if (config.heli.heliConfig[heliProfile].LockedCratesToSpawn > 0) {
                    SpawnLockedCrates(ownerId, skinId, heliProfile, position);
                }
                List<BaseEntity> ents = new List<BaseEntity>();
                Vis.Entities(position, 20f, ents);
                foreach (var ent in ents) {
                    if ((ent is HelicopterDebris) || (ent is LockedByEntCrate) || (ent is FireBall)) {
                        ent.OwnerID = ownerId;
                        ent.skinID = skinId;
                        ent._name = heliProfile;
                        ProcessHeliEnt(ent);
                    }
                }
                if (BotReSpawn && BotReSpawn.IsLoaded && !heli.myAI.isRetiring) {
                    var botReSpawnProfile = config.heli.heliConfig[heliProfile].BotReSpawnProfile;
                    if (botReSpawnProfile != string.Empty) BotReSpawn?.Call("AddGroupSpawn", position, botReSpawnProfile, $"{botReSpawnProfile}Group", 0);
                }
                timer.Once(5f, () => {
                    if (HeliSignalData.ContainsKey(heliId)) HeliSignalData.Remove(heliId);
                }
                );
            }
            return null;
        }
        private object CanHelicopterStrafeTarget(PatrolHelicopterAI heliAI, BasePlayer player) {
            PatrolHelicopter heli = heliAI?.helicopterBase;
            if (!heli) return null;
            if (!IsHeliSignal(heli.skinID)) return null;
            string heliProfile = heli._name;
            if (heliProfile == null || heliProfile == string.Empty) return false;
            if (!config.heli.heliConfig[heliProfile].TargetOtherPlayers && !IsOwnerOrFriend(player.userID, heli.OwnerID)) {
                heliAI.ExitCurrentState();
                for (int i = 0; i < heliAI._targetList.Count; i++) {
                    if (heliAI._targetList[i].ply == player) {
                        heliAI._targetList.Remove(heliAI._targetList[i]);
                        continue;
                    }
                }
                return false;
            }
            return null;
        }
        private object CanHelicopterUseNapalm(PatrolHelicopterAI heliAI) => CanHelicopterStrafe(heliAI);
        private object CanHelicopterStrafe(PatrolHelicopterAI heliAI) {
            PatrolHelicopter heli = heliAI?.helicopterBase;
            if (heli == null) return null;
            HeliComponent heliComp = heli.GetComponent<HeliComponent>();
            if (heliComp != null) {
                if (heliComp.isRetiring) return false;
            }
            return null;
        }
        private object OnHelicopterTarget(HelicopterTurret turret, BasePlayer player) {
            PatrolHelicopter heli = turret._heliAI?.helicopterBase;
            PatrolHelicopterAI heliAI = turret?._heliAI;
            if (!heli || !heliAI) return null;
            if (IsHeliSignal(heli.skinID)) return CanCustomHeliTarget(heliAI, player);
            return null;
        }
        private object CanHelicopterTarget(PatrolHelicopterAI heliAI, BasePlayer player) {
            PatrolHelicopter heli = heliAI?.helicopterBase;
            if (!heli) return null;
            if (IsHeliSignal(heli.skinID)) return CanCustomHeliTarget(heliAI, player);
            return null;
        }
        private object CanCustomHeliTarget(PatrolHelicopterAI heliAI, BasePlayer player) {
            if (Vanish && (bool)Vanish?.Call("IsInvisible", player))  // Don't target players in Vanish
            return null;
            PatrolHelicopter heli = heliAI?.helicopterBase;
            string heliProfile = heli._name;
            if (heliProfile == null || heliProfile == string.Empty) return false;
            if (config.heli.heliConfig.ContainsKey(heliProfile)) {
                if (!config.heli.heliConfig[heliProfile].TargetOtherPlayers && !IsOwnerOrFriend(player.userID, heli.OwnerID)) {
                    HeliComponent heliComp = heli.GetComponent<HeliComponent>();
                    if (heliComp != null) {
                        heliAI.interestZoneOrigin = heliComp.calledPosition + new Vector3(0f, 30f, 0f);
                        heliAI.hasInterestZone = true;
                    }
                    return false;
                }
            }
            if (config.heli.maxHitDistance > 0 && (Vector3.Distance(heli.transform.position, player.transform.position) > config.heli.maxHitDistance)) return false;
            return null;
        }
        private object OnHelicopterRetire(PatrolHelicopterAI heliAI) {
            PatrolHelicopter heli = heliAI?.helicopterBase;
            if (heli == null) return null;
            if (IsHeliSignal(heli.skinID) && heliAI.IsAlive()) {
                heliAI.leftGun.maxTargetRange = 0f;
                heliAI.rightGun.maxTargetRange = 0f;
                if (config.discord.sendHeliRetire) {
                    var gridPos = PositionToGrid(heli.transform.position);
                    if (gridPos == null) gridPos = "Unknown";
                    BasePlayer player = FindPlayer(heli.OwnerID.ToString())?.Object as BasePlayer;
                    if (player == null) return null;
                    string discordMsg = string.Format(lang.GetMessage("DiscordRetire", this), heli._name, player.displayName, gridPos);
                    SendToDiscord(discordMsg);
                }
                timer.Once(2f, ()=> {
                    if (HeliSignalData.ContainsKey(heli.net.ID.Value)) HeliSignalData.Remove(heli.net.ID.Value);
                }
                );
            }
            return null;
        }
        private object CanLootEntity(BasePlayer player, LockedByEntCrate entity) {
            if (entity?._name == null) return null;
            if (IsHeliSignal(entity.skinID)) {
                string heliProfile = entity._name;
                if (heliProfile != null) {
                    if (config.heli.heliConfig.ContainsKey(heliProfile)) {
                        if (config.heli.heliConfig[heliProfile].ProtectCrates && entity.OwnerID != 0) {
                            if (!IsOwnerOrFriend(player.userID, entity.OwnerID)) {
                                Message(player, "CannotLoot");
                                return false;
                            }
                        }
                    }
                }
            }
            return null;
        }
        private object OnPlayerAttack(BasePlayer attacker, HitInfo info) {
            if (attacker == null || info == null) return null;
            BaseEntity entity = info.HitEntity;
            if (entity != null) {
                if (entity is ServerGib && IsHeliSignal(entity.skinID)) {
                    var heliProfile = entity._name;
                    if (heliProfile != null) {
                        if (config.heli.heliConfig.ContainsKey(heliProfile)) {
                            if (config.heli.heliConfig[heliProfile].ProtectGibs && entity.OwnerID != 0) {
                                if (!IsOwnerOrFriend(attacker.userID, entity.OwnerID)) {
                                    Message(attacker, "CannotHarvest");
                                    CancelHit(info);
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
            return null;
        }
        private void OnLootSpawn(LootContainer lootContainer) {
            NextTick(() => {
                var skinId = lootContainer.skinID;
                if (IsHeliSignal(skinId)) {
                    var heliProfile = lootContainer._name;
                    if (heliProfile == null) return;
                    bool useCustomLoot = config.heli.heliConfig[heliProfile].Loot.UseCustomLoot;
                    if (lootContainer.ShortPrefabName.Contains("heli_crate") && useCustomLoot) SpawnHeliCrateLoot(lootContainer, heliProfile);
                    bool useExtraLoot = config.heli.heliConfig[heliProfile].ExtraLoot.UseExtraLoot;
                    if (lootContainer.ShortPrefabName.Contains("heli_crate") && useExtraLoot) AddExtraHeliCrateLoot(lootContainer, heliProfile);
                    bool useLockedCrateLoot = config.heli.heliConfig[heliProfile].LockedCrateLoot.UseLockedCrateLoot;
                    if (lootContainer.ShortPrefabName.Contains("codelockedhackablecrate") && useLockedCrateLoot) SpawnLockedCrateLoot(lootContainer, heliProfile);
                }
            }
            );
        }
        private string PositionToGrid(Vector3 position) => PhoneController.PositionToGridCoord(position);
#endregion Oxide Hooks
#region Core
        private void HeliSignalThrown(BasePlayer player, SupplySignal entity, Item signal) {
            if (signal.name == null || !config.heli.heliConfig.ContainsKey(signal.name)) FixSignalInfo(signal);
            var skinId = signal.skin;
            var heliProfile = signal.name;
            var permSuffix = config.heli.heliConfig[heliProfile].GiveItemCommand.ToLower();
            var perm = $"{Name.ToLower()}.{permSuffix}";
            if (!HasPermission(player.UserIDString, perm)) {
                Message(player, "Permission", heliProfile);
                entity.Kill();
                GiveHeliDrop(player, skinId, heliProfile, 1, "refund");
                return;
            }
            if (NoEscape && config.heli.UseNoEscape) {
                if ((bool)NoEscape.CallHook("IsRaidBlocked", player)) {
                    Message(player, "RaidBlocked", heliProfile);
                    entity.Kill();
                    GiveHeliDrop(player, skinId, heliProfile, 1, "refund");
                    return;
                }
                else if ((bool)NoEscape.CallHook("IsCombatBlocked", player)) {
                    Message(player, "CombatBlocked", heliProfile);
                    entity.Kill();
                    GiveHeliDrop(player, skinId, heliProfile, 1, "refund");
                    return;
                }
            }
            if (config.heli.playerCooldown > 0f && !HasPermission(player.UserIDString, permBypasscooldown)) {
                float cooldown;
                if (PlayerCooldowns.TryGetValue(player.userID, out cooldown)) {
                    TimeSpan time = TimeSpan.FromSeconds(cooldown - UnityEngine.Time.time);
                    Message(player, "CooldownTime", time.ToString(@"hh\:mm\:ss"));
                    entity.Kill();
                    GiveHeliDrop(player, skinId, heliProfile, 1, "refund");
                    return;
                }
                else if (config.heli.teamCooldown) {
                    foreach (var playerId in PlayerCooldowns.Keys) {
                        if (PlayerCooldowns.TryGetValue(playerId, out cooldown) && IsOwnerOrFriend(player.userID, playerId)) {
                            TimeSpan time = TimeSpan.FromSeconds(cooldown - UnityEngine.Time.time);
                            Message(player, "TeamCooldownTime", time.ToString(@"hh\:mm\:ss"));
                            entity.Kill();
                            GiveHeliDrop(player, skinId, heliProfile, 1, "refund");
                            return;
                        }
                    }
                }
                cooldown = config.heli.playerCooldown;
                foreach (KeyValuePair<string, float> keyPair in config.heli.vipCooldowns) {
                    if (HasPermission(player.UserIDString, keyPair.Key)) {
                        cooldown = keyPair.Value;
                    }
                }
                ulong userId = player.userID;
                PlayerCooldowns[userId] = UnityEngine.Time.time + cooldown;
                timer.Once(cooldown, () => {
                    if (PlayerCooldowns.ContainsKey(userId)) {
                        PlayerCooldowns.Remove(userId);
                    }
                }
                );
            }
            HeliSignalComponent signalComponent = entity.gameObject.AddComponent<HeliSignalComponent>();
            if (signalComponent != null) {
                signalComponent.signal = entity;
                signalComponent.player = player;
                signalComponent.skinId = skinId;
                signalComponent.heliProfile = heliProfile;
            }
        }
        private void ProcessHeliEnt (BaseEntity entity) {
            if (entity != null) {
                NextTick(() => {
                    var heliProfile = entity._name;
                    if (heliProfile != null) {
                        if (entity is HelicopterDebris) {
                            var debris = entity?.GetComponent<HelicopterDebris>() ?? null;
                            if (debris != null) {
                                debris.InitializeHealth(config.heli.heliConfig[heliProfile].GibsHealth, config.heli.heliConfig[heliProfile].GibsHealth);
                                debris.SendNetworkUpdate();
                                if (config.heli.heliConfig[heliProfile].KillGibs) entity.Kill();
                                else if (config.heli.heliConfig[heliProfile].DisableFire) debris.tooHotUntil = UnityEngine.Time.realtimeSinceStartup;
                                else if (config.heli.heliConfig[heliProfile].GibsHotTime > 0) debris.tooHotUntil = UnityEngine.Time.realtimeSinceStartup + config.heli.heliConfig[heliProfile].GibsHotTime;
                                if (config.heli.heliConfig[heliProfile].ProtectGibs && config.heli.heliConfig[heliProfile].UnlockGibs > 0) {
                                    float unlockTime = config.heli.heliConfig[heliProfile].DisableFire ? config.heli.heliConfig[heliProfile].UnlockGibs : (config.heli.heliConfig[heliProfile].FireDuration + config.heli.heliConfig[heliProfile].UnlockGibs);
                                    RemoveHeliOwner(entity, unlockTime);
                                }
                                debris.SendNetworkUpdateImmediate();
                            }
                        }
                        else if (entity is FireBall) {
                            var fireball = entity?.GetComponent<FireBall>() ?? null;
                            if (fireball != null) {
                                if (config.heli.heliConfig[heliProfile].DisableFire) {
                                    fireball.enableSaving = false;
                                    entity.Kill();
                                }
                                else {
                                    timer.Once(config.heli.heliConfig[heliProfile].FireDuration, () => {
                                        if (entity != null || !entity.IsDestroyed || fireball != null) {
                                            fireball.enableSaving = false;
                                            entity.Kill();
                                        }
                                    }
                                    );
                                }
                                fireball.SendNetworkUpdateImmediate();
                            }
                        }
                        else if (entity is LockedByEntCrate) {
                            var crate = entity?.GetComponent<LockedByEntCrate>();
                            if (crate != null) {
                                if (config.heli.heliConfig[heliProfile].FireDuration > 0 && !config.heli.heliConfig[heliProfile].DisableFire) {
                                    timer.Once(config.heli.heliConfig[heliProfile].FireDuration, () => {
                                        if (crate != null) {
                                            if (crate.lockingEnt != null) {
                                                var lockingEnt = crate.lockingEnt.GetComponent<FireBall>();
                                                if (lockingEnt != null) {
                                                    lockingEnt.enableSaving = false;
                                                    lockingEnt.Kill();
                                                }
                                            }
                                            crate.CancelInvoke(crate.Think);
                                            crate.SetLocked(false);
                                            crate.lockingEnt = null;
                                        }
                                    }
                                    );
                                }
                                else {
                                    if (crate.lockingEnt != null) {
                                        var lockingEnt = crate?.lockingEnt.GetComponent<FireBall>();
                                        if (lockingEnt != null) {
                                            lockingEnt.enableSaving = false;
                                            lockingEnt.Kill();
                                        }
                                    }
                                    crate.CancelInvoke(crate.Think);
                                    crate.SetLocked(false);
                                    crate.lockingEnt = null;
                                }
                                if (config.heli.heliConfig[heliProfile].ProtectCrates && config.heli.heliConfig[heliProfile].UnlockCrates > 0) {
                                    float unlockTime = config.heli.heliConfig[heliProfile].DisableFire ? config.heli.heliConfig[heliProfile].UnlockCrates : (config.heli.heliConfig[heliProfile].FireDuration + config.heli.heliConfig[heliProfile].UnlockCrates);
                                    RemoveHeliOwner(entity, unlockTime);
                                }
                            }
                        }
                    }
                }
                );
            }
        }
#endregion Core
#region Loot
        private void SpawnHeliCrateLoot(LootContainer lootContainer, string heliProfile) {
            if (lootContainer == null || heliProfile == null) return;
            timer.Once(2f, () => {
                lootContainer.inventory.capacity = 12;
                // unlock all slots
                lootContainer.inventory.Clear();
                ItemManager.DoRemoves();
                List<LootItem> lootTable = new List<LootItem>(config.heli.heliConfig[heliProfile].Loot.LootTable);
                List<LootItem> items = lootTable;
                if (items == null || lootTable == null) return;
                var minItems = config.heli.heliConfig[heliProfile].Loot.MinCrateItems;
                var maxItems = config.heli.heliConfig[heliProfile].Loot.MaxCrateItems;
                int count = UnityEngine.Random.Range(minItems, maxItems + 1);
                int given = 0;
                for (int i = 0; i < count; i++) {
                    LootItem lootItem = items.GetRandom();
                    if (lootItem == null) {
                        i--;
                        continue;
                    }
                    if (lootItem.Chance < UnityEngine.Random.Range(0f, 100f)) {
                        if (given < minItems) {
                            i--;
                            continue;
                        }
                        break;
                    }
                    // Only remove if enough in loot table (if loot table not adequate)
                    if (!config.heli.heliConfig[heliProfile].Loot.AllowDupes && count <= items.Count) items.Remove(lootItem);
                    // Re-add loot if items run out (if loot table not adequate)
                    if (items.Count == 0) items.AddRange(lootTable);
                    var amount = UnityEngine.Random.Range(lootItem.AmountMin, lootItem.AmountMax + 1);
                    Item item = ItemManager.CreateByName(lootItem.ShortName, amount, lootItem.SkinId);
                    if (item != null) {
                        item.name = lootItem.DisplayName;
                        if (item.MoveToContainer(lootContainer.inventory)) {
                            lootContainer.inventory.MarkDirty();
                            given++;
                            if (item.amount == 0) item.Remove(0f);
                            continue;
                        }
                        item.Remove(0f);
                    }
                }
            }
            );
        }
        private void AddExtraHeliCrateLoot (LootContainer lootContainer, string heliProfile) {
            if (lootContainer == null || heliProfile == null) return;
            timer.Once(2.25f, () => {
                List<LootItem> lootTable = new List<LootItem>(config.heli.heliConfig[heliProfile].ExtraLoot.LootTable);
                List<LootItem> items = lootTable;
                if (items == null || lootTable == null) return;
                lootContainer.inventory.capacity = 12;
                // unlock all slots
                var minItems = config.heli.heliConfig[heliProfile].ExtraLoot.MinExtraItems;
                var maxItems = config.heli.heliConfig[heliProfile].ExtraLoot.MaxExtraItems;
                int count = UnityEngine.Random.Range(minItems, maxItems + 1);
                int given = 0;
                for (int i = 0; i < count; i++) {
                    LootItem lootItem = items.GetRandom();
                    if (lootItem == null) {
                 
// ... [Code preview truncated due to length. Full source in attached file] ...

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