Advertisement
Guest User

Untitled

a guest
May 20th, 2019
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 33.72 KB | None | 0 0
  1. using Network;
  2. using Newtonsoft.Json;
  3. using Oxide.Core;
  4. using Oxide.Core.Libraries.Covalence;
  5. using Oxide.Game.Rust.Cui;
  6. using Rust;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.IO;
  10. using System.Linq;
  11. using UnityEngine;
  12.  
  13. namespace Oxide.Plugins
  14. {
  15. [Info("Vanish", "nivex", "0.7.2")]
  16. [Description("Allows players with permission to become truly invisible")]
  17. public class Vanish : RustPlugin
  18. {
  19. #region Configuration
  20.  
  21. static Vanish ins;
  22. private Configuration config;
  23.  
  24. public class Configuration
  25. {
  26. // TODO: Add config option to not show other vanished for custom group
  27.  
  28. [JsonProperty(PropertyName = "Image URL for vanish icon (.png or .jpg)")]
  29. public string ImageUrlIcon { get; set; } = "http://i.imgur.com/Gr5G3YI.png";
  30.  
  31. [JsonProperty(PropertyName = "Performance mode (true/false)")]
  32. public bool PerformanceMode { get; set; } = false;
  33.  
  34. [JsonProperty(PropertyName = "Play sound effect (true/false)")]
  35. public bool PlaySoundEffect { get; set; } = true;
  36.  
  37. [JsonProperty(PropertyName = "Show visual indicator (true/false)")]
  38. public bool ShowGuiIcon { get; set; } = true;
  39.  
  40. [JsonProperty(PropertyName = "Vanish timeout (seconds, 0 to disable)")]
  41. public int VanishTimeout { get; set; } = 0;
  42.  
  43. [JsonProperty(PropertyName = "Visible to admin (true/false)")]
  44. public bool VisibleToAdmin { get; set; } = false;
  45.  
  46. //[JsonProperty(PropertyName = "Visible to moderators (true/false)")]
  47. //public bool VisibleToMods { get; set; } = false;
  48.  
  49. [JsonProperty(PropertyName = "Command cooldown (seconds, 0 to disable)")]
  50. public int CommandCooldown { get; set; } = 0;
  51.  
  52. [JsonProperty(PropertyName = "Daily limit (amount, 0 to disable)")]
  53. public int DailyLimit { get; set; } = 0;
  54.  
  55. [JsonProperty(PropertyName = "Sound effect prefab")]
  56. public string DefaultEffect { get; set; } = "assets/prefabs/npc/patrol helicopter/effects/rocket_fire.prefab";
  57.  
  58. [JsonProperty(PropertyName = "Appear while wounded")]
  59. public bool AppearWhileWounded { get; set; } = false;
  60.  
  61. [JsonProperty(PropertyName = "Appear while running")]
  62. public bool AppearWhileRunning { get; set; } = false;
  63.  
  64. [JsonProperty(PropertyName = "Bypass Antihack")]
  65. public bool BypassAntihack { get; set; } = false;
  66.  
  67. [JsonProperty(PropertyName = "Image Color")]
  68. public string ImageColor { get; set; } = "1 1 1 0.3";
  69.  
  70. [JsonProperty(PropertyName = "Image AnchorMin")]
  71. public string ImageAnchorMin { get; set; } = "0.175 0.017";
  72.  
  73. [JsonProperty(PropertyName = "Image AnchorMax")]
  74. public string ImageAnchorMax { get; set; } = "0.22 0.08";
  75. }
  76.  
  77. protected override void LoadConfig()
  78. {
  79. base.LoadConfig();
  80. try
  81. {
  82. config = Config.ReadObject<Configuration>();
  83. if (config == null)
  84. {
  85. LoadDefaultConfig();
  86. }
  87. }
  88. catch
  89. {
  90. LoadDefaultConfig();
  91. }
  92. SaveConfig();
  93. }
  94.  
  95. protected override void LoadDefaultConfig()
  96. {
  97. string configPath = $"{Interface.Oxide.ConfigDirectory}{Path.DirectorySeparatorChar}{Name}.json";
  98. PrintWarning($"Could not load a valid configuration file, creating a new configuration file at {configPath}");
  99. config = new Configuration();
  100. }
  101.  
  102. protected override void SaveConfig() => Config.WriteObject(config);
  103.  
  104. #endregion Configuration
  105.  
  106. #region Localization
  107.  
  108. private new void LoadDefaultMessages()
  109. {
  110. // English
  111. lang.RegisterMessages(new Dictionary<string, string>
  112. {
  113. ["CantDamageBuilds"] = "You can't damage buildings while vanished",
  114. ["CantHurtAnimals"] = "You can't hurt animals while vanished",
  115. ["CantHurtPlayers"] = "You can't hurt players while vanished",
  116. ["CantUseTeleport"] = "You can't teleport while vanished",
  117. ["CommandVanish"] = "vanish",
  118. ["NotAllowed"] = "Sorry, you can't use '{0}' right now",
  119. ["NotAllowedPerm"] = "You are missing permissions! ({0})",
  120. ["PlayersOnly"] = "Command '{0}' can only be used by a player",
  121. ["VanishDisabled"] = "You are no longer invisible!",
  122. ["VanishEnabled"] = "You have vanished from sight...",
  123. ["VanishTimedOut"] = "Vanish time limit reached!",
  124. ["Cooldown"] = "You must wait {0} seconds to use this command again!",
  125. ["DailyLimitReached"] = "Daily limit of {0} uses has been reached!",
  126. ["InvalidSoundPrefab"] = "Invalid sound effect prefab: {0}"
  127. }, this);
  128. }
  129.  
  130. #endregion Localization
  131.  
  132. #region Initialization
  133.  
  134. private const string permAbilitiesInvulnerable = "vanish.abilities.invulnerable";
  135. private const string permAbilitiesTeleport = "vanish.abilities.teleport";
  136. private const string permAbilitiesHideWeapons = "vanish.abilities.hideweapons";
  137. private const string permDamageAnimals = "vanish.damage.animals";
  138. private const string permDamageBuildings = "vanish.damage.buildings";
  139. private const string permDamagePlayers = "vanish.damage.players";
  140. private const string permUse = "vanish.use";
  141. private bool soundEffectIsValid;
  142.  
  143. long TimeStamp() => (DateTime.Now.Ticks - DateTime.Parse("01/01/1970 00:00:00").Ticks) / 10000000;
  144.  
  145. private void Init()
  146. {
  147. ins = this;
  148. permission.RegisterPermission(permAbilitiesInvulnerable, this);
  149. permission.RegisterPermission(permAbilitiesTeleport, this);
  150. permission.RegisterPermission(permAbilitiesHideWeapons, this);
  151. permission.RegisterPermission(permDamageAnimals, this);
  152. permission.RegisterPermission(permDamageBuildings, this);
  153. permission.RegisterPermission(permDamagePlayers, this);
  154. permission.RegisterPermission(permUse, this);
  155.  
  156. AddLocalizedCommand("CommandVanish", "VanishCommand");
  157.  
  158. if (config.ImageUrlIcon == null)
  159. {
  160. config.ImageUrlIcon = "http://i.imgur.com/Gr5G3YI.png";
  161. }
  162.  
  163. Unsubscribe();
  164. }
  165.  
  166. private void Loaded()
  167. {
  168. soundEffectIsValid = !string.IsNullOrEmpty(config.DefaultEffect) && Prefab.DefaultManager.FindPrefab(config.DefaultEffect) != null;
  169.  
  170. if (!string.IsNullOrEmpty(config.DefaultEffect) && !soundEffectIsValid && config.PlaySoundEffect)
  171. {
  172. Puts(Lang("InvalidSoundPrefab", null, config.DefaultEffect));
  173. }
  174.  
  175. try
  176. {
  177. storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name);
  178. }
  179. catch { }
  180.  
  181. if (storedData == null)
  182. storedData = new StoredData();
  183.  
  184. if (config.CommandCooldown <= 0)
  185. storedData.Cooldowns.Clear();
  186.  
  187. if (config.DailyLimit <= 0)
  188. storedData.Limits.Clear();
  189. }
  190.  
  191. private void OnServerInitialized()
  192. {
  193. foreach (var basePlayer in BasePlayer.activePlayerList)
  194. {
  195. OnPlayerInit(basePlayer);
  196. }
  197. }
  198.  
  199. private void OnServerSave() => timer.Once(5f, () => SaveData());
  200.  
  201. private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(Name, storedData);
  202.  
  203. private void Subscribe()
  204. {
  205. if (config.PerformanceMode)
  206. {
  207. Unsubscribe(nameof(CanNetworkTo));
  208. }
  209. else if (Interface.CallHook("OnVanishNetwork") == null)
  210. {
  211. Subscribe(nameof(CanNetworkTo));
  212. }
  213.  
  214. if (config.AppearWhileWounded)
  215. {
  216. Subscribe(nameof(OnPlayerRecover));
  217. Subscribe(nameof(OnPlayerWound));
  218. }
  219.  
  220. if (config.BypassAntihack)
  221. {
  222. Subscribe(nameof(OnPlayerViolation));
  223. }
  224.  
  225. Subscribe(nameof(CanBeTargeted));
  226. Subscribe(nameof(CanBradleyApcTarget));
  227. Subscribe(nameof(OnNpcPlayerTarget));
  228. Subscribe(nameof(OnNpcTarget));
  229. Subscribe(nameof(OnEntityTakeDamage));
  230. Subscribe(nameof(OnPlayerSleepEnded));
  231. Subscribe(nameof(OnPlayerLand));
  232. }
  233.  
  234. private void UnsubscribeNetwork()
  235. {
  236. Unsubscribe(nameof(CanNetworkTo));
  237. }
  238.  
  239. private void Unsubscribe()
  240. {
  241. Unsubscribe(nameof(CanNetworkTo));
  242. Unsubscribe(nameof(CanBeTargeted));
  243. Unsubscribe(nameof(CanBradleyApcTarget));
  244. Unsubscribe(nameof(OnNpcPlayerTarget));
  245. Unsubscribe(nameof(OnNpcTarget));
  246. Unsubscribe(nameof(OnEntityTakeDamage));
  247. Unsubscribe(nameof(OnPlayerSleepEnded));
  248. Unsubscribe(nameof(OnPlayerLand));
  249. Unsubscribe(nameof(OnPlayerRecover));
  250. Unsubscribe(nameof(OnPlayerWound));
  251. Unsubscribe(nameof(OnPlayerViolation));
  252. }
  253.  
  254. #endregion Initialization
  255.  
  256. #region Data Storage
  257.  
  258. private class Runner : FacepunchBehaviour
  259. {
  260. private BasePlayer basePlayer;
  261.  
  262. private void Awake()
  263. {
  264. basePlayer = GetComponent<BasePlayer>();
  265. InvokeRepeating(Repeater, 0f, 0.5f);
  266. }
  267.  
  268. private void Repeater()
  269. {
  270. if (basePlayer == null || !basePlayer.IsConnected)
  271. {
  272. GameObject.Destroy(this);
  273. return;
  274. }
  275.  
  276. if (basePlayer.IsRunning())
  277. {
  278. if (ins.IsInvisible(basePlayer))
  279. {
  280. ins.Reappear(basePlayer);
  281. }
  282. }
  283. else
  284. {
  285. if (!ins.IsInvisible(basePlayer))
  286. {
  287. ins.Disappear(basePlayer);
  288. }
  289. }
  290. }
  291.  
  292. private void OnDestroy()
  293. {
  294. CancelInvoke(Repeater);
  295. GameObject.Destroy(this);
  296. }
  297. }
  298.  
  299. private class WeaponBlock : FacepunchBehaviour
  300. {
  301. private BasePlayer basePlayer;
  302. private uint svActiveItemID;
  303.  
  304. private void Awake()
  305. {
  306. basePlayer = GetComponent<BasePlayer>();
  307. svActiveItemID = basePlayer.svActiveItemID;
  308. InvokeRepeating(Repeater, 0f, 0.1f);
  309. }
  310.  
  311. private void Repeater()
  312. {
  313. if (basePlayer == null || !basePlayer.IsConnected)
  314. {
  315. GameObject.Destroy(this);
  316. return;
  317. }
  318.  
  319. var activeItem = basePlayer.svActiveItemID;
  320.  
  321. if (activeItem == svActiveItemID)
  322. {
  323. return;
  324. }
  325.  
  326. svActiveItemID = activeItem;
  327. if (ins.IsInvisible(basePlayer))
  328. {
  329. HeldEntity heldEntity = basePlayer.GetHeldEntity();
  330. if (heldEntity != null)
  331. {
  332. heldEntity.SetHeld(false);
  333. }
  334. }
  335. }
  336.  
  337. private void OnDestroy()
  338. {
  339. CancelInvoke(Repeater);
  340. GameObject.Destroy(this);
  341. }
  342. }
  343.  
  344. private class OnlinePlayer
  345. {
  346. public BasePlayer Player;
  347. public bool IsInvisible;
  348. }
  349.  
  350. [OnlinePlayers]
  351. private Hash<BasePlayer, OnlinePlayer> onlinePlayers = new Hash<BasePlayer, OnlinePlayer>();
  352.  
  353. private Dictionary<ulong, Timer> timers = new Dictionary<ulong, Timer>();
  354. private static StoredData storedData = new StoredData();
  355. private class StoredData
  356. {
  357. public class Limit
  358. {
  359. public string Date;
  360. public int Uses;
  361.  
  362. public Limit()
  363. {
  364. }
  365. }
  366.  
  367. public List<ulong> Invisible = new List<ulong>();
  368. public Dictionary<string, long> Cooldowns = new Dictionary<string, long>();
  369. public Dictionary<string, Limit> Limits = new Dictionary<string, Limit>();
  370.  
  371. public StoredData()
  372. {
  373. }
  374. }
  375.  
  376. #endregion Data Storage
  377.  
  378. #region Public Helpers
  379.  
  380. public void _Disappear(BasePlayer basePlayer) => Disappear(basePlayer);
  381. public void _Reappear(BasePlayer basePlayer) => Reappear(basePlayer);
  382. public void _VanishGui(BasePlayer basePlayer) => VanishGui(basePlayer);
  383. public bool _IsInvisible(BasePlayer basePlayer) => IsInvisible(basePlayer);
  384.  
  385. #endregion
  386.  
  387. #region Commands
  388.  
  389. private void VanishCommand(IPlayer player, string command, string[] args)
  390. {
  391. BasePlayer basePlayer = player.Object as BasePlayer;
  392. if (basePlayer == null)
  393. {
  394. player.Reply(Lang("PlayersOnly", player.Id, command));
  395. return;
  396. }
  397.  
  398. if (!player.HasPermission(permUse))
  399. {
  400. Message(player, Lang("NotAllowedPerm", player.Id, permUse));
  401. return;
  402. }
  403.  
  404. if (config.DailyLimit > 0)
  405. {
  406. if (!storedData.Limits.ContainsKey(player.Id))
  407. {
  408. storedData.Limits.Add(player.Id, new StoredData.Limit());
  409. var limit = storedData.Limits[player.Id];
  410. limit.Date = DateTime.Now.ToString();
  411. limit.Uses = 0;
  412. }
  413. else
  414. {
  415. var limit = storedData.Limits[player.Id];
  416.  
  417. if (DateTime.Parse(limit.Date).Day < DateTime.Now.Day)
  418. {
  419. limit.Date = DateTime.Now.ToString();
  420. limit.Uses = 0;
  421. }
  422. else if (++limit.Uses > config.DailyLimit && !IsInvisible(basePlayer))
  423. {
  424. Message(player, Lang("DailyLimitReached", player.Id, config.DailyLimit));
  425. return;
  426. }
  427. }
  428. }
  429.  
  430. long stamp = TimeStamp();
  431.  
  432. if (config.CommandCooldown > 0 && storedData.Cooldowns.ContainsKey(player.Id) && !IsInvisible(basePlayer))
  433. {
  434. if (storedData.Cooldowns[player.Id] - stamp > 0)
  435. {
  436. Message(player, Lang("Cooldown", player.Id, storedData.Cooldowns[player.Id] - stamp));
  437. return;
  438. }
  439.  
  440. storedData.Cooldowns.Remove(player.Id);
  441. }
  442.  
  443. if (config.PlaySoundEffect && soundEffectIsValid)
  444. {
  445. Effect.server.Run(config.DefaultEffect, basePlayer.transform.position);
  446. }
  447.  
  448. if (IsInvisible(basePlayer))
  449. {
  450. Reappear(basePlayer);
  451. }
  452. else
  453. {
  454. Disappear(basePlayer);
  455. }
  456.  
  457. if (config.CommandCooldown > 0 && !storedData.Cooldowns.ContainsKey(player.Id))
  458. {
  459. storedData.Cooldowns.Add(player.Id, stamp + config.CommandCooldown);
  460. }
  461.  
  462. if (config.DailyLimit > 0 && storedData.Limits.ContainsKey(player.Id) && IsInvisible(basePlayer))
  463. {
  464. storedData.Limits[player.Id].Uses++;
  465. }
  466. }
  467.  
  468. #endregion Commands
  469.  
  470. #region Vanishing Act
  471.  
  472. private void Disappear(BasePlayer basePlayer, bool showNotification = true)
  473. {
  474. if (Interface.CallHook("OnVanishDisappear", basePlayer) != null)
  475. {
  476. return;
  477. }
  478.  
  479. if (onlinePlayers[basePlayer] == null)
  480. {
  481. onlinePlayers[basePlayer] = new OnlinePlayer();
  482. }
  483.  
  484. List<Connection> connections = new List<Connection>();
  485. foreach (BasePlayer target in BasePlayer.activePlayerList)
  486. {
  487. if (basePlayer == target || !target.IsConnected || config.VisibleToAdmin && target.IPlayer.IsAdmin)
  488. {
  489. continue;
  490. }
  491.  
  492. connections.Add(target.net.connection);
  493. }
  494.  
  495. if (config.PerformanceMode)
  496. {
  497. basePlayer.limitNetworking = true;
  498. }
  499.  
  500. HeldEntity heldEntity = basePlayer.GetHeldEntity();
  501. if (heldEntity != null)
  502. {
  503. heldEntity.SetHeld(false);
  504. heldEntity.UpdateVisiblity_Invis();
  505. heldEntity.SendNetworkUpdate();
  506. }
  507.  
  508. if (Net.sv.write.Start())
  509. {
  510. Net.sv.write.PacketID(Network.Message.Type.EntityDestroy);
  511. Net.sv.write.EntityID(basePlayer.net.ID);
  512. Net.sv.write.UInt8((byte)BaseNetworkable.DestroyMode.None);
  513. Net.sv.write.Send(new SendInfo(connections));
  514. }
  515.  
  516. basePlayer.UpdatePlayerCollider(false);
  517.  
  518. onlinePlayers[basePlayer].IsInvisible = true;
  519.  
  520. if (basePlayer.GetComponent<WeaponBlock>() == null && basePlayer.IPlayer.HasPermission(permAbilitiesHideWeapons))
  521. {
  522. basePlayer.gameObject.AddComponent<WeaponBlock>();
  523. }
  524.  
  525. if (config.AppearWhileRunning && basePlayer.GetComponent<Runner>() == null)
  526. {
  527. basePlayer.gameObject.AddComponent<Runner>();
  528. }
  529.  
  530. if (config.VanishTimeout > 0f)
  531. {
  532. ulong userId = basePlayer.userID;
  533.  
  534. if (timers.ContainsKey(userId))
  535. {
  536. timers[userId].Reset();
  537. }
  538. else
  539. {
  540. timers.Add(userId, timer.Once(config.VanishTimeout, () =>
  541. {
  542. if (basePlayer != null && basePlayer.IsConnected && IsInvisible(basePlayer))
  543. {
  544. Reappear(basePlayer);
  545. Message(basePlayer.IPlayer, "VanishTimedOut");
  546. }
  547.  
  548. timers.Remove(userId);
  549. }));
  550. }
  551. }
  552.  
  553. if (!storedData.Invisible.Contains(basePlayer.userID))
  554. {
  555. storedData.Invisible.Add(basePlayer.userID);
  556. }
  557.  
  558. Subscribe();
  559.  
  560. if (config.ShowGuiIcon)
  561. {
  562. VanishGui(basePlayer);
  563. }
  564.  
  565. if (showNotification)
  566. {
  567. Message(basePlayer.IPlayer, "VanishEnabled");
  568. }
  569. }
  570.  
  571. // Hide from other players
  572. private object CanNetworkTo(BaseNetworkable entity, BasePlayer target)
  573. {
  574. var basePlayer = entity as BasePlayer ?? (entity as HeldEntity)?.GetOwnerPlayer();
  575. if (basePlayer == null || target == null || basePlayer == target || config.VisibleToAdmin && target.IsAdmin)
  576. {
  577. return null;
  578. }
  579.  
  580. if (IsInvisible(basePlayer))
  581. {
  582. return false;
  583. }
  584.  
  585. return null;
  586. }
  587.  
  588. // Hide from helis/turrets
  589. private object CanBeTargeted(BaseCombatEntity entity)
  590. {
  591. BasePlayer basePlayer = entity as BasePlayer;
  592. if (IsInvisible(basePlayer))
  593. {
  594. return false;
  595. }
  596.  
  597. return null;
  598. }
  599.  
  600. // Hide from the bradley APC
  601. private object CanBradleyApcTarget(BradleyAPC apc, BaseEntity entity)
  602. {
  603. BasePlayer basePlayer = entity as BasePlayer;
  604. if (IsInvisible(basePlayer))
  605. {
  606. return false;
  607. }
  608.  
  609. return null;
  610. }
  611.  
  612. // Hide from the patrol helicopter
  613. private object CanHelicopterTarget(PatrolHelicopterAI heli, BasePlayer basePlayer)
  614. {
  615. if (IsInvisible(basePlayer))
  616. {
  617. return false;
  618. }
  619.  
  620. return null;
  621. }
  622.  
  623. // Hide from scientist NPCs
  624. private object OnNpcPlayerTarget(NPCPlayerApex npc, BaseEntity entity)
  625. {
  626. BasePlayer basePlayer = entity as BasePlayer;
  627. if (IsInvisible(basePlayer))
  628. {
  629. return true; // Cancel, not a bool hook
  630. }
  631.  
  632. return null;
  633. }
  634.  
  635. /*private object OnNpcPlayerTarget(HTNPlayer htnPlayer, BasePlayer basePlayer)
  636. {
  637. if (IsInvisible(basePlayer))
  638. {
  639. return true; // Cancel, not a bool hook
  640. }
  641.  
  642. return null;
  643. }*/
  644.  
  645. // Hide from all other NPCs
  646. private object OnNpcTarget(BaseNpc npc, BaseEntity entity)
  647. {
  648. BasePlayer basePlayer = entity as BasePlayer;
  649. if (IsInvisible(basePlayer))
  650. {
  651. return true; // Cancel, not a bool hook
  652. }
  653.  
  654. return null;
  655. }
  656.  
  657. // Disappear when waking up if vanished
  658. private void OnPlayerSleepEnded(BasePlayer basePlayer)
  659. {
  660. if (!basePlayer || !basePlayer.IsConnected)
  661. {
  662. return;
  663. }
  664.  
  665. if (IsInvisible(basePlayer))
  666. {
  667. if (basePlayer.IPlayer.HasPermission(permUse))
  668. {
  669. Disappear(basePlayer);
  670. }
  671. else
  672. {
  673. Reappear(basePlayer);
  674. }
  675. }
  676. else if (storedData.Invisible.Contains(basePlayer.userID))
  677. {
  678. if (basePlayer.IPlayer.HasPermission(permUse))
  679. {
  680. Disappear(basePlayer);
  681. }
  682. else
  683. {
  684. storedData.Invisible.Remove(basePlayer.userID);
  685. }
  686. }
  687. }
  688.  
  689. // Prevent sound on player landing
  690. private object OnPlayerLand(BasePlayer player, float num)
  691. {
  692. if (IsInvisible(player))
  693. {
  694. return true; // Cancel, not a bool hook
  695. }
  696.  
  697. return null;
  698. }
  699.  
  700. // Prevent hostility
  701. private object CanEntityBeHostile(BasePlayer player)
  702. {
  703. if (IsInvisible(player))
  704. {
  705. return false;
  706. }
  707.  
  708. return null;
  709. }
  710.  
  711. // Cancel hostility
  712. private object OnEntityMarkHostile(BasePlayer player)
  713. {
  714. if (IsInvisible(player))
  715. {
  716. return true;
  717. }
  718.  
  719. return null;
  720. }
  721.  
  722. private object CanUseLockedEntity(BasePlayer player, BaseLock baseLock)
  723. {
  724. if (IsInvisible(player))
  725. {
  726. // Allow vanished players to open boxes while vanished without noise
  727. if (permission.UserHasPermission(player.UserIDString, permAbilitiesInvulnerable) || player.IsImmortal())
  728. {
  729. return true;
  730. }
  731.  
  732. // Don't make lock sound if you're not authed while vanished
  733. CodeLock codeLock = baseLock as CodeLock;
  734. if (codeLock != null)
  735. {
  736. if (!codeLock.whitelistPlayers.Contains(player.userID) && !codeLock.guestPlayers.Contains(player.userID))
  737. {
  738. return false;
  739. }
  740. }
  741. }
  742.  
  743. return null;
  744. }
  745.  
  746. void OnPlayerWound(BasePlayer player)
  747. {
  748. if (IsInvisible(player))
  749. {
  750. Reappear(player);
  751. }
  752. }
  753.  
  754. void OnPlayerRecover(BasePlayer player)
  755. {
  756. if (storedData.Invisible.Contains(player.userID))
  757. {
  758. Disappear(player);
  759. }
  760. }
  761.  
  762. object OnPlayerViolation(BasePlayer player, AntiHackType type, float amount)
  763. {
  764. if (IsInvisible(player))
  765. {
  766. return false;
  767. }
  768.  
  769. return null;
  770. }
  771.  
  772. #endregion Vanishing Act
  773.  
  774. #region Reappearing Act
  775.  
  776. private void Reappear(BasePlayer basePlayer)
  777. {
  778. if (onlinePlayers[basePlayer] != null)
  779. {
  780. onlinePlayers[basePlayer].IsInvisible = false;
  781.  
  782. if (basePlayer.GetComponent<WeaponBlock>() != null)
  783. {
  784. GameObject.Destroy(basePlayer.GetComponent<WeaponBlock>());
  785. }
  786.  
  787. if (basePlayer.GetComponent<Runner>() != null)
  788. {
  789. GameObject.Destroy(basePlayer.GetComponent<Runner>());
  790. }
  791. }
  792. basePlayer.SendNetworkUpdate();
  793. basePlayer.limitNetworking = false;
  794.  
  795. HeldEntity heldEnity = basePlayer.GetHeldEntity();
  796. if (heldEnity != null)
  797. {
  798. heldEnity.UpdateVisibility_Hand();
  799. heldEnity.SendNetworkUpdate();
  800. }
  801.  
  802. basePlayer.UpdatePlayerCollider(true);
  803.  
  804. string gui;
  805. if (guiInfo.TryGetValue(basePlayer.userID, out gui))
  806. {
  807. CuiHelper.DestroyUi(basePlayer, gui);
  808. }
  809.  
  810. Message(basePlayer.IPlayer, "VanishDisabled");
  811. if (onlinePlayers.Values.Count(p => p.IsInvisible) <= 0)
  812. {
  813. Unsubscribe(nameof(CanNetworkTo));
  814. }
  815. Interface.CallHook("OnVanishReappear", basePlayer);
  816. storedData.Invisible.Remove(basePlayer.userID);
  817. }
  818.  
  819. #endregion Reappearing Act
  820.  
  821. #region GUI Indicator
  822.  
  823. private readonly Dictionary<ulong, string> guiInfo = new Dictionary<ulong, string>();
  824.  
  825. private void VanishGui(BasePlayer basePlayer)
  826. {
  827. if (!basePlayer || !basePlayer.IsConnected || !IsInvisible(basePlayer))
  828. {
  829. return;
  830. }
  831.  
  832. if (basePlayer.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot))
  833. {
  834. timer.Once(0.1f, () => VanishGui(basePlayer));
  835. return;
  836. }
  837.  
  838. string gui;
  839. if (guiInfo.TryGetValue(basePlayer.userID, out gui))
  840. {
  841. CuiHelper.DestroyUi(basePlayer, gui);
  842. }
  843.  
  844. CuiElementContainer elements = new CuiElementContainer();
  845. guiInfo[basePlayer.userID] = CuiHelper.GetGuid();
  846.  
  847. elements.Add(new CuiElement
  848. {
  849. Name = guiInfo[basePlayer.userID],
  850. Components =
  851. {
  852. new CuiRawImageComponent
  853. {
  854. Color = config.ImageColor,
  855. Url = config.ImageUrlIcon
  856. },
  857. new CuiRectTransformComponent
  858. {
  859. AnchorMin = config.ImageAnchorMin,
  860. AnchorMax = config.ImageAnchorMax
  861. }
  862. }
  863. });
  864.  
  865. CuiHelper.AddUi(basePlayer, elements);
  866. }
  867.  
  868. #endregion GUI Indicator
  869.  
  870. #region Damage Blocking
  871.  
  872. private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
  873. {
  874. // Check if victim or attacker is a player
  875. BasePlayer basePlayer = info?.Initiator as BasePlayer ?? entity as BasePlayer;
  876. if (basePlayer == null || !basePlayer.IsConnected)
  877. {
  878. return null;
  879. }
  880.  
  881. // Check if player is invisible
  882. if (!IsInvisible(basePlayer))
  883. {
  884. return null;
  885. }
  886.  
  887. IPlayer player = basePlayer.IPlayer;
  888.  
  889. // Block damage to animals
  890. if (entity is BaseNpc)
  891. {
  892. if (player.HasPermission(permDamageAnimals))
  893. {
  894. return null;
  895. }
  896.  
  897. Message(player, "CantHurtAnimals");
  898. return true;
  899. }
  900.  
  901. // Block damage to buildings
  902. if (!(entity is BasePlayer))
  903. {
  904. if (player.HasPermission(permDamageBuildings))
  905. {
  906. return null;
  907. }
  908.  
  909. Message(player, "CantDamageBuilds");
  910. return true;
  911. }
  912.  
  913. // Block damage to players
  914. if (info?.Initiator is BasePlayer)
  915. {
  916. if (player.HasPermission(permDamagePlayers))
  917. {
  918. return null;
  919. }
  920.  
  921. Message(player, "CantHurtPlayers");
  922. return true;
  923. }
  924.  
  925. // Block damage to self
  926. if (basePlayer == info?.HitEntity)
  927. {
  928. if (player.HasPermission(permAbilitiesInvulnerable))
  929. {
  930. info.damageTypes = new DamageTypeList();
  931. info.HitMaterial = 0;
  932. info.PointStart = Vector3.zero;
  933. return true;
  934. }
  935. }
  936.  
  937. return null;
  938. }
  939.  
  940. #endregion Damage Blocking
  941.  
  942. #region Teleport Blocking
  943.  
  944. private object CanTeleport(BasePlayer basePlayer)
  945. {
  946. // Ignore for normal teleport plugins
  947. if (onlinePlayers[basePlayer] == null || !onlinePlayers[basePlayer].IsInvisible)
  948. {
  949. return null;
  950. }
  951.  
  952. bool canTeleport = basePlayer.IPlayer.HasPermission(permAbilitiesTeleport);
  953. return !canTeleport ? Lang("CantUseTeleport", basePlayer.UserIDString) : null;
  954. }
  955.  
  956. #endregion Teleport Blocking
  957.  
  958. #region Persistence Handling
  959.  
  960. private void OnPlayerInit(BasePlayer basePlayer)
  961. {
  962. if (!basePlayer || !basePlayer.IsConnected)
  963. return;
  964.  
  965. if (storedData.Invisible.Contains(basePlayer.userID))
  966. {
  967. if (basePlayer.IPlayer.HasPermission(permUse))
  968. {
  969. Disappear(basePlayer, false);
  970. }
  971. }
  972. }
  973.  
  974. #endregion Persistence Handling
  975.  
  976. #region Cleanup
  977.  
  978. private void Unload()
  979. {
  980. if (!Interface.Oxide.IsShuttingDown)
  981. {
  982. foreach (BasePlayer basePlayer in BasePlayer.activePlayerList.Where(p => p != null))
  983. {
  984. string gui;
  985. if (guiInfo.TryGetValue(basePlayer.userID, out gui))
  986. {
  987. CuiHelper.DestroyUi(basePlayer, gui);
  988. }
  989. }
  990.  
  991. var blocks = UnityEngine.Object.FindObjectsOfType(typeof(WeaponBlock));
  992.  
  993. if (blocks != null)
  994. {
  995. foreach (var gameObj in blocks)
  996. {
  997. UnityEngine.Object.Destroy(gameObj);
  998. }
  999. }
  1000.  
  1001. var runners = UnityEngine.Object.FindObjectsOfType(typeof(Runner));
  1002.  
  1003. if (runners != null)
  1004. {
  1005. foreach (var gameObj in runners)
  1006. {
  1007. UnityEngine.Object.Destroy(gameObj);
  1008. }
  1009. }
  1010. }
  1011.  
  1012. foreach (var entry in storedData.Limits.ToList())
  1013. {
  1014. if (DateTime.Parse(entry.Value.Date).Day < DateTime.Now.Day)
  1015. {
  1016. storedData.Limits.Remove(entry.Key);
  1017. }
  1018. }
  1019.  
  1020. SaveData();
  1021. }
  1022.  
  1023. #endregion Cleanup
  1024.  
  1025. #region Helpers
  1026.  
  1027. private string Lang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);
  1028.  
  1029. private void AddLocalizedCommand(string key, string command)
  1030. {
  1031. foreach (string language in lang.GetLanguages(this))
  1032. {
  1033. Dictionary<string, string> messages = lang.GetMessages(language, this);
  1034. foreach (KeyValuePair<string, string> message in messages.Where(m => m.Key.Equals(key)))
  1035. {
  1036. if (!string.IsNullOrEmpty(message.Value))
  1037. {
  1038. AddCovalenceCommand(message.Value, command);
  1039. }
  1040. }
  1041. }
  1042. }
  1043.  
  1044. private void Message(IPlayer player, string key, params object[] args) => player.Reply(Lang(key, player.Id, args));
  1045.  
  1046. private bool IsInvisible(BasePlayer player) => player != null && (onlinePlayers[player]?.IsInvisible ?? false);
  1047.  
  1048. #endregion Helpers
  1049. }
  1050. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement