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

FREE TruePVE : 2.1.2 2.1.2

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Plugins.TruePVEExtensionMethods;
using Rust;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
/*
Fix damage to patrol helicopter when crashing into terrain
Added `heliturrets cannot hurt players` to default config - you MUST add this to prevent damage if you have `anything can hurt players` rule

{
    "name": "heliturrets",
    "members": "turret_attackheli",
    "exclusions": ""
},

heliturrets cannot hurt players
*/
namespace Oxide.Plugins {
    [Info("TruePVE", "nivex", "2.1.2")]
    [Description("Improvement of the default Rust PVE behavior")]
    internal  // Thanks to the original author, ignignokt84.class TruePVE : RustPlugin
    {
#region Variables
        private static TruePVE Instance;
        // config/data container
        private Configuration config = new Configuration();
        [PluginReference]
        Plugin ZoneManager, LiteZones, Clans, Friends, AbandonedBases, RaidableBases;
        public string usageString;
        private enum Command {
            def, sched, trace, usage, enable, sleepers
        }
        ;
        //[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
        private class RuleFlags : FlagsAttribute {
            public const long None = 0;
            public const long AdminsHurtSleepers = 1L << 1;
            public const long AnimalsIgnoreSleepers = 1L << 2;
            public const long AuthorizedDamage = 1L << 3;
            public const long AuthorizedDamageRequiresOwnership = 1L << 4;
            public const long CupboardOwnership = 1L << 5;
            public const long FriendlyFire = 1L << 6;
            public const long HeliDamageLocked = 1L << 7;
            public const long HumanNPCDamage = 1L << 8;
            public const long LockedBoxesImmortal = 1L << 9;
            public const long LockedDoorsImmortal = 1L << 10;
            public const long NoPlayerDamageToCar = 1L << 11;
            public const long NoPlayerDamageToMini = 1L << 12;
            public const long NoPlayerDamageToScrap = 1L << 13;
            public const long NoHeliDamage = 1L << 14;
            public const long NoHeliDamagePlayer = 1L << 15;
            public const long NoHeliDamageQuarry = 1L << 16;
            public const long NoHeliDamageRidableHorses = 1L << 17;
            public const long NoHeliDamageSleepers = 1L << 18;
            public const long NoMLRSDamage = 1L << 19;
            public const long NpcsCanHurtAnything = 1L << 20;
            public const long PlayerSamSitesIgnorePlayers = 1L << 21;
            public const long ProtectedSleepers = 1L << 22;
            public const long TrapsIgnorePlayers = 1L << 23;
            public const long TrapsIgnoreScientist = 1L << 24;
            public const long TurretsIgnorePlayers = 1L << 25;
            public const long TurretsIgnoreScientist = 1L << 26;
            public const long TwigDamage = 1L << 27;
            public const long TwigDamageRequiresOwnership = 1L << 28;
            public const long VehiclesTakeCollisionDamageWithoutDriver = 1L << 29;
            public const long SamSitesIgnoreMLRS = 1L << 30;
            public const long SelfDamage = 1L << 31;
            public const long StaticSamSitesIgnorePlayers = 1L << 32;
            public const long StaticTurretsIgnorePlayers = 1L << 33;
            public const long SafeZoneTurretsIgnorePlayers = 1L << 34;
            public const long SuicideBlocked = 1L << 35;
            public const long NoHeliDamageBuildings = 1L << 36;
            public const long WoodenDamage = 1L << 37;
            public const long WoodenDamageRequiresOwnership = 1L << 38;
            public static long Get(string value) {
                switch (value) {
                    case "None" : default : return RuleFlags.None;
                    case "AdminsHurtSleepers" : return RuleFlags.AdminsHurtSleepers;
                    case "AnimalsIgnoreSleepers" : return RuleFlags.AnimalsIgnoreSleepers;
                    case "AuthorizedDamage" : return RuleFlags.AuthorizedDamage;
                    case "AuthorizedDamageRequiresOwnership" : return RuleFlags.AuthorizedDamageRequiresOwnership;
                    case "CupboardOwnership" : return RuleFlags.CupboardOwnership;
                    case "FriendlyFire" : return RuleFlags.FriendlyFire;
                    case "HeliDamageLocked" : return RuleFlags.HeliDamageLocked;
                    case "HumanNPCDamage" : return RuleFlags.HumanNPCDamage;
                    case "LockedBoxesImmortal" : return RuleFlags.LockedBoxesImmortal;
                    case "LockedDoorsImmortal" : return RuleFlags.LockedDoorsImmortal;
                    case "NoPlayerDamageToCar" : return RuleFlags.NoPlayerDamageToCar;
                    case "NoPlayerDamageToMini" : return RuleFlags.NoPlayerDamageToMini;
                    case "NoPlayerDamageToScrap" : return RuleFlags.NoPlayerDamageToScrap;
                    case "NoHeliDamage" : return RuleFlags.NoHeliDamage;
                    case "NoHeliDamagePlayer" : return RuleFlags.NoHeliDamagePlayer;
                    case "NoHeliDamageQuarry" : return RuleFlags.NoHeliDamageQuarry;
                    case "NoHeliDamageRidableHorses" : return RuleFlags.NoHeliDamageRidableHorses;
                    case "NoHeliDamageSleepers" : return RuleFlags.NoHeliDamageSleepers;
                    case "NoMLRSDamage" : return RuleFlags.NoMLRSDamage;
                    case "NpcsCanHurtAnything" : return RuleFlags.NpcsCanHurtAnything;
                    case "PlayerSamSitesIgnorePlayers" : return RuleFlags.PlayerSamSitesIgnorePlayers;
                    case "ProtectedSleepers" : return RuleFlags.ProtectedSleepers;
                    case "TrapsIgnorePlayers" : return RuleFlags.TrapsIgnorePlayers;
                    case "TrapsIgnoreScientist" : return RuleFlags.TrapsIgnoreScientist;
                    case "TurretsIgnorePlayers" : return RuleFlags.TurretsIgnorePlayers;
                    case "TurretsIgnoreScientist" : return RuleFlags.TurretsIgnoreScientist;
                    case "TwigDamage" : return RuleFlags.TwigDamage;
                    case "TwigDamageRequiresOwnership" : return RuleFlags.TwigDamageRequiresOwnership;
                    case "VehiclesTakeCollisionDamageWithoutDriver" : return RuleFlags.VehiclesTakeCollisionDamageWithoutDriver;
                    case "SamSitesIgnoreMLRS" : return RuleFlags.SamSitesIgnoreMLRS;
                    case "SelfDamage" : return RuleFlags.SelfDamage;
                    case "StaticSamSitesIgnorePlayers" : return RuleFlags.StaticSamSitesIgnorePlayers;
                    case "StaticTurretsIgnorePlayers" : return RuleFlags.StaticTurretsIgnorePlayers;
                    case "SafeZoneTurretsIgnorePlayers" : return RuleFlags.SafeZoneTurretsIgnorePlayers;
                    case "SuicideBlocked" : return RuleFlags.SuicideBlocked;
                    case "WoodenDamage" : return RuleFlags.WoodenDamage;
                    case "WoodenDamageRequiresOwnership" : return RuleFlags.WoodenDamageRequiresOwnership;
                }
            }
            public static long Get(int value) {
                switch (value) {
                    case 0 : default : return RuleFlags.None;
                    case 1 : return RuleFlags.AdminsHurtSleepers;
                    case 2 : return RuleFlags.AnimalsIgnoreSleepers;
                    case 3 : return RuleFlags.AuthorizedDamage;
                    case 4 : return RuleFlags.AuthorizedDamageRequiresOwnership;
                    case 5 : return RuleFlags.CupboardOwnership;
                    case 6 : return RuleFlags.FriendlyFire;
                    case 7 : return RuleFlags.HeliDamageLocked;
                    case 8 : return RuleFlags.HumanNPCDamage;
                    case 9 : return RuleFlags.LockedBoxesImmortal;
                    case 10 : return RuleFlags.LockedDoorsImmortal;
                    case 11 : return RuleFlags.NoPlayerDamageToCar;
                    case 12 : return RuleFlags.NoPlayerDamageToMini;
                    case 13 : return RuleFlags.NoPlayerDamageToScrap;
                    case 14 : return RuleFlags.NoHeliDamage;
                    case 15 : return RuleFlags.NoHeliDamagePlayer;
                    case 16 : return RuleFlags.NoHeliDamageQuarry;
                    case 17 : return RuleFlags.NoHeliDamageRidableHorses;
                    case 18 : return RuleFlags.NoHeliDamageSleepers;
                    case 19 : return RuleFlags.NoMLRSDamage;
                    case 20 : return RuleFlags.NpcsCanHurtAnything;
                    case 21 : return RuleFlags.PlayerSamSitesIgnorePlayers;
                    case 22 : return RuleFlags.ProtectedSleepers;
                    case 23 : return RuleFlags.TrapsIgnorePlayers;
                    case 24 : return RuleFlags.TrapsIgnoreScientist;
                    case 25 : return RuleFlags.TurretsIgnorePlayers;
                    case 26 : return RuleFlags.TurretsIgnoreScientist;
                    case 27 : return RuleFlags.TwigDamage;
                    case 28 : return RuleFlags.TwigDamageRequiresOwnership;
                    case 29 : return RuleFlags.VehiclesTakeCollisionDamageWithoutDriver;
                    case 30 : return RuleFlags.SamSitesIgnoreMLRS;
                    case 31 : return RuleFlags.SelfDamage;
                    case 32 : return RuleFlags.StaticSamSitesIgnorePlayers;
                    case 33 : return RuleFlags.StaticTurretsIgnorePlayers;
                    case 34 : return RuleFlags.SafeZoneTurretsIgnorePlayers;
                    case 35 : return RuleFlags.SuicideBlocked;
                    case 36 : return RuleFlags.WoodenDamage;
                    case 37 : return RuleFlags.WoodenDamageRequiresOwnership;
                }
            }
        }
        private Timer scheduleUpdateTimer;
        // timer to check for schedule updates
        private bool shareRedirectEnabled;
        // undocumented.UAYOR.private RuleSet dudRuleSet;                                     // dud ruleset when no locations are shared
        private RuleSet currentRuleSet;
        // current ruleset
        private string currentBroadcastMessage;
        // current broadcast message
        private bool useZones;
        // internal useZones flag
        private const string Any = "any";
        // constant "any" string for rules
        private const string AllZones = "allzones";
        // constant "allzones" string for mappings
        private const string PermCanMap = "truepve.canmap";
        // permission for mapping command
        private bool animalsIgnoreSleepers;
        // toggle flag to protect sleepers
        private bool trace = false;
        // trace flag
        private const string traceFile = "ruletrace";
        // tracefile name
        private const float traceTimeout = 300f;
        // auto-disable trace after 300s (5m)
        private Timer traceTimer;
        // trace timeout timer
        private bool tpveEnabled = true;
        // toggle flag for damage handling
        private List<DamageType> damageTypes = new List<DamageType> {
            DamageType.Arrow, DamageType.Blunt, DamageType.Bullet, DamageType.Explosion, DamageType.Heat, DamageType.Generic, DamageType.Slash, DamageType.Stab,
        }
        ;
#endregion
#region Loading/Unloading
        private void Unload() {
            Instance = null;
            scheduleUpdateTimer?.Destroy();
        }
        private void OnPluginLoaded(Plugin plugin) {
            if (plugin.Name == "ZoneManager") ZoneManager = plugin;
            if (plugin.Name == "LiteZones") LiteZones = plugin;
            if (ZoneManager != null || LiteZones != null) useZones = config?.options.useZones ?? true;
        }
        private void OnPluginUnloaded(Plugin plugin) {
            if (plugin.Name == "ZoneManager") ZoneManager = null;
            if (plugin.Name == "LiteZones") LiteZones = null;
            if (ZoneManager == null && LiteZones == null) useZones = false;
            traceTimer?.Destroy();
        }
        private void Init() {
            Unsubscribe(nameof(OnEntityMarkHostile));
            Unsubscribe(nameof(OnEntitySpawned));
            Unsubscribe(nameof(OnEntityEnter));
            Unsubscribe(nameof(OnTurretTarget));
            Unsubscribe(nameof(OnEntityTakeDamage));
            Unsubscribe(nameof(OnPlayerConnected));
            Unsubscribe(nameof(OnSamSiteTarget));
            Unsubscribe(nameof(OnTrapTrigger));
            Unsubscribe(nameof(OnNpcTarget));
            Unsubscribe(nameof(OnMlrsFire));
            Instance = this;
            // register console commands automagically
            foreach (Command command in Enum.GetValues(typeof(Command))) {
                AddCovalenceCommand($"tpve.{command}", nameof(CommandDelegator));
            }
            // register chat commands
            AddCovalenceCommand("tpve_prod", nameof(CommandDelegator));
            AddCovalenceCommand("tpve_enable", nameof(CommandDelegator));
            AddCovalenceCommand("tpve", nameof(CommandDelegator));
            permission.RegisterPermission(PermCanMap, this);
            // build usage string for console (without sizing)
            usageString = WrapColor("orange", GetMessage("Header_Usage")) + $" - {Version}{Environment.NewLine}" + WrapColor("cyan", $"tpve.{Command.def}") + $" - {GetMessage("Cmd_Usage_def")}{Environment.NewLine}" + WrapColor("cyan", $"tpve.{Command.trace}") + $" - {GetMessage("Cmd_Usage_trace")}{Environment.NewLine}" + WrapColor("cyan", $"tpve.{Command.sched} [enable|disable]") + $" - {GetMessage("Cmd_Usage_sched")}{Environment.NewLine}" + WrapColor("cyan", $"/tpve_prod") + $" - {GetMessage("Cmd_Usage_prod")}{Environment.NewLine}" + WrapColor("cyan", $"/tpve map") + $" - {GetMessage("Cmd_Usage_map")}";
        }
        private void OnServerInitialized(bool isStartup) {
            // check for server pve setting
            if (ConVar.Server.pve) WarnPve();
            // load configuration
            config.Init();
            currentRuleSet = config.GetDefaultRuleSet();
            dudRuleSet = config.GetDudRuleSet();
            if (currentRuleSet == null) PrintWarning(GetMessage("Warning_NoRuleSet"), config.defaultRuleSet);
            useZones = config.options.useZones && (LiteZones != null || ZoneManager != null);
            if (useZones && config.mappings.Count == 1 && config.mappings.FirstOrDefault().Key.Equals(config.defaultRuleSet)) useZones = false;
            if (config.schedule.enabled) TimerLoop(true);
            if (config.ruleSets.Exists(ruleSet => ruleSet.HasFlag(RuleFlags.AnimalsIgnoreSleepers))) Subscribe(nameof(OnNpcTarget));
            if (currentRuleSet == null) return;
            if (config.ruleSets.Exists(ruleSet => (ruleSet._flags & (RuleFlags.SafeZoneTurretsIgnorePlayers | RuleFlags.StaticTurretsIgnorePlayers | RuleFlags.TrapsIgnorePlayers | RuleFlags.TrapsIgnoreScientist | RuleFlags.TurretsIgnorePlayers | RuleFlags.TurretsIgnoreScientist)) != 0)) {
                Subscribe(nameof(OnEntityEnter));
                Subscribe(nameof(OnTurretTarget));
            }
            if (config.ruleSets.Exists(ruleSet => (ruleSet._flags & (RuleFlags.SamSitesIgnoreMLRS | RuleFlags.PlayerSamSitesIgnorePlayers | RuleFlags.StaticSamSitesIgnorePlayers)) != 0)) {
                Subscribe(nameof(OnSamSiteTarget));
            }
            if (config.ruleSets.Exists(ruleSet => (ruleSet._flags & (RuleFlags.TrapsIgnorePlayers | RuleFlags.TrapsIgnoreScientist)) != 0)) {
                Subscribe(nameof(OnTrapTrigger));
            }
            if (config.schedule.enabled && config.schedule.broadcast && currentBroadcastMessage != null) {
                Subscribe(nameof(OnPlayerConnected));
            }
            if (config.options.disableBaseOvenSplash) {
                BaseNetworkable.serverEntities.OfType<BaseOven>().ForEach(oven => oven.disabledBySplash = false);
            }
            if (config.options.disableHostility) {
                Subscribe(nameof(OnEntityMarkHostile));
            }
            Subscribe(nameof(OnEntitySpawned));
            Subscribe(nameof(OnEntityTakeDamage));
            Subscribe(nameof(OnMlrsFire));
        }
#endregion
#region Command Handling
        // delegation method for commands
        private void CommandDelegator(IPlayer user, string command, string[] args) {
            // return if user doesn't have access to run console command
            if (!user.IsServer && !(user.Object as BasePlayer).IsAdmin) return;
            if (args.Length > 0 && args[0] == "map" && user.HasPermission(PermCanMap)) {
                CommandMap(user, command, args);
                return;
            }
            if (args.Contains("pvp")) {
                if (!currentRuleSet.rules.Remove("players cannot hurt players")) {
                    currentRuleSet.rules.Add("players cannot hurt players");
                }
                Puts("PVP toggled {0}", currentRuleSet.rules.Contains("players cannot hurt players") ? "on" : "off");
                SaveConfig();
                return;
            }
            if (command == "tpve_prod") {
                HandleProd(user);
                return;
            }
            if (command == "tpve_enable") {
                tpveEnabled = !tpveEnabled;
                Message(user, "Enable", tpveEnabled);
                return;
            }
            if (command == "tpve" && args.Length != 0) command = args[0];
            else command = command.Replace("tpve.", string.Empty);
            TruePVE.Command @enum;
            if (!Enum.TryParse(command, out @enum)) {
                user.Reply($"Invalid argument: {command}");
                return;
            }
            switch (@enum) {
                case Command.sleepers : HandleSleepers(user);
                return;
                case Command.def : HandleDef(user);
                return;
                case Command.sched : HandleScheduleSet(user, args);
                return;
                case Command.trace : _tracesToServerConsole = 0;
                trace = !trace;
                if (!trace) {
                    tracePlayer = null;
                    traceEntity = null;
                }
                else tracePlayer = user.Object as BasePlayer;
                Message(user, "Notify_TraceToggle", new object[] {
                    trace ? "on" : "off"
                }
                );
                if (trace) {
                    traceTimer = timer.In(traceTimeout, () => trace = false);
                }
                else traceTimer?.Destroy();
                return;
                case Command.enable : tpveEnabled = !tpveEnabled;
                Message(user, "Enable", tpveEnabled);
                return;
                case Command.usage : default : ShowUsage(user);
                return;
            }
        }
        private void HandleSleepers(IPlayer user) {
            if (animalsIgnoreSleepers) {
                animalsIgnoreSleepers = false;
                if (!config.ruleSets.Exists(ruleSet => ruleSet.HasFlag(RuleFlags.AnimalsIgnoreSleepers))) Unsubscribe(nameof(OnNpcTarget));
                user.Reply("Sleepers are no longer protected from animals.");
            }
            else {
                animalsIgnoreSleepers = true;
                Subscribe(nameof(OnNpcTarget));
                user.Reply("Sleepers are now protected from animals.");
            }
        }
        // handle setting defaults
        private void HandleDef(IPlayer user) {
            config.options = new ConfigurationOptions();
            Message(user, "Notify_DefConfigLoad");
            LoadDefaultData();
            Message(user, "Notify_DefDataLoad");
            SaveConfig();
        }
        // handle prod command (raycast to determine what player is looking at)
        private void HandleProd(IPlayer user) {
            var player = user.Object as BasePlayer;
            if (player == null || !player.IsAdmin) {
                Message(user, "Error_NoPermission");
                return;
            }
            object entity;
            if (!GetRaycastTarget(player, out entity) || entity.IsNull()) {
                SendReply(player, WrapSize(12, WrapColor("red", GetMessage("Error_NoEntityFound", player.UserIDString))));
                return;
            }
            Message(player, "Notify_ProdResult", new object[] {
                entity.GetType(), (entity as BaseEntity).ShortPrefabName
            }
            );
        }
        private void CommandMap(IPlayer user, string command, string[] args) {
            // assume args[0] is the command (beyond /tpve)
            if (args.Length > 0) command = args[0];
            // shift arguments
            args = args.Length > 1 ? args.Skip(1) : new string[0];
            if (command != "map") {
                Message(user, "Error_InvalidCommand");
            }
            else if (args.Length == 0) {
                Message(user, "Error_InvalidParamForCmd", command);
            }
            else {
                string from = args[0];
                // mapping name
                string to = args.Length == 2 ? args[1] : null;
                // target ruleSet/exclude, otherwise delete mapping
                if (to != null) {
                    if (to != "exclude" && !config.ruleSets.Exists(r => r.name == to)) {
                        // target ruleset must exist, or be "exclude"
                        Message(user, "Error_InvalidMapping", from, to);
                        return;
                    }
                    if (config.HasMapping(from)) {
                        string old = config.mappings[from];
                        Message(user, "Notify_MappingUpdated", from, old, to);
                        // update existing mapping
                    }
                    else Message(user, "Notify_MappingCreated", from, to);
                    // add new mapping
                    config.mappings[from] = to;
                    SaveConfig();
                }
                else {
                    if (config.HasMapping(from)) {
                        Message(user, "Notify_MappingDeleted", from, config.mappings[from]);
                        config.mappings.Remove(from);
                        // remove mapping
                        SaveConfig();
                    }
                    else Message(user, "Error_NoMappingToDelete", from);
                }
            }
        }
        // handles schedule enable/disable
        private void HandleScheduleSet(IPlayer user, string[] args) {
            if (args.Length == 0) {
                Message(user, "Error_InvalidParamForCmd");
                return;
            }
            if (!config.schedule.valid) {
                Message(user, "Notify_InvalidSchedule");
            }
            else if (args[0] == "enable") {
                if (config.schedule.enabled) return;
                config.schedule.enabled = true;
                TimerLoop();
                Message(user, "Notify_SchedSetEnabled");
            }
            else if (args[0] == "disable") {
                if (!config.schedule.enabled) return;
                config.schedule.enabled = false;
                if (scheduleUpdateTimer != null) scheduleUpdateTimer.Destroy();
                Message(user, "Notify_SchedSetDisabled");
            }
            else {
                Message(user, "Error_InvalidParameter", args[0]);
            }
        }
#endregion
#region Configuration/Data
        // load config
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                config = Config.ReadObject<Configuration>();
                if (config == null) LoadDefaultConfig();
                CheckData();
                SaveConfig();
            }
            catch (Exception ex) {
                Puts("{0}", ex);
                LoadDefaultConfig();
                return;
            }
            // check config version, update version to current version
            if (config.configVersion != Version.ToString()) {
                config.configVersion = Version.ToString();
                SaveConfig();
            }
        }
        protected override void LoadDefaultConfig() {
            config = new Configuration {
                configVersion = Version.ToString(), options = new ConfigurationOptions()
            }
            ;
            LoadDefaultData();
        }
        // save data
        protected override void SaveConfig() {
            Config.WriteObject(config);
        }
        // check rulesets and groups
        private void CheckData() {
            if (config.ruleSets.IsNullOrEmpty() || config.groups.IsNullOrEmpty()) {
                LoadDefaultData();
            }
            if (config.schedule == null) {
                config.schedule = new Schedule();
            }
            CheckMappings();
        }
        // rebuild mappings
        private bool CheckMappings() {
            bool dirty = false;
            foreach (RuleSet rs in config.ruleSets) {
                if (!config.mappings.ContainsValue(rs.name)) {
                    config.mappings[rs.name] = rs.name;
                    dirty = true;
                }
            }
            return dirty;
        }
        // load default data to mappings, rulesets, and groups
        private bool LoadDefaultData() {
            config.mappings.Clear();
            config.ruleSets.Clear();
            config.groups.Clear();
            config.schedule = new Schedule();
            config.defaultRuleSet = "default";
            // build groups first
            config.groups.Add(new EntityGroup("barricades") {
                members = "Barricade, icewall, GraveYardFence",  // "barricade.cover.wood, door_barricade_a, door_barricade_a_large, door_barricade_b, door_barricade_dbl_a, door_barricade_dbl_a_large, door_barricade_dbl_b, door_barricade_dbl_b_large",
                exclusions = "barricade.concrete, barricade.sandbags, barricade.metal, barricade.stone, barricade.wood, barricade.woodwire"
            }
            );
            config.groups.Add(new EntityGroup("dispensers") {
                members = "BaseCorpse, HelicopterDebris, PlayerCorpse, NPCPlayerCorpse, HorseCorpse, SkyLantern"
            }
            );
            config.groups.Add(new EntityGroup("fire") {
                members = "FireBall, FlameExplosive, FlameThrower, BaseOven, FlameTurret, rocket_heli_napalm, napalm, oilfireball2"
            }
            );
            config.groups.Add(new EntityGroup("guards") {
                members = "bandit_guard, scientistpeacekeeper, sentry.scientist.static"
            }
            );
            config.groups.Add(new EntityGroup("heli") {
                members = "PatrolHelicopter"
            }
            );
            config.groups.Add(new EntityGroup("highwalls") {
                members = "SimpleBuildingBlock, wall.external.high.ice, gates.external.high.stone, gates.external.high.wood"
            }
            );
            config.groups.Add(new EntityGroup("ridablehorses") {
                members = "RidableHorse"
            }
            );
            config.groups.Add(new EntityGroup("cars") {
                members = "BasicCar, ModularCar, BaseModularVehicle, BaseVehicleModule, VehicleModuleEngine, VehicleModuleSeating, VehicleModuleStorage, VehicleModuleTaxi, ModularCarSeat"
            }
            );
            config.groups.Add(new EntityGroup("mini") {
                members = "minicopter.entity"
            }
            );
            config.groups.Add(new EntityGroup("scrapheli") {
                members = "ScrapTransportHelicopter"
            }
            );
            config.groups.Add(new EntityGroup("ch47") {
                members = "ch47.entity"
            }
            );
            config.groups.Add(new EntityGroup("npcs") {
                members = "ch47scientists.entity, BradleyAPC, CustomScientistNpc, ScarecrowNPC, HumanNPC, NPCPlayer, ScientistNPC, TunnelDweller, SimpleShark, UnderwaterDweller, ZombieNPC"
            }
            );
            config.groups.Add(new EntityGroup("players") {
                members = "BasePlayer, FrankensteinPet"
            }
            );
            config.groups.Add(new EntityGroup("resources") {
                members = "ResourceEntity, TreeEntity, OreResourceEntity, LootContainer", exclusions = "hobobarrel.deployed"
            }
            );
            config.groups.Add(new EntityGroup("snowmobiles") {
                members = "snowmobile, tomahasnowmobile"
            }
            );
            config.groups.Add(new EntityGroup("traps") {
                members = "AutoTurret, BearTrap, FlameTurret, Landmine, GunTrap, ReactiveTarget, TeslaCoil, spikes.floor"
            }
            );
            config.groups.Add(new EntityGroup("junkyard") {
                members = "magnetcrane.entity, carshredder.entity"
            }
            );
            config.groups.Add(new EntityGroup("tugboats") {
                members = "Tugboat"
            }
            );
            config.groups.Add(new EntityGroup("heliturrets") {
                members = "turret_attackheli"
            }
            );
            // create default ruleset
            RuleSet defaultRuleSet = new RuleSet(config.defaultRuleSet) {
                _flags = RuleFlags.HumanNPCDamage | RuleFlags.LockedBoxesImmortal | RuleFlags.LockedDoorsImmortal | RuleFlags.PlayerSamSitesIgnorePlayers | RuleFlags.TrapsIgnorePlayers | RuleFlags.TurretsIgnorePlayers, flags = "HumanNPCDamage, LockedBoxesImmortal, LockedDoorsImmortal, PlayerSamSitesIgnorePlayers, TrapsIgnorePlayers, TurretsIgnorePlayers"
            }
            ;
            // create rules and add to ruleset
            defaultRuleSet.AddRule("anything can hurt dispensers");
            defaultRuleSet.AddRule("anything can hurt resources");
            defaultRuleSet.AddRule("anything can hurt barricades");
            defaultRuleSet.AddRule("anything can hurt traps");
            defaultRuleSet.AddRule("anything can hurt heli");
            defaultRuleSet.AddRule("anything can hurt npcs");
            defaultRuleSet.AddRule("anything can hurt players");
            defaultRuleSet.AddRule("nothing can hurt ch47");
            defaultRuleSet.AddRule("nothing can hurt cars");
            defaultRuleSet.AddRule("nothing can hurt mini");
            defaultRuleSet.AddRule("nothing can hurt snowmobiles");
            //defaultRuleSet.AddRule("nothing can hurt guards");
            defaultRuleSet.AddRule("nothing can hurt ridablehorses");
            defaultRuleSet.AddRule("cars cannot hurt anything");
            defaultRuleSet.AddRule("mini cannot hurt anything");
            defaultRuleSet.AddRule("ch47 cannot hurt anything");
            defaultRuleSet.AddRule("scrapheli cannot hurt anything");
            defaultRuleSet.AddRule("players cannot hurt players");
            defaultRuleSet.AddRule("players cannot hurt traps");
            defaultRuleSet.AddRule("guards cannot hurt players");
            defaultRuleSet.AddRule("fire cannot hurt players");
            defaultRuleSet.AddRule("traps cannot hurt players");
            defaultRuleSet.AddRule("highwalls cannot hurt players");
            defaultRuleSet.AddRule("barricades cannot hurt players");
            defaultRuleSet.AddRule("mini cannot hurt mini");
            defaultRuleSet.AddRule("npcs can hurt players");
            defaultRuleSet.AddRule("junkyard cannot hurt anything");
            defaultRuleSet.AddRule("junkyard can hurt cars");
            defaultRuleSet.AddRule("players cannot hurt tugboats");
            defaultRuleSet.AddRule("heliturrets cannot hurt players");
            config.ruleSets.Add(defaultRuleSet);
            // add ruleset to rulesets list
            config.mappings[config.defaultRuleSet] = config.defaultRuleSet;
            // create mapping for ruleset
            return true;
        }
        private bool ResetRules(string key) {
            if (string.IsNullOrEmpty(key) || config == null) {
                return false;
            }
            string old = config.defaultRuleSet;
            config.defaultRuleSet = key;
            currentRuleSet = config.GetDefaultRuleSet();
            if (currentRuleSet == null) {
                config.defaultRuleSet = old;
                currentRuleSet = config.GetDefaultRuleSet();
                return false;
            }
            return true;
        }
#endregion
#region Trace
        private StringBuilder _tsb = new StringBuilder();
        private BaseEntity traceEntity;
        private BasePlayer tracePlayer;
        private const int _tracesToServerConsoleLimit = 50;
        private int _tracesToServerConsole = 0;
        private void Trace(string message, int indentation = 0) {
            if (config.options.PlayerConsole || config.options.ServerConsole) {
                if (tracePlayer.IsReallyConnected() && traceEntity != null) {
                    if (config.options.MaxTraceDistance == 0 || tracePlayer.Distance(traceEntity) <= config.options.MaxTraceDistance) {
                        if (config.options.PlayerConsole) {
                            tracePlayer.ConsoleMessage(message);
                        }
                        if (config.options.ServerConsole && ++_tracesToServerConsole <= _tracesToServerConsoleLimit) {
                            Puts(message);
                        }
                        _tsb.AppendLine(string.Empty.PadLeft(indentation, ' ') + message);
                    }
                }
            }
            else _tsb.AppendLine(string.Empty.PadLeft(indentation, ' ') + message);
        }
        private void LogTrace() {
            var text = _tsb.ToString();
            traceEntity = null;
            try {
                if (!string.IsNullOrEmpty(text)) {
                    LogToFile(traceFile, text, this);
                }
            }
            catch (IOException) {
                timer.Once(1f, () => LogToFile(traceFile, text, this));
                return;
            }
            _tsb.Length = 0;
        }
#endregion Trace
#region Hooks/Handler Procedures
        private void OnPlayerConnected(BasePlayer player) {
            SendReply(player, GetMessage("Prefix") + currentBroadcastMessage);
        }
        private string CurrentRuleSetName() => currentRuleSet?.name;
        private bool IsEnabled() => tpveEnabled;
        // handle damage - if another mod must override TruePVE damages or take priority,
        // set handleDamage to false and reference HandleDamage from the other mod(s)
        private object OnEntityTakeDamage(ResourceEntity entity, HitInfo hitInfo) {
            // if default global is not enabled, return true (allow all damage)
            if (hitInfo == null || currentRuleSet == null || currentRuleSet.IsEmpty() || !currentRuleSet.enabled) {
                return null;
            }
            // get entity and initiator locations (zones)
            List<string> entityLocations = GetLocationKeys(entity);
            List<string> initiatorLocations = GetLocationKeys(hitInfo.Initiator);
            // check for exclusion zones (zones with no rules mapped)
            if (CheckExclusion(entityLocations, initiatorLocations, trace)) {
                if (trace) Trace("Exclusion found; allow and return", 1);
                return null;
            }
            if (trace) Trace("No exclusion found - looking up RuleSet...", 1);
            // process location rules
            RuleSet ruleSet = GetRuleSet(entityLocations, initiatorLocations);
            return EvaluateRules(entity, hitInfo, ruleSet) ? (object)null : true;
        }
        private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitInfo) {
            if (entity.IsNull() || entity.IsDestroyed || hitInfo == null || AllowKillingSleepers(entity, hitInfo)) {
                return null;
            }
            object extCanTakeDamage = Interface.CallHook("CanEntityTakeDamage", new object[] {
                entity, hitInfo
            }
            );
            if (extCanTakeDamage is bool) {
                if ((bool)extCanTakeDamage) {
                    return null;
                }
                CancelHit(hitInfo);
                return true;
            }
            if (!config.options.handleDamage || hitInfo.damageTypes.Total() <= 0f) {
                return null;
            }
            var majority = hitInfo.damageTypes.GetMajorityDamageType();
            if (majority == DamageType.Decay || majority == DamageType.Fall || majority == DamageType.Radiation) {
                return null;
            }
            if (!AllowDamage(entity, hitInfo)) {
                if (trace) LogTrace();
                CancelHit(hitInfo);
                return true;
            }
            if (trace) LogTrace();
            return null;
        }
        private void CancelHit(HitInfo hitInfo) {
            hitInfo.damageTypes = new DamageTypeList();
            hitInfo.DidHit = false;
            hitInfo.DoHitEffects = false;
        }
        private bool AllowKillingSleepers(BaseCombatEntity entity, HitInfo hitInfo) {
            if (entity.ShortPrefabName == "player" && (config.AllowKillingSleepersAlly || config.AllowKillingSleepers || config.AllowKillingSleepersAuthorization)) {
                var victim = entity.ToPlayer();
                if (!victim.IsSleeping()) {
                    return false;
                }
                if (config.AllowKillingSleepersAuthorization && hitInfo.Initiator is BasePlayer && AllowAuthorizationDamage(victim, hitInfo.InitiatorPlayer)) {
                    return true;
                }
                if (config.AllowKillingSleepersAlly && hitInfo.Initiator is BasePlayer) {
                    return victim.IsSleeping() && IsAlly(victim.userID, hitInfo.InitiatorPlayer.userID);
                }
                if (config.AllowKillingSleepers) {
                    return victim.IsSleeping();
                }
            }
            return false;
        }
        private bool AllowAuthorizationDamage(BasePlayer victim, BasePlayer attacker) {
            if (!attacker.userID.IsSteamId()) {
                return false;
            }
            var tugboat = victim.GetParentEntity() as Tugboat;
            if (tugboat != null && tugboat.IsAuthed(attacker)) {
                return true;
            }
            var priv = victim.GetBuildingPrivilege();
            if (priv != null && priv.IsAuthed(attacker)) {
                return true;
            }
            return false;
        }
        // determines if an entity is "allowed" to take damage
        private bool AllowDamage(BaseCombatEntity entity, HitInfo hitInfo) {
            if (trace) {
                traceEntity = entity;
                _tsb.Length = 0;
            }
            // if default global is not enabled or entity is npc, allow all damage
            if (currentRuleSet == null || currentRuleSet.IsEmpty() || !currentRuleSet.enabled || entity is BaseNpc) {
                return true;
            }
            // allow damage to door barricades and covers
            if (entity is TrainBarricade || entity is Barricade && (entity.ShortPrefabName.Contains("door_barricade") || entity.ShortPrefabName.Contains("cover"))) {
                return true;
            }
            // if entity is a barrel, trash can, or giftbox, allow damage (exclude water and hobo barrels)
            if (!entity.ShortPrefabName.Equals("waterbarrel") && entity.prefabID != 1748062128 && (entity.ShortPrefabName.Contains("barrel") || entity.ShortPrefabName.Equals("loot_trash") || entity.ShortPrefabName.Equals("giftbox_loot"))) {
                return true;
            }
            var weapon = hitInfo.Initiator ?? hitInfo.Weapon ?? hitInfo.WeaponPrefab;
            TrySetInitiator(hitInfo, weapon);
            if (trace) {
                // Sometimes the initiator is not the attacker (turrets)
                Trace("======================" + Environment.NewLine + "==  STARTING TRACE  ==" + Environment.NewLine + "==  " + DateTime.Now.ToString("HH:mm:ss.fffff") + "  ==" + Environment.NewLine + "======================");
                Trace($"From: {weapon?.GetType().Name ?? "Unknown_Weapon"}, {weapon?.ShortPrefabName ?? "Unknown_Prefab"}", 1);
                Trace($"To: {entity.GetType().Name}, {entity.ShortPrefabName}", 1);
            }
            // get entity and initiator locations (zones)
            List<string> entityLocations = GetLocationKeys(entity);
            List<string> initiatorLocations = GetLocationKeys(weapon);
            // check for exclusion zones (zones with no rules mapped)
            if (CheckExclusion(entityLocations, initiatorLocations, trace)) {
                if (trace) Trace("Exclusion found; allow and return", 1);
                return true;
            }
            if (trace) Trace("No exclusion found - looking up RuleSet...", 1);
            // process location rules
            RuleSet ruleSet = GetRuleSet(entityLocations, initiatorLocations);
            if (trace) Trace($"Using RuleSet \"{ruleSet.name}\"", 1);
            if (entity is PatrolHelicopter) {
                if (weapon is BasePlayer) {
                    bool isBlocked = !EvaluateRules(entity, weapon, ruleSet, false);
                    if (trace) Trace($"Target is PatrolHelicopter; {(isBlocked ? "block and return" : "allow and return")}", 1);
                    return !isBlocked;
                }
                return true;
            }
            if (weapon?.ShortPrefabName == "maincannonshell" || weapon is BradleyAPC) {
                if (trace) Trace("Initiator is BradleyAPC; evaluating RuleSet rules...", 1);
                return EvaluateRules(entity, weapon, ruleSet);
            }
            if (ruleSet.HasFlag(RuleFlags.VehiclesTakeCollisionDamageWithoutDriver) && entity is BaseVehicle && weapon == entity && (entity as BaseVehicle).GetDriver() == null) {
                if (trace) Trace($"Vehicle collision: No driver; allow and return", 1);
                return true;
            }
            // Check storage containers and doors for locks
            if (ruleSet.HasFlag(RuleFlags.LockedBoxesImmortal) && entity is StorageContainer && !(entity is LootContainer) || ruleSet.HasFlag(RuleFlags.LockedDoorsImmortal) && entity is Door) {
                object hurt = CheckLock(ruleSet, entity, hitInfo);
                // check for lock
                if (trace) Trace($"Door/StorageContainer detected with immortal flag; lock check results: {(hurt == null ? "null (no lock or unlocked);
                continue checks" : (bool)hurt ? "allow and return" : "block and return")}", 1);
                if (hurt is bool) return (bool)hurt;
            }
            // check heli and turret
            var heli = CheckHeliInitiator(ruleSet, hitInfo);
            if (config.Firework && entity is BaseFirework) {
                if (heli is bool) return false;
                return true;
            }
            if (heli is bool) {
                return HandleHelicopter(ruleSet, entity, weapon, (bool)heli);
            }
            // after heli check, return true if initiator is null
            if (hitInfo.Initiator.IsRealNull()) {
                if (damageTypes.Exists(x => hitInfo.damageTypes.Get(x) > 0f)) {
                    if (trace) Trace($"Initiator empty for player damage; block and return", 1);
                    return false;
                }
                if (weapon is MLRSRocket) {
                    if (trace) Trace($"Initiator empty for MLRS Rocket; block and return", 1);
                    return false;
                }
                if (trace) Trace($"Initiator empty; allow and return", 1);
                return true;
            }
            if (hitInfo.Initiator is SamSite && (entity is BasePlayer || entity is BaseMountable)) {
                if (CheckExclusion(hitInfo.Initiator)) {
                    if (trace) Trace($"Initiator is samsite, and target is player; exclusion found; allow and return", 1);
                    return true;
                }
                bool isAllowed = (hitInfo.Initiator as SamSite).staticRespawn ? !ruleSet.HasFlag(RuleFlags.StaticSamSitesIgnorePlayers) : !ruleSet.HasFlag(RuleFlags.PlayerSamSitesIgnorePlayers);
                if (trace) Trace($"Initiator is samsite, and target is player; {(isAllowed ? "flag not set;
                allow and return" : "flag set;
                block and return")}", 1);
                return isAllowed;
            }
            var isVictim = entity is BasePlayer;
            var isAttacker = hitInfo.Initiator is BasePlayer;
            var attacker = isAttacker ? hitInfo.Initiator as BasePlayer : null;
            if (isAttacker && !attacker.userID.IsSteamId() || hitInfo.Initiator is BaseNpc) {
                if (isVictim && ruleSet.HasFlag(RuleFlags.ProtectedSleepers) && entity.ToPlayer().IsSleeping()) {
                    if (trace) Trace("Target is sleeping player, with ProtectedSleepers flag set; block and return", 1);
                    return false;
                }
                if (ruleSet.HasFlag(RuleFlags.NpcsCanHurtAnything)) {
                    if (trace) Trace("Initiator is NPC; flag set; allow damage and return", 1);
                    return true;
                }
            }
            if (isVictim) {
                var victim = entity as BasePlayer;
                if (ruleSet.HasFlag(RuleFlags.SafeZoneTurretsIgnorePlayers) && hitInfo.Initiator is NPCAutoTurret && hitInfo.Initiator.OwnerID == 0) {
                    return true;
                }
                if (!ruleSet.HasFlag(RuleFlags.StaticTurretsIgnorePlayers) && hitInfo.Initiator is AutoTurret && !hitInfo.Initiator.OwnerID.IsSteamId()) {
                    return true;
                }
                var damageType = hitInfo.damageTypes.GetMajorityDamageType();
                if ((damageType == DamageType.Slash || damageType == DamageType.Stab) && hitInfo.Initiator == null) {
                    var lastAttacker = entity.lastAttacker as BasePlayer;
                    if (lastAttacker == null || !lastAttacker.userID.IsSteamId()) {
                        if (trace) Trace("Initiator is hurt trigger; allow damage and return", 1);
                        return true;
                    }
                }
                if (entity == attacker && damageType == DamageType.Bullet && hitInfo.damageTypes.Total() < 0f) {
                    return true;
             
// ... [Code preview truncated due to length. Full source in attached file] ...

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