Advertisement
JimDeadlock

NpcRaiders.cs

May 10th, 2025
8
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 201.47 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using Rust;
  3. using System.Collections;
  4. using Oxide.Core.Configuration;
  5. using Newtonsoft.Json;
  6. using Oxide.Core.Plugins;
  7. using UnityEngine;
  8. using System.Linq;
  9. using Oxide.Core;
  10. using System;
  11. using Oxide.Game.Rust.Cui;
  12. using UnityEngine.SceneManagement;
  13. using System.Text.RegularExpressions;
  14. using Color = UnityEngine.Color;
  15. using UnityEngine.AI;
  16. using Facepunch;
  17. using VLB;
  18. using System.Globalization;
  19. using ProtoBuf;
  20. using Newtonsoft.Json.Linq;
  21.  
  22. namespace Oxide.Plugins
  23. {
  24. [Info("NpcRaiders", "Razor", "1.8.2")]
  25. [Description("Spawn Npc to raid your base..")]
  26. public class NpcRaiders : RustPlugin
  27. {
  28. #region Loading
  29. public static bool debug = false;
  30.  
  31. [PluginReference]
  32. private Plugin Kits, TruePVE, ServerRewards, Economics, LifeSupport, AlphaLoot;
  33.  
  34. PlayerEntity pcdData;
  35. private DynamicConfigFile PCDDATA;
  36.  
  37. PlayerStats statsData;
  38. private DynamicConfigFile STATSDATA;
  39.  
  40. public static NpcRaiders _;
  41. private Dictionary<BasePlayer, eventList> EventList = new Dictionary<BasePlayer, eventList>();
  42. private Dictionary<ulong, List<ulong>> corpsLock = new Dictionary<ulong, List<ulong>>();
  43. public static double GrabCurrentTime() => DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
  44. public static List<MLRS> mlrs = new List<MLRS>();
  45.  
  46. private static int groundLayer;
  47. private static int groundLayerWater;
  48. private static int terainLayer;
  49. private static int BuildingLayer;
  50. private static Vector3 Vector3Down;
  51. private Color backgroundColor;
  52. private Color PanelColor;
  53. private static string usePerm = "npcraiders.use";
  54. private static string coolPerm = "npcraiders.nocooldown";
  55. private static string adminPerm = "npcraiders.admin";
  56. private static string bypassPerm = "npcraiders.bypass";
  57. private static string bypassCost = "npcraiders.nocost";
  58. private float nextTime;
  59. private string chatComand = "raidme";
  60. public class eventList
  61. {
  62. public string type;
  63. public Vector3 location;
  64. public BuildingPrivlidge priv;
  65. }
  66.  
  67. private void Init()
  68. {
  69. ColorExtensions.TryParseHexString("#2b2b2b", out backgroundColor);
  70. ColorExtensions.TryParseHexString("#404141F2", out PanelColor);
  71. cmd.AddConsoleCommand("npcraiders", this, "ConsolStartRaid");
  72. if (!string.IsNullOrEmpty(configData.settings.chatcommand))
  73. {
  74. chatComand = configData.settings.chatcommand;
  75. cmd.AddChatCommand(configData.settings.chatcommand, this, "cmdChatStartRaid");
  76. }
  77. else
  78. {
  79. cmd.AddChatCommand("raidme", this, "cmdChatStartRaid");
  80. }
  81. PCDDATA = Interface.Oxide.DataFileSystem.GetFile(Name + "/PlayerCooldowns");
  82. STATSDATA = Interface.Oxide.DataFileSystem.GetFile(Name + "/PlayerStats");
  83. LoadData();
  84. _ = this;
  85. permission.RegisterPermission(usePerm, this);
  86. permission.RegisterPermission(coolPerm, this);
  87. permission.RegisterPermission(adminPerm, this);
  88. permission.RegisterPermission(bypassPerm, this);
  89. permission.RegisterPermission(bypassCost, this);
  90. }
  91.  
  92. private void OnServerInitialized()
  93. {
  94. if (TruePVE != null)
  95. {
  96. Unsubscribe("OnEntityTakeDamage");
  97. Unsubscribe("CanBeTargeted");
  98. }
  99. groundLayer = LayerMask.GetMask("Construction", "Terrain", "World");
  100. groundLayerWater = LayerMask.GetMask("Terrain", "World");
  101. terainLayer = LayerMask.GetMask("Terrain", "World", "Water");
  102. BuildingLayer = LayerMask.GetMask("Construction");
  103. Vector3Down = new Vector3(0f, -1f, 0f);
  104. if (configData.raidSettings.raidTypes.Count <= 0)
  105. {
  106. if (configData.raidBuyOptions.BuyOptions.Count <= 0)
  107. {
  108. configData.raidBuyOptions.BuyOptions.Add("easy", new raidBuy("-932201673", 500));
  109. configData.raidBuyOptions.BuyOptions.Add("medium", new raidBuy("-932201673", 1000));
  110. configData.raidBuyOptions.BuyOptions.Add("hard", new raidBuy("-932201673", 1500));
  111. configData.raidBuyOptions.BuyOptions.Add("expert", new raidBuy("-932201673", 1500));
  112. configData.raidBuyOptions.BuyOptions.Add("nightmare", new raidBuy("-932201673", 1500));
  113. }
  114.  
  115. if (configData.raidRewardOptions.RewardOptions.Count <= 0)
  116. {
  117. configData.raidRewardOptions.RewardOptions.Add("easy", new raidReward("-932201673", 500));
  118. configData.raidRewardOptions.RewardOptions.Add("medium", new raidReward("-932201673", 1000));
  119. configData.raidRewardOptions.RewardOptions.Add("hard", new raidReward("-932201673", 1500));
  120. configData.raidRewardOptions.RewardOptions.Add("expert", new raidReward("-932201673", 1500));
  121. configData.raidRewardOptions.RewardOptions.Add("nightmare", new raidReward("-932201673", 1500));
  122. }
  123.  
  124. configData.raidSettings.raidTypes.Add("easy", new raidConfig(10, true, 100, 640, new List<string>(), new List<string>() { "explosive.timed", "explosive.satchel" }, 2, "npcraiders.easy", 15000, 1.0));
  125. configData.raidSettings.raidTypes.Add("medium", new raidConfig(15, true, 200, 900, new List<string>(), new List<string>() { "explosive.timed", "explosive.satchel" }, 3, "npcraiders.medium", 30000, 1.0));
  126. configData.raidSettings.raidTypes.Add("hard", new raidConfig(20, true, 400, 1200, new List<string>(), new List<string>() { "explosive.timed", "explosive.satchel" }, 4, "npcraiders.hard", 50000, 1.0));
  127. configData.raidSettings.raidTypes.Add("expert", new raidConfig(30, true, 400, 1500, new List<string>(), new List<string>() { "explosive.timed", "explosive.satchel" }, 4, "npcraiders.expert", 65000, 1.0));
  128. configData.raidSettings.raidTypes.Add("nightmare", new raidConfig(30, true, 400, 2100, new List<string>(), new List<string>() { "explosive.timed", "explosive.satchel" }, 5, "npcraiders.nightmare", 100000, 1.0));
  129. SaveConfig();
  130. }
  131.  
  132. if (configData.raidVipOptions == null)
  133. {
  134. configData.raidVipOptions = new ConfigData.RaidVipOptions();
  135. configData.raidVipOptions.VipOptions = new Dictionary<string, raidVip>();
  136. configData.raidVipOptions.VipOptions.Add("npcraiders.vip1", new raidVip(3600, 43200));
  137. configData.raidVipOptions.VipOptions.Add("npcraiders.vip2", new raidVip(3600, 43200));
  138. configData.raidVipOptions.VipOptions.Add("npcraiders.vip3", new raidVip(3600, 43200));
  139. SaveConfig();
  140. }
  141.  
  142. timer.Every(10f, () =>
  143. {
  144. if (EventList.Count <= 0) return;
  145.  
  146. if (EventRaidManager._AllRaids.Count < configData.settings.MaxRaids)
  147. {
  148. foreach (var key in EventList.ToList())
  149. {
  150. if (key.Key == null)
  151. {
  152. EventList.Remove(key.Key);
  153. continue;
  154. }
  155. if (key.Value.priv == null)
  156. {
  157. if (key.Key != null)
  158. SendReply(key.Key, lang.GetMessage("TcWasAlreadyDestroyed", this, key.Key.UserIDString));
  159. continue;
  160. }
  161. if (key.Key != null)
  162. {
  163. if (configData.settings.gtip)
  164. GameTipsMessage(key.Key, lang.GetMessage("waitingToStart", this, key.Key.UserIDString));
  165. if (configData.settings.ctip)
  166. SendReply(key.Key, lang.GetMessage("waitingToStart", this, key.Key.UserIDString));
  167. }
  168. timer.Once(59, () => startRaidForPlayer(key.Key, key.Value.location, key.Value.priv, key.Value.type));
  169. EventList.Remove(key.Key);
  170. break;
  171. }
  172. }
  173. });
  174.  
  175. foreach (var perm in configData.raidSettings.raidTypes)
  176. {
  177. if (!String.IsNullOrEmpty(perm.Value.Permission) && !permission.PermissionExists(perm.Value.Permission, this))
  178. permission.RegisterPermission(perm.Value.Permission, this);
  179. }
  180.  
  181. if (configData.raidVipOptions != null && configData.raidVipOptions.VipOptions.Count > 0)
  182. foreach (var perms in configData.raidVipOptions.VipOptions)
  183. if (!String.IsNullOrEmpty(perms.Key) && !permission.PermissionExists(perms.Key, this))
  184. permission.RegisterPermission(perms.Key, this);
  185. }
  186.  
  187. private void Unload()
  188. {
  189. foreach (var eventRunning in EventRaidManager._AllRaids)
  190. eventRunning.Destroy();
  191.  
  192. EventRaidManager._AllRaids.Clear();
  193. foreach (BasePlayer player in BasePlayer.activePlayerList.ToList())
  194. {
  195. CuiHelper.DestroyUi(player, UIMain);
  196. player.SendConsoleCommand("gametip.hidegametip");
  197. }
  198.  
  199. _ = null;
  200. }
  201.  
  202. #endregion Loading
  203.  
  204. #region Data
  205. private void LoadData()
  206. {
  207. try
  208. {
  209. pcdData = Interface.GetMod().DataFileSystem.ReadObject<PlayerEntity>(Name + "/PlayerCooldowns");
  210. }
  211. catch
  212. {
  213. PrintWarning("Couldn't load Player data, creating new Playerfile");
  214. pcdData = new PlayerEntity();
  215. }
  216. try
  217. {
  218. statsData = Interface.GetMod().DataFileSystem.ReadObject<PlayerStats>(Name + "/PlayerStats");
  219. }
  220. catch
  221. {
  222. PrintWarning("Couldn't load Player stats, creating new Player stats file");
  223. statsData = new PlayerStats();
  224. }
  225. }
  226.  
  227. public class PlayerEntity
  228. {
  229. public Dictionary<ulong, PCDInfo> pEntity = new Dictionary<ulong, PCDInfo>();
  230. }
  231.  
  232. public class PCDInfo
  233. {
  234. public int total;
  235. public long cooldown;
  236. public Dictionary<ulong, long> tcCooldown = new Dictionary<ulong, long>();
  237. }
  238.  
  239. public void SaveData()
  240. {
  241. PCDDATA.WriteObject(pcdData);
  242. }
  243.  
  244. public class PlayerStats
  245. {
  246. public Dictionary<ulong, StatsInfo> pEntity = new Dictionary<ulong, StatsInfo>();
  247. }
  248.  
  249. public class StatsInfo
  250. {
  251. public string name;
  252. public int played;
  253. public int lost;
  254. public int won;
  255. public int killed;
  256. public int deaths;
  257. }
  258.  
  259. public void SaveStats()
  260. {
  261. STATSDATA.WriteObject(statsData);
  262. }
  263.  
  264. public class LootEntity
  265. {
  266. public int MaxItems;
  267. public int MinItems;
  268. public List<itemInfo> items = new List<itemInfo>();
  269. }
  270.  
  271. public class itemInfo
  272. {
  273. public string item;
  274. public ulong skin;
  275. public string name;
  276. public int amountMax;
  277. public int amountMin;
  278. public string location;
  279. }
  280.  
  281. public static bool HasSaveFile(string id) =>
  282. Interface.Oxide.DataFileSystem.ExistsDatafile(_.Name + "/LootProfiles/" + id);
  283.  
  284. private static void SaveLootData<T>(T data, string filename = null) =>
  285. Interface.Oxide.DataFileSystem.WriteObject(filename ?? _.Name, data);
  286.  
  287. private static void LoadLootData<T>(out T data, string filename = null) =>
  288. data = Interface.Oxide.DataFileSystem.ReadObject<T>(filename ?? _.Name);
  289.  
  290. #endregion Data
  291.  
  292. #region Config
  293. private ConfigData configData;
  294. class ConfigData
  295. {
  296. [JsonProperty(PropertyName = "Random settings")]
  297. public Settings settings { get; set; }
  298.  
  299. [JsonProperty(PropertyName = "All Raid Types")]
  300. public RaidSettings raidSettings { get; set; }
  301.  
  302. [JsonProperty(PropertyName = "Raid Buy Options")]
  303. public RaidBuyOptions raidBuyOptions { get; set; }
  304.  
  305. [JsonProperty(PropertyName = "Raid Reward Options")]
  306. public RaidRewardOptions raidRewardOptions { get; set; }
  307.  
  308. [JsonProperty(PropertyName = "Raid Vip Options")]
  309. public RaidVipOptions raidVipOptions { get; set; }
  310.  
  311. [JsonProperty(PropertyName = "Block raid in colider")]
  312. public BlockedColliders blockedColliders { get; set; }
  313.  
  314. public class Settings
  315. {
  316. [JsonProperty(PropertyName = "Chat command")]
  317. public string chatcommand { get; set; }
  318. [JsonProperty(PropertyName = "The Maxum amount of raid events that can go on at once")]
  319. public int MaxRaids { get; set; }
  320. [JsonProperty(PropertyName = "Cooldown before you can call in another raid")]
  321. public int cooldownSeconds { get; set; }
  322. [JsonProperty(PropertyName = "Cooldown after authorising on a tc be for you can start a raid")]
  323. public int TcAuthCooldown { get; set; }
  324. [JsonProperty(PropertyName = "The maxum amount of time a rocket will fly before exploding")]
  325. public float RocketExplodeTime { get; set; }
  326. [JsonProperty(PropertyName = "Limit the damage to players building")]
  327. public bool DamagePlayerBuilding { get; set; }
  328. [JsonProperty(PropertyName = "Npc spawn damage delay")]
  329. public float damageDelay { get; set; }
  330. [JsonProperty(PropertyName = "Log raidme buy chat command")]
  331. public bool logToFile { get; set; }
  332. [JsonProperty(PropertyName = "Use GameTip messages")]
  333. public bool gtip { get; set; } = true;
  334. [JsonProperty(PropertyName = "Use chat messages")]
  335. public bool ctip { get; set; } = true;
  336. }
  337.  
  338. public class RaidSettings
  339. {
  340. [JsonProperty(PropertyName = "Raid types must be in lowercase")]
  341. public Dictionary<string, raidConfig> raidTypes { get; set; }
  342. }
  343.  
  344. public class RaidBuyOptions
  345. {
  346. public Dictionary<string, raidBuy> BuyOptions { get; set; }
  347. }
  348.  
  349. public class RaidRewardOptions
  350. {
  351. public Dictionary<string, raidReward> RewardOptions { get; set; }
  352. }
  353.  
  354. public class RaidVipOptions
  355. {
  356. public Dictionary<string, raidVip> VipOptions { get; set; }
  357. }
  358.  
  359. public class BlockedColliders
  360. {
  361. public List<string> Blocked { get; set; }
  362. }
  363.  
  364.  
  365. public Oxide.Core.VersionNumber Version { get; set; }
  366. }
  367.  
  368. protected override void LoadConfig()
  369. {
  370. base.LoadConfig();
  371. configData = Config.ReadObject<ConfigData>();
  372.  
  373. if (configData.Version < Version)
  374. UpdateConfigValues();
  375.  
  376. Config.WriteObject(configData, true);
  377. }
  378.  
  379. protected override void LoadDefaultConfig() => configData = GetBaseConfig();
  380.  
  381. private ConfigData GetBaseConfig()
  382. {
  383. return new ConfigData
  384. {
  385. settings = new ConfigData.Settings
  386. {
  387. chatcommand = "raidme",
  388. MaxRaids = 6,
  389. cooldownSeconds = 3600,
  390. TcAuthCooldown = 86400,
  391. RocketExplodeTime = 4.0f,
  392. DamagePlayerBuilding = false,
  393. damageDelay = 2f,
  394. logToFile = false
  395. },
  396.  
  397. raidSettings = new ConfigData.RaidSettings
  398. {
  399. raidTypes = new Dictionary<string, raidConfig>()
  400. },
  401.  
  402. raidBuyOptions = new ConfigData.RaidBuyOptions
  403. {
  404. BuyOptions = new Dictionary<string, raidBuy>()
  405. },
  406.  
  407. raidRewardOptions = new ConfigData.RaidRewardOptions
  408. {
  409. RewardOptions = new Dictionary<string, raidReward>()
  410. },
  411.  
  412. raidVipOptions = new ConfigData.RaidVipOptions
  413. {
  414. VipOptions = new Dictionary<string, raidVip>()
  415. },
  416.  
  417. blockedColliders = new ConfigData.BlockedColliders
  418. {
  419. Blocked = new List<string>() { "iceberg", "ice_berg", "ice_sheet", "icesheet", "prevent moving", "cliff" }
  420. },
  421. Version = Version
  422. };
  423. }
  424.  
  425. protected override void SaveConfig() => Config.WriteObject(configData, true);
  426.  
  427. private void UpdateConfigValues()
  428. {
  429. PrintWarning("Version update detected!");
  430.  
  431. ConfigData baseConfig = GetBaseConfig();
  432.  
  433. if (configData.Version < new VersionNumber(1, 0, 1))
  434. {
  435. configData = baseConfig;
  436. PrintWarning("Config update was needed and now completed!");
  437. }
  438. configData.Version = Version;
  439. PrintWarning("Version update completed!");
  440. }
  441.  
  442. public class mlrsConfig
  443. {
  444. [JsonProperty(PropertyName = "Fire On Wave Start")]
  445. public int wave;
  446. [JsonProperty(PropertyName = "Total To Fire")]
  447. public int totalFire;
  448. }
  449.  
  450. public class raidConfig
  451. {
  452. [JsonProperty(PropertyName = "The Permission")]
  453. public string Permission;
  454. [JsonProperty(PropertyName = "Total npcs per wave")]
  455. public int TotalNpcs;
  456. [JsonProperty(PropertyName = "How many extra waves")]
  457. public int TotalNpcWaves;
  458. [JsonProperty(PropertyName = "Seconds untell next wave")]
  459. public int NextWaveSeconds;
  460. [JsonProperty(PropertyName = "Npc fires Mlrs at base")]
  461. public bool FireMlrs;
  462. [JsonProperty(PropertyName = "Mlrs waves and amounts")]
  463. public Dictionary<int, int> mlrsOption;
  464. [JsonProperty(PropertyName = "Total event time in seconds")]
  465. public int RunTimeSeconds;
  466. [JsonProperty(PropertyName = "Block event players from repairing")]
  467. public bool canNotRepair;
  468. [JsonProperty(PropertyName = "Npc drop loot on death")]
  469. public bool NpcDropLoot;
  470. [JsonProperty(PropertyName = "AlphaLoot profile names For Npc Loot")]
  471. public List<string> lootProfileA;
  472. [JsonProperty(PropertyName = "Npc drop loot config names")]
  473. public List<string> NpcDropLootConfig;
  474. [JsonProperty(PropertyName = "Spawn health of the npc")]
  475. public float Health;
  476. [JsonProperty(PropertyName = "Rocket damage scale")]
  477. public double DamageScale;
  478. [JsonProperty(PropertyName = "Player damage scale from npc")]
  479. public float playerDamage;
  480. [JsonProperty(PropertyName = "Auto turret damage scale to npc")]
  481. public float AutoTurretDamage;
  482. [JsonProperty(PropertyName = "External Tc Scan Range")]
  483. public float ExternalTcRange;
  484. [JsonProperty(PropertyName = "Explosive item shortnames")]
  485. public List<string> explosive;
  486. [JsonProperty(PropertyName = "Names to give the npcs")]
  487. public List<string> NpcNames;
  488. [JsonProperty(PropertyName = "Spawn kits for the npcs")]
  489. public List<string> kits;
  490. [JsonProperty(PropertyName = "NPC aimConeScale default 2.0")]
  491. public float aimConeScale;
  492.  
  493. public raidConfig(int TotalNpcs, bool OnlyAuthedMembers, float Health, int RunTimeSeconds, List<string> kits, List<string> explosive, int waves, string perms, int reward, double damage)
  494. {
  495. this.TotalNpcs = TotalNpcs;
  496. this.NpcDropLoot = OnlyAuthedMembers;
  497. this.Health = Health;
  498. this.kits = kits;
  499. this.RunTimeSeconds = RunTimeSeconds;
  500. this.explosive = explosive;
  501. this.TotalNpcWaves = waves;
  502. this.NextWaveSeconds = 120;
  503. this.Permission = perms;
  504. this.NpcNames = new List<string>() { "Cobalt Scientist" };
  505. this.DamageScale = damage;
  506. this.AutoTurretDamage = 1.0f;
  507. this.lootProfileA = new List<string>();
  508. this.NpcDropLootConfig = new List<string>();
  509. this.FireMlrs = false;
  510. this.canNotRepair = false;
  511. this.playerDamage = 1.0f;
  512. this.ExternalTcRange = 150f;
  513. this.aimConeScale = 2.0f;
  514. this.mlrsOption = new Dictionary<int, int>() { { 1, 6 } };
  515. }
  516. }
  517.  
  518. public class raidBuy
  519. {
  520. public string BuyType;
  521. public object BuyAmmount;
  522.  
  523. public raidBuy(string thetipe, object needed)
  524. {
  525. this.BuyType = thetipe;
  526. this.BuyAmmount = needed;
  527. }
  528. }
  529.  
  530. public class raidReward
  531. {
  532. public bool enabled;
  533. public bool rewardAll;
  534. public string RewardType;
  535. public object RewardAmmount;
  536.  
  537. public raidReward(string thetipe, object needed)
  538. {
  539. this.enabled = false;
  540. this.rewardAll = false;
  541. this.RewardType = thetipe;
  542. this.RewardAmmount = needed;
  543. }
  544. }
  545.  
  546. public class raidVip
  547. {
  548. public int cooldownSeconds;
  549. public int TcAuthCooldown;
  550.  
  551. public raidVip(int cool, int tcCool)
  552. {
  553. this.cooldownSeconds = cool;
  554. this.TcAuthCooldown = tcCool;
  555. }
  556. }
  557. #endregion Config
  558.  
  559. #region Event
  560. public static float ProjectileDistToGravity(float x, float y, float θ, float v)
  561. {
  562. float f1 = θ * ((float)Math.PI / 180f);
  563. float f2 = (float)(((double)v * (double)v * (double)x * (double)Mathf.Sin(2f * f1) - 2.0 * (double)v * (double)v * (double)y * (double)Mathf.Cos(f1) * (double)Mathf.Cos(f1)) / ((double)x * (double)x));
  564. if (float.IsNaN(f2) || (double)f2 < 0.00999999977648258)
  565. f2 = -Physics.gravity.y;
  566. return f2;
  567. }
  568.  
  569. public class RaidThinkManager : MonoBehaviour
  570. {
  571. EventRaidManager RM { get; set; }
  572.  
  573. public void Setup(EventRaidManager R)
  574. {
  575. RM = R;
  576. }
  577.  
  578. public void Update()
  579. {
  580. if (RM != null && !RM.isDestroyed)
  581. RM.update();
  582. else if (this.gameObject != null) Destroy(this);
  583. }
  584. }
  585.  
  586. public class EventRaidManager
  587. {
  588. internal static List<EventRaidManager> _AllRaids = new List<EventRaidManager>();
  589. internal static List<ulong> _AllPlayers = new List<ulong>();
  590. internal static List<NpcRaider> _AllMembers = new List<NpcRaider>();
  591. internal static bool isFireingMlrs;
  592.  
  593. internal List<NpcRaider> members;
  594. internal List<ulong> authorizedPlayers;
  595. internal bool isDestroyed = false;
  596. internal Vector3 location;
  597. internal raidConfig config;
  598. internal string waveType;
  599. internal BasePlayer player;
  600. internal ulong playerID;
  601. internal BuildingPrivlidge priv;
  602. internal bool newWave;
  603. internal Coroutine QueuedRoutine;
  604. internal BuildingPrivlidge building;
  605. internal BaseCombatEntity tc;
  606. internal RaidThinkManager timerObject;
  607. internal float EndEventTime;
  608. internal float nextWaveTime = 0;
  609. internal int totalWaves = 0;
  610. internal float MlrsEventTime;
  611. internal List<int> MlrsEventFired = new List<int>();
  612. internal int MlrsWaves = 0;
  613. internal bool active = false;
  614. internal int totalCopters = 3;
  615. internal GameObject thetimerObject;
  616.  
  617. internal static EventRaidManager Create(BasePlayer p, ulong id, Vector3 l, raidConfig c, string t, RaidThinkManager timer, BuildingPrivlidge pr, GameObject gobj)
  618. {
  619. EventRaidManager manager = new EventRaidManager
  620. {
  621. members = Pool.GetList<NpcRaider>(),
  622. authorizedPlayers = Pool.GetList<ulong>(),
  623. newWave = true,
  624. config = c,
  625. waveType = t,
  626. player = p,
  627. playerID = id,
  628. location = l,
  629. timerObject = timer,
  630. building = pr,
  631. thetimerObject = gobj
  632. };
  633.  
  634. _AllRaids.Add(manager);
  635. return manager;
  636. }
  637.  
  638. internal void Start()
  639. {
  640. Interface.Oxide.CallHook("NpcRaidersEventStart", player, playerID, waveType, location, this);
  641.  
  642. MlrsEventTime = Time.time + UnityEngine.Random.Range(15f, 30f);
  643. EndEventTime = Time.time + config.RunTimeSeconds;
  644. nextWaveTime = Time.time + 3800;
  645. if (building != null)
  646. foreach (var user in building.authorizedPlayers.ToList())
  647. {
  648. if (!authorizedPlayers.Contains(user.userid))
  649. authorizedPlayers.Add(user.userid);
  650. if (config.canNotRepair && !_AllPlayers.Contains(user.userid))
  651. _AllPlayers.Add(user.userid);
  652.  
  653. }
  654. QueuedRoutine = ServerMgr.Instance.StartCoroutine(GenerateEventMembers());
  655. }
  656. //R Thanks to HellFire on UMOD
  657. internal static void setupMlrs(EventRaidManager man, int totalToFire, float damage = 1.0f)
  658. {
  659. if (isFireingMlrs || man == null || man.building == null) return;
  660.  
  661. _.timer.Repeat(0.5f, totalToFire, () =>
  662. {
  663. if (man == null || man.building == null) return;
  664. float baseGravity;
  665. Vector3 posUP = man.building.transform.position;
  666. posUP.y = posUP.y + 240f;
  667. Vector3 posFire = new Vector3(man.building.transform.position.x + UnityEngine.Random.Range(-10.0f, 10.0f), man.building.transform.position.y, man.building.transform.position.z + UnityEngine.Random.Range(-10.0f, 10.0f));
  668.  
  669. Vector3 aimToTarget = GetAimToTarget(posUP, man.building.transform.position, out baseGravity);
  670.  
  671. var startPoint = posUP;
  672. startPoint.y += 15f;
  673.  
  674. ServerProjectile projectile;
  675.  
  676. if (CreateAndSpawnRocket(startPoint, aimToTarget, damage, out projectile) == false)
  677. return;
  678. TimedExplosive component = projectile.GetComponent<TimedExplosive>();
  679. component.creatorEntity = man.player;
  680. projectile.gravityModifier = baseGravity / (0f - Physics.gravity.y);
  681. });
  682.  
  683. }
  684.  
  685. internal static Vector3 GetAimToTarget(Vector3 startPosition, Vector3 targetPos, out float baseGravity)
  686. {
  687. Vector3 vector = targetPos - startPosition;
  688. //vector = new Vector3(4.8654f, 2.6241f, 1.3869f);
  689. float num = 90f;
  690. float num2 = vector.Magnitude2D();
  691. float y = vector.y;
  692. float num5 = 40f;
  693.  
  694. baseGravity = ProjectileDistToGravity(Mathf.Max(num2, 50f), y, num5, num);
  695.  
  696. vector.Normalize();
  697. vector.y = 0f;
  698.  
  699. Vector3 axis = Vector3.Cross(vector, Vector3.up);
  700.  
  701. vector = Quaternion.AngleAxis(num5, axis) * vector;
  702.  
  703. return vector;
  704. }
  705.  
  706. internal static bool CreateAndSpawnRocket(Vector3 firingPos, Vector3 firingDir, float damage, out ServerProjectile mlrsRocketProjectile)
  707. {
  708. RaycastHit hitInfo;
  709.  
  710. float launchOffset = 0f;
  711.  
  712. if (Physics.Raycast(firingPos, firingDir, out hitInfo, launchOffset, 1236478737))
  713. launchOffset = hitInfo.distance - 0.1f;
  714.  
  715. var mlrsRocketEntity = GameManager.server.CreateEntity("assets/content/vehicles/mlrs/rocket_mlrs.prefab", firingPos + firingDir * launchOffset);
  716.  
  717. if (mlrsRocketEntity == null)
  718. {
  719. mlrsRocketProjectile = null;
  720. return false;
  721. }
  722.  
  723. mlrsRocketProjectile = mlrsRocketEntity.GetComponent<ServerProjectile>();
  724.  
  725. var velocityVector = mlrsRocketProjectile.initialVelocity + firingDir * mlrsRocketProjectile.speed;
  726.  
  727. mlrsRocketProjectile.InitializeVelocity(velocityVector);
  728.  
  729. var mlrsRocket = mlrsRocketEntity as MLRSRocket;
  730.  
  731. if (mlrsRocket == null)
  732. return false;
  733.  
  734. mlrsRocket.OwnerID = 0;
  735. TimedExplosive component = mlrsRocket.GetComponent<TimedExplosive>();
  736. component.SendMessage("SetDamageScale", damage);
  737. component.timerAmountMin = 20f;
  738. component.timerAmountMax = 30f;
  739. // component.explosionRadius += 10f;
  740. mlrsRocket.Spawn();
  741.  
  742. return true;
  743. }
  744.  
  745.  
  746. internal void update()
  747. {
  748. ulong id = 0UL;
  749. if (isDestroyed || !active)
  750. return;
  751.  
  752. if (EndEventTime < Time.time)
  753. {
  754. Destroy();
  755. return;
  756. }
  757.  
  758. /* if (config.FireMlrs && MlrsEventTime < Time.time && !EventRaidManager.isFireingMlrs && MlrsEventTime != 0)
  759. {
  760. MlrsEventTime = 0;
  761. setupMlrs(this);
  762. }*/
  763.  
  764. if (config.FireMlrs && config.mlrsOption.ContainsKey(MlrsWaves) && !MlrsEventFired.Contains(MlrsWaves))
  765. {
  766. MlrsEventFired.Add(MlrsWaves);
  767. setupMlrs(this, config.mlrsOption[MlrsWaves]);
  768. }
  769.  
  770. if (config.TotalNpcWaves > 0 && totalWaves <= config.TotalNpcWaves && nextWaveTime < Time.time)
  771. {
  772. nextWaveTime = Time.time + config.NextWaveSeconds;
  773. if (QueuedRoutine != null)
  774. stopSpawning();
  775. QueuedRoutine = ServerMgr.Instance.StartCoroutine(GenerateEventMembers());
  776. return;
  777. }
  778.  
  779. if ((totalWaves - 1) == config.TotalNpcWaves && members.Count <= 0)
  780. {
  781. Destroy(true);
  782. return;
  783. }
  784.  
  785. if ((totalWaves - 1) < config.TotalNpcWaves)
  786. {
  787. if (!notify && (nextWaveTime - Time.time) <= 30)
  788. {
  789. notify = true;
  790. notifyWaveTime = totalWaves;
  791. notifyWave();
  792. }
  793. else if (!notify60 && (nextWaveTime - Time.time) <= 60 )
  794. {
  795. notify60 = true;
  796. notifyWaveTime = totalWaves;
  797. notifyWave();
  798. }
  799. else if (notifyWaveTime != totalWaves && members.Count <= 0)
  800. {
  801. notifyWaveTime = totalWaves;
  802. notifyWave();
  803. }
  804. }
  805. if (!notifyEnd && (EndEventTime - 60) <= Time.time)
  806. {
  807. notifyEnd = true;
  808. string EndTime = _.FormatTime((long)(EndEventTime - Time.time));
  809. for (int i = authorizedPlayers.Count - 1; i >= 0; i--)
  810. {
  811. id = authorizedPlayers[i];
  812. if (id != 0UL)
  813. {
  814. BasePlayer TCplayer = BasePlayer.FindByID(id);
  815. if (TCplayer != null)
  816. {
  817. if (_.configData.settings.gtip)
  818. GameTipsMessage(TCplayer, string.Format(_.lang.GetMessage("EventEndINTime", _, player.UserIDString), EndTime));
  819. if (_.configData.settings.ctip)
  820. _.SendReply(TCplayer, _.lang.GetMessage("EventEndINTime", _, player.UserIDString), EndTime);
  821. }
  822. }
  823. }
  824. }
  825. else if (!notifyEnd1 && (EndEventTime - 30) <= Time.time)
  826. {
  827. notifyEnd1 = true;
  828. string EndTime = _.FormatTime((long)(EndEventTime - Time.time));
  829. for (int i = authorizedPlayers.Count - 1; i >= 0; i--)
  830. {
  831. id = authorizedPlayers[i];
  832. if (id != 0UL)
  833. {
  834. BasePlayer TCplayer = BasePlayer.FindByID(id);
  835. if (TCplayer != null)
  836. {
  837. if (_.configData.settings.gtip)
  838. GameTipsMessage(TCplayer, string.Format(_.lang.GetMessage("EventEndINTime", _, player.UserIDString), EndTime));
  839. if (_.configData.settings.ctip)
  840. _.SendReply(TCplayer, _.lang.GetMessage("EventEndINTime", _, player.UserIDString), EndTime);
  841. }
  842. }
  843. }
  844. }
  845. }
  846.  
  847. internal bool notify { get; set; }
  848. internal bool notify60 { get; set; }
  849. internal bool notifyEnd { get; set; }
  850. internal bool notifyEnd1 { get; set; }
  851. internal int notifyWaveTime = 0;
  852.  
  853. internal void notifyWave()
  854. {
  855. ulong id = 0UL;
  856. string waveWaitTime = _.FormatTime((long)(nextWaveTime - Time.time));
  857. for (int i = authorizedPlayers.Count - 1; i >= 0; i--)
  858. {
  859. id = authorizedPlayers[i];
  860. if (id != 0UL)
  861. {
  862. BasePlayer TCplayer = BasePlayer.FindByID(id);
  863. if (TCplayer != null)
  864. {
  865. if (_.configData.settings.gtip)
  866. GameTipsMessage(TCplayer, string.Format(_.lang.GetMessage("ArivalTimeNext", _, player.UserIDString), config.TotalNpcWaves + 1, totalWaves + 1, waveWaitTime), 3f);
  867. if (_.configData.settings.ctip)
  868. _.SendReply(TCplayer, _.lang.GetMessage("ArivalTimeNext", _, player.UserIDString), config.TotalNpcWaves + 1, totalWaves + 1, waveWaitTime);
  869. }
  870. }
  871. }
  872. }
  873.  
  874. internal void RemoveNpc(NpcRaider player)
  875. {
  876. if (members != null && members.Contains(player))
  877. members.Remove(player);
  878. if (_AllMembers != null && _AllMembers.Contains(player))
  879. _AllMembers.Remove(player);
  880. }
  881.  
  882. internal void Destroy(bool win = false)
  883. {
  884. if (isDestroyed)
  885. return;
  886. ulong id = 0UL;
  887. active = false;
  888. isDestroyed = true;
  889. MlrsEventTime = 1;
  890. Interface.Oxide.CallHook("NpcRaidersEventEnd", player, playerID, waveType, location);
  891. stopSpawning();
  892.  
  893. for (int i = members.Count - 1; i >= 0; i--)
  894. {
  895. NpcRaider npc = members[i];
  896. if (npc != null && !npc.IsDestroyed && !npc.isMounted)
  897. {
  898. npc.Kill();
  899. }
  900. }
  901.  
  902. for (int i = authorizedPlayers.Count - 1; i >= 0; i--)
  903. {
  904. id = authorizedPlayers[i];
  905. if (id != 0UL)
  906. {
  907. BasePlayer TCplayer = BasePlayer.FindByID(id);
  908. if (TCplayer != null)
  909. {
  910. if (win)
  911. {
  912. if (_.configData.settings.ctip)
  913. _.SendReply(TCplayer, _.lang.GetMessage("eventOverWin", _, TCplayer.UserIDString));
  914. if (_.configData.settings.gtip)
  915. GameTipsMessage(TCplayer, _.lang.GetMessage("eventOverWin", _, TCplayer.UserIDString), 3f);
  916. if (!_.statsData.pEntity.ContainsKey(id))
  917. _.statsData.pEntity.Add(id, new StatsInfo() { name = TCplayer.displayName });
  918. _.statsData.pEntity[id].played++;
  919. _.statsData.pEntity[id].won++;
  920. _.SaveStats();
  921. }
  922. else
  923. {
  924. if (_.configData.settings.ctip)
  925. _.SendReply(TCplayer, _.lang.GetMessage("eventOver", _, TCplayer.UserIDString));
  926. if (_.configData.settings.gtip)
  927. GameTipsMessage(TCplayer, _.lang.GetMessage("eventOver", _, TCplayer.UserIDString), 3f);
  928. if (!_.statsData.pEntity.ContainsKey(id))
  929. _.statsData.pEntity.Add(id, new StatsInfo() { name = TCplayer.displayName });
  930. _.statsData.pEntity[id].played++;
  931. _.statsData.pEntity[id].lost++;
  932. _.SaveStats();
  933. }
  934. }
  935. }
  936. }
  937.  
  938. if (win && player != null)
  939. {
  940. if (_.configData.raidRewardOptions.RewardOptions.ContainsKey(waveType))
  941. {
  942. rewardPlayers(_.configData.raidRewardOptions.RewardOptions[waveType]);
  943. }
  944. }
  945.  
  946. foreach (ulong privey in authorizedPlayers.ToList())
  947. {
  948. if (_AllPlayers.Contains(privey))
  949. _AllPlayers.Remove(privey);
  950. }
  951. if (thetimerObject != null)
  952. {
  953. UnityEngine.GameObject.DestroyImmediate(thetimerObject, true);
  954. }
  955.  
  956. _.NextTick(() =>
  957. {
  958. members.Clear();
  959. Pool.FreeList(ref members);
  960. authorizedPlayers.Clear();
  961. Pool.FreeList(ref authorizedPlayers);
  962. _AllRaids.Remove(this);
  963. });
  964. }
  965.  
  966. internal void rewardPlayers(raidReward reward)
  967. {
  968. if (!reward.enabled)
  969. return;
  970.  
  971. ItemDefinition def = null;
  972. var ids = default(int);
  973. object totals = reward.RewardAmmount;
  974. List<string> kitList = new List<string>();
  975. if (int.TryParse(reward.RewardType, out ids))
  976. {
  977. def = ItemManager.FindItemDefinition(ids);
  978. }
  979. if (def != null)
  980. {
  981. if (reward.rewardAll)
  982. {
  983. foreach (var playerid in authorizedPlayers.ToList())
  984. {
  985. BasePlayer RewardPlayer = BasePlayer.FindAwakeOrSleeping(playerid.ToString());
  986. if (RewardPlayer == null || !RewardPlayer.IsConnected)
  987. continue;
  988.  
  989. giveItem(RewardPlayer, ids, Convert.ToInt32(totals));
  990. _.SendReply(RewardPlayer, String.Format(_.lang.GetMessage("RewardedItem", _), Convert.ToInt32(totals), def.displayName.english));
  991. }
  992. }
  993.  
  994. else if (player != null)
  995. {
  996. giveItem(player, ids, Convert.ToInt32(totals));
  997. _.SendReply(player, String.Format(_.lang.GetMessage("RewardedItem", _), Convert.ToInt32(totals), def.displayName.english));
  998. }
  999. }
  1000. else if (def == null)
  1001. {
  1002. int totalPlayers = 0;
  1003. List<BasePlayer> onlinePlayer = new List<BasePlayer>();
  1004. object totalsSplit = 0;
  1005.  
  1006. foreach (var playerid in authorizedPlayers.ToList())
  1007. {
  1008. BasePlayer RewardPlayer = BasePlayer.FindAwakeOrSleeping(playerid.ToString());
  1009. if (RewardPlayer == null || !RewardPlayer.IsConnected)
  1010. continue;
  1011. totalPlayers++;
  1012. onlinePlayer.Add(RewardPlayer);
  1013. }
  1014.  
  1015. if (reward.rewardAll && totalPlayers > 1)
  1016. {
  1017. foreach (var RewardPlayer in onlinePlayer.ToList())
  1018. {
  1019. if (RewardPlayer == null || !RewardPlayer.IsConnected)
  1020. continue;
  1021.  
  1022. if (reward.RewardType.ToLower() == "serverrewards")
  1023. {
  1024. totalsSplit = ((Convert.ToInt32(totals)) / totalPlayers);
  1025. _.ServerRewards?.Call("AddPoints", RewardPlayer.userID.Get(), Convert.ToInt32(totalsSplit));
  1026. _.SendReply(RewardPlayer, String.Format(_.lang.GetMessage("MoneyIssued", _), Convert.ToInt32(totalsSplit), RewardPlayer.displayName));
  1027. }
  1028. else if (reward.RewardType.ToLower() == "economics")
  1029. {
  1030. totalsSplit = ((Convert.ToInt32(totals)) / totalPlayers);
  1031. _.Economics?.Call("Deposit", RewardPlayer.userID.Get(), Convert.ToDouble(totalsSplit));
  1032. _.SendReply(RewardPlayer, String.Format(_.lang.GetMessage("MoneyIssued", _), Convert.ToDouble(totalsSplit), RewardPlayer.displayName));
  1033. }
  1034. else if (reward.RewardType.ToLower() == "kits" || reward.RewardType.ToLower() == "kit")
  1035. {
  1036. kitList = getObjects(totals);
  1037. if (totals is string)
  1038. {
  1039. if (!string.IsNullOrEmpty(Convert.ToString(totals)))
  1040. {
  1041. object success = _.Kits?.Call("GiveKit", RewardPlayer, Convert.ToString(totals));
  1042. if (success == null)
  1043. _.PrintWarning($"Unable to find a kit with the name {Convert.ToString(totals)}");
  1044. else if (success is string)
  1045. {
  1046. _.SendReply(RewardPlayer, (string)success, _);
  1047. _.PrintWarning($"Ops {(string)success}");
  1048. }
  1049. }
  1050. else _.PrintWarning($"Invalid kitname in RewardAmmount");
  1051. }
  1052. else if (kitList != null)
  1053. {
  1054. if (kitList.Count <= 0) continue;
  1055. string rand = kitList.GetRandom();
  1056. object success = _.Kits?.Call("GiveKit", RewardPlayer, rand);
  1057. if (success == null)
  1058. _.PrintWarning($"Unable to find a kit with the name {rand}");
  1059. else if (success is string)
  1060. {
  1061. _.SendReply(RewardPlayer, (string)success, _);
  1062. _.PrintWarning($"Ops {(string)success}");
  1063. }
  1064. }
  1065. }
  1066. }
  1067. }
  1068. else
  1069. {
  1070. if (player != null)
  1071. {
  1072. if (reward.RewardType.ToLower() == "serverrewards")
  1073. {
  1074. _.ServerRewards?.Call("AddPoints", player.userID.Get(), Convert.ToInt32(totals));
  1075. _.SendReply(player, String.Format(_.lang.GetMessage("MoneyIssued", _), Convert.ToInt32(totals), player.displayName));
  1076. }
  1077. else if (reward.RewardType.ToLower() == "economics")
  1078. {
  1079. _.Economics?.Call("Deposit", player.userID.Get(), Convert.ToDouble(totals));
  1080. _.SendReply(player, String.Format(_.lang.GetMessage("MoneyIssued", _), Convert.ToDouble(totals), player.displayName));
  1081. }
  1082. else if (reward.RewardType.ToLower() == "kits" || reward.RewardType.ToLower() == "kit")
  1083. {
  1084. kitList = getObjects(totals);
  1085. if (totals is string)
  1086. {
  1087. if (!string.IsNullOrEmpty(Convert.ToString(totals)))
  1088. {
  1089. object success = _.Kits?.Call("GiveKit", player, Convert.ToString(totals));
  1090. if (success == null)
  1091. _.PrintWarning($"Unable to find a kit with the name {Convert.ToString(totals)}");
  1092. else if (success is string)
  1093. {
  1094. _.SendReply(player, (string)success, _);
  1095. _.PrintWarning($"Ops {(string)success}");
  1096. }
  1097. }
  1098. else _.PrintWarning($"Invalid kitname in RewardAmmount");
  1099. }
  1100. else if (kitList != null && kitList.Count > 0)
  1101. {
  1102. if (kitList.Count <= 0) return;
  1103. string rand = kitList.GetRandom();
  1104.  
  1105. object success = _.Kits?.Call("GiveKit", player, rand);
  1106. if (success == null)
  1107. _.PrintWarning($"Unable to find a kit with the name {rand}");
  1108. else if (success is string)
  1109. {
  1110. _.SendReply(player, (string)success, _);
  1111. _.PrintWarning($"Ops {(string)success}");
  1112. }
  1113. }
  1114. }
  1115. }
  1116. }
  1117. }
  1118. }
  1119.  
  1120. private List<string> getObjects(object name)
  1121. {
  1122. List<string> kitObject = new List<string>();
  1123. if (name is string || name is int || name is float)
  1124. return kitObject;
  1125. var json = JsonConvert.SerializeObject(name);
  1126. if (json != null)
  1127. kitObject = JsonConvert.DeserializeObject<List<string>>(json) as List<string>;
  1128. return kitObject;
  1129. }
  1130. internal static void giveItem(BasePlayer RPlayer, int itemID, int total)
  1131. {
  1132. var item = ItemManager.CreateByItemID(itemID, total, 0);
  1133. if (item == null) return;
  1134.  
  1135. if (item.MoveToContainer(RPlayer.inventory.containerBelt, -1, true))
  1136. return;
  1137.  
  1138. else if (item.MoveToContainer(RPlayer.inventory.containerMain, -1, true))
  1139. return;
  1140.  
  1141. Vector3 velocity = Vector3.zero;
  1142. item.Drop(RPlayer.transform.position + new Vector3(0.5f, 1f, 0), velocity);
  1143. _.SendReply(RPlayer, _.lang.GetMessage("RewardDropedOnGround", _));
  1144. }
  1145.  
  1146. internal void stopSpawning()
  1147. {
  1148. if (QueuedRoutine != null)
  1149. ServerMgr.Instance.StopCoroutine(QueuedRoutine);
  1150. QueuedRoutine = null;
  1151. float newTime = config.NextWaveSeconds + (config.TotalNpcs * 0.1f) + 12f;
  1152. nextWaveTime = Time.time + newTime;
  1153. totalWaves++;
  1154. notify = false;
  1155. notify60 = false;
  1156. }
  1157.  
  1158. internal NpcRaider hookSpawnMember(Vector3 position, bool mounted = false, bool driver = false)
  1159. {
  1160. NpcRaider theNewGuy = SpawnNPC(position);
  1161. if (theNewGuy != null)
  1162. {
  1163. members.Add(theNewGuy);
  1164. return theNewGuy;
  1165. }
  1166. return null;
  1167. }
  1168. internal IEnumerator GenerateEventMembers()
  1169. {
  1170. MlrsWaves++;
  1171. Interface.Oxide.CallHook("NpcRaidersGenerateEventMembers", player, playerID, waveType, totalWaves, location, this);
  1172. ulong id = 0UL;
  1173. if (newWave)
  1174. {
  1175. for (int i = authorizedPlayers.Count - 1; i >= 0; i--)
  1176. {
  1177. id = authorizedPlayers[i];
  1178. if (id != 0UL)
  1179. {
  1180. BasePlayer TCplayer = BasePlayer.FindByID(id);
  1181. if (TCplayer != null && TCplayer.IsConnected)
  1182. {
  1183. if (_.configData.settings.gtip)
  1184. GameTipsMessage(TCplayer, _.lang.GetMessage("start", _, player.UserIDString));
  1185. if (_.configData.settings.ctip)
  1186. _.SendReply(TCplayer, _.lang.GetMessage("start", _, player.UserIDString));
  1187. }
  1188. }
  1189. }
  1190. _.PrintWarning($"EventStarted for {player.displayName}");
  1191. }
  1192. else
  1193. {
  1194. for (int i = authorizedPlayers.Count - 1; i >= 0; i--)
  1195. {
  1196. id = authorizedPlayers[i];
  1197. if (id != 0UL)
  1198. {
  1199. BasePlayer TCplayer = BasePlayer.FindByID(id);
  1200. if (TCplayer != null && TCplayer.IsConnected)
  1201. {
  1202. if (_.configData.settings.ctip)
  1203. _.SendReply(TCplayer, _.lang.GetMessage("nextWave", _, TCplayer.UserIDString));
  1204. if (_.configData.settings.gtip)
  1205. GameTipsMessage(TCplayer, _.lang.GetMessage("nextWave", _, TCplayer.UserIDString), 3f);
  1206. if (!_.statsData.pEntity.ContainsKey(id))
  1207. _.statsData.pEntity.Add(id, new StatsInfo() { name = TCplayer.displayName });
  1208. _.statsData.pEntity[id].played++;
  1209. }
  1210. }
  1211. }
  1212. _.SaveStats();
  1213. }
  1214. newWave = false;
  1215. int totalNpc = 0;
  1216. float spawnDictance = 40;
  1217. if (config == null)
  1218. {
  1219. stopSpawning();
  1220. }
  1221. List<Vector3> positions = generateSpawnList(location, spawnDictance, 200 / config.TotalNpcs);
  1222. yield return CoroutineEx.waitForSeconds(5f);
  1223. while (positions.Count < config.TotalNpcs)
  1224. {
  1225. positions = generateSpawnList(location, spawnDictance, 2f);
  1226. spawnDictance = spawnDictance + 20f;
  1227. _.PrintWarning($"Not enough spawn positions increasing radius for building to {spawnDictance}");
  1228. yield return CoroutineEx.waitForSeconds(5f);
  1229. }
  1230. yield return CoroutineEx.waitForSeconds(1f);
  1231. while (totalNpc < config.TotalNpcs)
  1232. {
  1233. Vector3 position = positions.GetRandom();
  1234. positions.Remove(position);
  1235. NpcRaider theNewGuy = SpawnNPC(position);
  1236. if (theNewGuy != null)
  1237. {
  1238. members.Add(theNewGuy);
  1239. yield return CoroutineEx.waitForSeconds(0.1f);
  1240. if (theNewGuy != null && theNewGuy != null)
  1241. _AllMembers.Add(theNewGuy);
  1242. if (!active)
  1243. active = true;
  1244. }
  1245.  
  1246. totalNpc++;
  1247. yield return CoroutineEx.waitForSeconds(1.0f);
  1248. }
  1249. /* float newTime = config.NextWaveSeconds + (config.TotalNpcs * 0.1f) + 12f;
  1250. nextWaveTime = Time.time + newTime;
  1251. totalWaves++;
  1252. raidernewID = "";*/
  1253. stopSpawning();
  1254. }
  1255.  
  1256. #region Spawning
  1257. internal NpcRaider SpawnNPC(Vector3 pos)
  1258. {
  1259. //pos.y = TerrainMeta.HeightMap.GetHeight(pos);
  1260. // object position = FindPointOnNavmesh(pos, 10f);
  1261. if (pos is Vector3 && (Vector3)pos != Vector3.zero)
  1262. {
  1263. NpcRaider scientistNPC = InstantiateEntity((Vector3)pos, Quaternion.Euler(0, 0, 0));
  1264.  
  1265. if (scientistNPC == null) return null;
  1266.  
  1267. scientistNPC.enableSaving = false;
  1268. scientistNPC.Spawn();
  1269. // _allNPC.Add(scientistNPC);
  1270. scientistNPC.gameObject.SetActive(true);
  1271. scientistNPC.manager = this;
  1272. _.NextTick(() =>
  1273. {
  1274. scientistNPC.InitNewSettings(location, config.Health);
  1275. if (_.Kits != null && config.kits.Count > 0)
  1276. scientistNPC.setUpGear(config.kits.GetRandom());
  1277. else scientistNPC.setUpGear("");
  1278. });
  1279. if (scientistNPC != null)
  1280. {
  1281. if (config.NpcNames.Count > 0)
  1282. {
  1283. string name = config.NpcNames.GetRandom();
  1284. scientistNPC.displayName = name;
  1285. scientistNPC.npcName = name;
  1286. }
  1287. else
  1288. {
  1289. scientistNPC.displayName = "A Raiding Npc";
  1290. scientistNPC.npcName = "A Raiding Npc";
  1291. }
  1292.  
  1293. return scientistNPC;
  1294. }
  1295. }
  1296.  
  1297. return null;
  1298. }
  1299.  
  1300. private static NpcRaider InstantiateEntity(Vector3 position, Quaternion rotation)
  1301. {
  1302. GameObject gameObject = Instantiate.GameObject(GameManager.server.FindPrefab("assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_any.prefab"), position, Quaternion.identity);
  1303. gameObject.name = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_any.prefab";
  1304. gameObject.SetActive(false);
  1305. ScientistNPC scientistNPC = gameObject.GetComponent<ScientistNPC>();
  1306. ScientistBrain defaultBrain = gameObject.GetComponent<ScientistBrain>();
  1307.  
  1308. defaultBrain._baseEntity = scientistNPC;
  1309.  
  1310. NpcRaider component = gameObject.AddComponent<NpcRaider>();
  1311. NpcRaiderBrain brains = gameObject.AddComponent<NpcRaiderBrain>();
  1312. brains.Pet = false;
  1313. brains.AllowedToSleep = false;
  1314. CopyFields<NPCPlayer>(scientistNPC, component);
  1315.  
  1316. brains._baseEntity = component;
  1317.  
  1318. UnityEngine.Object.DestroyImmediate(defaultBrain, true);
  1319. UnityEngine.Object.DestroyImmediate(scientistNPC, true);
  1320. UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene(gameObject, Rust.Server.EntityScene);
  1321. UnityEngine.Object.Destroy(gameObject.GetComponent<Spawnable>());
  1322.  
  1323. return component;
  1324. }
  1325.  
  1326. private static void CopyFields<T>(T src, T dst)
  1327. {
  1328. var fields = typeof(T).GetFields();
  1329.  
  1330. foreach (var field in fields)
  1331. {
  1332. if (field.IsStatic) continue;
  1333. object value = field.GetValue(src);
  1334. field.SetValue(dst, value);
  1335. }
  1336. }
  1337.  
  1338. private static List<Vector3> generateSpawnList(Vector3 position, float radius = 100, float next = 2f)
  1339. {
  1340. List<Vector3> placement = new List<Vector3>();
  1341.  
  1342. placement = GetCircumferencePositions(position, radius, next, position.y);
  1343. foreach (Vector3 locat in placement.ToList())
  1344. {
  1345. if (HasCupboard(locat) != null)
  1346. placement.Remove(locat);
  1347.  
  1348. if (IsInRockPrefab(locat))
  1349. placement.Remove(locat);
  1350. }
  1351. return placement;
  1352. }
  1353.  
  1354. private static List<Vector3> GetCircumferencePositions(Vector3 center, float radius, float next, float y) // Thanks to ArenaWallGenerator
  1355. {
  1356. var positions = new List<Vector3>();
  1357. float degree = 0f;
  1358.  
  1359. while (degree < 360)
  1360. {
  1361. float angle = (float)(2 * Math.PI / 360) * degree;
  1362. float x = center.x + radius * (float)Math.Cos(angle);
  1363. float z = center.z + radius * (float)Math.Sin(angle);
  1364. var position = new Vector3(x, center.y, z);
  1365. object success = FindPointOnNavmesh(position, 10f);
  1366. if (success != null)
  1367. positions.Add((Vector3)success);
  1368.  
  1369. degree += next;
  1370. }
  1371.  
  1372. return positions;
  1373. }
  1374.  
  1375. //Help from Umod Plugins RaidableBases
  1376. private static NavMeshHit navmeshHit;
  1377. private static RaycastHit _hit;
  1378.  
  1379. internal static object FindPointOnNavmesh(Vector3 targetPosition, float maxDistance = 4f)
  1380. {
  1381. for (int i = 0; i < 15; i++)
  1382. {
  1383. Vector3 position = i == 0 ? targetPosition : targetPosition + (UnityEngine.Random.onUnitSphere * maxDistance);
  1384. if (NavMesh.SamplePosition(position, out navmeshHit, maxDistance, 1))
  1385. {
  1386.  
  1387. if (IsInRockPrefab(navmeshHit.position))
  1388. continue;
  1389.  
  1390. return navmeshHit.position;
  1391. }
  1392. }
  1393. return null;
  1394. }
  1395.  
  1396. internal static bool IsInRockPrefab(Vector3 position)
  1397. {
  1398. Physics.queriesHitBackfaces = true;
  1399.  
  1400. bool flag = IsInside(position);
  1401.  
  1402. Physics.queriesHitBackfaces = false;
  1403.  
  1404. return flag;
  1405. }
  1406.  
  1407. internal static bool IsInside(Vector3 point) => Physics.Raycast(point, Vector3.up, out _hit, 30f, Layers.Mask.World, QueryTriggerInteraction.Ignore) && IsRock(_hit.collider.name);
  1408.  
  1409. internal static bool IsRock(string name) => _prefabs.Exists(value => name.Contains(value, CompareOptions.OrdinalIgnoreCase));
  1410.  
  1411. internal static List<string> _prefabs = new List<string> { "rock", "formation", "cliff", "dunes", "prevent_movement", "prevent", "BQV4" };
  1412.  
  1413. #endregion
  1414.  
  1415. #region GetingRaidBuilding
  1416.  
  1417. internal void findNewBuilding(NpcRaider raider)
  1418. {
  1419. if (player != null)
  1420. {
  1421. building = GetBuildingPrivilege(config.ExternalTcRange);
  1422. if (building == null)
  1423. {
  1424. Destroy();
  1425. }
  1426. else
  1427. {
  1428. raider.currentTargetOverride = building;
  1429. foreach (var user in building.authorizedPlayers.ToList())
  1430. {
  1431. if (!authorizedPlayers.Contains(user.userid))
  1432. authorizedPlayers.Add(user.userid);
  1433. if (config.canNotRepair && !_AllPlayers.Contains(user.userid))
  1434. _AllPlayers.Add(user.userid);
  1435. }
  1436. }
  1437. }
  1438. else
  1439. {
  1440. Destroy();
  1441. }
  1442. }
  1443.  
  1444. public BuildingPrivlidge GetBuildingPrivilege(float radius = 0f)
  1445. {
  1446. if (player == null || radius <= 0) return null;
  1447. BuildingBlock buildingBlock1 = (BuildingBlock)null;
  1448. BuildingPrivlidge buildingPrivlidge = (BuildingPrivlidge)null;
  1449. System.Collections.Generic.List<BuildingBlock> list = Facepunch.Pool.GetList<BuildingBlock>();
  1450. Vis.Entities<BuildingBlock>(location, radius, list, 2097152);
  1451. for (int index = 0; index < list.Count; ++index)
  1452. {
  1453. BuildingBlock buildingBlock2 = list[index];
  1454. if (buildingBlock2.IsOlderThan((BaseEntity)buildingBlock1) && Vector3.Distance(location, buildingBlock2.transform.position) <= 102.0)
  1455. {
  1456. BuildingManager.Building building = buildingBlock2.GetBuilding();
  1457. if (building != null)
  1458. {
  1459.  
  1460. BuildingPrivlidge buildingPrivilege = building.GetDominatingBuildingPrivilege();
  1461. if (!((UnityEngine.Object)buildingPrivilege == (UnityEngine.Object)null))
  1462. {
  1463. if (buildingPrivilege.IsAuthed(player))
  1464. {
  1465. buildingBlock1 = buildingBlock2;
  1466. buildingPrivlidge = buildingPrivilege;
  1467. }
  1468. }
  1469. }
  1470. }
  1471. }
  1472. Facepunch.Pool.FreeList<BuildingBlock>(ref list);
  1473. return buildingPrivlidge;
  1474. }
  1475. #endregion
  1476. }
  1477. #endregion
  1478.  
  1479. #region NpcRaider
  1480. public class NpcRaider : NPCPlayer, IAISenses, IAIAttack, IThinker
  1481. {
  1482. public int AdditionalLosBlockingLayer;
  1483. public LootContainer.LootSpawnSlot[] LootSpawnSlots;
  1484. public float aimConeScale = 2f;
  1485. public float lastDismountTime;
  1486. [NonSerialized]
  1487. protected bool lightsOn;
  1488. private float nextZoneSearchTime;
  1489. private AIInformationZone cachedInfoZone;
  1490. private float targetAimedDuration;
  1491. private float lastAimSetTime;
  1492.  
  1493. private Vector3 aimOverridePosition = Vector3.zero;
  1494.  
  1495. public EventRaidManager manager { get; set; }
  1496.  
  1497. private bool isInit { get; set; }
  1498.  
  1499. public BaseCombatEntity currentTarget { get; private set; }
  1500.  
  1501. public BaseCombatEntity currentTargetOverride { get; set; }
  1502.  
  1503. public List<int> _ProjectilesSlot { get; private set; }
  1504.  
  1505. public List<int> _BaseLauncherSlot { get; private set; }
  1506.  
  1507. public List<int> _MeleWeaponSlot { get; private set; }
  1508.  
  1509. public Vector3 HomePosition { get; set; }
  1510.  
  1511. private float lastTargetTime { get; set; }
  1512.  
  1513. private Vector3 lastTargetPosition { get; set; }
  1514.  
  1515. public Vector3 lostPosition() => lastTargetPosition;
  1516.  
  1517. public bool GoodLastTime() => lastTargetTime > Time.time;
  1518.  
  1519. public override float StartHealth() => this.startHealth;
  1520.  
  1521. public override float StartMaxHealth() => this.startHealth;
  1522.  
  1523. public override float MaxHealth() => this.startHealth;
  1524.  
  1525. public NpcRaiderBrain Brain { get; private set; }
  1526.  
  1527. public override bool IsLoadBalanced() => true;
  1528.  
  1529. public bool HasTarget() => (currentTarget != null);
  1530.  
  1531. public bool HasTargetOverride() => (currentTargetOverride != null);
  1532.  
  1533. public List<ulong> DontIgnorePlayers = new List<ulong>();
  1534.  
  1535. public string npcName { get; set; }
  1536.  
  1537. public override string displayName => npcName;
  1538.  
  1539. public override void ServerInit()
  1540. {
  1541. if (NavAgent == null)
  1542. NavAgent = GetComponent<NavMeshAgent>();
  1543.  
  1544. NavAgent.areaMask = 1;
  1545. NavAgent.agentTypeID = -1372625422;
  1546.  
  1547. GetComponent<BaseNavigator>().DefaultArea = "Walkable";
  1548.  
  1549. base.ServerInit();
  1550. Brain = this.GetComponent<NpcRaiderBrain>();
  1551.  
  1552. AIThinkManager.Add((IThinker)this);
  1553.  
  1554. InitNewSettings(this.transform.position);
  1555. InitMovementSettings();
  1556. setupweapons();
  1557. isInit = true;
  1558. }
  1559.  
  1560. public void InitNewSettings(Vector3 home, float health = 100f, float Memory = 20f, float SenseRange = 30f, float LostRange = 250f, float attackRange = 2f, bool isMounted = false)
  1561. {
  1562. if (!this.isServer && !isInit)
  1563. {
  1564. _.NextFrame(() => { if (this != null) InitNewSettings(home, health, Memory, SenseRange, LostRange, attackRange, isMounted); });
  1565. return;
  1566. }
  1567. if (home == Vector3.zero) HomePosition = this.transform.position;
  1568. else HomePosition = home;
  1569.  
  1570. this.startHealth = health;
  1571. InitializeHealth(health, health);
  1572. this.health = health;
  1573.  
  1574. Brain.Senses.MemoryDuration = Memory;
  1575. Brain.AttackRangeMultiplier = attackRange;
  1576. Brain.SenseRange = SenseRange;
  1577. Brain.TargetLostRange = LostRange;
  1578. }
  1579.  
  1580. public void InitMovementSettings(float Acceleration = 12f, float Speed = 6.0f, float TurnSpeed = 120f, float NormalSpeedFraction = 0.5f, float FastSpeedFraction = 1f, float LowHealthMaxSpeedFraction = 0.9f, float SlowestSpeedFraction = 0.16f, float SlowSpeedFraction = 0.3f, float BestMovementPointMaxDistance = 20f, float MaxRoamDistanceFromHome = 30f, float BestRoamPointMaxDistance = 25f, float BestCoverPointMaxDistance = 5f)
  1581. {
  1582. if (!this.isServer && !isInit)
  1583. {
  1584. _.NextFrame(() => { if (this != null) InitMovementSettings(Acceleration, Speed, TurnSpeed, NormalSpeedFraction, FastSpeedFraction, LowHealthMaxSpeedFraction, SlowestSpeedFraction, SlowSpeedFraction, BestMovementPointMaxDistance, MaxRoamDistanceFromHome, BestRoamPointMaxDistance, BestCoverPointMaxDistance); });
  1585. return;
  1586. }
  1587. _.NextFrame(() =>
  1588. {
  1589. Brain.Navigator.Acceleration = Acceleration;
  1590. Brain.Navigator.Speed = Speed;
  1591. Brain.Navigator.TurnSpeed = TurnSpeed;
  1592. Brain.Navigator.NormalSpeedFraction = NormalSpeedFraction;
  1593. Brain.Navigator.FastSpeedFraction = FastSpeedFraction;
  1594. Brain.Navigator.LowHealthMaxSpeedFraction = LowHealthMaxSpeedFraction;
  1595. Brain.Navigator.SlowestSpeedFraction = SlowestSpeedFraction;
  1596. Brain.Navigator.SlowSpeedFraction = SlowSpeedFraction;
  1597. Brain.Navigator.BestMovementPointMaxDistance = BestMovementPointMaxDistance;
  1598. Brain.Navigator.MaxRoamDistanceFromHome = MaxRoamDistanceFromHome;
  1599. Brain.Navigator.BestRoamPointMaxDistance = BestRoamPointMaxDistance;
  1600. Brain.Navigator.BestCoverPointMaxDistance = BestCoverPointMaxDistance;
  1601. aimConeScale = manager.config.aimConeScale;
  1602. });
  1603. }
  1604.  
  1605. public void setUpGear(string kitname = "")
  1606. {
  1607. if (this.IsDestroyed) return;
  1608. this.inventory.containerBelt.capacity = 8;
  1609. if (!string.IsNullOrEmpty(kitname))
  1610. {
  1611. this.inventory.Strip();
  1612. ItemManager.CreateByName("rocket.launcher").MoveToContainer(this.inventory.containerBelt, 6);
  1613. object success = _.Kits?.Call("GetKitInfo", kitname);
  1614. if ((bool)_.Kits.Call("IsKit", kitname) == false)
  1615. {
  1616. addDefaultGear();
  1617. _.PrintWarning($"Unable to find a kit with name {kitname}?");
  1618. }
  1619. else
  1620. {
  1621. _.Kits.Call($"GiveKit", this, kitname, false);
  1622.  
  1623. ItemManager.CreateByName("rocket.launcher").MoveToContainer(this.inventory.containerBelt, 6);
  1624. setupweapons();
  1625.  
  1626. _.timer.Once(1f, () =>
  1627. {
  1628. if (this == null) return;
  1629. if (_ProjectilesSlot.Count > 0)
  1630. EquipNewWeapon(_ProjectilesSlot[0]);
  1631. else if (_MeleWeaponSlot.Count > 0)
  1632. EquipNewWeapon(_MeleWeaponSlot[0]);
  1633. });
  1634. }
  1635. }
  1636. else
  1637. {
  1638. addDefaultGear();
  1639. EquipWeapon();
  1640. setupweapons();
  1641. }
  1642. }
  1643.  
  1644. private void addDefaultGear()
  1645. {
  1646. switch (UnityEngine.Random.Range(0, 7))
  1647. {
  1648. case 0:
  1649. ItemManager.CreateByName("scientistsuit_heavy").MoveToContainer(this.inventory.containerWear);
  1650. break;
  1651. case 1:
  1652. ItemManager.CreateByName("hazmatsuit_scientist_peacekeeper").MoveToContainer(this.inventory.containerWear);
  1653. break;
  1654. case 2:
  1655. ItemManager.CreateByName("hazmatsuit_scientist").MoveToContainer(this.inventory.containerWear);
  1656. break;
  1657. case 3:
  1658. ItemManager.CreateByName("hazmatsuit").MoveToContainer(this.inventory.containerWear);
  1659. break;
  1660. case 4:
  1661. ItemManager.CreateByName("scientistsuit_heavy").MoveToContainer(this.inventory.containerWear);
  1662. break;
  1663. case 5:
  1664. ItemManager.CreateByName("hazmatsuit_scientist_peacekeeper").MoveToContainer(this.inventory.containerWear);
  1665. break;
  1666. case 6:
  1667. ItemManager.CreateByName("hazmatsuit_scientist").MoveToContainer(this.inventory.containerWear);
  1668. break;
  1669. case 7:
  1670. ItemManager.CreateByName("hazmatsuit").MoveToContainer(this.inventory.containerWear);
  1671. break;
  1672. default:
  1673. ItemManager.CreateByName("hazmatsuit_scientist").MoveToContainer(this.inventory.containerWear);
  1674. break;
  1675. }
  1676.  
  1677. switch (UnityEngine.Random.Range(0, 9))
  1678. {
  1679. case 0:
  1680. ItemManager.CreateByName("smg.mp5").MoveToContainer(this.inventory.containerBelt, 0);
  1681. break;
  1682. case 1:
  1683. ItemManager.CreateByName("shotgun.spas12").MoveToContainer(this.inventory.containerBelt, 0);
  1684. break;
  1685. case 2:
  1686. ItemManager.CreateByName("rifle.lr300").MoveToContainer(this.inventory.containerBelt, 0);
  1687. break;
  1688. case 3:
  1689. ItemManager.CreateByName("lmg.m249").MoveToContainer(this.inventory.containerBelt, 0);
  1690. break;
  1691. case 4:
  1692. ItemManager.CreateByName("pistol.m92").MoveToContainer(this.inventory.containerBelt, 0);
  1693. break;
  1694. case 5:
  1695. ItemManager.CreateByName("smg.mp5").MoveToContainer(this.inventory.containerBelt, 0);
  1696. break;
  1697. case 6:
  1698. ItemManager.CreateByName("shotgun.spas12").MoveToContainer(this.inventory.containerBelt, 0);
  1699. break;
  1700. case 7:
  1701. ItemManager.CreateByName("rifle.lr300").MoveToContainer(this.inventory.containerBelt, 0);
  1702. break;
  1703. case 8:
  1704. ItemManager.CreateByName("lmg.m249").MoveToContainer(this.inventory.containerBelt, 0);
  1705. break;
  1706. case 9:
  1707. ItemManager.CreateByName("pistol.m92").MoveToContainer(this.inventory.containerBelt, 0);
  1708. break;
  1709. default:
  1710. ItemManager.CreateByName("pistol.m92").MoveToContainer(this.inventory.containerBelt, 0);
  1711. break;
  1712. }
  1713. ItemManager.CreateByName("rocket.launcher").MoveToContainer(this.inventory.containerBelt, 6);
  1714. this.inventory.containerBelt.OnChanged();
  1715. }
  1716.  
  1717. private void setupweapons()
  1718. {
  1719. _ProjectilesSlot = new List<int>();
  1720. _MeleWeaponSlot = new List<int>();
  1721. _BaseLauncherSlot = new List<int>();
  1722. foreach (Item slot in inventory.containerBelt.itemList)
  1723. {
  1724. if (slot != null)
  1725. {
  1726. BaseEntity heldEntity = slot.GetHeldEntity();
  1727. if (heldEntity != null)
  1728. {
  1729. AttackEntity _attackEntity = heldEntity.GetComponent<AttackEntity>();
  1730. if (_attackEntity != null)
  1731. {
  1732. _attackEntity.deployDelay = 0.5f;
  1733.  
  1734. if (_attackEntity is BaseLauncher)
  1735. {
  1736. _BaseLauncherSlot.Add(slot.position);
  1737. _attackEntity.aiOnlyInRange = false;
  1738. }
  1739. else if (_attackEntity is BaseProjectile)
  1740. {
  1741. _ProjectilesSlot.Add(slot.position);
  1742. _attackEntity.aiOnlyInRange = false;
  1743. // (_attackEntity as BaseProjectile).reloadTime = 0.1f; //edited to prevent new weapions from not shooting correctly
  1744.  
  1745. if (_attackEntity.effectiveRange <= 5)
  1746. _attackEntity.effectiveRange = 15f;
  1747. }
  1748. else _MeleWeaponSlot.Add(slot.position);
  1749. }
  1750. }
  1751. }
  1752. }
  1753. if (debug)
  1754. {
  1755. _.PrintWarning($"DEBUG: Current Projectiles: {_ProjectilesSlot.Count}, Current BaseLaunchers: {_BaseLauncherSlot.Count}, Current Outers: {_MeleWeaponSlot.Count}");
  1756. }
  1757. }
  1758.  
  1759. public HeldEntity EquipNewWeapon(int slot = 0)
  1760. {
  1761. if (this.IsDestroyed) return null;
  1762. Item weapon = this.inventory.containerBelt.GetSlot(slot);
  1763. if (weapon != null)
  1764. {
  1765. HeldEntity heldEntity = weapon.GetHeldEntity() as HeldEntity;
  1766. if (heldEntity != null)
  1767. {
  1768. AttackEntity _attackEntity = heldEntity.GetComponent<AttackEntity>();
  1769. if (_attackEntity == null) return null;
  1770.  
  1771. if (_attackEntity is BaseProjectile)
  1772. this.UpdateActiveItem(weapon.uid);
  1773.  
  1774. else this.UpdateActiveItem(weapon.uid);
  1775.  
  1776. _attackEntity.SetHeld(true);
  1777.  
  1778. if (_attackEntity is Chainsaw)
  1779. (_attackEntity as Chainsaw).ServerNPCStart();
  1780. heldEntity.SetHeld(true);
  1781. return heldEntity;
  1782. }
  1783. }
  1784. return null;
  1785. }
  1786.  
  1787. private BaseEntity UpdateTargets()
  1788. {
  1789. if (this.IsDestroyed) return null;
  1790. BaseEntity target = null;
  1791. float delta = -1f;
  1792. foreach (BaseEntity baseEntity in Brain.Senses.Memory.Targets)
  1793. {
  1794. if (baseEntity == null || baseEntity.Health() <= 0f)
  1795. continue;
  1796.  
  1797. if (baseEntity is BasePlayer && ShouldIgnorePlayer(baseEntity as BasePlayer))
  1798. continue;
  1799.  
  1800. if (!CanSeeTarget(baseEntity))
  1801. continue;
  1802.  
  1803. float distanceToTarget = Vector3.Distance(baseEntity.transform.position, transform.position);
  1804. if (distanceToTarget > Brain.TargetLostRange)
  1805. continue;
  1806.  
  1807. float rangeDelta = 1f - Mathf.InverseLerp(1f, Brain.SenseRange, distanceToTarget);
  1808.  
  1809. float dot = Vector3.Dot((baseEntity.transform.position - eyes.position).normalized, eyes.BodyForward());
  1810.  
  1811. rangeDelta += Mathf.InverseLerp(Brain.VisionCone, 1f, dot) / 2f;
  1812. rangeDelta += (Brain.Senses.Memory.IsLOS(baseEntity) ? 2f : 0f);
  1813.  
  1814. if (rangeDelta <= delta)
  1815. continue;
  1816.  
  1817. target = baseEntity;
  1818. delta = rangeDelta;
  1819. }
  1820.  
  1821. currentTarget = target as BaseCombatEntity;
  1822. if (target != null)
  1823. {
  1824. Brain.Senses.Memory.Threats.Add(target);
  1825. Brain.Senses.Memory.SetKnown(target, this, null);
  1826. lastTargetTime = Time.time + Brain.Senses.MemoryDuration;
  1827. lastTargetPosition = target.transform.position;
  1828. }
  1829. UpdateMemory();
  1830. GetRaidReady();
  1831. return target;
  1832. }
  1833.  
  1834. private float nextRaidTime { get; set; }
  1835. private void GetRaidReady()
  1836. {
  1837. if (this.IsDestroyed) return;
  1838. if (nextRaidTime < Time.time)
  1839. {
  1840. nextRaidTime = Time.time + 20;
  1841. if (this == null || this.IsDestroyed || this.IsDead())
  1842. return;
  1843. if (currentTargetOverride == null)
  1844. {
  1845. currentTargetOverride = GetBuilding();
  1846. if (currentTargetOverride != null)
  1847. {
  1848. DontIgnorePlayers.AddRange(manager.authorizedPlayers);
  1849. HomePosition = currentTargetOverride.transform.position;
  1850. }
  1851. if (debug) _.PrintWarning("set raid target");
  1852. return;
  1853. }
  1854. }
  1855. }
  1856.  
  1857. private BaseCombatEntity GetBuilding()
  1858. {
  1859. if (manager == null || this.IsDestroyed) return null;
  1860. if (manager.building == null)
  1861. {
  1862. manager.findNewBuilding(this);
  1863. if (manager.building == null)
  1864. return null;
  1865. }
  1866.  
  1867. return manager.building;
  1868. }
  1869.  
  1870. private BasePlayer[] playerQueryResults = new BasePlayer[64];
  1871.  
  1872. private void UpdateMemory()
  1873. {
  1874. int inSphere = BaseEntity.Query.Server.GetPlayersInSphere(this.transform.position, Brain.SenseRange, playerQueryResults, new Func<BaseEntity, bool>(AiCaresAbout));
  1875. for (int i = 0; i < inSphere; i++)
  1876. {
  1877. BaseCombatEntity baseCombatEntity = playerQueryResults[i] as BaseCombatEntity;
  1878. if (baseCombatEntity != null && !baseCombatEntity.EqualNetID(this) && IsVisibleToUs(baseCombatEntity))
  1879. {
  1880. Brain.Senses.Memory.SetKnown(baseCombatEntity, this, null);
  1881. }
  1882. }
  1883. }
  1884.  
  1885. private bool AiCaresAbout(BaseEntity entity)
  1886. {
  1887. BaseCombatEntity baseCombatEntity = entity as BaseCombatEntity;
  1888.  
  1889. if (baseCombatEntity == null || baseCombatEntity.IsDestroyed || baseCombatEntity.transform == null)
  1890. return false;
  1891.  
  1892. if (baseCombatEntity.Health() <= 0f)
  1893. return false;
  1894.  
  1895. if (baseCombatEntity is BasePlayer)
  1896. {
  1897. BasePlayer player = baseCombatEntity as BasePlayer;
  1898.  
  1899. if (this.userID == player.userID)
  1900. return false;
  1901.  
  1902. if (player is global::HumanNPC)
  1903. return false;
  1904.  
  1905. if (player is NpcRaider)
  1906. return false;
  1907.  
  1908. if (!player.userID.IsSteamId() && !player.IsNpc)
  1909. return false;
  1910.  
  1911. return true;
  1912. }
  1913.  
  1914. if (baseCombatEntity is BaseNpc)
  1915. return false;
  1916.  
  1917. return false;
  1918. }
  1919. public bool IsVisibleToUs(BaseCombatEntity baseCombatEntity)
  1920. {
  1921. if (baseCombatEntity is BasePlayer)
  1922. return IsPlayerVisibleToUs(baseCombatEntity as BasePlayer, Vector3.zero, 1218519041);
  1923. else return IsVisible(baseCombatEntity.CenterPoint(), eyes.worldStandingPosition, float.PositiveInfinity);
  1924. }
  1925.  
  1926. private bool ShouldIgnorePlayer(BasePlayer player)
  1927. {
  1928. if (player == null || player.IsDead()) return true;
  1929. if (manager != null && manager.authorizedPlayers != null && player.userID != null)
  1930. {
  1931. if (manager.authorizedPlayers.Contains(player.userID))
  1932. return false;
  1933. return true;
  1934. }
  1935. return false;
  1936. }
  1937.  
  1938. public bool TargetInThrowableRange()
  1939. {
  1940. if (currentTargetOverride == null)
  1941. return false;
  1942. return !hasWall(); //return Vector3.Distance(targetEntity.transform.position, Entity.transform.position) <= 7.5f;
  1943. }
  1944.  
  1945. public bool hasWall()
  1946. {
  1947. // var ray = new Ray(Entity.eyes.position, Entity.eyes.HeadForward());
  1948. RaycastHit hit;
  1949. if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, 5.2f, BuildingLayer))
  1950. {
  1951. return true;
  1952. }
  1953.  
  1954. return false;
  1955. }
  1956.  
  1957. public void SetDestination(Vector3 destination)
  1958. {
  1959. if (Brain.Navigator == null) return;
  1960. destination = new Vector3(destination.x, TerrainMeta.HeightMap.GetHeight(destination) + 0.5f, destination.z);
  1961. Brain.Navigator.SetDestination(destination, BaseNavigator.NavigationSpeed.Fast);
  1962. }
  1963.  
  1964. public override void DestroyShared()
  1965. {
  1966. if (manager != null)
  1967. manager.RemoveNpc(this);
  1968. base.DestroyShared();
  1969. AIThinkManager.Remove(this);
  1970. }
  1971.  
  1972. public void LightCheck()
  1973. {
  1974. if ((!TOD_Sky.Instance.IsNight || this.lightsOn) && (!TOD_Sky.Instance.IsDay || !this.lightsOn))
  1975. return;
  1976. this.LightToggle();
  1977. this.lightsOn = !this.lightsOn;
  1978. }
  1979.  
  1980. public override float GetAimConeScale() => this.aimConeScale;
  1981.  
  1982. public override void EquipWeapon(bool skipDeployDelay = false) => base.EquipWeapon(skipDeployDelay);
  1983.  
  1984. public override void DismountObject()
  1985. {
  1986. base.DismountObject();
  1987. this.lastDismountTime = Time.time;
  1988. }
  1989.  
  1990. public bool RecentlyDismounted() => (double)Time.time < (double)this.lastDismountTime + 10.0;
  1991.  
  1992. public virtual float GetIdealDistanceFromTarget() => Mathf.Max(5f, this.EngagementRange() * 0.75f);
  1993.  
  1994. public AIInformationZone GetInformationZone(Vector3 pos)
  1995. {
  1996. if ((UnityEngine.Object)this.VirtualInfoZone != (UnityEngine.Object)null)
  1997. return this.VirtualInfoZone;
  1998. if ((UnityEngine.Object)this.cachedInfoZone == (UnityEngine.Object)null || (double)Time.time > (double)this.nextZoneSearchTime)
  1999. {
  2000. this.cachedInfoZone = AIInformationZone.GetForPoint(pos);
  2001. this.nextZoneSearchTime = Time.time + 5f;
  2002. }
  2003. return this.cachedInfoZone;
  2004. }
  2005.  
  2006. public bool InEngagementRange()
  2007. {
  2008. AttackEntity attackEntity = this.GetAttackEntity();
  2009. if (currentTarget == null || attackEntity == null) return false;
  2010.  
  2011. return (double)Vector3Ex.Distance2D(this.transform.position, currentTarget.transform.position) <= (attackEntity.effectiveRange * this.Brain.AttackRangeMultiplier);
  2012. }
  2013.  
  2014. public float EngagementRange()
  2015. {
  2016. AttackEntity attackEntity = this.GetAttackEntity();
  2017.  
  2018. if (attackEntity is BaseProjectile && attackEntity.effectiveRange <= 1)
  2019. attackEntity.effectiveRange = 15f;
  2020.  
  2021. return (bool)(UnityEngine.Object)attackEntity ? attackEntity.effectiveRange * (attackEntity.aiOnlyInRange ? 1f : 2f) * this.Brain.AttackRangeMultiplier : 300f;
  2022. }
  2023.  
  2024. public void SetDucked(bool flag)
  2025. {
  2026. this.modelState.ducked = flag;
  2027. this.SendNetworkUpdate();
  2028. }
  2029.  
  2030. public float lastThinkTime { get; set; }
  2031.  
  2032. internal void Internal()
  2033. {
  2034. this.ServerThink(Time.time - this.lastThinkTime);
  2035. this.lastThinkTime = Time.time;
  2036. }
  2037.  
  2038. public virtual void TryThink() => Internal();
  2039.  
  2040. public override void ServerThink(float delta)
  2041. {
  2042. base.ServerThink(delta);
  2043. if (!this.Brain.ShouldServerThink())
  2044. return;
  2045. UpdateTargets();
  2046. this.Brain.DoThink();
  2047. }
  2048.  
  2049. public void TickAttack(float delta, BaseCombatEntity target, bool targetIsLOS)
  2050. {
  2051. if ((UnityEngine.Object)target == (UnityEngine.Object)null)
  2052. return;
  2053. float num = Vector3.Dot(this.eyes.BodyForward(), (target.CenterPoint() - this.eyes.position).normalized);
  2054. if (targetIsLOS)
  2055. {
  2056. if ((double)num > 0.200000002980232)
  2057. this.targetAimedDuration += delta;
  2058. }
  2059. else
  2060. {
  2061. if ((double)num < 0.5)
  2062. this.targetAimedDuration = 0.0f;
  2063. this.CancelBurst();
  2064. }
  2065. if ((double)this.targetAimedDuration >= 0.200000002980232 & targetIsLOS)
  2066. {
  2067. bool flag = false;
  2068. IAIAttack aiAttack = (IAIAttack)this;
  2069. float dist = 0.0f;
  2070. if (aiAttack != null)
  2071. {
  2072. flag = aiAttack.IsTargetInRange((BaseEntity)target, out dist);
  2073. }
  2074. else
  2075. {
  2076. AttackEntity attackEntity = this.GetAttackEntity();
  2077. if ((bool)(UnityEngine.Object)attackEntity)
  2078. {
  2079. dist = (UnityEngine.Object)target != (UnityEngine.Object)null ? Vector3.Distance(this.transform.position, target.transform.position) : -1f;
  2080. flag = (double)dist < (double)attackEntity.effectiveRange * (attackEntity.aiOnlyInRange ? 1.0 : 2.0);
  2081. }
  2082. }
  2083. if (!flag)
  2084. return;
  2085. this.ShotTest(dist);
  2086. }
  2087. else
  2088. this.CancelBurst();
  2089. }
  2090.  
  2091. private BasePlayer lastDamagePlayer { get; set; }
  2092.  
  2093. public override void Hurt(HitInfo info)
  2094. {
  2095. BaseEntity initiator = info.Initiator;
  2096. if (initiator != null && initiator.EqualNetID((BaseNetworkable)this))
  2097. return;
  2098. if (manager != null && initiator != null)
  2099. {
  2100. if (initiator is BasePlayer && !manager.authorizedPlayers.Contains((initiator as BasePlayer).userID))
  2101. {
  2102. GameTips((initiator as BasePlayer));
  2103. return;
  2104. }
  2105. if (_.configData.settings.damageDelay > 0 && Brain != null && (Brain.spawnAge + _.configData.settings.damageDelay) > Time.time)
  2106. return;
  2107. }
  2108. base.Hurt(info);
  2109. if (initiator == null || initiator.EqualNetID((BaseNetworkable)this))
  2110. return;
  2111. this.Brain.Senses.Memory.SetKnown(initiator, (BaseEntity)this, (AIBrainSenses)null);
  2112. lastTargetTime = Time.time + Brain.Senses.MemoryDuration;
  2113. lastTargetPosition = initiator.transform.position;
  2114. if (initiator is BasePlayer && manager.authorizedPlayers.Contains((initiator as BasePlayer).userID))
  2115. {
  2116. lastDamagePlayer = initiator as BasePlayer;
  2117. }
  2118. }
  2119.  
  2120. public static void GameTips(BasePlayer player)
  2121. {
  2122. if (player != null && player.userID.IsSteamId())
  2123. {
  2124. player?.SendConsoleCommand("gametip.hidegametip");
  2125. player?.SendConsoleCommand("gametip.showgametip", "You can not hurt this Npc.");
  2126. _.timer.Once(2f, () => player?.SendConsoleCommand("gametip.hidegametip"));
  2127. }
  2128. }
  2129.  
  2130. public float GetAimSwayScalar() => 1f - Mathf.InverseLerp(1f, 3f, Time.time - this.lastGunShotTime);
  2131.  
  2132. public override Vector3 GetAimDirection() => (UnityEngine.Object)this.Brain != (UnityEngine.Object)null && (UnityEngine.Object)this.Brain.Navigator != (UnityEngine.Object)null && this.Brain.Navigator.IsOverridingFacingDirection ? this.Brain.Navigator.FacingDirectionOverride : base.GetAimDirection();
  2133.  
  2134. public override void SetAimDirection(Vector3 newAim)
  2135. {
  2136. if (newAim == Vector3.zero)
  2137. return;
  2138. float num = Time.time - this.lastAimSetTime;
  2139. this.lastAimSetTime = Time.time;
  2140. AttackEntity attackEntity = this.GetAttackEntity();
  2141. if ((bool)(UnityEngine.Object)attackEntity)
  2142. newAim = attackEntity.ModifyAIAim(newAim, this.GetAimSwayScalar());
  2143. if (this.isMounted)
  2144. {
  2145. BaseMountable mounted = this.GetMounted();
  2146. Vector3 eulerAngles = mounted.transform.eulerAngles;
  2147. Vector3 vector3 = BaseMountable.ConvertVector(Quaternion.LookRotation(this.transform.InverseTransformDirection(Quaternion.Euler(Quaternion.LookRotation(newAim, mounted.transform.up).eulerAngles) * Vector3.forward), this.transform.up).eulerAngles);
  2148. newAim = BaseMountable.ConvertVector(Quaternion.LookRotation(this.transform.TransformDirection(Quaternion.Euler(Mathf.Clamp(vector3.x, mounted.pitchClamp.x, mounted.pitchClamp.y), Mathf.Clamp(vector3.y, mounted.yawClamp.x, mounted.yawClamp.y), eulerAngles.z) * Vector3.forward), this.transform.up).eulerAngles);
  2149. }
  2150. else
  2151. {
  2152. BaseEntity parentEntity = this.GetParentEntity();
  2153. if ((bool)(UnityEngine.Object)parentEntity)
  2154. {
  2155. Vector3 vector3 = parentEntity.transform.InverseTransformDirection(newAim);
  2156. this.eyes.rotation = Quaternion.Lerp(this.eyes.rotation, Quaternion.LookRotation(new Vector3(newAim.x, vector3.y, newAim.z), parentEntity.transform.up), num * 25f);
  2157. this.viewAngles = this.eyes.bodyRotation.eulerAngles;
  2158. this.ServerRotation = this.eyes.bodyRotation;
  2159. return;
  2160. }
  2161. }
  2162. this.eyes.rotation = this.isMounted ? Quaternion.Slerp(this.eyes.rotation, Quaternion.Euler(newAim), num * 70f) : Quaternion.Lerp(this.eyes.rotation, Quaternion.LookRotation(newAim, this.transform.up), num * 25f);
  2163. this.viewAngles = this.eyes.rotation.eulerAngles;
  2164. this.ServerRotation = this.eyes.rotation;
  2165. }
  2166.  
  2167. public void SetStationaryAimPoint(Vector3 aimAt) => this.aimOverridePosition = aimAt;
  2168.  
  2169. public void ClearStationaryAimPoint() => this.aimOverridePosition = Vector3.zero;
  2170.  
  2171. public override bool ShouldDropActiveItem() => false;
  2172.  
  2173. public override BaseCorpse CreateCorpse(BasePlayer.PlayerFlags flagsOnDeath, Vector3 posOnDeath, Quaternion rotOnDeath, List<TriggerBase> triggersOnDeath, bool forceServerSide = false)
  2174. {
  2175. if (manager.members.Contains(this))
  2176. manager.members.Remove(this);
  2177. if (lastDamagePlayer != null && lastDamagePlayer.userID.IsSteamId())
  2178. {
  2179. if (!_.statsData.pEntity.ContainsKey(lastDamagePlayer.userID))
  2180. _.statsData.pEntity.Add(lastDamagePlayer.userID, new StatsInfo() { name = lastDamagePlayer.displayName });
  2181. _.statsData.pEntity[lastDamagePlayer.userID].killed++;
  2182. }
  2183.  
  2184.  
  2185. NPCPlayerCorpse npcPlayerCorpse = this.DropCorpse("assets/prefabs/npc/scientist/scientist_corpse.prefab") as NPCPlayerCorpse;
  2186. if (npcPlayerCorpse != null)
  2187. {
  2188. npcPlayerCorpse.transform.position = npcPlayerCorpse.transform.position + Vector3.down * .05f;
  2189. npcPlayerCorpse.SetLootableIn(2f);
  2190. npcPlayerCorpse.SetFlag(BaseEntity.Flags.Reserved5, this.HasPlayerFlag(BasePlayer.PlayerFlags.DisplaySash));
  2191. npcPlayerCorpse.SetFlag(BaseEntity.Flags.Reserved2, true);
  2192. npcPlayerCorpse.TakeFrom(npcPlayerCorpse, this.inventory.containerMain, this.inventory.containerWear, this.inventory.containerBelt);
  2193. npcPlayerCorpse.playerName = this.OverrideCorpseName();
  2194. npcPlayerCorpse.playerSteamID = this.userID;
  2195. npcPlayerCorpse.Spawn();
  2196.  
  2197. for (int index = 0; index < npcPlayerCorpse.containers.Length; ++index)
  2198. {
  2199. ItemContainer container = npcPlayerCorpse.containers[index];
  2200. if (index != 1)
  2201. container.Clear();
  2202. }
  2203.  
  2204. global::HumanNPC theNPC = GameManager.server.FindPrefab("assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roamtethered.prefab").GetComponent<global::HumanNPC>();
  2205. LootSpawnSlots = theNPC.LootSpawnSlots;
  2206. if (_ != null && manager != null && manager.config.lootProfileA != null && manager.config.lootProfileA.Count > 0)
  2207. {
  2208. _.NextTick(() =>
  2209. {
  2210. if (npcPlayerCorpse != null)
  2211. {
  2212. _.AlphaLoot?.Call("PopulateLoot", npcPlayerCorpse.containers[0], manager.config.lootProfileA.GetRandom());
  2213. }
  2214. });
  2215. }
  2216. else if (manager != null && manager.config.NpcDropLoot)
  2217. {
  2218. List<ulong> copyList = new List<ulong>();
  2219. copyList.AddRange(manager.authorizedPlayers);
  2220. _.corpsLock.Add(npcPlayerCorpse.playerSteamID, copyList);
  2221. if (manager.config.NpcDropLootConfig.Count > 0)
  2222. {
  2223. string rand = manager.config.NpcDropLootConfig.GetRandom();
  2224. if (HasSaveFile(rand))
  2225. {
  2226. LootEntity newFile = null;
  2227. LoadLootData(out newFile, _.Name + "/LootProfiles/" + rand);
  2228.  
  2229. if (npcPlayerCorpse != null && newFile != null)
  2230. {
  2231. int total = UnityEngine.Random.Range(newFile.MinItems, newFile.MaxItems + 1);
  2232. for (int j = 0; j < total; j++)
  2233. {
  2234. itemInfo itemNew = newFile.items.GetRandom();
  2235. string item = itemNew.item;
  2236. int amount = UnityEngine.Random.Range(itemNew.amountMin, itemNew.amountMax);
  2237. ulong skin = itemNew.skin;
  2238. string location = itemNew.location;
  2239. if (amount == 0) amount = 1;
  2240.  
  2241. Item x = ItemManager.CreateByName(item, amount, skin);
  2242. if (x != null)
  2243. {
  2244. if (location == "containerMain")
  2245. x.MoveToContainer(npcPlayerCorpse.containers[0], -1);
  2246. else if (location == "containerBelt")
  2247. x.MoveToContainer(npcPlayerCorpse.containers[1], -1);
  2248. else if (location == "containerWear")
  2249. x.MoveToContainer(npcPlayerCorpse.containers[2], -1);
  2250. if (!String.IsNullOrEmpty(itemNew.name))
  2251. x.name = itemNew.name;
  2252. }
  2253. }
  2254. }
  2255. }
  2256. else
  2257. {
  2258. if (this.LootSpawnSlots != null && this.LootSpawnSlots.Length != 0)
  2259. {
  2260. foreach (LootContainer.LootSpawnSlot lootSpawnSlot in this.LootSpawnSlots)
  2261. {
  2262. for (int index = 0; index < lootSpawnSlot.numberToSpawn; ++index)
  2263. {
  2264. if ((double)UnityEngine.Random.Range(0.0f, 1f) <= (double)lootSpawnSlot.probability)
  2265. lootSpawnSlot.definition.SpawnIntoContainer(npcPlayerCorpse.containers[0]);
  2266. }
  2267. }
  2268. }
  2269. }
  2270. }
  2271. else
  2272. {
  2273. if (this.LootSpawnSlots != null && this.LootSpawnSlots.Length != 0)
  2274. {
  2275. foreach (LootContainer.LootSpawnSlot lootSpawnSlot in this.LootSpawnSlots)
  2276. {
  2277. for (int index = 0; index < lootSpawnSlot.numberToSpawn; ++index)
  2278. {
  2279. if ((double)UnityEngine.Random.Range(0.0f, 1f) <= (double)lootSpawnSlot.probability)
  2280. lootSpawnSlot.definition.SpawnIntoContainer(npcPlayerCorpse.containers[0]);
  2281. }
  2282. }
  2283. }
  2284. }
  2285. }
  2286. else removeCorpse(npcPlayerCorpse);
  2287. }
  2288.  
  2289. if (npcPlayerCorpse != null)
  2290. DropBags(npcPlayerCorpse);
  2291.  
  2292. return (BaseCorpse)npcPlayerCorpse;
  2293. }
  2294.  
  2295. protected virtual string OverrideCorpseName() => this.displayName;
  2296.  
  2297. public override void AttackerInfo(PlayerLifeStory.DeathInfo info)
  2298. {
  2299. base.AttackerInfo(info);
  2300. info.inflictorName = this.inventory.containerBelt.GetSlot(0).info.shortname;
  2301. info.attackerName = "scientist";
  2302. }
  2303.  
  2304. public bool IsThreat(BaseEntity entity) => this.IsTarget(entity);
  2305.  
  2306. public bool IsTarget(BaseEntity entity) => entity is BasePlayer && !entity.IsNpc || entity is BasePet;
  2307.  
  2308. public bool IsFriendly(BaseEntity entity) => !((UnityEngine.Object)entity == (UnityEngine.Object)null) && (int)entity.prefabID == (int)this.prefabID;
  2309.  
  2310. public bool CanAttack(BaseEntity entity) => true;
  2311.  
  2312. public bool IsTargetInRange(BaseEntity entity, out float dist)
  2313. {
  2314. dist = Vector3.Distance(entity.transform.position, this.transform.position);
  2315. return (double)dist <= (double)this.EngagementRange();
  2316. }
  2317.  
  2318. public bool CanSeeTarget(BaseEntity entity)
  2319. {
  2320. BasePlayer otherPlayer = entity as BasePlayer;
  2321. if ((UnityEngine.Object)otherPlayer == (UnityEngine.Object)null)
  2322. return true;
  2323. return this.AdditionalLosBlockingLayer == 0 ? this.IsPlayerVisibleToUs(otherPlayer, Vector3.zero, 1218519041) : this.IsPlayerVisibleToUs(otherPlayer, Vector3.zero, 1218519041 | 1 << this.AdditionalLosBlockingLayer);
  2324. }
  2325.  
  2326. public bool NeedsToReload() => false;
  2327.  
  2328. public bool Reload() => true;
  2329.  
  2330. public float CooldownDuration() => 5f;
  2331.  
  2332. public bool IsOnCooldown() => false;
  2333.  
  2334. public bool StartAttacking(BaseEntity entity) => true;
  2335.  
  2336. public void StopAttacking()
  2337. {
  2338. }
  2339.  
  2340. public float GetAmmoFraction() => this.AmmoFractionRemaining();
  2341.  
  2342. public BaseEntity GetBestTarget()
  2343. {
  2344. BaseEntity baseEntity = (BaseEntity)null;
  2345. float num1 = -1f;
  2346. foreach (BaseEntity player in this.Brain.Senses.Players)
  2347. {
  2348. if (!((UnityEngine.Object)player == (UnityEngine.Object)null) && (double)player.Health() > 0.0)
  2349. {
  2350. float num2 = 1f - Mathf.InverseLerp(1f, this.Brain.SenseRange, Vector3.Distance(player.transform.position, this.transform.position)) + Mathf.InverseLerp(this.Brain.VisionCone, 1f, Vector3.Dot((player.transform.position - this.eyes.position).normalized, this.eyes.BodyForward())) / 2f + (this.Brain.Senses.Memory.IsLOS(player) ? 2f : 0.0f);
  2351. if ((double)num2 > (double)num1)
  2352. {
  2353. baseEntity = player;
  2354. num1 = num2;
  2355. }
  2356. }
  2357. }
  2358. return baseEntity;
  2359. }
  2360.  
  2361. public void AttackTick(float delta, BaseEntity target, bool targetIsLOS)
  2362. {
  2363. BaseCombatEntity target1 = target as BaseCombatEntity;
  2364. this.TickAttack(delta, target1, targetIsLOS);
  2365. }
  2366.  
  2367. public override bool IsOnGround() => true;
  2368.  
  2369. private bool ShouldIgnoreDamage(BasePlayer player)
  2370. {
  2371. if (player == null)
  2372. return true;
  2373.  
  2374. if (manager.playerID == player.userID)
  2375. return false;
  2376.  
  2377. if (manager.building != null && manager.authorizedPlayers.Contains(player.userID))
  2378. return false;
  2379.  
  2380. return true;
  2381. }
  2382.  
  2383. internal bool ShouldIgnoreBuildingDamage(BaseCombatEntity entity)
  2384. {
  2385. if (entity == null)
  2386. return true;
  2387.  
  2388. BuildingPrivlidge Bprivilege = entity.GetBuildingPrivilege();
  2389. if (Bprivilege == null)
  2390. {
  2391. return false;
  2392. }
  2393. if (manager.building != null && manager.authorizedPlayers.Count > 0)
  2394. foreach (var userID in manager.authorizedPlayers.ToList())
  2395. if (Bprivilege.IsAuthed(userID) || entity.OwnerID == userID)
  2396. return false;
  2397. return true;
  2398. }
  2399. }
  2400. #endregion
  2401.  
  2402. #region Brain
  2403. public class NpcRaiderBrain : BaseAIBrain
  2404. {
  2405. private NpcRaider entityAI;
  2406. public float spawnAge { get; private set; }
  2407. NpcRaider humanNpc = null;
  2408.  
  2409. private void Awake()
  2410. {
  2411. entityAI = GetComponent<NpcRaider>();
  2412. spawnAge = Time.time;
  2413. }
  2414. public override void AddStates()
  2415. {
  2416. base.AddStates();
  2417. AddState(new IdleState(entityAI));
  2418. AddState(new CombatState(entityAI));
  2419. AddState(new BaseLauncherState(entityAI));
  2420. }
  2421.  
  2422. public override void InitializeAI()
  2423. {
  2424. humanNpc = GetBaseEntity().GetComponent<NpcRaider>();
  2425.  
  2426. UseAIDesign = false;
  2427.  
  2428. base.InitializeAI();
  2429.  
  2430. ThinkMode = AIThinkMode.Interval;
  2431. thinkRate = 0.25f;
  2432. PathFinder = new HumanPathFinder();
  2433. ((HumanPathFinder)PathFinder).Init(humanNpc);
  2434. }
  2435.  
  2436. public override void Think(float delta)
  2437. {
  2438. if (!ConVar.AI.think || states == null)
  2439. return;
  2440.  
  2441. this.ForceSetAge(this.Age + delta);
  2442. lastThinkTime = Time.time;
  2443.  
  2444. if (CurrentState != null)
  2445. CurrentState.StateThink(delta, this, humanNpc.currentTarget);
  2446.  
  2447. if (CurrentState == null || CurrentState.CanLeave())
  2448. {
  2449. float highest = 0f;
  2450. BasicAIState state = null;
  2451. AIState stateKey = new AIState();
  2452.  
  2453. foreach (var value in states)
  2454. {
  2455. if (value.Key == null || !value.Value.CanEnter())
  2456. continue;
  2457.  
  2458. float weight = value.Value.GetWeight();
  2459.  
  2460. if (weight <= highest)
  2461. continue;
  2462.  
  2463. highest = weight;
  2464. state = value.Value;
  2465. stateKey = value.Key;
  2466. }
  2467.  
  2468. if (state != CurrentState)
  2469. SwitchToState(stateKey, -1); //fix
  2470. }
  2471. }
  2472.  
  2473. public class IdleState : BasicAIState
  2474. {
  2475. private readonly NpcRaider entityAI;
  2476. private float nextStrafeTime;
  2477.  
  2478. public IdleState(NpcRaider entityAI) : base(AIState.Idle)
  2479. {
  2480. this.entityAI = entityAI;
  2481. }
  2482.  
  2483. public AIState GetState() => AIState.Idle;
  2484.  
  2485. public override float GetWeight()
  2486. {
  2487. if ((entityAI != null && entityAI.Brain.spawnAge < Time.time + 10) || (entityAI != null && !entityAI.HasTarget() && !entityAI.GoodLastTime() && entityAI.currentTargetOverride == null))
  2488. return 20f;
  2489.  
  2490. return 0f;
  2491. }
  2492.  
  2493. public override void StateEnter(BaseAIBrain brain, BaseEntity entity)
  2494. {
  2495. if (debug) _.PrintWarning("Enter idle state");
  2496. entityAI.SetPlayerFlag(BasePlayer.PlayerFlags.Relaxed, true);
  2497. base.StateEnter(brain, entity);
  2498. }
  2499.  
  2500. public override void StateLeave(BaseAIBrain brain, BaseEntity entity)
  2501. {
  2502. base.StateLeave(brain, entity);
  2503. }
  2504.  
  2505. public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity)
  2506. {
  2507. base.StateThink(delta, brain, entity);
  2508.  
  2509. if (entityAI == null || entityAI.IsDestroyed || entityAI.transform == null)
  2510. return StateStatus.Error;
  2511.  
  2512. if (Time.time > nextStrafeTime)
  2513. {
  2514. nextStrafeTime = Time.time + UnityEngine.Random.Range(5f, 8f);
  2515. if (entityAI != null)
  2516. {
  2517. Vector3 position = GetRandomPositionAround(entityAI.HomePosition, 1f, brain.Navigator.MaxRoamDistanceFromHome);
  2518. if (position != null && position is Vector3)
  2519. entityAI.SetDestination(position);
  2520. }
  2521. }
  2522.  
  2523.  
  2524. return StateStatus.Running;
  2525. }
  2526.  
  2527. public virtual Vector3 GetRandomPositionAround(Vector3 position, float minDistFrom = 0.0f, float maxDistFrom = 2f)
  2528. {
  2529. if ((double)maxDistFrom < 0.0)
  2530. maxDistFrom = 0.0f;
  2531. Vector2 vector2 = UnityEngine.Random.insideUnitCircle * maxDistFrom;
  2532. float x = Mathf.Clamp(Mathf.Max(Mathf.Abs(vector2.x), minDistFrom), minDistFrom, maxDistFrom) * Mathf.Sign(vector2.x);
  2533. float z = Mathf.Clamp(Mathf.Max(Mathf.Abs(vector2.y), minDistFrom), minDistFrom, maxDistFrom) * Mathf.Sign(vector2.y);
  2534. return position + new Vector3(x, 0.0f, z);
  2535. }
  2536. }
  2537.  
  2538. public class CombatState : BasicAIState
  2539. {
  2540. private readonly NpcRaider entityAI;
  2541. private IAIAttack attack;
  2542. private float nextStrafeTime;
  2543.  
  2544. public CombatState(NpcRaider entityAI) : base(AIState.Cooldown)
  2545. {
  2546. this.entityAI = entityAI;
  2547. }
  2548.  
  2549. public AIState GetState() => AIState.Cooldown;
  2550.  
  2551. public override float GetWeight()
  2552. {
  2553. if (entityAI.HasTarget())
  2554. return 30f;
  2555.  
  2556. return 0f;
  2557. }
  2558.  
  2559. public override void StateEnter(BaseAIBrain brain, BaseEntity entity)
  2560. {
  2561. if (debug) _.PrintWarning("Enter combat state");
  2562. entityAI.SetPlayerFlag(BasePlayer.PlayerFlags.Relaxed, false);
  2563. base.StateEnter(brain, entity);
  2564. this.attack = entityAI as IAIAttack;
  2565. if (!entityAI.HasTarget())
  2566. {
  2567. this.brain.Navigator.SetFacingDirectionOverride(GetAimDirection(this.brain.Navigator.transform.position, entityAI.lostPosition()));
  2568. }
  2569. else
  2570. {
  2571. this.brain.Navigator.SetFacingDirectionOverride(GetAimDirection(this.brain.Navigator.transform.position, entityAI.currentTarget.transform.position));
  2572. if (this.attack.CanAttack(entityAI.currentTarget))
  2573. this.StartAttacking(entityAI.currentTarget);
  2574.  
  2575. entityAI.SetDestination(entityAI.currentTarget.transform.position);
  2576.  
  2577. entityAI.SetPlayerFlag(BasePlayer.PlayerFlags.Relaxed, false);
  2578. if (entityAI.GetAttackEntity() is BaseProjectile)
  2579. this.brain.Navigator.StoppingDistance = 10f;
  2580. else this.brain.Navigator.StoppingDistance = 0.5f;
  2581.  
  2582. }
  2583. }
  2584.  
  2585.  
  2586. private void StopAttacking() => this.attack.StopAttacking();
  2587.  
  2588. public override void StateLeave(BaseAIBrain brain, BaseEntity entity)
  2589. {
  2590. base.StateLeave(brain, entity);
  2591. this.brain.Navigator.ClearFacingDirectionOverride();
  2592. this.brain.Navigator.Stop();
  2593. this.StopAttacking();
  2594. // entityAI.SetDucked(false);
  2595. }
  2596.  
  2597.  
  2598. public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity)
  2599. {
  2600. base.StateThink(delta, brain, entity);
  2601.  
  2602. if (this.attack == null) return StateStatus.Error;
  2603. if (!entityAI.HasTarget())
  2604. {
  2605. if (nextStrafeTime < Time.time)
  2606. {
  2607. this.brain.Navigator.ClearFacingDirectionOverride();
  2608. nextStrafeTime = Time.time + 5;
  2609. Vector3 position = GetRandomPositionAround(entityAI.lostPosition(), 1f, 10f);
  2610. if (position != null && position is Vector3)
  2611. {
  2612. this.brain.Navigator.SetDestination((Vector3)position, BaseNavigator.NavigationSpeed.Fast);
  2613. return StateStatus.Running;
  2614. }
  2615. }
  2616. return StateStatus.Running;
  2617. }
  2618. else if (entityAI.currentTarget != null)
  2619. {
  2620. if (entityAI == null || entityAI.IsDestroyed || entityAI.currentTarget == null || entityAI.currentTarget.IsDead() || entityAI.currentTarget.IsDestroyed)
  2621. return StateStatus.Error;
  2622.  
  2623.  
  2624. if (entityAI.currentTarget == null)
  2625. {
  2626. this.brain.Navigator.ClearFacingDirectionOverride();
  2627. this.StopAttacking();
  2628. return StateStatus.Finished;
  2629. }
  2630. if (this.brain.Senses.ignoreSafeZonePlayers)
  2631. {
  2632. BasePlayer basePlayer = entityAI.currentTarget as BasePlayer;
  2633. if ((UnityEngine.Object)basePlayer != (UnityEngine.Object)null && basePlayer.InSafeZone())
  2634. return StateStatus.Error;
  2635. }
  2636. if (entityAI.InEngagementRange())
  2637. entityAI.TickAttack(delta, entityAI.currentTarget, true);
  2638.  
  2639. if (!this.brain.Navigator.SetDestination(entityAI.currentTarget.transform.position, BaseNavigator.NavigationSpeed.Fast))
  2640. {
  2641. this.brain.Navigator.SetFacingDirectionOverride((entityAI.currentTarget.transform.position - entityAI.transform.position).normalized);
  2642. if (entityAI.InEngagementRange())
  2643. entityAI.TickAttack(delta, entityAI.currentTarget, true);
  2644. return StateStatus.Error;
  2645. }
  2646.  
  2647. this.brain.Navigator.SetFacingDirectionOverride((entityAI.currentTarget.transform.position - entityAI.transform.position).normalized);
  2648. if (this.attack.CanAttack(entityAI.currentTarget))
  2649. {
  2650. this.StartAttacking(entityAI.currentTarget);
  2651. if (entityAI.InEngagementRange())
  2652. entityAI.TickAttack(delta, entityAI.currentTarget, true);
  2653. }
  2654. else
  2655. this.StopAttacking();
  2656. }
  2657. return StateStatus.Running;
  2658. }
  2659.  
  2660. private Vector3 GetAimDirection(Vector3 from, Vector3 target) => Vector3Ex.Direction2D(target, from);
  2661.  
  2662. private void StartAttacking(BaseEntity entity) => this.attack.StartAttacking(entity);
  2663.  
  2664. public virtual Vector3 GetRandomPositionAround(Vector3 position, float minDistFrom = 0.0f, float maxDistFrom = 2f)
  2665. {
  2666. if ((double)maxDistFrom < 0.0)
  2667. maxDistFrom = 0.0f;
  2668. Vector2 vector2 = UnityEngine.Random.insideUnitCircle * maxDistFrom;
  2669. float x = Mathf.Clamp(Mathf.Max(Mathf.Abs(vector2.x), minDistFrom), minDistFrom, maxDistFrom) * Mathf.Sign(vector2.x);
  2670. float z = Mathf.Clamp(Mathf.Max(Mathf.Abs(vector2.y), minDistFrom), minDistFrom, maxDistFrom) * Mathf.Sign(vector2.y);
  2671. return position + new Vector3(x, TerrainMeta.HeightMap.GetHeight(position), z);
  2672. }
  2673. }
  2674.  
  2675. public class BaseLauncherState : BasicAIState
  2676. {
  2677. private readonly NpcRaider entityAI;
  2678. private float nextStrafeTime;
  2679. private float nextFireTime;
  2680. private Vector3 position;
  2681. private Vector3 position2;
  2682. private bool isFireing;
  2683. public BaseLauncherState(NpcRaider entityAI) : base(AIState.Attack)
  2684. {
  2685. this.entityAI = entityAI;
  2686. }
  2687.  
  2688. public AIState GetState() => AIState.Attack;
  2689.  
  2690. public override float GetWeight()
  2691. {
  2692. if (entityAI != null && !entityAI.HasTarget() && entityAI.currentTargetOverride != null)
  2693. return 25f;
  2694.  
  2695. return 0f;
  2696. }
  2697.  
  2698. public override void StateEnter(BaseAIBrain brain, BaseEntity entity)
  2699. {
  2700. if (debug) _.PrintWarning("Enter raid state");
  2701. position = entityAI.currentTargetOverride.transform.position;
  2702. position2 = Vector3.zero;
  2703. nextFireTime = Time.time + 0.5f;
  2704. isFireing = false;
  2705. entityAI.SetPlayerFlag(BasePlayer.PlayerFlags.Relaxed, false);
  2706. entityAI.EquipNewWeapon(6);
  2707. base.StateEnter(brain, entity);
  2708. }
  2709.  
  2710. public override void StateLeave(BaseAIBrain brain, BaseEntity entity)
  2711. {
  2712. this.brain.Navigator.ClearFacingDirectionOverride();
  2713. position = Vector3.zero;
  2714. if (entityAI._ProjectilesSlot != null && entityAI._ProjectilesSlot.Count > 0)
  2715. entityAI.EquipNewWeapon(entityAI._ProjectilesSlot.GetRandom());
  2716. else if (entityAI._MeleWeaponSlot != null && entityAI._MeleWeaponSlot.Count > 0)
  2717. entityAI.EquipNewWeapon(entityAI._MeleWeaponSlot.GetRandom());
  2718. base.StateLeave(brain, entity);
  2719. }
  2720.  
  2721. public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity)
  2722. {
  2723. base.StateThink(delta, brain, entity);
  2724.  
  2725. if (entityAI == null || entityAI.IsDestroyed || entityAI.transform == null || entityAI.HasTarget() || entityAI.currentTargetOverride == null || position == Vector3.zero)
  2726. return StateStatus.Error;
  2727. if (nextStrafeTime < Time.time)
  2728. {
  2729. entityAI.Brain.Navigator.SetNavMeshEnabled(true);
  2730. entityAI.Brain.Navigator.ClearFacingDirectionOverride();
  2731. if (entityAI != null)
  2732. {
  2733. Vector3 position = GetRandomPositionAround(entityAI.HomePosition, 1f, 20f);
  2734. if (position != null && position is Vector3)
  2735. entityAI.SetDestination(position);
  2736. }
  2737. nextStrafeTime = Time.time + UnityEngine.Random.Range(6f, 10f);
  2738. if (!isFireing && nextFireTime < Time.time && entityAI.Brain.spawnAge + 10 < Time.time)
  2739. {
  2740. isFireing = true;
  2741. nextFireTime = Time.time + UnityEngine.Random.Range(5f, 10f);
  2742. entityAI.Brain.Navigator.Stop();
  2743. entityAI.StartCoroutine(WeaponFireTest(position));
  2744. nextStrafeTime = Time.time + 1.2f;
  2745. isFireing = false;
  2746. }
  2747. }
  2748.  
  2749. return StateStatus.Running;
  2750. }
  2751.  
  2752. public IEnumerator WeaponFireTest(Vector3 locations, bool rocket = true)
  2753. {
  2754. entityAI.Brain.Navigator.SetFacingDirectionOverride((locations - entityAI.transform.position).normalized);
  2755. yield return CoroutineEx.waitForSeconds(0.1f);
  2756. if (entityAI == null || entityAI.IsDestroyed)
  2757. ServerMgr.Instance.StopCoroutine(WeaponFireTest(locations, rocket));
  2758. rocket = entityAI.TargetInThrowableRange();
  2759. if (rocket)
  2760. {
  2761. HeldEntity heldEntity = entityAI.inventory.containerBelt.GetSlot(6)?.GetHeldEntity() as HeldEntity;
  2762. entityAI.EquipNewWeapon(6);
  2763. entityAI.UpdateActiveItem(entityAI.inventory.containerBelt.GetSlot(6).uid);
  2764. entityAI.inventory.UpdatedVisibleHolsteredItems();
  2765. if (heldEntity != null && heldEntity is BaseLauncher)
  2766. {
  2767. entityAI.Brain.Navigator.SetFacingDirectionOverride((locations - entityAI.transform.position).normalized);
  2768. entityAI.SetAimDirection((locations - entityAI.transform.position).normalized);
  2769. yield return CoroutineEx.waitForSeconds(0.9f);
  2770. if (entityAI == null || entityAI.IsDestroyed)
  2771. ServerMgr.Instance.StopCoroutine(WeaponFireTest(locations, rocket));
  2772. fireRocket((heldEntity as BaseProjectile), locations);
  2773. }
  2774. yield return CoroutineEx.waitForSeconds(0.5f);
  2775. if (entityAI == null || entityAI.IsDestroyed)
  2776. ServerMgr.Instance.StopCoroutine(WeaponFireTest(locations, rocket));
  2777. if (entityAI._ProjectilesSlot.Count > 0)
  2778. entityAI.EquipNewWeapon(entityAI._ProjectilesSlot.GetRandom());
  2779. else if (entityAI._MeleWeaponSlot.Count > 0)
  2780. entityAI.EquipNewWeapon(entityAI._MeleWeaponSlot.GetRandom());
  2781. entityAI.Brain.Navigator.ClearFacingDirectionOverride();
  2782. ServerMgr.Instance.StopCoroutine(WeaponFireTest(locations, rocket));
  2783. }
  2784. else
  2785. {
  2786. Item itemC4 = ItemManager.CreateByName(entityAI.manager.config.explosive.GetRandom(), 1);
  2787. if (itemC4 != null)
  2788. {
  2789. itemC4.MoveToContainer(entityAI.inventory.containerBelt, 5);
  2790. ThrownWeapon _throwableWeapon = itemC4.GetHeldEntity() as ThrownWeapon;
  2791. entityAI.UpdateActiveItem(entityAI.inventory.containerBelt.GetSlot(5).uid);
  2792. if (_throwableWeapon != null)
  2793. {
  2794. _throwableWeapon.SetHeld(true);
  2795. entityAI.inventory.UpdatedVisibleHolsteredItems();
  2796. entityAI.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
  2797. yield return CoroutineEx.waitForSeconds(0.5f);
  2798. if (entityAI == null || entityAI.IsDestroyed)
  2799. {
  2800. itemC4?.Remove();
  2801. ServerMgr.Instance.StopCoroutine(WeaponFireTest(locations, rocket));
  2802. }
  2803. ServerThrow(locations, _throwableWeapon);
  2804.  
  2805. yield return CoroutineEx.waitForSeconds(0.5f);
  2806. }
  2807. }
  2808. if (entityAI == null || entityAI.IsDestroyed)
  2809. ServerMgr.Instance.StopCoroutine(WeaponFireTest(locations, rocket));
  2810. if (entityAI._ProjectilesSlot.Count > 0)
  2811. entityAI.EquipNewWeapon(entityAI._ProjectilesSlot.GetRandom());
  2812. else if (entityAI._MeleWeaponSlot.Count > 0)
  2813. entityAI.EquipNewWeapon(entityAI._MeleWeaponSlot.GetRandom());
  2814. entityAI.Brain.Navigator.ClearFacingDirectionOverride();
  2815. ServerMgr.Instance.StopCoroutine(WeaponFireTest(locations, rocket));
  2816. }
  2817.  
  2818. }
  2819.  
  2820. private void fireRocket(BaseProjectile _ProectileWeapon, Vector3 locations)
  2821. {
  2822. Vector3 vector3 = _ProectileWeapon.MuzzlePoint.transform.forward;
  2823. Vector3 position = _ProectileWeapon.MuzzlePoint.transform.position + (Vector3.up * 1.6f);
  2824. BaseEntity rocket = null;
  2825. rocket = GameManager.server.CreateEntity($"assets/prefabs/ammo/rocket/rocket_basic.prefab", position, entityAI.eyes.GetLookRotation());
  2826. if (rocket == null) return;
  2827. var proj = rocket.GetComponent<ServerProjectile>();
  2828. if (proj == null) return;
  2829. rocket.creatorEntity = entityAI;
  2830. if (entityAI != null)
  2831. rocket.OwnerID = entityAI.userID;
  2832. proj.InitializeVelocity(Quaternion.Euler(vector3) * rocket.transform.forward * 35f);
  2833. TimedExplosive rocketExplosion = rocket.GetComponent<TimedExplosive>();
  2834. rocketExplosion.timerAmountMin = _.configData.settings.RocketExplodeTime;
  2835. rocketExplosion.timerAmountMax = _.configData.settings.RocketExplodeTime;
  2836. if (entityAI.manager.config.DamageScale > 0)
  2837. rocket.SendMessage("SetDamageScale", (object)(float)((double)entityAI.manager.config.DamageScale));
  2838. rocket.Spawn();
  2839. }
  2840.  
  2841. public void ServerThrow(Vector3 targetPosition, ThrownWeapon wep)
  2842. {
  2843. if (wep == null) return;
  2844. Vector3 position = entityAI.eyes.position;
  2845. Vector3 vector3 = entityAI.eyes.BodyForward();
  2846. float num1 = 1f;
  2847. wep.SignalBroadcast(BaseEntity.Signal.Throw, string.Empty);
  2848. BaseEntity entity = GameManager.server.CreateEntity(wep.prefabToThrow.resourcePath, position, Quaternion.LookRotation(wep.overrideAngle == Vector3.zero ? -vector3 : wep.overrideAngle));
  2849. if ((UnityEngine.Object)entity == (UnityEngine.Object)null)
  2850. return;
  2851. entity.creatorEntity = (BaseEntity)entityAI;
  2852. if (entityAI != null)
  2853. entity.OwnerID = entityAI.userID;
  2854. Vector3 aimDir = vector3 + Quaternion.AngleAxis(10f, Vector3.right) * Vector3.up;
  2855. float f = 6f;
  2856. if (float.IsNaN(f))
  2857. {
  2858. aimDir = vector3 + Quaternion.AngleAxis(20f, Vector3.right) * Vector3.up;
  2859. f = 6f;
  2860. if (float.IsNaN(f))
  2861. f = 5f;
  2862. }
  2863. entity.SetVelocity(aimDir * f * num1);
  2864. if ((double)wep.tumbleVelocity > 0.0)
  2865. entity.SetAngularVelocity(new Vector3(UnityEngine.Random.Range(-1f, 1f), UnityEngine.Random.Range(-1f, 1f), UnityEngine.Random.Range(-1f, 1f)) * wep.tumbleVelocity);
  2866. DudTimedExplosive dud = entity.GetComponent<DudTimedExplosive>();
  2867. if (dud != null)
  2868. dud.dudChance = 0f;
  2869. entity.Spawn();
  2870. wep.StartAttackCooldown(wep.repeatDelay);
  2871. UseItemAmount(wep, 1);
  2872. }
  2873.  
  2874. private bool UseItemAmount(ThrownWeapon wep, int iAmount)
  2875. {
  2876. if (iAmount <= 0)
  2877. return true;
  2878. Item ownerItem = wep.GetItem();
  2879. if (ownerItem == null)
  2880. {
  2881. wep.DestroyThis();
  2882. return true;
  2883. }
  2884. ownerItem.amount -= iAmount;
  2885. ownerItem.MarkDirty();
  2886. if (ownerItem.amount > 0)
  2887. return false;
  2888. wep.DestroyThis();
  2889. return true;
  2890. }
  2891.  
  2892. public bool ReachedPosition(Vector3 position) => Vector2.Distance(position, this.entityAI.transform.position) <= 0.5f;
  2893.  
  2894. public virtual Vector3 GetRandomPositionAround(Vector3 position, float minDistFrom = 0.0f, float maxDistFrom = 2f)
  2895. {
  2896. if ((double)maxDistFrom < 0.0)
  2897. maxDistFrom = 0.0f;
  2898. Vector2 vector2 = UnityEngine.Random.insideUnitCircle * maxDistFrom;
  2899. float x = Mathf.Clamp(Mathf.Max(Mathf.Abs(vector2.x), minDistFrom), minDistFrom, maxDistFrom) * Mathf.Sign(vector2.x);
  2900. float z = Mathf.Clamp(Mathf.Max(Mathf.Abs(vector2.y), minDistFrom), minDistFrom, maxDistFrom) * Mathf.Sign(vector2.y);
  2901. return position + new Vector3(x, 0.0f, z);
  2902. }
  2903. }
  2904. }
  2905. #endregion
  2906.  
  2907. #region Helpers & Commands
  2908.  
  2909. private object IsEventTc(BuildingPrivlidge building)
  2910. {
  2911. if (building != null && EventRaidManager._AllRaids.Count > 0)
  2912. {
  2913. foreach (EventRaidManager e in EventRaidManager._AllRaids)
  2914. {
  2915. if (e.building != null && e.building == building)
  2916. return true;
  2917. }
  2918. }
  2919.  
  2920. return null;
  2921. }
  2922.  
  2923. private void ConsolStartRaid(ConsoleSystem.Arg args)
  2924. {
  2925. BasePlayer player;
  2926. if (args == null || args.Args == null || args.Args.Length == 1 || !args.IsServerside)
  2927. {
  2928. SendReply(args, "Usage: npcraiders buy <type> <optional playerID>");
  2929. return;
  2930. }
  2931.  
  2932. player = args.Player();
  2933. string type = args.Args[1];
  2934.  
  2935. if (player == null && args.Args.Length == 3)
  2936. {
  2937. var ids = default(ulong);
  2938. if (ulong.TryParse(args.Args[2], out ids))
  2939. player = BasePlayer.FindByID(ids);
  2940. }
  2941.  
  2942. if (player != null && args.Args[0].ToLower() == "buy" && !string.IsNullOrEmpty(type))
  2943. {
  2944. cmdChatStartRaidBuy(player, type);
  2945. }
  2946. else SendReply(args, "Usage: npcraiders buy <type> <optional playerID>");
  2947.  
  2948. }
  2949.  
  2950. public static void removeCorpse(NPCPlayerCorpse npcPlayerCorpse)
  2951. {
  2952. _.timer.Once(4f, () => { if (npcPlayerCorpse != null && !npcPlayerCorpse.IsDestroyed && npcPlayerCorpse.CanRemove()) npcPlayerCorpse.Kill(); });
  2953. }
  2954.  
  2955. public static void DropBags(NPCPlayerCorpse npcPlayerCorpse)
  2956. {
  2957. _.timer.Once(2f, () =>
  2958. {
  2959. if (npcPlayerCorpse != null && !npcPlayerCorpse.IsDestroyed && npcPlayerCorpse.CanRemove())
  2960. npcPlayerCorpse?.ResetRemovalTime(8f);
  2961. });
  2962. }
  2963.  
  2964. private void OnCupboardAuthorize(BuildingPrivlidge privilege, BasePlayer player)
  2965. {
  2966. double timeStamp = GrabCurrentTime();
  2967. if (!pcdData.pEntity.ContainsKey(player.userID))
  2968. pcdData.pEntity.Add(player.userID, new PCDInfo());
  2969. if (!pcdData.pEntity[player.userID].tcCooldown.ContainsKey(privilege.net.ID.Value))
  2970. pcdData.pEntity[player.userID].tcCooldown.Add(privilege.net.ID.Value, 0);
  2971. long coolTime = (long)timeStamp + configData.settings.TcAuthCooldown;
  2972. if (configData.raidVipOptions != null && configData.raidVipOptions.VipOptions.Count > 0)
  2973. {
  2974. foreach (var perm in configData.raidVipOptions.VipOptions)
  2975. if (permission.UserHasPermission(player.UserIDString, perm.Key))
  2976. coolTime = (long)timeStamp + perm.Value.TcAuthCooldown;
  2977. }
  2978. pcdData.pEntity[player.userID].tcCooldown[privilege.net.ID.Value] = coolTime;
  2979. SaveData();
  2980. }
  2981.  
  2982. private bool isBlockedTerain(Vector3 position)
  2983. {
  2984. Vector3 p1 = position + new Vector3(0, 200f, 0);
  2985. Vector3 p2 = position + new Vector3(0, -200f, 0);
  2986. Vector3 diff = p2 - p1;
  2987. RaycastHit[] hits;
  2988. hits = Physics.RaycastAll(p1, diff, diff.magnitude, terainLayer);
  2989. if (hits.Length > 0)
  2990. {
  2991. for (int j = 0; j < hits.Length; j++)
  2992. {
  2993. RaycastHit hit = hits[j];
  2994. if (hit.collider != null)
  2995. {
  2996. for (int i = configData.blockedColliders.Blocked.Count - 1; i >= 0; i--)
  2997. {
  2998. string g = configData.blockedColliders.Blocked[i];
  2999. if (hit.collider != null && hit.collider.name.Contains(g) || (hit.collider != null && hit.collider.name.Contains("BQV4")))
  3000. return true;
  3001. }
  3002. }
  3003. }
  3004. }
  3005. return false;
  3006. }
  3007.  
  3008. private string FormatTime(long seconds)
  3009. {
  3010. var timespan = TimeSpan.FromSeconds(seconds);
  3011. return string.Format(timespan.TotalHours >= 1 ? "{2:00}:{0:00}:{1:00}" : "{0:00}:{1:00}", timespan.Minutes, timespan.Seconds, System.Math.Floor(timespan.TotalHours));
  3012. }
  3013.  
  3014. private void cmdChatRaidClearDatsa(BasePlayer player)
  3015. {
  3016. if (permission.UserHasPermission(player.UserIDString, adminPerm))
  3017. {
  3018. PrintWarning($"{player.displayName} is resetting all player data & cooldowns");
  3019. pcdData = new PlayerEntity();
  3020. SendReply(player, "Resetting all player data & cooldowns");
  3021. return;
  3022. }
  3023. else return;
  3024. }
  3025.  
  3026. private void cmdChatRaidReload(BasePlayer player, string command, string[] args)
  3027. {
  3028. if (!permission.UserHasPermission(player.UserIDString, adminPerm))
  3029. {
  3030. SendReply(player, lang.GetMessage("noPermUse", this, player.UserIDString));
  3031. return;
  3032. }
  3033.  
  3034. switch (args[1].ToLower())
  3035. {
  3036. case "all":
  3037. foreach (var eventRunning in EventRaidManager._AllRaids)
  3038. eventRunning.Destroy();
  3039.  
  3040. EventRaidManager._AllRaids.Clear();
  3041. SendReply(player, "Killing events. All events have been cancelled.");
  3042. return;
  3043.  
  3044. case "player":
  3045. if (args.Length < 3)
  3046. {
  3047. SendReply(player, lang.GetMessage("UsageAdmin", this, player.UserIDString));
  3048. return;
  3049. }
  3050. else if (args.Length >= 3)
  3051. {
  3052. List<BasePlayer> players = FindPlayers(args[1], true);
  3053. if (players.Count <= 0)
  3054. {
  3055. SendReply(player, lang.GetMessage("PlayerNotFound", this, player.UserIDString));
  3056. return;
  3057. }
  3058. if (players.Count > 1)
  3059. {
  3060. SendReply(player, lang.GetMessage("MultiplePlayers", this, player.UserIDString), GetMultiplePlayers(players));
  3061. return;
  3062. }
  3063. if (players.Count == 1)
  3064. {
  3065. if (EventList.ContainsKey(players[0]))
  3066. {
  3067. SendReply(players[0], lang.GetMessage("EventCanceledByAdmin", this, players[0].UserIDString));
  3068. SendReply(player, lang.GetMessage("destroyEvent", this, player.UserIDString), players[0].displayName);
  3069. return;
  3070. }
  3071. foreach (var eventRunning in EventRaidManager._AllRaids)
  3072. {
  3073. if (eventRunning.player == players[0])
  3074. {
  3075. eventRunning.Destroy();
  3076. SendReply(player, lang.GetMessage("destroyEvent", this, player.UserIDString), players[0].displayName);
  3077. SendReply(players[0], lang.GetMessage("EventCanceledByAdmin", this, players[0].UserIDString));
  3078. return;
  3079. }
  3080. }
  3081. SendReply(player, lang.GetMessage("destroyEventNotFound", this, player.UserIDString), players[0].displayName);
  3082. }
  3083. }
  3084. return;
  3085. default:
  3086. break;
  3087. }
  3088. }
  3089.  
  3090. private void cmdChatStartRaid(BasePlayer player, string command, string[] args)
  3091. {
  3092. // UnityEngine.Application.OpenURL("http://google.com");
  3093. if (!permission.UserHasPermission(player.UserIDString, usePerm))
  3094. {
  3095. SendReply(player, lang.GetMessage("noPermUse", this, player.UserIDString));
  3096. return;
  3097. }
  3098. int permCount = 0;
  3099. string type = "unknown";
  3100. string types = "";
  3101. string level = "";
  3102. int count = 0;
  3103. int NPCs;
  3104. object reward;
  3105. int waves;
  3106. int cooldownTime = configData.settings.cooldownSeconds;
  3107.  
  3108. if (args.Length >= 1)
  3109. {
  3110. switch (args[0].ToLower())
  3111. {
  3112. case "stats":
  3113. UIStatsMainWindow(player);
  3114. return;
  3115.  
  3116. case "buy":
  3117. if (args.Length < 2)
  3118. cmdChatStartRaidBuy(player, null);
  3119. else
  3120. cmdChatStartRaidBuy(player, args[1]);
  3121. return;
  3122.  
  3123. case "clear":
  3124. cmdChatRaidClearDatsa(player);
  3125. return;
  3126.  
  3127. case "terrain":
  3128. string names = "Found Coliders In the Scan Up 200 down 200 Are:\n";
  3129. Vector3 p1 = player.transform.position + new Vector3(0, 200f, 0);
  3130. Vector3 p2 = player.transform.position + new Vector3(0, -200f, 0);
  3131. Vector3 diff = p2 - p1;
  3132. RaycastHit[] hits;
  3133. hits = Physics.RaycastAll(p1, diff, diff.magnitude);
  3134. if (hits.Length > 0)
  3135. {
  3136. for (int i = 0; i < hits.Length; i++)
  3137. {
  3138. RaycastHit hit = hits[i];
  3139. if (hit.collider != null)
  3140. names += $"{hit.collider.name},\n";
  3141. }
  3142. SendReply(player, $"{names}");
  3143. }
  3144. else
  3145. {
  3146. names += $"No Detected Coliders,\n";
  3147. SendReply(player, $"{names}");
  3148. }
  3149. return;
  3150.  
  3151. case "reload":
  3152. if (args.Length < 2)
  3153. {
  3154. SendReply(player, $"<color=orange>Admin Command Usage</color>:\n" +
  3155. $"<color=orange>/{chatComand} reload all</color> - Will cancel all events.\n" +
  3156. $"<color=orange>/{chatComand} reload player <player></color> - Will cancel their raid event.");
  3157. return;
  3158. }
  3159.  
  3160. switch (args[1].ToLower())
  3161. {
  3162. case "all":
  3163. cmdChatRaidReload(player, command, args);
  3164. return;
  3165.  
  3166. case "player":
  3167. cmdChatRaidReload(player, command, args);
  3168. return;
  3169.  
  3170. default:
  3171. break;
  3172. }
  3173. return;
  3174.  
  3175. case "loot":
  3176. if (!permission.UserHasPermission(player.UserIDString, adminPerm))
  3177. {
  3178. SendReply(player, lang.GetMessage("noPermUse", this, player.UserIDString));
  3179. return;
  3180. }
  3181. if (args.Length < 3)
  3182. {
  3183. SendReply(player, $"<color=orange>Admin Command Usage</color>:\n" +
  3184. $"<color=orange>/{chatComand} loot add <name></color> - Will add all inventory to loot file.\n" +
  3185. $"<color=orange>/{chatComand} loot remove <name> <player></color> - Will remove loot file.");
  3186. return;
  3187. }
  3188.  
  3189. switch (args[1].ToLower())
  3190. {
  3191. case "add":
  3192. cmdChatLoot(player, args[2].ToLower());
  3193. return;
  3194.  
  3195. case "clear":
  3196. cmdChatLoot(player, args[2].ToLower(), true);
  3197. return;
  3198.  
  3199. default:
  3200. break;
  3201. }
  3202. return;
  3203.  
  3204. default:
  3205. break;
  3206. }
  3207. }
  3208.  
  3209. foreach (var key in configData.raidSettings.raidTypes)
  3210. {
  3211. string rewards = "";
  3212. if (permission.UserHasPermission(player.UserIDString, configData.raidSettings.raidTypes[key.Key].Permission))
  3213. {
  3214. permCount++;
  3215. waves = configData.raidSettings.raidTypes[key.Key].TotalNpcWaves + 1;
  3216. NPCs = configData.raidSettings.raidTypes[key.Key].TotalNpcs;
  3217.  
  3218. if (configData.raidRewardOptions.RewardOptions.ContainsKey(key.Key))
  3219. {
  3220. if (configData.raidRewardOptions.RewardOptions[key.Key].enabled)
  3221. {
  3222. reward = configData.raidRewardOptions.RewardOptions[key.Key].RewardAmmount;
  3223. string typesRew = configData.raidRewardOptions.RewardOptions[key.Key].RewardType.ToLower();
  3224. if (typesRew == "serverrewards" || typesRew == "economics")
  3225. rewards = ", " + lang.GetMessage("Reward", this, player.UserIDString) + $"{Convert.ToInt32(reward)}</color>";
  3226. else if (typesRew == "kit" || typesRew == "kits")
  3227. {
  3228. if (reward is string)
  3229. {
  3230. rewards = $", {lang.GetMessage("RewardMessage", this)} <color=orange>{Convert.ToString(reward)}</color>";
  3231. }
  3232. else
  3233. {
  3234. rewards = $", {lang.GetMessage("RewardMessage", this)} <color=orange>{lang.GetMessage("Randomkit", this)}</color>";
  3235. }
  3236. }
  3237. else
  3238. {
  3239. var ids = default(int);
  3240. if (int.TryParse(configData.raidRewardOptions.RewardOptions[key.Key].RewardType, out ids))
  3241. {
  3242. ItemDefinition def = ItemManager.FindItemDefinition(ids);
  3243. if (def != null)
  3244. {
  3245. string rName = def.displayName.english;
  3246. if (rName.Length > 12)
  3247. rName = rName.Substring(0, rName.Length - (rName.Length - 12));
  3248. rewards = $", {lang.GetMessage("RewardMessage", this)} <color=orange>{rName}</color>";
  3249. }
  3250. }
  3251. }
  3252. }
  3253.  
  3254. }
  3255. if (permCount == 1)
  3256. types += ($"<color=yellow>{key.Key}</color>");
  3257. else types += ($" | <color=yellow>{key.Key}</color> ");
  3258.  
  3259. if (rewards != "")
  3260. level += $"<color=green>{lang.GetMessage("Mode", this)}</color>: <color=yellow>{key.Key}</color> - {lang.GetMessage("NPCs", this)} <color=orange>{NPCs}</color>, {lang.GetMessage("Waves", this)} <color=orange>{waves}</color>{rewards}\n";
  3261. else level += $"<color=green>{lang.GetMessage("Mode", this)}</color>: <color=yellow>{key.Key}</color> - {lang.GetMessage("NPCs", this)} <color=orange>{NPCs}</color>, {lang.GetMessage("Waves", this)} <color=orange>{waves}</color>\n";
  3262. }
  3263. }
  3264.  
  3265. if (permCount > 0)
  3266. {
  3267. SendReply(player, lang.GetMessage("ChatHeader", this, player.UserIDString) + $"\n" +
  3268. $"<color=orange>/{chatComand} {lang.GetMessage("Buy", this)}</color> {lang.GetMessage("buyMsg", this)}\n" +
  3269. $"<color=orange>/{chatComand} {lang.GetMessage("Buy", this)} {types}</color> {lang.GetMessage("buyMsg1", this)}\n\n" +
  3270. $"{level}");
  3271. }
  3272. else
  3273. {
  3274. SendReply(player, lang.GetMessage("ChatHeader", this, player.UserIDString) + $"\n" +
  3275. $"<color=orange>/{chatComand} {lang.GetMessage("Buy", this)}</color> {lang.GetMessage("buyMsg", this)}\n" +
  3276. $"<color=orange>/{chatComand} {lang.GetMessage("Buy", this)} {types}</color> {lang.GetMessage("buyMsg1", this)}\n\n" +
  3277. $"{lang.GetMessage("buyMsg2", this)}");
  3278. }
  3279. if (permission.UserHasPermission(player.UserIDString, adminPerm))
  3280. SendReply(player, $"<color=red>Admin Commands</color>:\n" +
  3281. $"<color=orange>/{chatComand} reload all</color> - Will cancel all events.\n" +
  3282. $"<color=orange>/{chatComand} reload player <player></color> - Will cancel their raid event.\n" +
  3283. $"<color=orange>/{chatComand} clear</color> - Reset all player data and cooldowns.");
  3284. return;
  3285. }
  3286.  
  3287. private void cmdChatLoot(BasePlayer player, string lootfile, bool remove = false)
  3288. {
  3289. if (remove)
  3290. {
  3291. if (HasSaveFile(lootfile))
  3292. {
  3293. LootEntity newFile = new LootEntity();
  3294. if (newFile != null)
  3295. {
  3296. SaveLootData(newFile, Name + "/LootProfiles/" + lootfile);
  3297. SendReply(player, lang.GetMessage("lootFileCleared", this, player.UserIDString));
  3298. }
  3299. }
  3300. else SendReply(player, lang.GetMessage("lootFileNotExists", this, player.UserIDString));
  3301.  
  3302. }
  3303. else
  3304. {
  3305. if (!HasSaveFile(lootfile))
  3306. {
  3307. LootEntity newFile = new LootEntity();
  3308. newFile.items = new List<itemInfo>();
  3309.  
  3310. if (player.inventory.containerMain != null)
  3311. foreach (Item itemUse in player.inventory.containerMain.itemList.ToList())
  3312. {
  3313. if (itemUse != null)
  3314. newFile.items.Add(new itemInfo() { item = itemUse.info.shortname, location = "containerMain", amountMax = itemUse.amount, amountMin = 1, skin = itemUse.skin, name = itemUse.name });
  3315. }
  3316. if (player.inventory.containerBelt != null)
  3317. foreach (Item itemUse in player.inventory.containerBelt.itemList.ToList())
  3318. {
  3319. if (itemUse != null)
  3320. newFile.items.Add(new itemInfo() { item = itemUse.info.shortname, location = "containerBelt", amountMax = itemUse.amount, amountMin = 1, skin = itemUse.skin, name = itemUse.name });
  3321. }
  3322. if (player.inventory.containerWear != null)
  3323. foreach (Item itemUse in player.inventory.containerWear.itemList.ToList())
  3324. {
  3325. if (itemUse != null)
  3326. newFile.items.Add(new itemInfo() { item = itemUse.info.shortname, location = "containerWear", amountMax = itemUse.amount, amountMin = 1, skin = itemUse.skin, name = itemUse.name });
  3327. }
  3328. // SaveLootData();
  3329. SaveLootData(newFile, Name + "/LootProfiles/" + lootfile);
  3330. SendReply(player, lang.GetMessage("lootFileAdded", this, player.UserIDString));
  3331.  
  3332. }
  3333. else if (HasSaveFile(lootfile))
  3334. {
  3335. LootEntity newFile = null;
  3336. LoadLootData(out newFile, Name + "/LootProfiles/" + lootfile);
  3337. if (newFile != null)
  3338. {
  3339. if (player.inventory.containerMain != null)
  3340. foreach (Item itemUse in player.inventory.containerMain.itemList.ToList())
  3341. {
  3342. if (itemUse != null)
  3343. newFile.items.Add(new itemInfo() { item = itemUse.info.shortname, location = "containerMain", amountMax = itemUse.amount, amountMin = 1, skin = itemUse.skin, name = itemUse.name });
  3344. }
  3345. if (player.inventory.containerBelt != null)
  3346. foreach (Item itemUse in player.inventory.containerBelt.itemList.ToList())
  3347. {
  3348. if (itemUse != null)
  3349. newFile.items.Add(new itemInfo() { item = itemUse.info.shortname, location = "containerBelt", amountMax = itemUse.amount, amountMin = 1, skin = itemUse.skin, name = itemUse.name });
  3350. }
  3351. if (player.inventory.containerWear != null)
  3352. foreach (Item itemUse in player.inventory.containerWear.itemList.ToList())
  3353. {
  3354. if (itemUse != null)
  3355. newFile.items.Add(new itemInfo() { item = itemUse.info.shortname, location = "containerWear", amountMax = itemUse.amount, amountMin = 1, skin = itemUse.skin, name = itemUse.name });
  3356. }
  3357. // SaveLootData();
  3358. SaveLootData(newFile, Name + "/LootProfiles/" + lootfile);
  3359. SendReply(player, lang.GetMessage("LootFileAddMore", this, player.UserIDString));
  3360. }
  3361.  
  3362. }
  3363. }
  3364. }
  3365.  
  3366. private void cmdChatStartRaidBuy(BasePlayer player, string command, string cooldowntime = "1746912412")
  3367. {
  3368. string type = "unknown";
  3369. if (command != null)
  3370. type = command.ToLower();
  3371.  
  3372. string types = "";
  3373. string typesTotal = "";
  3374. int count = 0;
  3375. int cooldownTime = configData.settings.cooldownSeconds;
  3376. string buyname = "";
  3377.  
  3378. if (command == null)
  3379. {
  3380. foreach (var key in configData.raidBuyOptions.BuyOptions)
  3381. {
  3382. count++;
  3383. if (configData.raidSettings.raidTypes.ContainsKey(key.Key) && permission.UserHasPermission(player.UserIDString, configData.raidSettings.raidTypes[key.Key].Permission))
  3384. {
  3385. if (count <= 1)
  3386. types += ($"<color=yellow>{key.Key}</color> ");
  3387. else types += ($"| <color=yellow>{key.Key}</color> ");
  3388.  
  3389. var ids = default(int);
  3390. if (int.TryParse(key.Value.BuyType, out ids))
  3391. {
  3392. ItemDefinition def = ItemManager.FindItemDefinition(ids);
  3393. if (def != null)
  3394. buyname = def.displayName.english;
  3395. }
  3396. else buyname = key.Value.BuyType.ToString();
  3397.  
  3398. if (buyname == "serverrewards" || buyname == "economics")
  3399. buyname = "$";
  3400.  
  3401. if (buyname == "$")
  3402. typesTotal += ($"\n<color=green>{lang.GetMessage("RaidType", this)}</color>: <color=yellow>{key.Key}</color> - {lang.GetMessage("Cost", this)} <color=green>{buyname}</color><color=yellow>{key.Value.BuyAmmount}</color>");
  3403. else
  3404. typesTotal += ($"\n<color=green>{lang.GetMessage("RaidType", this)}</color>: <color=yellow>{key.Key}</color> - {lang.GetMessage("Cost", this)} <color=yellow>{key.Value.BuyAmmount}</color> <color=green>{buyname}</color>");
  3405. }
  3406. }
  3407. if (command == null && types.Length > 0)
  3408. {
  3409. SendReply(player, lang.GetMessage("ChatHeader", this, player.UserIDString) + $"\n" +
  3410. $"<color=orange>/{chatComand} {lang.GetMessage("Buy", this)} {types} </color>{lang.GetMessage("buyMsg1", this)} \n{typesTotal}");
  3411. return;
  3412. }
  3413. else if (types.Length <= 0)
  3414. {
  3415. SendReply(player, lang.GetMessage("ChatHeader", this, player.UserIDString) + $"\n" +
  3416. $"<color=orange>{lang.GetMessage("Nothing", this)}</color>");
  3417. return;
  3418. }
  3419. }
  3420. else
  3421. {
  3422. if (canBuyRaid(player, type))
  3423. {
  3424. Vector3 pos = player.transform.position;
  3425. float y = TerrainMeta.HeightMap.GetHeight(new Vector3(player.transform.position.x, 0, player.transform.position.z)) + 2f;
  3426. if (y != null)
  3427. {
  3428. pos.y = y;
  3429. }
  3430.  
  3431. if (EventRaidManager._AllRaids.Count >= configData.settings.MaxRaids)
  3432. {
  3433. int totalH = configData.settings.MaxRaids - EventRaidManager._AllRaids.Count;
  3434. if (totalH <= 0)
  3435. SendReply(player, lang.GetMessage("waitingNext", this, player.UserIDString), EventRaidManager._AllRaids.Count);
  3436. else
  3437. SendReply(player, lang.GetMessage("waitingLine", this, player.UserIDString), EventRaidManager._AllRaids.Count, EventList.Count);
  3438. }
  3439. else
  3440. SendReply(player, lang.GetMessage("waiting", this, player.UserIDString));
  3441.  
  3442. BuildingPrivlidge priv = player.GetBuildingPrivilege();
  3443. EventList.Add(player, new eventList() { type = type, location = pos, priv = priv });
  3444. if (configData.raidVipOptions != null && configData.raidVipOptions.VipOptions.Count > 0)
  3445. {
  3446. foreach (var perm in configData.raidVipOptions.VipOptions)
  3447. if (permission.UserHasPermission(player.UserIDString, perm.Key))
  3448. cooldownTime = perm.Value.cooldownSeconds;
  3449. }
  3450. hasCooldown(player, player.userID, cooldownTime);
  3451. foreach (var user in priv.authorizedPlayers.ToList())
  3452. {
  3453. if (user.userid == player.userID)
  3454. continue;
  3455. if (configData.raidVipOptions != null && configData.raidVipOptions.VipOptions.Count > 0)
  3456. {
  3457. foreach (var perm in configData.raidVipOptions.VipOptions)
  3458. if (permission.UserHasPermission(user.userid.ToString(), perm.Key))
  3459. cooldownTime = perm.Value.cooldownSeconds;
  3460. }
  3461. BasePlayer TCplayer = BasePlayer.FindByID(user.userid);
  3462. hasCooldown(TCplayer, player.userID, cooldownTime, true);
  3463. }
  3464. if (configData.settings.logToFile)
  3465. LogToFile("NpcRaiders", $"[{DateTime.Now}] {player.displayName}({player.userID}) is calling raid {type} at {pos}", this);
  3466. }
  3467. }
  3468. }
  3469.  
  3470. private bool canBuyRaid(BasePlayer player, string type)
  3471. {
  3472. double timeStamp = GrabCurrentTime();
  3473. ItemDefinition def = null;
  3474.  
  3475. if (!configData.raidBuyOptions.BuyOptions.ContainsKey(type) || !configData.raidSettings.raidTypes.ContainsKey(type))
  3476. return false;
  3477.  
  3478. BuildingPrivlidge privCheck = player.GetBuildingPrivilege();
  3479. if (privCheck != null && isBlockedTerain(privCheck.transform.position))
  3480. {
  3481. SendReply(player, lang.GetMessage("Blockedhere", this, player.UserIDString));
  3482. return false;
  3483. }
  3484.  
  3485. if (privCheck != null && privCheck.transform.position.y <= -0.1f)
  3486. {
  3487. SendReply(player, lang.GetMessage("BlockedhereWater", this, player.UserIDString));
  3488. return false;
  3489. }
  3490.  
  3491. if (privCheck != null)
  3492. {
  3493. Vector3 checkLocation = privCheck.transform.position;
  3494. checkLocation.y = TerrainMeta.HeightMap.GetHeight(checkLocation);
  3495. float waterLevel = WaterLevel.GetWaterDepth(checkLocation, true, false);
  3496. if (waterLevel > 0.44f)
  3497. {
  3498. SendReply(player, lang.GetMessage("BlockedhereWaterDeep", this, player.UserIDString));
  3499. return false;
  3500. }
  3501. }
  3502.  
  3503. if (EventList.ContainsKey(player))
  3504. {
  3505. SendReply(player, lang.GetMessage("ThereAlready", this, player.UserIDString));
  3506. return false;
  3507. }
  3508.  
  3509. if (player.IsBuildingBlocked() || !player.IsBuildingAuthed())
  3510. {
  3511. SendReply(player, lang.GetMessage("blocked", this, player.UserIDString));
  3512. return false;
  3513. }
  3514.  
  3515. if (pcdData.pEntity.ContainsKey(player.userID) && !permission.UserHasPermission(player.UserIDString, coolPerm))
  3516. {
  3517. if (pcdData.pEntity.ContainsKey(player.userID))
  3518. {
  3519. BuildingPrivlidge priv = player.GetBuildingPrivilege();
  3520. if (priv != null)
  3521. {
  3522. if (pcdData.pEntity[player.userID].tcCooldown.ContainsKey(priv.net.ID.Value))
  3523. {
  3524. var cdTime = pcdData.pEntity[player.userID].tcCooldown[priv.net.ID.Value];
  3525. if (cdTime > timeStamp)
  3526. {
  3527. string time = FormatTime((long)(cdTime - timeStamp));
  3528. SendReply(player, lang.GetMessage("cooldownAuth", this, player.UserIDString), time);
  3529. return false;
  3530. }
  3531. }
  3532. }
  3533. }
  3534. }
  3535.  
  3536. string buyType = configData.raidBuyOptions.BuyOptions[type].BuyType;
  3537.  
  3538. if (pcdData.pEntity.ContainsKey(player.userID) && !permission.UserHasPermission(player.UserIDString, coolPerm))
  3539. {
  3540. var cdTime = pcdData.pEntity[player.userID].cooldown;
  3541. if (cdTime > timeStamp)
  3542. {
  3543. string timeNow1 = FormatTime((long)(cdTime - timeStamp));
  3544. SendReply(player, lang.GetMessage("cooldown", this, player.UserIDString), timeNow1);
  3545. return false;
  3546. }
  3547. }
  3548.  
  3549. if (!permission.UserHasPermission(player.UserIDString, configData.raidSettings.raidTypes[type].Permission))
  3550. {
  3551. SendReply(player, lang.GetMessage("noPerm", this, player.UserIDString));
  3552. return false;
  3553. }
  3554.  
  3555. if (!permission.UserHasPermission(player.UserIDString, bypassCost))
  3556. {
  3557. var ids = default(int);
  3558. if (int.TryParse(buyType, out ids))
  3559. {
  3560. def = ItemManager.FindItemDefinition(ids);
  3561. }
  3562. if (def != null)
  3563. {
  3564. int ammount = Convert.ToInt32(configData.raidBuyOptions.BuyOptions[type].BuyAmmount);
  3565. if (player.inventory.GetAmount(ids) < ammount)
  3566. {
  3567. SendReply(player, lang.GetMessage("noMoney", this, player.UserIDString), ammount, def.displayName.english);
  3568. return false;
  3569. }
  3570. player.inventory.Take(null, ids, ammount);
  3571. return true;
  3572. }
  3573. else if (def == null)
  3574. {
  3575. object totals = configData.raidBuyOptions.BuyOptions[type].BuyAmmount;
  3576. if (buyType.ToLower() == "serverrewards")
  3577. {
  3578. int totalHave = (int)ServerRewards.Call("CheckPoints", player.userID.Get());
  3579. if (totalHave < Convert.ToInt32(totals))
  3580. {
  3581. SendReply(player, lang.GetMessage("noMoney", this, player.UserIDString), totals, "Reward Points");
  3582. return false;
  3583. }
  3584. ServerRewards.Call("TakePoints", player.userID.Get(), Convert.ToInt32(totals));
  3585. return true;
  3586. }
  3587. else if (buyType.ToLower() == "economics")
  3588. {
  3589. double totalHave = (double)Economics.Call("Balance", player.userID.Get());
  3590. if (totalHave < Convert.ToDouble(totals))
  3591. {
  3592. SendReply(player, lang.GetMessage("noMoney", this, player.UserIDString), totals, "Eco Points");
  3593. return false;
  3594. }
  3595. Economics.Call("Withdraw", player.userID.Get(), Convert.ToDouble(totals));
  3596. return true;
  3597. }
  3598. }
  3599. }
  3600. else return true;
  3601.  
  3602. return false;
  3603. }
  3604. private bool hasCooldown(BasePlayer player, ulong userID, int time, bool notify = false)
  3605. {
  3606. double timeStamp = GrabCurrentTime();
  3607. if (!pcdData.pEntity.ContainsKey(userID))
  3608. pcdData.pEntity.Add(userID, new PCDInfo());
  3609.  
  3610. if (!notify)
  3611. {
  3612. if (pcdData.pEntity.ContainsKey(userID) && !permission.UserHasPermission(userID.ToString(), coolPerm)) // Check if the player already has a cooldown for this
  3613. {
  3614. pcdData.pEntity[userID].cooldown = (long)timeStamp + time;
  3615. SaveData();
  3616. }
  3617.  
  3618. }
  3619. else if (!permission.UserHasPermission(userID.ToString(), coolPerm))
  3620. {
  3621. pcdData.pEntity[userID].cooldown = (long)timeStamp + time;
  3622. SaveData();
  3623. if (player != null)
  3624. SendReply(player, lang.GetMessage("InEvent", this, player.UserIDString));
  3625. }
  3626. return false;
  3627. }
  3628.  
  3629. private static void StripInventory(BasePlayer player, bool skipWear = false)
  3630. {
  3631. List<Item> list = Pool.GetList<Item>();
  3632. player.inventory.GetAllItems(list);
  3633.  
  3634. for (int i = list.Count - 1; i >= 0; i--)
  3635. {
  3636. Item item = list[i];
  3637.  
  3638. if (skipWear && item?.parent == player.inventory.containerWear)
  3639. continue;
  3640.  
  3641. item.RemoveFromContainer();
  3642. item.Remove();
  3643. }
  3644.  
  3645. Pool.FreeList(ref list);
  3646. }
  3647.  
  3648. private static void StripCorpsInventory(NPCPlayerCorpse player)
  3649. {
  3650. foreach (var cont in player.containers)
  3651. {
  3652. cont?.Clear();
  3653. ItemManager.DoRemoves();
  3654. }
  3655. }
  3656.  
  3657. public static void startRaidForPlayer(BasePlayer player, Vector3 loc, BuildingPrivlidge priv, string type)
  3658. {
  3659. if (priv == null && player != null)
  3660. _.SendReply(player, _.lang.GetMessage("TcNotFound", _, player.UserIDString));
  3661.  
  3662. if (priv != null && _.configData.raidSettings.raidTypes.ContainsKey(type))
  3663. {
  3664. GameObject theObject = new GameObject();
  3665. RaidThinkManager newThinker = theObject.AddComponent<RaidThinkManager>();
  3666. EventRaidManager managers = EventRaidManager.Create(player, player.userID, loc, _.configData.raidSettings.raidTypes[type], type, newThinker, priv, theObject);
  3667. newThinker.Setup(managers);
  3668. managers.Start();
  3669. }
  3670. _.EventList.Remove(player);
  3671. if (priv != null)
  3672. {
  3673. foreach (var user in priv.authorizedPlayers.ToList())
  3674. {
  3675. if (user.userid == player.userID)
  3676. {
  3677. if (!_.statsData.pEntity.ContainsKey(user.userid))
  3678. _.statsData.pEntity.Add(user.userid, new StatsInfo() { name = player.displayName });
  3679. _.statsData.pEntity[user.userid].played++;
  3680. continue;
  3681. }
  3682. BasePlayer TCplayer = BasePlayer.FindByID(user.userid);
  3683. if (TCplayer != null)
  3684. {
  3685. if (_.configData.settings.gtip)
  3686. GameTipsMessage(TCplayer, _.lang.GetMessage("start", _, TCplayer.UserIDString));
  3687. if (_.configData.settings.ctip)
  3688. _.SendReply(TCplayer, _.lang.GetMessage("start", _, TCplayer.UserIDString));
  3689. if (!_.statsData.pEntity.ContainsKey(user.userid))
  3690. _.statsData.pEntity.Add(user.userid, new StatsInfo() { name = TCplayer.displayName });
  3691. _.statsData.pEntity[user.userid].played++;
  3692. }
  3693. }
  3694. _.SaveStats();
  3695. }
  3696. }
  3697.  
  3698. private static BuildingPrivlidge HasCupboard(Vector3 position)
  3699. {
  3700. BuildingPrivlidge f = null;
  3701. var list = Pool.GetList<BuildingPrivlidge>();
  3702. Vis.Entities(position, 5f, list);
  3703. foreach (var i in list)
  3704. {
  3705. if (i.IsValid() && i is BuildingPrivlidge)
  3706. {
  3707. f = i;
  3708. break;
  3709. }
  3710. }
  3711. Pool.FreeList(ref list);
  3712. return f;
  3713. }
  3714.  
  3715. private object CanBeTargeted(NpcRaider scientistNPC, MonoBehaviour behaviour)
  3716. {
  3717. if (EventRaidManager._AllRaids.Count <= 0) return null;
  3718. if (EventRaidManager._AllMembers.Contains(scientistNPC))
  3719. {
  3720. if ((behaviour is AutoTurret))
  3721. {
  3722. if (scientistNPC != null && scientistNPC.manager != null && scientistNPC.manager.config.AutoTurretDamage <= 0)
  3723. return false;
  3724. }
  3725. }
  3726.  
  3727. return null;
  3728. }
  3729.  
  3730. private object CanEntityBeTargeted(NpcRaider scientistNPC, AutoTurret turret)
  3731. {
  3732. if (EventRaidManager._AllRaids.Count <= 0) return null;
  3733. if (EventRaidManager._AllMembers.Contains(scientistNPC))
  3734. {
  3735. if (scientistNPC != null && scientistNPC.manager != null && scientistNPC.manager.config.AutoTurretDamage <= 0)
  3736. return false;
  3737. return true;
  3738. }
  3739.  
  3740. return null;
  3741. }
  3742.  
  3743. private object OnEntityTakeDamage(NpcRaider entity, HitInfo hitinfo)
  3744. {
  3745. if (EventRaidManager._AllRaids.Count <= 0) return null;
  3746. if (entity != null)
  3747. {
  3748. if (hitinfo.Initiator != null && hitinfo.Initiator is AutoTurret)
  3749. {
  3750. if (entity != null && entity.manager != null)
  3751. {
  3752. float damageTotal = entity.manager.config.AutoTurretDamage;
  3753. if (damageTotal != 0)
  3754. hitinfo.damageTypes.ScaleAll(damageTotal);
  3755. return null;
  3756. }
  3757. }
  3758. else if (hitinfo != null && hitinfo.WeaponPrefab != null && hitinfo.Initiator != null && hitinfo.Initiator is NpcRaider)
  3759. {
  3760. if (hitinfo.WeaponPrefab.ShortPrefabName.Contains("rocket"))
  3761. return true;
  3762. else if (hitinfo.WeaponPrefab.ShortPrefabName.Contains("timed"))
  3763. return true;
  3764. }
  3765. }
  3766. return null;
  3767. }
  3768.  
  3769. private void OnPlayerDeath(BasePlayer player, HitInfo info)
  3770. {
  3771. if (EventRaidManager._AllRaids.Count <= 0) return;
  3772. if (player == null || info == null || info.Initiator == null) return;
  3773.  
  3774. if (info.Initiator.GetComponent<NpcRaider>() != null && player.userID.IsSteamId())
  3775. {
  3776. if (!statsData.pEntity.ContainsKey(player.userID))
  3777. statsData.pEntity.Add(player.userID, new StatsInfo() { name = player.displayName });
  3778. statsData.pEntity[player.userID].deaths++;
  3779. }
  3780. }
  3781.  
  3782. private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitinfo)
  3783. {
  3784. if (EventRaidManager._AllRaids.Count <= 0) return null;
  3785.  
  3786. if (hitinfo != null && hitinfo.WeaponPrefab != null && hitinfo.WeaponPrefab.name.Contains("rocket_mlrs"))
  3787. {
  3788. if (hitinfo.Weapon == null)
  3789. {
  3790. if (entity.GetComponent<NpcRaider>() != null)
  3791. return false;
  3792. if (entity is BuildingBlock)
  3793. return true;
  3794. }
  3795. }
  3796. else if (entity != null && entity is BuildingPrivlidge || entity is BuildingBlock || entity.name.Contains("wall.external") || entity.name.Contains("gates.external"))
  3797. {
  3798. if (!configData.settings.DamagePlayerBuilding) return null;
  3799. if (entity.name.Contains("wall.external") || entity.name.Contains("gates.external"))
  3800. return null;
  3801. if (hitinfo.Initiator != null)
  3802. {
  3803. NpcRaider raider = hitinfo.Initiator.GetComponent<NpcRaider>();
  3804. if (raider != null)
  3805. {
  3806. if (raider.ShouldIgnoreBuildingDamage(entity))
  3807. return true;
  3808. }
  3809. }
  3810. }
  3811. else if (entity != null && entity is BasePlayer && hitinfo != null && hitinfo.Initiator is NpcRaider && (hitinfo.Initiator as NpcRaider).manager != null)
  3812. {
  3813. if ((hitinfo.Initiator as NpcRaider).manager.config.playerDamage != 1.0f) hitinfo?.damageTypes?.ScaleAll((hitinfo.Initiator as NpcRaider).manager.config.playerDamage);
  3814. }
  3815. return null;
  3816. }
  3817.  
  3818. private object CanEntityTakeDamage(BaseCombatEntity entity, HitInfo hitinfo)
  3819. {
  3820. if (EventRaidManager._AllRaids.Count <= 0) return null;
  3821.  
  3822. if (hitinfo != null && hitinfo.WeaponPrefab != null && hitinfo.WeaponPrefab.name.Contains("rocket_mlrs"))
  3823. {
  3824. if (hitinfo.Weapon == null)
  3825. {
  3826. if (entity.GetComponent<NpcRaider>() != null)
  3827. return false;
  3828. if (entity is BuildingBlock)
  3829. return true;
  3830. }
  3831. }
  3832. else if (entity != null && entity is NpcRaider)
  3833. {
  3834. if (hitinfo != null && hitinfo.Initiator is NpcRaider)
  3835. {
  3836. return false;
  3837. }
  3838. else if (entity != null && hitinfo.Initiator != null && hitinfo.Initiator is AutoTurret)
  3839. {
  3840. NpcRaider raider = entity.GetComponent<NpcRaider>();
  3841. if (raider != null && raider.manager != null)
  3842. {
  3843. float damageTotal = raider.manager.config.AutoTurretDamage;
  3844. if (damageTotal != 0)
  3845. {
  3846. hitinfo.damageTypes.ScaleAll(damageTotal);
  3847. return true;
  3848. }
  3849. }
  3850. }
  3851. if (hitinfo != null && hitinfo.Initiator is BasePlayer)
  3852. return true;
  3853. }
  3854. else if (entity != null && hitinfo != null && hitinfo.Initiator != null && hitinfo.Initiator is NpcRaider)
  3855. {
  3856. if (entity is BuildingPrivlidge || entity is BuildingBlock || entity.name.Contains("wall.external") || entity.name.Contains("gates.external") || entity.name.Contains("barricade"))
  3857. {
  3858. if (entity.name.Contains("wall.external") || entity.name.Contains("gates.external") || entity.name.Contains("barricade"))
  3859. return true;
  3860.  
  3861. if (configData.settings.DamagePlayerBuilding)
  3862. {
  3863. if ((hitinfo.Initiator as NpcRaider).ShouldIgnoreBuildingDamage(entity))
  3864. return false;
  3865. else return true;
  3866. }
  3867. else return true;
  3868. }
  3869. else if (entity is BasePlayer && hitinfo != null && hitinfo.Initiator is NpcRaider && (hitinfo.Initiator as NpcRaider).manager != null)
  3870. {
  3871. if ((hitinfo.Initiator as NpcRaider).manager.config.playerDamage != 1.0f)
  3872. hitinfo?.damageTypes?.ScaleAll((hitinfo.Initiator as NpcRaider).manager.config.playerDamage);
  3873. return true;
  3874. }
  3875. }
  3876. return null;
  3877. }
  3878.  
  3879. private object CanLootEntity(BasePlayer player, NPCPlayerCorpse corpse)
  3880. {
  3881. if (corpse == null || player == null) return null;
  3882. if (corpsLock.ContainsKey(corpse.playerSteamID))
  3883. {
  3884. if (corpsLock[corpse.playerSteamID].Contains(player.userID))
  3885. {
  3886. corpsLock.Remove(corpse.playerSteamID);
  3887. return null;
  3888. }
  3889. GameTipsMessage(player, lang.GetMessage("NoLoot", this));
  3890. return false;
  3891. }
  3892. return null;
  3893. }
  3894.  
  3895. private object CanLootEntity(BasePlayer player, DroppedItemContainer corpse)
  3896. {
  3897. if (corpse == null || player == null) return null;
  3898. if (corpsLock.ContainsKey(corpse.playerSteamID))
  3899. {
  3900. if (corpsLock[corpse.playerSteamID].Contains(player.userID))
  3901. {
  3902. corpsLock.Remove(corpse.playerSteamID);
  3903. return null;
  3904. }
  3905. GameTipsMessage(player, lang.GetMessage("NoLoot", this));
  3906. return false;
  3907. }
  3908. return null;
  3909.  
  3910. }
  3911.  
  3912. //From Nteleportation
  3913. private List<BasePlayer> FindPlayers(string arg, bool all = false)
  3914. {
  3915. var players = Pool.GetList<BasePlayer>();
  3916.  
  3917. if (string.IsNullOrEmpty(arg))
  3918. {
  3919. return players;
  3920. }
  3921.  
  3922. foreach (var p in all ? BasePlayer.allPlayerList : BasePlayer.activePlayerList)
  3923. {
  3924. if (p == null || string.IsNullOrEmpty(p.displayName) || players.Contains(p))
  3925. {
  3926. continue;
  3927. }
  3928.  
  3929. if (p.UserIDString == arg || p.displayName.Contains(arg, CompareOptions.OrdinalIgnoreCase))
  3930. {
  3931. players.Add(p);
  3932. }
  3933. }
  3934.  
  3935. return players;
  3936. }
  3937.  
  3938. private object OnLifeSupportSavingLife(BasePlayer player)
  3939. {
  3940. foreach (EventRaidManager raids in EventRaidManager._AllRaids)
  3941. if (raids.authorizedPlayers.Contains(player.userID))
  3942. return true;
  3943. return null;
  3944. }
  3945.  
  3946. //From Nteleportation
  3947. private string GetMultiplePlayers(List<BasePlayer> players)
  3948. {
  3949. var list = Pool.GetList<string>();
  3950.  
  3951. foreach (var player in players)
  3952. {
  3953. list.Add(player.displayName);
  3954. }
  3955.  
  3956. return string.Join(", ", list.ToArray());
  3957. }
  3958.  
  3959. private object OnStructureRepair(BaseCombatEntity entity, BasePlayer player)
  3960. {
  3961. if (EventRaidManager._AllRaids.Count <= 0 || entity == null) return null;
  3962.  
  3963. if (player != null)
  3964. {
  3965. if (EventRaidManager._AllPlayers.Contains(player.userID))
  3966. {
  3967. if (entity.health > entity.MaxHealth())
  3968. {
  3969. return null;
  3970. }
  3971.  
  3972. GameTipsMessage(player, lang.GetMessage("NoRepair", this));
  3973. return true;
  3974. }
  3975. }
  3976. return null;
  3977. }
  3978.  
  3979. private object OnStructureUpgrade(BuildingBlock entity, BasePlayer player, BuildingGrade.Enum grade)
  3980. {
  3981. if (EventRaidManager._AllRaids.Count <= 0 || entity == null) return null;
  3982.  
  3983. if (player != null)
  3984. {
  3985. if (EventRaidManager._AllPlayers.Contains(player.userID))
  3986. {
  3987. if (entity.health > entity.MaxHealth())
  3988. {
  3989. return null;
  3990. }
  3991.  
  3992. GameTipsMessage(player, lang.GetMessage("NoRepair", this));
  3993. return true;
  3994. }
  3995. }
  3996. return null;
  3997. }
  3998.  
  3999. public static void GameTipsMessage(BasePlayer player, string message, float howlong = 2f)
  4000. {
  4001. if (player != null && player.userID.IsSteamId())
  4002. {
  4003. player.SendConsoleCommand("gametip.hidegametip");
  4004. player.SendConsoleCommand("gametip.showgametip", message);
  4005. _.timer.Once(howlong, () => player?.SendConsoleCommand("gametip.hidegametip"));
  4006. }
  4007. }
  4008. #endregion
  4009.  
  4010. #region UiStats
  4011. //Thanks to PlayerChalanges
  4012.  
  4013. private IEnumerable<KeyValuePair<ulong, StatsInfo>> generateTopPlayerWins()
  4014. {
  4015. IEnumerable<KeyValuePair<ulong, StatsInfo>> leaders = statsData.pEntity.OrderByDescending(a => a.Value.won).Take(25);
  4016. return leaders;
  4017. }
  4018.  
  4019. private IEnumerable<KeyValuePair<ulong, StatsInfo>> generateTopPlayerKills()
  4020. {
  4021. IEnumerable<KeyValuePair<ulong, StatsInfo>> leaders = statsData.pEntity.OrderByDescending(a => a.Value.killed).Take(25);
  4022. return leaders;
  4023. }
  4024.  
  4025. private IEnumerable<KeyValuePair<ulong, StatsInfo>> generateTopPlayerDeaths()
  4026. {
  4027. IEnumerable<KeyValuePair<ulong, StatsInfo>> leaders = statsData.pEntity.OrderByDescending(a => a.Value.deaths).Take(25);
  4028. return leaders;
  4029. }
  4030.  
  4031. private IEnumerable<KeyValuePair<ulong, StatsInfo>> generateTopPlayerLoses()
  4032. {
  4033. IEnumerable<KeyValuePair<ulong, StatsInfo>> leaders = statsData.pEntity.OrderByDescending(a => a.Value.lost).Take(25);
  4034. return leaders;
  4035. }
  4036.  
  4037. private IEnumerable<KeyValuePair<ulong, StatsInfo>> generateTopPlayerWaves()
  4038. {
  4039. IEnumerable<KeyValuePair<ulong, StatsInfo>> leaders = statsData.pEntity.OrderByDescending(a => a.Value.played).Take(25);
  4040. return leaders;
  4041. }
  4042.  
  4043. public static class UI
  4044. {
  4045. public static CuiElementContainer Container(string panelName, string aMin, string aMax, bool cursor = false)
  4046. {
  4047. CuiElementContainer container = new CuiElementContainer()
  4048. {
  4049. {
  4050. new CuiPanel
  4051. {
  4052. Image = {Color = ColorExtensions.ToRustFormatString(_.backgroundColor)},
  4053. RectTransform = {AnchorMin = aMin, AnchorMax = aMax},
  4054. CursorEnabled = cursor
  4055. },
  4056. new CuiElement().Parent = "Overlay",
  4057. panelName
  4058. }
  4059. };
  4060. return container;
  4061. }
  4062.  
  4063. public static void Panel(ref CuiElementContainer container, string panel, string aMin, string aMax, bool cursor = false)
  4064. {
  4065. container.Add(new CuiPanel
  4066. {
  4067. Image = { Color = ColorExtensions.ToRustFormatString(_.PanelColor) },
  4068. RectTransform = { AnchorMin = aMin, AnchorMax = aMax },
  4069. CursorEnabled = cursor
  4070. },
  4071. panel);
  4072. }
  4073.  
  4074. public static void Label(ref CuiElementContainer container, string panel, string text, int size, string aMin, string aMax, TextAnchor align = TextAnchor.MiddleCenter, float fadein = 0f)
  4075. {
  4076. container.Add(new CuiLabel
  4077. {
  4078. Text = { FontSize = size, Align = align, FadeIn = fadein, Text = text },
  4079. RectTransform = { AnchorMin = aMin, AnchorMax = aMax }
  4080. },
  4081. panel);
  4082.  
  4083. }
  4084.  
  4085. public static void Button(ref CuiElementContainer container, string panel, string text, int size, string aMin, string aMax, string command, TextAnchor align = TextAnchor.MiddleCenter, float fadein = 0f)
  4086. {
  4087. container.Add(new CuiButton
  4088. {
  4089. Button = { Color = ColorExtensions.ToRustFormatString(_.backgroundColor), Command = command, FadeIn = fadein },
  4090. RectTransform = { AnchorMin = aMin, AnchorMax = aMax },
  4091. Text = { Text = text, FontSize = size, Align = align }
  4092. },
  4093. panel);
  4094. }
  4095. }
  4096.  
  4097. [ConsoleCommand("UI_DestroyAllRaiders")]
  4098. private void cmdDestroyAll(ConsoleSystem.Arg arg)
  4099. {
  4100. BasePlayer player = arg.Connection.player as BasePlayer;
  4101. if (player == null)
  4102. return;
  4103.  
  4104. CuiHelper.DestroyUi(player, UIMain);
  4105. }
  4106.  
  4107. private string UIMain = "PCUI_Main";
  4108.  
  4109. private void UIStatsMainWindow(BasePlayer player)
  4110. {
  4111. CuiHelper.DestroyUi(player, UIMain);
  4112. CreateMenuContents(player, 0);
  4113. }
  4114.  
  4115. private static List<string> elements = new List<string>() { "WINS", "LOSES", "KILLS", "DEATHS", "WAVES" };
  4116. private void CreateMenuContents(BasePlayer player, int page = 0)
  4117. {
  4118. CuiElementContainer container = UI.Container(UIMain, "0 0", "1 1", true);
  4119. UI.Panel(ref container, UIMain, "0.005 0.93", "0.995 0.99");
  4120.  
  4121. int count = page * 5;
  4122. int number = 0;
  4123. float dimension = 0.19f;
  4124. for (int i = count; i < count + 5; i++)
  4125. {
  4126. if (elements.Count < i + 1) continue;
  4127. float leftPos = 0.005f + (number * (dimension + 0.01f));
  4128. AddMenuStats(ref container, UIMain, elements[i], leftPos, 0.01f, leftPos + dimension, 0.92f);
  4129. number++;
  4130. }
  4131.  
  4132. UI.Button(ref container, UIMain, "Close", 16, "0.85 0.94", "0.95 0.98", "UI_DestroyAllRaiders");
  4133. UI.Button(ref container, UIMain, "My Stats", 16, "0.05 0.94", "0.15 0.98", "UI_MyStatsRaiders");
  4134. UI.Label(ref container, UIMain, $"<color=yellow>Npc Raider Top Stats</color>", 19, "0.25 0.94", "0.75 0.98", TextAnchor.MiddleCenter);
  4135. CuiHelper.AddUi(player, container);
  4136. }
  4137.  
  4138. private void AddMenuStats(ref CuiElementContainer MenuElement, string panel, string type, float left, float bottom, float right, float top)
  4139. {
  4140. IEnumerable<KeyValuePair<ulong, StatsInfo>> stat = null;
  4141. switch (type.ToLower())
  4142. {
  4143. case "wins":
  4144. {
  4145. stat = generateTopPlayerWins();
  4146. break;
  4147. }
  4148. case "kills":
  4149. {
  4150. stat = generateTopPlayerKills();
  4151. break;
  4152. }
  4153. case "deaths":
  4154. {
  4155. stat = generateTopPlayerDeaths();
  4156. break;
  4157. }
  4158. case "loses":
  4159. {
  4160. stat = generateTopPlayerLoses();
  4161. break;
  4162. }
  4163. case "waves":
  4164. {
  4165. stat = generateTopPlayerWaves();
  4166. break;
  4167. }
  4168. default:
  4169. break;
  4170. }
  4171. UI.Panel(ref MenuElement, UIMain, $"{left} {bottom}", $"{right} {top}");
  4172. UI.Label(ref MenuElement, UIMain, $"<color=red>TOP {type}</color>", 16, $"{left + 0.005f} {bottom + 0.01f}", $"{right - 0.005f} {top - 0.01f}", TextAnchor.UpperCenter);
  4173. if (stat != null)
  4174. {
  4175. bottom = bottom + 0.05f;
  4176. top = top - 0.05f;
  4177. left = left + 0.025f;
  4178. right = right - 0.025f;
  4179. string inputText = "Unknown";
  4180. foreach (var key in stat)
  4181. {
  4182. switch (type.ToLower())
  4183. {
  4184. case "wins":
  4185. {
  4186. inputText = key.Value.won.ToString();
  4187. break;
  4188. }
  4189. case "kills":
  4190. {
  4191. inputText = key.Value.killed.ToString();
  4192. break;
  4193. }
  4194. case "deaths":
  4195. {
  4196. inputText = key.Value.deaths.ToString();
  4197. break;
  4198. }
  4199. case "loses":
  4200. {
  4201. inputText = key.Value.lost.ToString();
  4202. break;
  4203. }
  4204. case "waves":
  4205. {
  4206. inputText = key.Value.played.ToString();
  4207. break;
  4208. }
  4209. default:
  4210. break;
  4211. }
  4212. bottom = bottom + 0.025f;
  4213. top = top - 0.025f;
  4214. UI.Label(ref MenuElement, UIMain, $"<color=orange>{key.Value.name}</color>: {inputText}", 13, $"{left} {bottom}", $"{right} {top}", TextAnchor.UpperLeft);
  4215. }
  4216. }
  4217. }
  4218.  
  4219. #region UiColorHelpers
  4220. private static string HexToColor(string hex)
  4221. {
  4222. if (string.IsNullOrEmpty(hex))
  4223. {
  4224. hex = "#FFFFFFFF";
  4225. }
  4226.  
  4227. var str = hex.Trim('#');
  4228.  
  4229. if (str.Length == 6)
  4230. str += "FF";
  4231.  
  4232. if (str.Length != 8)
  4233. {
  4234. throw new InvalidOperationException("Cannot convert a wrong format.");
  4235. }
  4236.  
  4237. var r = byte.Parse(str.Substring(0, 2), NumberStyles.HexNumber);
  4238. var g = byte.Parse(str.Substring(2, 2), NumberStyles.HexNumber);
  4239. var b = byte.Parse(str.Substring(4, 2), NumberStyles.HexNumber);
  4240. var a = byte.Parse(str.Substring(6, 2), NumberStyles.HexNumber);
  4241.  
  4242. Color color = new Color32(r, g, b, a);
  4243.  
  4244. return $"{color.r:F2} {color.g:F2} {color.b:F2} {color.a:F2}";
  4245. }
  4246.  
  4247. public static bool TryParseHexString(string hexString, out Color color)
  4248. {
  4249. try
  4250. {
  4251. color = FromHexString(hexString);
  4252. return true;
  4253. }
  4254. catch
  4255. {
  4256. color = Color.white;
  4257. return false;
  4258. }
  4259. }
  4260. private static Color FromHexString(string hexString)
  4261. {
  4262. if (string.IsNullOrEmpty(hexString))
  4263. {
  4264. throw new InvalidOperationException("Cannot convert an empty/null string.");
  4265. }
  4266. var trimChars = new[] { '#' };
  4267. var str = hexString.Trim(trimChars);
  4268. switch (str.Length)
  4269. {
  4270. case 3:
  4271. {
  4272. var chArray2 = new[] { str[0], str[0], str[1], str[1], str[2], str[2], 'F', 'F' };
  4273. str = new string(chArray2);
  4274. break;
  4275. }
  4276. case 4:
  4277. {
  4278. var chArray3 = new[] { str[0], str[0], str[1], str[1], str[2], str[2], str[3], str[3] };
  4279. str = new string(chArray3);
  4280. break;
  4281. }
  4282. default:
  4283. if (str.Length < 6)
  4284. {
  4285. str = str.PadRight(6, '0');
  4286. }
  4287. if (str.Length < 8)
  4288. {
  4289. str = str.PadRight(8, 'F');
  4290. }
  4291. break;
  4292. }
  4293. var r = byte.Parse(str.Substring(0, 2), NumberStyles.HexNumber);
  4294. var g = byte.Parse(str.Substring(2, 2), NumberStyles.HexNumber);
  4295. var b = byte.Parse(str.Substring(4, 2), NumberStyles.HexNumber);
  4296. var a = byte.Parse(str.Substring(6, 2), NumberStyles.HexNumber);
  4297.  
  4298. return new Color32(r, g, b, a);
  4299. }
  4300. public static class ColorExtensions
  4301. {
  4302. public static string ToRustFormatString(Color color)
  4303. {
  4304. return string.Format("{0:F2} {1:F2} {2:F2} {3:F2}", color.r, color.g, color.b, color.a);
  4305. }
  4306.  
  4307. public static string ToHexStringRGB(Color col)
  4308. {
  4309. Color32 color = col;
  4310. return string.Format("{0}{1}{2}", color.r, color.g, color.b);
  4311. }
  4312.  
  4313. public static string ToHexStringRGBA(Color col)
  4314. {
  4315. Color32 color = col;
  4316. return string.Format("{0}{1}{2}{3}", color.r, color.g, color.b, color.a);
  4317. }
  4318.  
  4319. public static bool TryParseHexString(string hexString, out Color color)
  4320. {
  4321. try
  4322. {
  4323. color = FromHexString(hexString);
  4324. return true;
  4325. }
  4326. catch
  4327. {
  4328. color = Color.white;
  4329. return false;
  4330. }
  4331. }
  4332. }
  4333. #endregion UiColorHelpers
  4334. #endregion UiStats
  4335.  
  4336. #region Localization
  4337. private new void LoadDefaultMessages()
  4338. {
  4339. lang.RegisterMessages(new Dictionary<string, string>
  4340. {
  4341. ["blocked"] = "<color=orange>You need to be in a building area!</color>",
  4342. ["start"] = "<color=orange>Your event is starting!</color>",
  4343. ["nextWave"] = "<color=orange>The next wave of raiders are coming.</color>",
  4344. ["eventOver"] = "<color=orange>Your event is now over!</color>",
  4345. ["eventOverWin"] = "<color=orange>Your just won the event!</color>",
  4346. ["waiting"] = "<color=orange>Your event will start shortly!</color>",
  4347. ["noHurt"] = "You can not hurt the event npc! ",
  4348. ["max"] = "<color=orange>The maximum amount of event's are running. There is {0} ahead of you.</color>",
  4349. ["noTypeRaid"] = "<color=orange>There is no raid type named {0}</color>",
  4350. ["cooldown"] = "<color=orange>You are in cooldown for {0} seconds!</color>",
  4351. ["cooldownAuth"] = "<color=orange>You are in cooldown for Cupboard Authorize {0} seconds!</color>",
  4352. ["ThereAlready"] = "<color=orange>You are already wating on the event.</color>",
  4353. ["InEvent"] = "<color=orange>Someone authed on the TC just started a raid event.</color>",
  4354. ["noPerm"] = "<color=orange>You do not have permission to use this raid type!</color>",
  4355. ["noPermUse"] = "<color=orange>You do not have permission to execute this command!</color>",
  4356. ["noMoney"] = "<color=orange>You need {0} {1} to start this event!</color>",
  4357. ["MultiplePlayers"] = "<color=orange>Found to many matches {0}!</color>",
  4358. ["destroyEvent"] = "<color=orange>Event for {0} destroyed!</color>",
  4359. ["destroyEventNotFound"] = "<color=orange>Event for {0} was not found!</color>",
  4360. ["MoneyIssued"] = "<color=orange>{1} you just recived ${0} for winning the event.</color>",
  4361. ["Blockedhere"] = "<color=orange>The Admin has blocked raids on this terrain type.</color>",
  4362. ["BlockedhereWater"] = "<color=orange>You can not start the event underground.</color>",
  4363. ["BlockedhereWaterDeep"] = "<color=orange>You can not start the event in this water depth.</color>",
  4364. ["RewardedItem"] = "<color=orange>You just won the event and got {0} {1}</color>",
  4365. ["waitingNext"] = "<color=orange>There is currently {0} events running you are next in line!</color>",
  4366. ["waitingLine"] = "<color=orange>There is currently {0} events running and {1} ahead of you. You will be notified before your event starts.</color>",
  4367. ["waitingToStart"] = "<color=orange>Your event will start in 60 seconds.</color>",
  4368. ["TcNotFound"] = "<color=orange>Your event tc was not found, Event canceled!</color>",
  4369. ["NoLoot"] = "<color=orange>You can not loot this event corpse!</color>",
  4370. ["UIHeader"] = "<color=orange>NPC RAIDERS STATS</color>",
  4371. ["UI1"] = "<color=orange>Total events played</color><color=white>:</color>",
  4372. ["UI2"] = "<color=orange>Total events won</color><color=white>:</color>",
  4373. ["UI3"] = "<color=orange>Total events lost</color><color=white>:</color>",
  4374. ["UI4"] = "<color=orange>Total npc's killed</color><color=white>:</color>",
  4375. ["ArivalTimeNext"] = "<color=orange>Wave {1}/{0} will start in</color><color=white>:</color><color=yellow>{2}</color>",
  4376. ["NoRepair"] = "You can not repair while in this event!",
  4377. ["EventEndINTime"] = "<color=orange>You're event will end in {0}</color>",
  4378. ["ChatHeader"] = "<size=22><color=green>NpcRaiders</color></size> <color=#ffffff>by Razor</color>",
  4379. ["Reward"] = "Reward <color=orange>$",
  4380. ["RewardMessage"] = "Reward",
  4381. ["Mode"] = "Mode",
  4382. ["NPCs"] = "NPCs",
  4383. ["Waves"] = "Waves",
  4384. ["Buy"] = "buy",
  4385. ["RaidType"] = "Raid Type",
  4386. ["Cost"] = "Cost:",
  4387. ["Nothing"] = "Nothing you can buy here!",
  4388. ["buyMsg"] = "- Shows the costs of each buyable raiding type.",
  4389. ["buyMsg1"] = "- Start an NPC Raiding event on your base that you have TC Auth on.",
  4390. ["buyMsg2"] = "You do not have any buy permisions!",
  4391. ["Randomkit"] = "Random kit"
  4392. }, this);
  4393. }
  4394. #endregion
  4395.  
  4396. }
  4397. }
  4398.  
  4399.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement