using System; using System.Linq; using System.Reflection; using System.Collections.Generic; using Newtonsoft.Json; using Oxide.Core; using Oxide.Core.Plugins; using Rust; using UnityEngine; #region Changelogs and ToDo /********************************************************************** * * 1.0.0 : - Initial release * 1.0.1 : - Added support for GUIAnnouncements * - Added Estemated GridLocations to messages * - Made messages more dynamic * - Vanilla Bradleys will now spawn on random (true false setting) * 1.0.2 : - Added dmg and accuracy * - Added support for Economics and ServerRewards * 1.0.3 : - Added Lootprofiles per tier * 1.0.4 : - Added chatmessage on 1st hit to show tier (2 minutes between messages) * - Added Chat/announcement options to cfg (true false) * - Fixed a typo in the language section * 1.0.5 - Fix for NRE when bradley inflicts selfdamage * 1.0.6 - crates Should now be removing the vanilla loot better before adding custom profile loot * Vanilla Bradley loot and crates will now remain vanilla * Option to custom rename the tiers * 1.0.7 - Possible fix for top 2 tiers having wrong HP on occasion * 1.0.8 - Patch for nov 4 rust update * 1.0.9 - Extra nullcheck (OnEntityTakeDamage) * 1.1.0 - Improved GridLocation call * - Added Attackmessage to lang file * - Added support for Notify and UINotify * - Cleaned up and refractured the Bradley spawning modifiers * - Cleaned up and refractured the Bradley Spawning messagesystem * - Cleaned up and refractured the Bradley Kills messagesystem * - Optimised colorscheme * 1.1.1 - Added KillNotification that was previously hardcoded to lang file * - Fixed Notifcations when it is a Convoy Bradley * - Fixed Vanilla Bradley colors in messages * 1.1.2 - Added SpawnMessage to Lang file * - Single message line is now used from Lang file on bradley spawns * - Pre patched for Armored Train plugin update * 1.1.3 - Fixed ServerRewards not handing out rewards * - Fixed the console notification for Convoy check * - fixed Exploit upgrading leftover crates from previous bradley * 1.1.4 - Delayed checks for ArmoredTrain apc spawns * - Possible fix for messages forcing themselves when not a tiered apc * - Fixed Targeting ArmoredTrain apc * **********************************************************************/ #endregion namespace Oxide.Plugins { [Info("BradleyTiers", "Krungh Crow", "1.1.4")] [Description("Bradley with difficulties and events")] class BradleyTiers : RustPlugin { [PluginReference] Plugin ArmoredTrain, Convoy ,Economics, GUIAnnouncements, Notify, UINotify, ServerRewards; #region Variables const string Use_Perm = "bradleytiers.use"; private System.Random random = new System.Random(); private Dictionary> Skins { get; set; } = new Dictionary>(); ulong chaticon = 76561199183246772; string prefix; float accuracy; string _announce; int CaseCount; string color1; string color2; float damagescale; string difficulty; string _vanilla; string _easy; string _medium; string _hard; string _nightmare; string lootprofile; int reward; int total; int Pid = 0; bool Debug = false; bool showchat = true; bool showchatannouncement = true; bool showchatreward = true; bool UseNotify = false; bool IsConvoyAPC = false; #endregion #region Timers Dictionary CoolDowns = new Dictionary(); public class CooldownTimer { public Timer timer; public float start; public float countdown; } #endregion #region Configuration void Init() { if (!LoadConfigVariables()) { Puts("Config file issue detected. Please delete file, or check syntax and fix."); return; } permission.RegisterPermission(Use_Perm, this); Debug = configData.PlugCFG.Debug; showchat = configData.PlugCFG.ChatUse; showchatannouncement = configData.PlugCFG.ChatAnnounceUse; showchatreward = configData.PlugCFG.ChatRewardUse; UseNotify = configData.PlugCFG.UseNotify; Pid = configData.PlugCFG.PiD; prefix = configData.PlugCFG.Prefix; _vanilla = configData.Naming.Vanilla; _easy = configData.Naming.Easy; _medium = configData.Naming.Medium; _hard = configData.Naming.Hard; _nightmare = configData.Naming.Nightmare; if (Debug) Puts($"[Debug] Debug is Activated ,if unintentional check cfg and set to false"); } private ConfigData configData; class ConfigData { [JsonProperty(PropertyName = "Main config")] public SettingsPlugin PlugCFG = new SettingsPlugin(); [JsonProperty(PropertyName = "Tier Names")] public SettingsNames Naming = new SettingsNames(); [JsonProperty(PropertyName = "Kill Rewards")] public SettingsReward Rewards = new SettingsReward(); [JsonProperty(PropertyName = "Loot Tables")] public SettingsLoot Loot = new SettingsLoot(); [JsonProperty(PropertyName = "Easy Bradley")] public SettingsBradEasy Easy = new SettingsBradEasy(); [JsonProperty(PropertyName = "Medium Bradley")] public SettingsBradMedium Medium = new SettingsBradMedium(); [JsonProperty(PropertyName = "Hard Bradley")] public SettingsBradHard Hard = new SettingsBradHard(); [JsonProperty(PropertyName = "Nightmare Bradley")] public SettingsBradNightmare Nightmare = new SettingsBradNightmare(); } class SettingsPlugin { [JsonProperty(PropertyName = "Debug")] public bool Debug = false; [JsonProperty(PropertyName = "Chat Prefix")] public string Prefix = "[Bradley Tiers] "; [JsonProperty(PropertyName = "Use GUIAnnouncement")] public bool GUIAUse = false; [JsonProperty(PropertyName = "Reply to player in chat on attack")] public bool ChatUse = true; [JsonProperty(PropertyName = "Reply to player in chat on reward")] public bool ChatRewardUse = true; [JsonProperty(PropertyName = "Show kills/spawns in Global chat")] public bool ChatAnnounceUse = true; [JsonProperty(PropertyName = "Use Notify")] public bool UseNotify = false; [JsonProperty(PropertyName = "Notify profile ID")] public int PiD = 0; [JsonProperty(PropertyName = "Include Vanilla Bradley")] public bool VanillaUse = false; } class SettingsNames { [JsonProperty(PropertyName = "Vanilla")] public string Vanilla = "Vanilla"; [JsonProperty(PropertyName = "Easy")] public string Easy = "Easy"; [JsonProperty(PropertyName = "Medium")] public string Medium = "Medium"; [JsonProperty(PropertyName = "Hard")] public string Hard = "Hard"; [JsonProperty(PropertyName = "Nightmare")] public string Nightmare = "Nightmare"; } class SettingsReward { [JsonProperty(PropertyName = "Use Economics?")] public bool UseEco = false; [JsonProperty(PropertyName = "Use ServerRewards?")] public bool UseSR = false; [JsonProperty(PropertyName = "Vanilla amount")] public int Vanilla = 500; [JsonProperty(PropertyName = "Easy amount")] public int Easy = 1000; [JsonProperty(PropertyName = "Medium amount")] public int Medium = 1500; [JsonProperty(PropertyName = "Hard amount")] public int Hard = 2000; [JsonProperty(PropertyName = "Nightmare amount")] public int Nightmare = 2500; } class SettingsBradEasy { [JsonProperty(PropertyName = "Bradley Health")] public int BradleyHealth = 2000; [JsonProperty(PropertyName = "Bradley Max Fire Range")] public int BradleyMaxFireRange = 100; [JsonProperty(PropertyName = "Bradley Throttle Responce")] public float BradleySpeed = 1.0f; [JsonProperty(PropertyName = "Bradley Accuracy (0-1)")] public float BradleyAccuracy = 0.6f; [JsonProperty(PropertyName = "Bradley Damage scale (0-1)")] public float BradleyDamageScale = 0.6f; [JsonProperty(PropertyName = "Bradley Max crates after kill")] public int BradleyCratesAmount = 4; [JsonProperty(PropertyName = "Spawn Min Amount Items")] public int MinAmount { get; set; } = 2; [JsonProperty(PropertyName = "Spawn Max Amount Items")] public int MaxAmount { get; set; } = 6; [JsonProperty(PropertyName = "Loot Table", ObjectCreationHandling = ObjectCreationHandling.Replace)] public List Loot { get; set; } = DefaultLoot; } class SettingsBradMedium { [JsonProperty(PropertyName = "Bradley Health")] public int BradleyHealth = 4000; [JsonProperty(PropertyName = "Bradley Max Fire Range")] public int BradleyMaxFireRange = 100; [JsonProperty(PropertyName = "Bradley Throttle Responce")] public float BradleySpeed = 1.0f; [JsonProperty(PropertyName = "Bradley Accuracy (0-1)")] public float BradleyAccuracy = 0.75f; [JsonProperty(PropertyName = "Bradley Damage scale (0-1)")] public float BradleyDamageScale = 0.7f; [JsonProperty(PropertyName = "Bradley Max crates after kill")] public int BradleyCratesAmount = 5; [JsonProperty(PropertyName = "Spawn Min Amount Items")] public int MinAmount { get; set; } = 2; [JsonProperty(PropertyName = "Spawn Max Amount Items")] public int MaxAmount { get; set; } = 6; [JsonProperty(PropertyName = "Loot Table", ObjectCreationHandling = ObjectCreationHandling.Replace)] public List Loot { get; set; } = DefaultLoot; } class SettingsBradHard { [JsonProperty(PropertyName = "Bradley Health")] public int BradleyHealth = 10000; [JsonProperty(PropertyName = "Bradley Max Fire Range")] public int BradleyMaxFireRange = 100; [JsonProperty(PropertyName = "Bradley Throttle Responce")] public float BradleySpeed = 1.0f; [JsonProperty(PropertyName = "Bradley Accuracy (0-1)")] public float BradleyAccuracy = 0.8f; [JsonProperty(PropertyName = "Bradley Damage scale (0-1)")] public float BradleyDamageScale = 0.85f; [JsonProperty(PropertyName = "Bradley Max crates after kill")] public int BradleyCratesAmount = 8; [JsonProperty(PropertyName = "Spawn Min Amount Items")] public int MinAmount { get; set; } = 2; [JsonProperty(PropertyName = "Spawn Max Amount Items")] public int MaxAmount { get; set; } = 6; [JsonProperty(PropertyName = "Loot Table", ObjectCreationHandling = ObjectCreationHandling.Replace)] public List Loot { get; set; } = DefaultLoot; } class SettingsBradNightmare { [JsonProperty(PropertyName = "Bradley Health")] public int BradleyHealth = 15000; [JsonProperty(PropertyName = "Bradley Max Fire Range")] public int BradleyMaxFireRange = 100; [JsonProperty(PropertyName = "Bradley Throttle Responce")] public float BradleySpeed = 1.0f; [JsonProperty(PropertyName = "Bradley Accuracy (0-1)")] public float BradleyAccuracy = 0.85f; [JsonProperty(PropertyName = "Bradley Damage scale (0-1)")] public float BradleyDamageScale = 1.0f; [JsonProperty(PropertyName = "Bradley Max crates after kill")] public int BradleyCratesAmount = 12; [JsonProperty(PropertyName = "Spawn Min Amount Items")] public int MinAmount { get; set; } = 2; [JsonProperty(PropertyName = "Spawn Max Amount Items")] public int MaxAmount { get; set; } = 6; [JsonProperty(PropertyName = "Loot Table", ObjectCreationHandling = ObjectCreationHandling.Replace)] public List Loot { get; set; } = DefaultLoot; } class SettingsLoot { [JsonProperty(PropertyName = "Use lootsystem")] public bool UseLoot = false; [JsonProperty(PropertyName = "Use Random Skins")] public bool RandomSkins { get; set; } = true; } private bool LoadConfigVariables() { try { configData = Config.ReadObject(); } catch { return false; } SaveConf(); return true; } protected override void LoadDefaultConfig() { Puts("Fresh install detected Creating a new config file."); configData = new ConfigData(); SaveConf(); } void SaveConf() => Config.WriteObject(configData, true); #endregion #region LanguageAPI protected override void LoadDefaultMessages() { lang.RegisterMessages(new Dictionary { ["Bradley"] = "Bradley", ["SpawnMessage"] = "A {0} Bradley has spawned around {1}", ["Destroyed"] = "finally destroyed the", ["Info"] = "\nAvailable Commands\n/bt info : Shows info on version/author and commands", ["InvalidInput"] = "Please enter a valid command!", ["KillRewardMessage"] = "You recieved {0}$ for Destroying the {1} BradleyApc", ["KillNotification"] = "{0} Destroyed a {1} BradleyApc", ["AttackMessage"] = "You are taking on a {0} Bradleyapc", ["Version"] = "Version : V", ["NoPermission"] = "You do not have permission to use that command!", }, this); } #endregion #region Commands [ChatCommand("bt")] private void cmdPrimary(BasePlayer player, string command, string[] args) { if (!permission.UserHasPermission(player.UserIDString, Use_Perm)) { Player.Message(player, prefix + string.Format(msg("NoPermission", player.UserIDString)), chaticon); if (Debug) Puts($"[Debug] {player} had no permission for using Commands"); return; } if (args.Length == 0) { Player.Message(player, prefix + string.Format(msg("InvalidInput", player.UserIDString)), chaticon); } else { if (args[0].ToLower() == "info") { Player.Message(player, prefix + string.Format(msg("Version", player.UserIDString)) + this.Version.ToString() + " By : " + this.Author.ToString() + msg("Info") , chaticon); return; } else { Player.Message(player, prefix + string.Format(msg("InvalidInput", player.UserIDString)), chaticon); } } } #endregion #region Message helper private string msg(string key, string id = null) => lang.GetMessage(key, this, id); #endregion #region Hooks private void OnBradleyApcInitialize(BradleyAPC bradley) { if (bradley.skinID == 755446 || bradley.OwnerID == 755446)//Adem plugin reference 1114526 { Puts($"Disabled Tiered apc spawn Settings for Convoy/Armored Train {bradley}"); return; } var dropposition = bradley.transform.position; string Grid = GetGrid(dropposition); int CaseCount = 4; if (configData.PlugCFG.VanillaUse) CaseCount = 5; timer.Once(0.5f, () => { if (bradley.skinID != 0 || bradley.OwnerID != 0) { if (Debug) Puts($"Disabled Tiered apc for Armored Train {bradley}"); return; } switch (UnityEngine.Random.Range(0, CaseCount)) { case 0: bradley._maxHealth = configData.Easy.BradleyHealth; bradley.health = configData.Easy.BradleyHealth; bradley.viewDistance = configData.Easy.BradleyMaxFireRange; bradley.searchRange = configData.Easy.BradleyMaxFireRange; bradley.throttle = configData.Easy.BradleySpeed; bradley.leftThrottle = bradley.throttle; bradley.rightThrottle = bradley.throttle; bradley.maxCratesToSpawn = configData.Easy.BradleyCratesAmount; bradley.name = $"{_easy} BradleyApc[{bradley.net.ID}]"; difficulty = _easy; color1 = "green"; _announce = "BradEasy"; break; case 1: bradley._maxHealth = configData.Medium.BradleyHealth; bradley.health = configData.Medium.BradleyHealth; bradley.viewDistance = configData.Medium.BradleyMaxFireRange; bradley.searchRange = configData.Medium.BradleyMaxFireRange; bradley.throttle = configData.Medium.BradleySpeed; bradley.leftThrottle = bradley.throttle; bradley.rightThrottle = bradley.throttle; bradley.maxCratesToSpawn = configData.Medium.BradleyCratesAmount; bradley.name = $"{_medium} BradleyApc[{bradley.net.ID}]"; difficulty = _medium; color1 = "purple"; _announce = "BradMedium"; break; case 2: bradley._maxHealth = configData.Hard.BradleyHealth; bradley.health = configData.Hard.BradleyHealth; bradley.viewDistance = configData.Hard.BradleyMaxFireRange; bradley.searchRange = configData.Hard.BradleyMaxFireRange; bradley.throttle = configData.Hard.BradleySpeed; bradley.leftThrottle = bradley.throttle; bradley.rightThrottle = bradley.throttle; bradley.maxCratesToSpawn = configData.Hard.BradleyCratesAmount; bradley.name = $"{_hard} BradleyApc[{bradley.net.ID}]"; difficulty = _hard; color1 = "red"; _announce = "BradHard"; break; case 3: bradley._maxHealth = configData.Nightmare.BradleyHealth; bradley.health = configData.Nightmare.BradleyHealth; bradley.viewDistance = configData.Nightmare.BradleyMaxFireRange; bradley.searchRange = configData.Nightmare.BradleyMaxFireRange; bradley.throttle = configData.Nightmare.BradleySpeed; bradley.leftThrottle = bradley.throttle; bradley.rightThrottle = bradley.throttle; bradley.maxCratesToSpawn = configData.Nightmare.BradleyCratesAmount; bradley.name = $"{_nightmare} BradleyApc[{bradley.net.ID}]"; difficulty = _nightmare; color1 = "yellow"; _announce = "BradNightmare"; break; default: bradley._maxHealth = 1000; bradley.health = 1000; bradley.maxCratesToSpawn = 3; difficulty = _vanilla; color1 = "#EC1349"; _announce = "BradVanilla"; break; } //timer.Once(0.2f, () => //{ if (bradley.skinID != 0 || bradley.OwnerID != 0) { if(Debug) Puts($"Disabled Tiered apc spawn message for Convoy/Armored Train {bradley}"); return; } var bradleytype = $"{difficulty}"; var Gridcolor = $"{Grid}"; string _MSG = $"A {bradleytype} BradleyAPC spawned at {Grid}"; if ((Notify || UINotify) && UseNotify == true) foreach (var player in BasePlayer.activePlayerList) { if (Notify) Notify.Call("SendNotify", player, Pid, _MSG); if (UINotify) UINotify.Call("SendNotify", player, Pid, _MSG); } if (showchatannouncement) Server.Broadcast(prefix + string.Format(msg($"SpawnMessage"), bradleytype, Gridcolor), chaticon); if (_announce == "BradVanilla") color1 = "green"; if (GUIAnnouncements != null && configData.PlugCFG.GUIAUse) GUIAnnouncements?.Call("CreateAnnouncement", string.Format(msg($"SpawnMessage"), difficulty, Grid), color1, "white"); if (difficulty != _vanilla) Puts($"Upgraded a BradleyApc to a [{difficulty}] Tier"); if (difficulty == _vanilla) Puts($"Allowed a Vanilla BradleyApc to spawn"); }); } void OnEntityDeath(BradleyAPC apc, HitInfo info) { if (apc.OwnerID == 755446 || apc.skinID == 755446)//Adem plugin reference { Puts($"Disabled APC Notification for Convoy/ArmoredTrain {apc}"); return; } if (apc._maxHealth == 1000) { difficulty = _vanilla; reward = configData.Rewards.Vanilla; color1 = "#EC1349"; color2 = "white"; } else if (apc._maxHealth == configData.Easy.BradleyHealth) { difficulty = _easy; reward = configData.Rewards.Easy; color1 = "green"; color2 = "white"; } else if (apc._maxHealth == configData.Medium.BradleyHealth) { difficulty = _medium; reward = configData.Rewards.Medium; color1 = "purple"; color2 = "white"; } else if (apc._maxHealth == configData.Hard.BradleyHealth) { difficulty = _hard; reward = configData.Rewards.Hard; color1 = "red"; color2 = "white"; } else if (apc._maxHealth == configData.Nightmare.BradleyHealth) { difficulty = _nightmare; reward = configData.Rewards.Nightmare; color1 = "yellow"; color2 = "red"; } if (apc.skinID != 0 || apc.OwnerID != 0) { if (Debug) Puts($"Disabled Tiered apc kill message for Armored Train {apc}"); return; } var killer = info.InitiatorPlayer.displayName; var bradleytype = $"{difficulty}"; var _MSG = string.Format(msg("KillNotification"), killer, $" {bradleytype}"); Puts($"{difficulty} {apc} at {GetGrid(apc.transform.position)} {apc.transform.position} was destroyed by {killer}"); if (showchatannouncement) Server.Broadcast(prefix + _MSG , chaticon); if (GUIAnnouncements != null && configData.PlugCFG.GUIAUse) { if (apc._maxHealth == 1000) color1 = "green"; GUIAnnouncements?.Call("CreateAnnouncement", (_MSG), color1, color2); } if (apc._maxHealth == 1000) color1 = "#EC1349"; if ((Notify || UINotify) && UseNotify == true) foreach (var player in BasePlayer.activePlayerList) { if (Notify) Notify.Call("SendNotify", player, Pid, _MSG); if (UINotify) UINotify.Call("SendNotify", player, Pid, _MSG); } if (ServerRewards && configData.Rewards.UseSR == true) { ServerRewards?.Call("AddPoints", info.InitiatorPlayer.UserIDString, reward); if (Debug) Puts($"[Debug] ServerRewards reward : {reward}RP handed out to {info.InitiatorPlayer}"); if (showchatreward) Player.Message(info.InitiatorPlayer, prefix + string.Format(msg($"KillRewardMessage", info.InitiatorPlayer.UserIDString), $"{reward}", $"{difficulty}"), chaticon); } else if (Economics && configData.Rewards.UseEco == true) { if ((bool)Economics?.Call("Deposit", info.InitiatorPlayer.UserIDString, (double)reward)); if (Debug) Puts($"[Debug] Economics reward : {reward}$ handed out to {info.InitiatorPlayer}"); if (showchatreward) Player.Message(info.InitiatorPlayer, prefix + string.Format(msg($"KillRewardMessage", info.InitiatorPlayer.UserIDString), $"{reward}", $"{difficulty}"), chaticon); } Vector3 position = apc.transform.position; int count = 0; if (configData.Loot.UseLoot == true) { timer.Once(1f, () => { float distance = 15f; List list = new List(); Vis.Entities(position, distance, list); foreach (LootContainer crate in list) if (crate.PrefabName.Contains("bradley_crate") && crate.skinID != 290578) { count++; //crate.inventory.itemList.Clear(); if (difficulty == _vanilla) { crate.panelName = "generic_resizable"; crate.name = $"{difficulty}_Crate[{crate.net.ID}]"; crate.skinID = 290578; return; } else if (difficulty == _easy) { crate.inventory.itemList.Clear(); SpawnLoot(crate.inventory, configData.Easy.Loot.ToList()); } else if (difficulty == _medium) { crate.inventory.itemList.Clear(); SpawnLoot(crate.inventory, configData.Medium.Loot.ToList()); } else if (difficulty == _hard) { crate.inventory.itemList.Clear(); SpawnLoot(crate.inventory, configData.Hard.Loot.ToList()); } else if (difficulty == _nightmare) { crate.inventory.itemList.Clear(); SpawnLoot(crate.inventory, configData.Nightmare.Loot.ToList()); if (Debug) Puts($"[Debug] {difficulty} bradley loot test trigger"); } crate.panelName = "generic_resizable"; crate.name = $"{difficulty}_Crate[{crate.net.ID}]"; crate.skinID = 290578; } Puts($"{count.ToString()} vanilla crates upgraded with {difficulty} Loot"); }); return; } if (Debug) Puts($"[Debug] Lootsystem skipped"); return; } void OnEntityTakeDamage(BradleyAPC bradley, HitInfo info) { if(info.Initiator.IsValid()) { if (bradley.OwnerID == 755446 || bradley.skinID == 755446) return;//Adem plugin reference if (bradley.OwnerID != 0 || bradley.skinID != 0) return; BasePlayer player = info.InitiatorPlayer; if (!player) return; string id = player.UserIDString; var Cooldown = new CooldownTimer(); if (info?.Initiator is BasePlayer && info != null) { if (bradley._maxHealth == 1000) { difficulty = _vanilla; color1 = "#EC1349"; } else if (bradley._maxHealth == configData.Easy.BradleyHealth) { difficulty = _easy; color1 = "green"; } else if (bradley._maxHealth == configData.Medium.BradleyHealth) { difficulty = _medium; color1 = "purple"; } else if (bradley._maxHealth == configData.Hard.BradleyHealth) { difficulty = _hard; color1 = "red"; } else if (bradley._maxHealth == configData.Nightmare.BradleyHealth) { difficulty = _nightmare; color1 = "yellow"; } } if (!CoolDowns.ContainsKey(player.UserIDString) && info != null) { if (player != null) { Cooldown.timer = timer.Once((float)120, () => { CoolDowns.Remove(id); if (Debug) Puts($"[Debug] Removed cooldown for {player}"); }); Cooldown.start = Time.realtimeSinceStartup; Cooldown.countdown = 120f; CoolDowns.Add(id, Cooldown); if (Debug) Puts($"[Debug] Added cooldown for {player}"); var BradType = $" {difficulty}"; if (showchat) Player.Message(player, prefix + string.Format(msg($"AttackMessage"), BradType), chaticon); if (Debug) Puts($"[Debug] {player} hit on a {difficulty} Bradleyapc"); } } string timesince = Math.Floor((CoolDowns[player.UserIDString].start + CoolDowns[player.UserIDString].countdown - Time.realtimeSinceStartup)).ToString(); if (Debug) Puts($"[Debug] Msg cooldown {player} on a {difficulty} Bradleyapc with {timesince} sec left"); //Player.Message(player, prefix + string.Format(msg($"[Debug] msg cooldown {player.displayName}\nOn a {$"{difficulty}"} Bradleyapc with {timesince} sec left", player.UserIDString)), chaticon);//dev debugging } } private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) { if (info?.Initiator is BradleyAPC && entity.IsNpc) return null; if (info?.Initiator is BradleyAPC && entity is BasePlayer) { var bradley = info?.Initiator.GetComponent() ?? null; { if (bradley.OwnerID == 755446 || bradley.skinID == 755446) return null;//Adem plugin reference if (bradley.OwnerID != 0 || bradley.skinID != 0) return null; if (bradley._maxHealth == 1000) { accuracy = 1; difficulty = _vanilla; damagescale = 1; } else if (bradley._maxHealth == configData.Easy.BradleyHealth) { accuracy = configData.Easy.BradleyAccuracy; difficulty = _easy; damagescale = configData.Easy.BradleyDamageScale; } else if (bradley._maxHealth == configData.Medium.BradleyHealth) { accuracy = configData.Medium.BradleyAccuracy; difficulty = _medium; damagescale = configData.Medium.BradleyDamageScale; } else if (bradley._maxHealth == configData.Hard.BradleyHealth) { accuracy = configData.Hard.BradleyAccuracy; difficulty = _hard; damagescale = configData.Hard.BradleyDamageScale; } else if (bradley._maxHealth == configData.Nightmare.BradleyHealth) { accuracy = configData.Nightmare.BradleyAccuracy; difficulty = _nightmare; damagescale = configData.Nightmare.BradleyDamageScale; } } float rand = (float)random.Next(1, 100) / 100f; if (accuracy < rand) { if (Debug) Puts($"[Debug] Accuracy randomiser is {rand * 100}% with {accuracy * 100}% in cfg : skipped dmg dealing"); return true; } else { if (Debug) Puts($"[Debug] A {difficulty} BradleyApc dealth {info.damageTypes.Total() * damagescale} Damage to {entity} with {damagescale * 100}% force"); info.damageTypes.ScaleAll(damagescale); return null; } } return null; } #endregion #region Event helpers private static string GetGrid(Vector3 position) => PhoneController.PositionToGridCoord(position); #endregion #region Loot System private static List DefaultLoot { get { return new List { new BradleyItem { shortname = "ammo.pistol", amount = 5, skin = 0, amountMin = 5 }, new BradleyItem { shortname = "ammo.pistol.fire", amount = 5, skin = 0, amountMin = 5 }, new BradleyItem { shortname = "ammo.pistol.hv", amount = 5, skin = 0, amountMin = 5 }, new BradleyItem { shortname = "ammo.rifle", amount = 5, skin = 0, amountMin = 5 }, new BradleyItem { shortname = "ammo.rifle.explosive", amount = 5, skin = 0, amountMin = 5 }, new BradleyItem { shortname = "ammo.rifle.hv", amount = 5, skin = 0, amountMin = 5 }, new BradleyItem { shortname = "ammo.rifle.incendiary", amount = 5, skin = 0, amountMin = 5 }, new BradleyItem { shortname = "ammo.shotgun", amount = 12, skin = 0, amountMin = 8 }, new BradleyItem { shortname = "explosive.timed", amount = 1, skin = 0, amountMin = 1 }, new BradleyItem { shortname = "explosives", amount = 1, skin = 0, amountMin = 1 }, new BradleyItem { shortname = "pistol.m92", amount = 1, skin = 0, amountMin = 1 }, new BradleyItem { shortname = "shotgun.spas12", amount = 1, skin = 0, amountMin = 1 }, new BradleyItem { shortname = "pickaxe", amount = 1, skin = 0, amountMin = 1 }, new BradleyItem { shortname = "hatchet", amount = 1, skin = 0, amountMin = 1 }, new BradleyItem { shortname = "can.beans", amount = 3, skin = 0, amountMin = 1 }, new BradleyItem { shortname = "can.tuna", amount = 3, skin = 0, amountMin = 1 }, new BradleyItem { shortname = "black.raspberries", amount = 5, skin = 0, amountMin = 3 }, }; } } public class BradleyItem { public string shortname { get; set; } public int amount { get; set; } public ulong skin { get; set; } public int amountMin { get; set; } } private void SpawnLoot(ItemContainer container, List loot) { if (difficulty == _vanilla) { if (Debug) Puts($"[Debug] {difficulty} bradley loot test trigger"); } else if (difficulty == _easy) { total = UnityEngine.Random.Range(Math.Min(loot.Count, configData.Easy.MinAmount), Math.Min(loot.Count, configData.Easy.MaxAmount)); if (Debug) Puts($"[Debug] {difficulty} bradley loot test trigger"); } else if (difficulty == _medium) { total = UnityEngine.Random.Range(Math.Min(loot.Count, configData.Medium.MinAmount), Math.Min(loot.Count, configData.Medium.MaxAmount)); if (Debug) Puts($"[Debug] {difficulty} bradley loot test trigger"); } else if (difficulty == _hard) { total = UnityEngine.Random.Range(Math.Min(loot.Count, configData.Hard.MinAmount), Math.Min(loot.Count, configData.Hard.MaxAmount)); if (Debug) Puts($"[Debug] {difficulty} bradley loot test trigger"); } else if (difficulty == _nightmare) { total = UnityEngine.Random.Range(Math.Min(loot.Count, configData.Nightmare.MinAmount), Math.Min(loot.Count, configData.Nightmare.MaxAmount)); if (Debug) Puts($"[Debug] {difficulty} bradley loot test trigger"); } if (total == 0 || loot.Count == 0) { return; } if (Debug) Puts($"[Debug] Upgraded a {difficulty} crate with {total} items"); container.Clear(); container.capacity = total; ItemDefinition def; List skins; BradleyItem lootItem; for (int j = 0; j < total; j++) { if (loot.Count == 0) { break; } lootItem = loot.GetRandom(); loot.Remove(lootItem); if (lootItem.amount <= 0) { continue; } string shortname = lootItem.shortname; bool isBlueprint = shortname.EndsWith(".bp"); if (isBlueprint) { shortname = shortname.Replace(".bp", string.Empty); } def = ItemManager.FindItemDefinition(shortname); if (def == null) { Puts("Invalid shortname: {0}", lootItem.shortname); continue; } ulong skin = lootItem.skin; if (configData.Loot.RandomSkins && skin == 0) { skins = GetItemSkins(def); if (skins.Count > 0) { skin = skins.GetRandom(); } } int amount = lootItem.amount; if (amount <= 0) { continue; } if (lootItem.amountMin > 0 && lootItem.amountMin < lootItem.amount) { amount = UnityEngine.Random.Range(lootItem.amountMin, lootItem.amount); } Item item; if (isBlueprint) { item = ItemManager.CreateByItemID(-996920608, 1, 0); if (item == null) continue; item.blueprintTarget = def.itemid; item.amount = amount; } else item = ItemManager.Create(def, amount, skin); if (!item.MoveToContainer(container, -1, false)) { item.Remove(); } } } private List GetItemSkins(ItemDefinition def) { List skins; if (!Skins.TryGetValue(def.shortname, out skins)) { Skins[def.shortname] = skins = ExtractItemSkins(def, skins); } return skins; } private List ExtractItemSkins(ItemDefinition def, List skins) { skins = new List(); foreach (var skin in def.skins) { skins.Add(Convert.ToUInt64(skin.id)); } foreach (var asi in Rust.Workshop.Approved.All.Values) { if (!string.IsNullOrEmpty(asi.Skinnable.ItemName) && asi.Skinnable.ItemName == def.shortname) { skins.Add(Convert.ToUInt64(asi.WorkshopdId)); } } return skins; } #endregion } }