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

FREE DeathNotices : 1.1.2 1.1.2

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

using Newtonsoft.Json;
using Oxide.Core;
using Rust;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using System.ComponentModel;
using System.Globalization;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;

namespace Oxide.Plugins
{
    [Info("Death Notices", "DarkAz", "1.1.2")]
    [Description("Announce kills within game chat.")]
    class DeathNotices : RustPlugin
    {


        #region Configuration

        private static Configuration _config;

        private class Configuration
        {
            [JsonProperty(PropertyName = "PostToDiscord")]
            public bool PostToDiscord = false;

            [JsonProperty(PropertyName = "DiscordWebhookURL")]
            public string DiscordWebhookURL = "";

            [JsonProperty(PropertyName = "HighlightHeadshots")]
            public bool HighlightHeadshots = true;

            [JsonProperty(PropertyName = "Colors")]
            public Dictionary<string, string> Colors = new Dictionary<string, string>()
            {
                ["default"] = "#AAAAAA",
                ["killer"] = "#C4FF00",
                ["victim"] = "#C4FF00",
                ["victimself"] = "#FF0000",
                ["victimowner"] = "#FFC400",
                ["weapon"] = "#C4FF00",
                ["attachments"] = "#C4FF00",
                ["distance"] = "#C4FF00",
                ["owner"] = "#C4FF00",
                ["headshot"] = "#FF0000",
            };

            [JsonProperty(PropertyName = "Entities")]
            public Dictionary<string, string> Entities = new Dictionary<string, string>()
            {
                ["banditguard"] = "a Bandit Guard",
                ["scientist"] = "a Scientist",
                ["heavyscientist"] = "a Heavy Scientist",
                ["tunneldweller"] = "a Tunnel Dweller",
                ["murderer"] = "a Murderer",
                ["scarecrow"] = "a Scarecrow",
                ["bear"] = "a Bear",
                ["boar"] = "a Boar",
                ["chicken"] = "a Chicken",
                ["horse"] = "a Horse",
                ["shark"] = "a Shark",
                ["stag"] = "a Stag",
                ["wolf"] = "a Wolf",
                ["zombie"] = "a Zombie",
                ["beartrap"] = "a Bear Trap",
                ["floorspikes"] = "Floor Spikes",
                ["flameturret"] = "a Flame Turret",
                ["landmine"] = "a Land Mine",
                ["autoturret"] = "an Auto Turret",
                ["guntrap"] = "a Gun Trap",
                ["sam_site_turret_deployed"] = "a SAM Site",
                ["napalm"] = "Napalm",
                ["barricadewood"] = "a Wooden Barricade",
                ["barricadewire"] = "a Wire Barricade",
                ["codelock"] = "a Code Lock",
                ["patrolhelicopter"] = "the Patrol Helicopter",
                ["bradleyapc"] = "the Bradley APC",
                ["highexternalwallwood"] = "a High External Wooden Wall",
                ["highexternalgatewood"] = "a High External Wooden Gate",
                ["highexternalwallstone"] = "a High External Stone Wall",
                ["highexternalgatestone"] = "a High External Stone Gate",
                ["highexternalwallice"] = "a High External Ice Wall",
                ["campfire"] = "a Campfire",
                ["skullfirepit"] = "a Skill Firepit",
                ["furnacelarge"] = "a Large Furnace",
                ["furnace"] = "a Furnace",
                ["woodenboxsmall"] = "a Small Wooden Box",
                ["woodenboxlarge"] = "a Large Wooden Box",
                ["toolcupboard"] = "a Tool Cupboard",
                ["foundation"] = "a Foundation",
            };

            [JsonProperty(PropertyName = "WeaponEntities")]
            public Dictionary<string, string> WeaponEntities = new Dictionary<string, string>()
            {
                ["ak47u.entity"] = "Assault Rifle",
                ["ak47u_ice.entity"] = "Assault Rifle",
                ["axe_salvaged.entity"] = "Salvaged Axe",
                ["bolt_rifle.entity"] = "Bolt Action Rifle",
                ["bone_club.entity"] = "Bone Club",
                ["bow_hunting.entity"] = "Hunting Bow",
                ["butcherknife.entity"] = "Butcher Knife",
                ["cake.entity"] = "Cake",
                ["candy_cane.entity"] = "Candy Cane",
                ["chainsaw.entity"] = "Chainsaw",
                ["compound_bow.entity"] = "Compound Bow",
                ["crossbow.entity"] = "Crossbow",
                ["double_shotgun.entity"] = "Double Barrel Shotgun",
                ["explosive.satchel.deployed"] = "Explosive Satchel",
                ["explosive.timed.deployed"] = "Timed Explosive Charge",
                ["explosive.satchel.entity"] = "Explosive Satchel",
                ["flamethrower_fireball"] = "Flamethrower",
                ["flamethrower.entity"] = "Flamethrower",
                ["flashlight.entity"] = "Flashlight",
                ["grenade.beancan.deployed"] = "Bean Can Grenade",
                ["grenade.beancan.entity"] = "Bean Can Grenade",
                ["grenade.f1.deployed"] = "F1 Grenade",
                ["grenade.f1.entity"] = "F1 Grenade",
                ["hacksaw.weapon"] = "",
                ["hammer_salvaged.entity"] = "Salvaged Hammer",
                ["hammer.entity"] = "Hammer",
                ["hatchet.entity"] = "Hatchet",
                ["icepick_salvaged.entity"] = "Salvaged Icepick",
                ["jackhammer.entity"] = "Jackhammer",
                ["knife_bone.entity"] = "Bone Knife",
                ["knife.combat.entity"] = "Combat Knife",
                ["l96.entity"] = "L96 Rifle",
                ["longsword.entity"] = "Longsword",
                ["lr300.entity"] = "LR-300 Assault Rifle",
                ["m249.entity"] = "M249",
                ["m39.entity"] = "M39 Rifle",
                ["m92.entity"] = "M92 Pistol",
                ["mace.entity"] = "Mace",
                ["machete.weapon"] = "machete",
                ["mgl.entity"] = "",
                ["militaryflamethrower.entity"] = "Flame Thrower",
                ["mp5.entity"] = "MP5A4",
                ["nailgun.entity"] = "Nailgun",
                ["paddle.entity"] = "Paddle",
                ["pickaxe.entity"] = "Pickaxe",
                ["pistol_eoka.entity"] = "Eoka Pistol",
                ["pistol_revolver.entity"] = "Revolver",
                ["pistol_semiauto.entity"] = "Semi-Automatic Pistol",
                ["pitchfork.entity"] = "Pitchfork",
                ["python.entity"] = "Python Revolver",
                ["rock.entity"] = "Rock",
                ["rocket_basic"] = "Rocket",
                ["rocket_fire"] = "Incendiary Rocket",
                ["rocket_hv"] = "High Velocity Rocket",
                ["rocket_launcher.entity"] = "Rocket Launcher",
                ["rocket_sam"] = "SAM Site",
                ["salvaged_cleaver.entity"] = "Salvaged Cleaver",
                ["salvaged_sword.entity"] = "Salvaged Sword",
                ["semi_auto_rifle.entity"] = "Semi-Automatic Rifle",
                ["shotgun_pump.entity"] = "Pump Action Shotgun",
                ["shotgun_waterpipe.entity"] = "Waterpipe Shotgun",
                ["sickle.entity"] = "Sickle",
                ["smg.entity"] = "Custom SMG",
                ["snowballgun.entity"] = "Snowball Gun",
                ["spas12.entity"] = "SPAS-12 Shotgun",
                ["spear_stone.entity"] = "Stone Spear",
                ["spear_wooden.entity"] = "Wooden Spear",
                ["stone_pickaxe.entity"] = "Stone Pickaxe",
                ["stonehatchet.entity"] = "Stone Hatchet",
                ["thompson.entity"] = "Thompson",
                ["toolgun.entity"] = "Toolgun",
                ["torch.entity"] = "Torch",
                ["waterball"] = "Water",
                ["waterbucket.entity"] = "Water Bucket",
            };            

            [JsonProperty(PropertyName = "Verbs")]
            public Dictionary<string, string> Verbs = new Dictionary<string, string>()
            {
                ["default"] = "fought off",
                ["playerdefault"] = "killed",
                ["bite"] = "bit",
                ["blunt"] = "bashed",
                ["explosion"] = "blew up",
                ["shot"] = "shot",
                ["shotarrow"] = "shot",
                ["slash"] = "slashed",
                ["stab"] = "stabbed",
                ["nailgun"] = "nailed",
                ["flamethrower"] = "roasted",
                ["chainsaw"] = "cut up",
                ["hatchet"] = "bashed",
                ["pickaxe"] = "bashed",
                ["jackhammer"] = "destroyed",
                ["grenade"] = "blew up",
                ["beancangrenade"] = "blew up",
                ["satchel"] = "blew up",
                ["snowball"] = "snowballed",
                ["landmine"] = "destroyed",
                ["funwater"] = "saturated",
                ["antivehicle"] = "took out",
                ["vehicle"] = "ran over",
            };

            [JsonProperty(PropertyName = "DiscordIcons")]
            public Dictionary<string, string> DiscordIcons = new Dictionary<string, string>()
            {
                ["default"] = "skull_crossbones",
                ["playerdefault"] = "skull_crossbones",
                ["bite"] = "vampire",
                ["blunt"] = "fist",
                ["explosion"] = "boom",
                ["shot"] = "gun",
                ["shotarrow"] = "bow_and_arrow",
                ["slash"] = "knife",
                ["stab"] = "dagger",
                ["nailgun"] = "gun",
                ["flamethrower"] = "fire",
                ["chainsaw"] = "carpentry_saw",
                ["hatchet"] = "axe",
                ["pickaxe"] = "hammer_pick",
                ["jackhammer"] = "hammer",
                ["grenade"] = "boom",
                ["snowball"] = "snowman",
                ["landmine"] = "boom",
                ["funwater"] = "sweat_drops",
                ["antivehicle"] = "boom",
                ["vehicle"] = "blue_car",
                ["beancangrenade"] = "canned_food",
                ["satchel"] = "school_satchel",
                ["bear"] = "bear",
                ["boar"] = "boar",
                ["chicken"] = "chicken",
                ["shark"] = "shark",
                ["stag"] = "deer",
                ["wolf"] = "wolf",
                ["cold"] = "cold_face",
                ["fall"] = "parachute",
                ["bleeding"] = "drop_of_blood",
                ["heat"] = "hot_face",
                ["drowned"] = "ocean",
                ["radiation"] = "radioactive",
            };
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                _config = Config.ReadObject<Configuration>();
                if (_config == null) throw new Exception();
                SaveConfig();
            }
            catch
            {
                PrintError("Your configuration file contains an error.Using default configuration values.");
                LoadDefaultConfig();
            }
        }

        protected override void SaveConfig() => Config.WriteObject(_config);

        protected override void LoadDefaultConfig() => _config = new Configuration();

        #endregion

        #region Private Data

        private readonly Regex _colorTagRegex = new Regex(@"<color=.{0,7}>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
        private readonly Regex _sizeTagRegex = new Regex(@"<size=\d*>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
        private readonly List<string> _richTextLiterals = new List<string>
        {
            "</color>", "</size>", "<b>", "</b>", "<i>", "</i>"
        };
        private readonly List<string> _environmentalDamage = new List<string>
        {
            "Cold"
        };

        private Dictionary<string, string> _entityShortPrefabs = new Dictionary<string, string>()
        {
            // players
            { "player", "player" },
            { "npcplayertest", "player" },
            // bandit
            { "bandit_guard", "banditguard" },
            // scientists
            { "scientist_astar_full_any", "scientist" },
            { "scientist_full_any", "scientist" },
            { "scientist_full_lr300", "scientist" },
            { "scientist_full_mp5", "scientist" },
            { "scientist_full_pistol", "scientist" },
            { "scientist_full_shotgun", "scientist" },
            { "scientist_junkpile_pistol", "scientist" },
            { "scientist_turret_any", "scientist" },
            { "scientist_turret_lr300", "scientist" },
            { "scientist", "scientist" },
            { "scientist_gunner", "scientist" },
            { "scientistnpc_cargo", "scientist" },
            { "scientistnpc_excavator", "scientist" },
            { "scientistnpc_oilrig", "scientist" },
            { "scientistnpc_patrol", "scientist" },
            { "scientistnpc_roam", "scientist" },
            { "scientistjunkpile", "scientist" },
            { "scientistpeacekeeper", "scientist" },
            { "scientiststationary", "scientist" },
            { "scientistnpc", "scientist" },
            { "humannpc", "scientist" },
            { "heavyscientist", "heavyscientist" },
            { "heavyscientistad", "heavyscientist" },
            { "tunneldweller", "tunneldweller" },
            // halloween
            { "murderer", "murderer" },
            { "scarecrow", "scarecrow" },
            // animals
            { "bear", "bear" },
            { "boar", "boar" },
            { "chicken", "chicken" },
            { "horse", "horse" },
            { "testridablehorse", "horse" },
            { "polarbear", "polarbear"},                               
            { "simpleshark", "shark" },
            { "stag", "stag" },
            { "wolf", "wolf" },
            // zombie
            { "zombie", "zombie" },
            // traps, etc
            { "beartrap", "beartrap" },
            { "spikes.floor", "floorspikes" },
            { "flameturret_fireball", "flameturret" },
            { "landmine", "landmine" },
            { "autoturret_deployed", "autoturret" },
            { "guntrap.deployed", "guntrap" },
            { "flameturret.deployed", "flameturret" },
            { "napalm", "napalm" },
            { "barricade.wood", "barricadewood" },
            { "barricade.woodwire", "barricadewire" },
            { "lock.code", "codelock" },
            // helicopter
            { "patrolhelicopter", "patrolhelicopter" },
            // bradley
            { "bradleyapc", "bradleyapc"},
            // misc
            { "wall.external.high", "highexternalwallwood" },
            { "wall.external.high.stone", "highexternalwallstone" },
            { "wall.external.high.ice", "highexternalwallice" },
            { "gates.external.high.wood", "highexternalgatewood" },
            { "gates.external.high.stone", "highexternalgatestone" },
            { "campfire", "campfire" },
            { "skull_fire_pit", "skullfirepit" },
            //exceptions (require further handling)
            { "flamethrower_fireball", "other" },
            // building entities
            { "furnace.large", "furnacelarge" },
            { "furnace", "furnace" },
            { "box.wooden.large", "woodenboxlarge" },
            { "woodbox_deployed", "woodenboxsmall" },
            { "cupboard.tool.deployed", "toolcupboard" },
            { "foundation", "foundation" },
        };

        #endregion

        #region Helpers

#if DEBUG
        private static void LogDebug(string text)
        {
            if (BasePlayer.activePlayerList.Count >= 1)
            {
                BasePlayer.activePlayerList[0].ConsoleMessage($"<color=orange>{text}</color>");
            }
        } 
#endif


        private string StripRichText(string text)
        {
            if (string.IsNullOrEmpty(text))
                return string.Empty;

            text = _colorTagRegex.Replace(text, string.Empty);
            text = _sizeTagRegex.Replace(text, string.Empty);

            foreach (var richTextLiteral in _richTextLiterals)
                text = text.Replace(richTextLiteral, string.Empty, StringComparison.InvariantCulture);

            return text;
        }

        private struct DeathData
        {
            public String KillerEntityType { get; set; }
            [JsonIgnore] public BaseEntity KillerEntity { get; set; }
            public String KillerName { get; set; }

            public String VictimEntityType { get; set; }
            [JsonIgnore] public BaseCombatEntity VictimEntity { get; set; }
            public String VictimName { get; set; }

            public string VictimEntityOwner { get; set; }

            public DamageType DamageType { get; set; }
            [JsonIgnore] public HitInfo HitInfo { get; set; }

            public String WeaponType { get; set; }

            public String Distance { get; set; }

            public String IconType { get; set; }

            public String Message { get; set; }

            public Dictionary<string, object> ToDictionary() => new Dictionary<string, object>
            {
                ["KillerEntity"] = KillerEntity,
                ["KillerEntityType"] = KillerEntityType,
                ["KillerName"] = KillerName,
                ["VictimEntity"] = VictimEntity,
                ["VictimEntityType"] = VictimEntityType,
                ["VictimName"] = VictimName,
                ["DamageType"] = DamageType,
                ["HitInfo"] = HitInfo,
                ["WeaponType"] = WeaponType,
                ["Distance"] = Distance,
                ["IconType"] = IconType,
                ["Message"] = Message,
            };
        }

        private String GetCombatEntityType(BaseEntity entity)
        {
            if (entity == null)
                return "none";

            String EntityName;
            String ConfigEntityName;

            bool knownEntity = _entityShortPrefabs.TryGetValue(entity.ShortPrefabName, out EntityName);

            if (knownEntity)
            {
                bool knownEntityName = _config.Entities.TryGetValue(EntityName, out ConfigEntityName);

                if (knownEntityName)
                    return ConfigEntityName;

                    Puts("******* Death Notices : Unknown Entity NAME *******");
                    Puts($"Entity Name: {EntityName}");

            }

#if DEBUG
        Puts("******* Death Notices : Unknown Combat Entity Start *******");
        Puts($"Entity: {entity}");
        Puts($"Entity PrefabName: {entity?.PrefabName}");
        Puts($"Entity ShortPrefabName: {entity?.ShortPrefabName}");
        Puts("******* Death Notices : Unknown Combat Entity End *******");
#endif

            // if (CombatEntityType.ContainsKey(entity.ShortPrefabName))
            //   return CombatEntityType.Other;
            //     return CombatEntityType[entity.ShortPrefabName];

            // if (CombatEntityType.Contents.ContainsKey(entity.GetType().Name))
            //     return CombatEntityType[entity.GetType().Name];

            // if (entity is BaseOven)
            //     return CombatEntityType.HeatSource;

            // if (entity is SimpleBuildingBlock)
            //     return CombatEntityType.ExternalWall;

            // if (entity is BaseAnimalNPC)
            //     return CombatEntityType.Animal;

            // if (entity is BaseTrap)
            //     return CombatEntityType.Trap;

            // if (entity is Barricade)
            //     return CombatEntityType.Barricade;

            // if (entity is IOEntity)
            //     return CombatEntityType.Trap;

            return EntityName;

        }


        private String GetWeaponType(BaseEntity entity)
        {
            if (entity == null)
                return "none";

            String EntityName;

            bool knownEntity = _config.WeaponEntities.TryGetValue(entity.ShortPrefabName, out EntityName);

            if (knownEntity)
                return EntityName;

#if DEBUG
        Puts("********************* Death Notices : Unknown Weapon Entity Start *******");
        Puts($"Entity: {entity}");
        Puts($"Entity PrefabName: {entity?.PrefabName}");
        Puts($"Entity ShortPrefabName: {entity?.ShortPrefabName}");
        Puts("********************* Death Notices : Unknown Weapon Entity End *******");
#endif
            return "other";
        }

        private DeathData BuildKillMessage(DeathData data)
        {

            string message = $"<color={_config.Colors["default"]}>";

            message += $"<color={_config.Colors["killer"]}>";
            message += FirstLetterToUpper(data.KillerName);
            message += "</color>";

            string verbage = "";

            switch (data.DamageType)
            {
                case DamageType.Bullet:
                    verbage = _config.Verbs["shot"];
                    data.IconType = _config.DiscordIcons["shot"];
                    if (data.WeaponType == "Nailgun")
                    { // fix: because, nailguns
                        verbage = _config.Verbs["nailgun"];
                        data.IconType = _config.DiscordIcons["nailgun"];
                    }
                    break;

                case DamageType.Arrow:
                    verbage = _config.Verbs["shotarrow"];
                    data.IconType = _config.DiscordIcons["shotarrow"];
                    break;

                case DamageType.Slash:
                    verbage = "slashed";
                    data.IconType = _config.DiscordIcons["slash"];
                    if (data.WeaponType == "Flamethrower" || data.KillerEntity?.ShortPrefabName == "flameturret.deployed")
                    { // fix: Flamethrowers do slash damage!
                        verbage = _config.Verbs["flamethrower"];
                        data.IconType = _config.DiscordIcons["flamethrower"];
                    }
                    if (data.WeaponType == "Chainsaw")
                    { // fix: Chainsaws do slash damage!
                        verbage = _config.Verbs["chainsaw"];
                        data.IconType = _config.DiscordIcons["chainsaw"];
                    }
                    if (data.WeaponType == "Hatchet" || data.WeaponType == "Hatchet")
                    { // fix: Hatchets do slash damage!
                        verbage = _config.Verbs["hatchet"];
                        data.IconType = _config.DiscordIcons["hatchet"];
                    }
                    break;

                case DamageType.Stab:
                    verbage = "stabbed";
                    data.IconType = _config.DiscordIcons["stab"];
                    if (data.WeaponType == "Bean Can Grenade")
                    { // fix: bean can grenades and explosive satchels do stab damage!
                        verbage = _config.Verbs["beancangrenade"];
                        data.IconType = _config.DiscordIcons["beancangrenade"];
                    }
                    if (data.WeaponType == "Explosive Satchel")
                    { // fix: bean can grenades and explosive satchels do stab damage!
                        verbage = _config.Verbs["satchel"];
                        data.IconType = _config.DiscordIcons["satchel"];
                    }
                    if (data.WeaponType == "Stone Pickaxe")
                    { // fix: Stone Pickaxe do stab damage!
                        verbage = _config.Verbs["pickaxe"];
                        data.IconType = _config.DiscordIcons["pickaxe"];
                    }
                    if (data.WeaponType == "Jackhammer")
                    { // fix: Jackhammers do stab damage!
                        verbage = _config.Verbs["jackhammer"];
                        data.IconType = _config.DiscordIcons["jackhammer"];
                    }
                    break;

                case DamageType.Bite:
                    verbage = _config.Verbs["bite"];
                        data.IconType = _config.DiscordIcons["bite"];
                    break;

                case DamageType.Blunt:
                    verbage = _config.Verbs["blunt"];
                    data.IconType = _config.DiscordIcons["blunt"];
                    if (data.WeaponType == "F1 Grenade")
                    { // fix: F1 grenades do blunt damage!
                        verbage = _config.Verbs["grenade"];
                        data.IconType = _config.DiscordIcons["grenade"];
                    }
                    if (data.WeaponType == "Snowball Gun")
                    { // fix: Snowball Guns do blunt damage!
                        verbage = _config.Verbs["snowball"];
                        data.IconType = _config.DiscordIcons["snowball"];
                    }
                    if (data.KillerEntity.ShortPrefabName == "landmine")
                    { // fix: Landmines do blunt damage!
                        verbage = _config.Verbs["landmine"];
                        data.IconType = _config.DiscordIcons["landmine"];
                    }
                    break;

                case DamageType.Fun_Water:
                    verbage = _config.Verbs["funwater"];
                    data.IconType = _config.DiscordIcons["funwater"];
                    break;

                case DamageType.AntiVehicle:
                    verbage = _config.Verbs["antivehicle"];
                    data.IconType = _config.DiscordIcons["antivehicle"];
                    break;

                case DamageType.Explosion:
                    verbage = _config.Verbs["explosion"];
                    data.IconType = _config.DiscordIcons["explosion"];
                    break;

                case DamageType.Generic:
                    if (data.KillerEntity.ToPlayer().isMounted)
                    {
                        verbage = _config.Verbs["vehicle"];
                        data.IconType = _config.DiscordIcons["vehicle"];
                        break;
                    } else {
                        // this is a weird damage that we don't want to be broadcasting
                        data.Message = null;
                        return data;
                    }
                    break;
                
                default:
                    if (data.VictimEntityType == "player") {
                        verbage = _config.Verbs["playerdefault"];
                        data.IconType = _config.DiscordIcons["playerdefault"];
                    } else {
                        verbage = _config.Verbs["default"];
                        data.IconType = _config.DiscordIcons["default"];
                    }
                    break;

            }

            message += $" {verbage} ";

            if (data.VictimName == data.KillerName || string.IsNullOrEmpty(data.KillerName))
            {
                message += $"<color={_config.Colors["victimself"]}>themself!</color>";
            }
            else
            {
                message += $"<color={_config.Colors["victim"]}>{data.VictimName}</color>";
            }

            if (!string.IsNullOrEmpty(data.VictimEntityOwner))
            {
                message += $" owned by <color={_config.Colors["victimowner"]}>{data.VictimEntityOwner}</color>";
            }

            if (data.WeaponType != "other" && data.WeaponType != "none" && data.KillerEntity.ShortPrefabName != "autoturret_deployed" && data.KillerEntity.ShortPrefabName != "sam_site_turret_deployed")
            {
                message += $" with their <color={_config.Colors["weapon"]}>{data.WeaponType}</color>";
            }

            if (data.Distance != "" && verbage == _config.Verbs["shot"] && data.VictimName != data.KillerName)
            {
                message += $" over a distance of <color={_config.Colors["distance"]}>{data.Distance}</color>";
            }

            if(_config.HighlightHeadshots && data.HitInfo.boneArea == HitArea.Head) {
                message += $"<color={_config.Colors["headshot"]}> [Headshot]</color>";
            }

            message += "</color>";

            data.Message = message;

            return data;
        }


        private DeathData BuildOtherMessage(DeathData data)
        {
            string message = $"<color={_config.Colors["default"]}>";
            message += $"<color={_config.Colors["victim"]}>{data.VictimName}</color>";

            bool isValidMessage = false;

            switch (data.DamageType)
            {
                case DamageType.Radiation:
                    message += " died of radiation poisoning";
                    data.IconType = _config.DiscordIcons["radiation"];
                    isValidMessage = true;
                    break;

                case DamageType.Bleeding:
                    message += " bled to death";
                    data.IconType = _config.DiscordIcons["bleeding"];
                    isValidMessage = true;
                    break;

                case DamageType.Drowned:
                    message += " drowned";
                    data.IconType = _config.DiscordIcons["drowned"];
                    isValidMessage = true;
                    break;

            }

            message += "</color>";

            data.Message = isValidMessage ? message : "";

            return data;
        }

        private DeathData DiscordAnimalIcons(DeathData data)
        {
            if (string.IsNullOrEmpty(data.KillerEntityType))
                return data;
            
            string entityKey = _config.Entities.FirstOrDefault(x => x.Value == data.KillerEntityType).Key;

            if (string.IsNullOrEmpty(entityKey))
                return data;

            String iconName;

            bool entityIconExists = _config.DiscordIcons.TryGetValue(entityKey, out iconName);

            if (entityIconExists)
                data.IconType = iconName;

            return data;
        }

        private String BuildEnvironmentalMessage(BaseCombatEntity victimEntity)
        {

            String victimName = StripRichText(victimEntity.ToPlayer().displayName);

            String message = "<color=#aaaaaa>";

            message += $"<color={_config.Colors["victim"]}>{victimName}</color>";

            switch (victimEntity?.lastDamage)
            {

                // case "Collision":
                case DamageType.Cold:
                    message += " froze to death";
                    break;

                case DamageType.Fall:
                    message += " fell to their death";
                    break;

                case DamageType.Bleeding:
                    message += " bled to death";
                    break;

                case DamageType.Heat:
                    message += " overheated";
                    break;

                default:
                    return "";
            }

            message += "</color>";

            return message;
        }

        private void BroadcastMessage(String message)
        {
            if (string.IsNullOrEmpty(message))
                return;

            foreach (var player in BasePlayer.activePlayerList)
            {
                Player.Reply(
                    player,
                    message,
                    ulong.Parse("0")
                );
            }

        }

        private static string GetDistance(BaseEntity killerEntity, BaseCombatEntity victimEntity)
        {
            if (killerEntity == null || victimEntity == null)
                return "";

            var distance = Math.Round(killerEntity.Distance(victimEntity), 2);
            string unit = distance == 1
                ? "meter"
                : "meters";

            if (distance <= 0)
                return "";

            return $"{distance} {unit}";
        }


        public static string FirstLetterToUpper(string s)
        {
            if (string.IsNullOrEmpty(s))
                return string.Empty;

            char[] a = s.ToCharArray();
            a[0] = char.ToUpper(a[0]);
            return new string(a);
        }

        #endregion

        #region Hooks

        private void OnEntityDeath(BaseCombatEntity victimEntity, HitInfo hitInfo)
        {
            // Ignore - there is no victim for some reason
            if (victimEntity == null)
                return;

            var killerEntity = victimEntity?.lastAttacker ?? hitInfo?.Initiator;
            
            // Ignore if killer is null - rare, but happens
            if (killerEntity == null)
                return;
            
            // Ignore "Generic" damage
            if (victimEntity.lastDamage == DamageType.Generic) {
                if (killerEntity.ToPlayer().isMounted) {
                } else {
                    string VictimEntityType = GetCombatEntityType(victimEntity);
 #if DEBUG
                    Puts("------- Death Notices Skipped as damage was Generic -------");
                    Puts($"Killer: {killerEntity.ShortPrefabName} Victim: {victimEntity.ShortPrefabName}");
                    Puts("---------------------------------------------------------------------------------");
 #endif
                    return;
                }
            }                                                        

            // if there's no hitInfo we should still handle environmental deaths
            if (hitInfo == null)
            {
                bool validDamage = false;
                string discordIcon = _config.DiscordIcons["default"];

                switch (victimEntity.lastDamage)
                {
                    case DamageType.Cold:
                        validDamage = true;
                        discordIcon = _config.DiscordIcons["cold"];
                        break;
                    case DamageType.Fall:
                        validDamage = true;
                        discordIcon = _config.DiscordIcons["fall"];
                        break;
                    case DamageType.Bleeding:
                        validDamage = true;
                        discordIcon = _config.DiscordIcons["bleeding"];
                        break;
                    case DamageType.Heat:
                        validDamage = true;
                        discordIcon = _config.DiscordIcons["heat"];
                        break;
                }

                if(validDamage) {
                    String environmentalMessage = BuildEnvironmentalMessage(victimEntity);
                    BroadcastMessage(environmentalMessage);
                    // @todo: environmental icons
                    if(_config.PostToDiscord) {
                        SendDiscordMessage(environmentalMessage, discordIcon);
                    }
                }
                return;
            }

            // Try to avoid error when entity was destroyed
            if (victimEntity.gameObject == null)
                return;

            var data = new DeathData
            {
                VictimEntity = victimEntity,
                KillerEntity = killerEntity,
                VictimEntityType = GetCombatEntityType(victimEntity),
                KillerEntityType = GetCombatEntityType(victimEntity?.lastAttacker),
                VictimEntityOwner =  covalence.Players.FindPlayerById(victimEntity.OwnerID.ToString())?.Name ?? "",
                DamageType = victimEntity.lastDamage,
                HitInfo = hitInfo,
                WeaponType = GetWeaponType(hitInfo?.WeaponPrefab),
                Distance = GetDistance(victimEntity.lastAttacker ?? hitInfo?.Initiator, victimEntity),
            };

            if(string.IsNullOrEmpty(data.VictimEntityType))
                return;

            // Ignore decay
            if (data.DamageType == DamageType.Decay)
                return;

            // Ignore "other" ?
            // if (data.VictimEntityType == "other" || data.KillerEntityType == "other")
            //   return;
            bool hasPlayer = false;

            if (data.VictimEntityType == "player")
            {
                hasPlayer = true;
                data.VictimName = StripRichText(data.VictimEntity.ToPlayer().displayName);
            }
            else if (data.VictimEntityType == _config.Entities["murderer"])
            {
                data.VictimName = StripRichText(data.VictimEntity.ToPlayer().displayName);
            }
            else
            {
                data.VictimName = data.VictimEntityType;
            }

            if (data.KillerEntityType == "player")
            {
                hasPlayer = true;
                data.KillerName = StripRichText(data.KillerEntity.ToPlayer().displayName);
            }
            else if (data.KillerEntityType == _config.Entities["murderer"])
            {
                data.KillerName = StripRichText(data.KillerEntity.ToPlayer().displayName);
            }
            else
            {
                data.KillerName = data.KillerEntityType;
                if (data.HitInfo?.WeaponPrefab?.ShortPrefabName == "rocket_sam")
                {
                    data.KillerName = "A SAM Site";
                }
            }

            // we only want to consider things that involve a player somewhere
            if (hasPlayer == false)
            {
// #if DEBUG
//                 Puts("------- Death Notices Skipped as No Player Was Involved -------");
//                 Puts($"Killer: {data.KillerName} Victim: {data.VictimName}");
//                 Puts("---------------------------------------------------------------------------------");
// #endif
                return;
            }

#if DEBUG
            Puts("------- Death Notices Debug Start -------");
            Puts($"VictimEntity: {data.VictimEntity}");
            Puts($"VictimEntity PrefabName: {data.VictimEntity?.PrefabName}");
            Puts($"VictimEntity ShortPrefabName: {data.VictimEntity?.ShortPrefabName}");
            Puts($"VictimEntityType: {data.VictimEntityType}");
            Puts($"VictimEntityOwner: {data.VictimEntityOwner}");
            Puts($"VictimName: {data.VictimName}");
            Puts($"KillerEntity: {data.KillerEntity}");
            Puts($"KillerEntity PrefabName: {data.KillerEntity?.PrefabName}");
            Puts($"KillerEntity ShortPrefabName: {data.KillerEntity?.ShortPrefabName}");
            Puts($"KillerEntityType: {data.KillerEntityType}");
            Puts($"KillerName: {data.KillerName}");
            Puts($"DamageType: {data.DamageType}");
            Puts($"HitInfo: {data.HitInfo}");
            Puts($"HitInfo.boneArea: {data.HitInfo?.boneArea}");
            Puts($"HitInfo.WeaponPrefab: {data.HitInfo?.WeaponPrefab}");
            Puts($"HitInfo.WeaponPrefab.ShortPrefabName: {data.HitInfo?.WeaponPrefab?.ShortPrefabName}");
            Puts($"WeaponType: {data.WeaponType}");
            Puts($"Distance: {data.Distance}");
            Puts("------- Death Notices Debug End -------");
#endif

            string message = "";

            if (data.KillerEntityType == "none")
            {
                data = BuildOtherMessage(data);
            }
            else
            {
                data = BuildKillMessage(data);
            }

            BroadcastMessage(data.Message);
            if(_config.PostToDiscord) {
                data = DiscordAnimalIcons(data);
                SendDiscordMessage(data.Message, data.IconType);
            }

        }

        #endregion

        #region Discord

        private readonly Dictionary<string, string> _discordHeaders = new Dictionary<string, string>()
        {
            {"Content-Type", "application/json"}
        };

        private class DiscordMessage
        {
            [JsonProperty("content")]
            private string Content { get; set; }

            public DiscordMessage(string content)
            {
                Content = content;
            }

            public StringBuilder ToJson() => new StringBuilder(JsonConvert.SerializeObject(this, Formatting.None,
                new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore}));
        }

        private void SendDiscordMessage(string message, string discordIcon)
        {
            if(string.IsNullOrEmpty(_config.DiscordWebhookURL))
                return;

            DiscordMessage dmessage = new DiscordMessage(FormatDiscordMessage(message, discordIcon));

            StringBuilder json = dmessage.ToJson();

            webrequest.Enqueue(_config.DiscordWebhookURL, json.ToString(), SendDiscordMessageCallback, this, RequestMethod.POST, _discordHeaders);
        }

        private void SendDiscordMessageCallback(int code, string message)
        {
            if (code != 204)
            {
                PrintError(message);
            }
        }

        private readonly List<Regex> _regexTags = new List<Regex>
        {
            new Regex("<color=.+?>", RegexOptions.Compiled),
            new Regex("<size=.+?>", RegexOptions.Compiled)
        };

        private readonly List<string> _tags = new List<string>
        {
            "</color>",
            "</size>",
            "<i>",
            "</i>",
            "<b>",
            "</b>"
        };

        private string FormatDiscordMessage(string original, string discordIcon)
        {
            if (string.IsNullOrEmpty(original))
            {
                return string.Empty;
            }

            foreach (string tag in _tags)
            {
                original = original.Replace(tag, "");
            }

            foreach (Regex regexTag in _regexTags)
            {
                original = regexTag.Replace(original, "");
            }


            original = $":{discordIcon}: {original}";

            return original;
        }
        #endregion

    }

}

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