C#:
//#define DEBUG
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Facepunch;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Game.Rust.Libraries;
using Rust;
using UnityEngine;
/*
Fixed boat, rhib, and horse tracking
Added modular cars to Cars filter
Added LockedByEntCrate to Loot filter (bradley apc crate)
Added `Drawing Distances > Radar Drops Command` (150 meters) - /radar drops
*/
namespace Oxide.Plugins {
[Info("Admin Radar", "nivex", "5.1.0")]
[Description("Radar tool for Admins and Developers.")]
class AdminRadar : RustPlugin {
[PluginReference]
Plugin Vanish, DiscordMessages;
private const string permAllowed = "adminradar.allowed";
private const string permBypass = "adminradar.bypass";
private const string permAuto = "adminradar.auto";
private const string permBypassOverride = "adminradar.bypass.override";
private const string permList = "adminradar.list";
private const float flickerDelay = 0.05f;
private static AdminRadar ins;
private StoredData storedData = new StoredData();
private bool init;
// don't use cache while false
private bool isUnloading;
private float startupTime;
private List<string> tags = new List<string> {
"ore", "cluster", "1", "2", "3", "4", "5", "6", "_", ".", "-", "deployed", "wooden", "large", "pile", "prefab", "collectable", "loot", "small"
}
;
// strip these from names to reduce the size of the text and make it more readable
private readonly Dictionary<ulong, Color> playersColor = new Dictionary<ulong, Color>();
private readonly List<BasePlayer> accessList = new List<BasePlayer>();
private readonly Dictionary<ulong, Timer> voices = new Dictionary<ulong, Timer>();
private readonly List<Radar> activeRadars = new List<Radar>();
private readonly List<string> warnings = new List<string>();
private readonly Dictionary<ulong, float> cooldowns = new Dictionary<ulong, float>();
private static Cache cache = new Cache();
private Coroutine coroutine;
private const bool True = true;
private const bool False = false;
public enum CupboardAction {
Authorize, Clear, Deauthorize
}
public class TrackType {
public string ExactShortname;
public string PartialShortname;
public string Text;
public TrackType(string exact, string partial, string text) {
ExactShortname = exact;
PartialShortname = partial;
Text = text;
}
}
private class CachedStringBuilder {
private readonly StringBuilder _builder = new StringBuilder();
private string _str;
public void TrimEnd(int num) {
_builder.Length -= num;
}
public void Append(string val) {
_builder.Append(val);
}
public void Append(object obj) {
_builder.Append(obj);
}
public override string ToString() {
_str = _builder.ToString();
_builder.Clear();
return _str;
}
internal void Replace(string v1, string v2) {
_builder.Replace(v1, v2);
}
}
private static CachedStringBuilder _cachedStringBuilder {
get;
set;
}
private class Cache {
public readonly List<BaseNpc> Animals = new List<BaseNpc>();
public readonly List<BaseEntity> CargoPlanes = new List<BaseEntity>();
public readonly List<DroppedItemContainer> Backpacks = new List<DroppedItemContainer>();
public readonly Dictionary<Vector3, CachedInfo> Bags = new Dictionary<Vector3, CachedInfo>();
public readonly List<BaseEntity> Boats = new List<BaseEntity>();
public readonly List<BradleyAPC> BradleyAPCs = new List<BradleyAPC>();
public readonly List<BaseEntity> CargoShips = new List<BaseEntity>();
public readonly List<BaseEntity> Cars = new List<BaseEntity>();
public readonly List<CCTV_RC> CCTV = new List<CCTV_RC>();
public readonly List<BaseEntity> CH47 = new List<BaseEntity>();
public readonly List<BuildingPrivlidge> Cupboards = new List<BuildingPrivlidge>();
public readonly Dictionary<Vector3, CachedInfo> Collectibles = new Dictionary<Vector3, CachedInfo>();
public readonly List<StorageContainer> Containers = new List<StorageContainer>();
public readonly Dictionary<PlayerCorpse, CachedInfo> Corpses = new Dictionary<PlayerCorpse, CachedInfo>();
public readonly List<BaseHelicopter> Helicopters = new List<BaseHelicopter>();
public readonly List<BaseEntity> MiniCopter = new List<BaseEntity>();
public readonly List<BasePlayer> NPCPlayers = new List<BasePlayer>();
public readonly Dictionary<Vector3, CachedInfo> Ores = new Dictionary<Vector3, CachedInfo>();
public readonly List<BaseEntity> RHIB = new List<BaseEntity>();
public readonly List<BaseEntity> RidableHorse = new List<BaseEntity>();
public readonly List<SupplyDrop> SupplyDrops = new List<SupplyDrop>();
public readonly List<AutoTurret> Turrets = new List<AutoTurret>();
public readonly List<Zombie> Zombies = new List<Zombie>();
public void Clear() {
Animals.Clear();
CargoPlanes.Clear();
Backpacks.Clear();
Bags.Clear();
Boats.Clear();
BradleyAPCs.Clear();
CargoShips.Clear();
Cars.Clear();
CCTV.Clear();
CH47.Clear();
Cupboards.Clear();
Collectibles.Clear();
Containers.Clear();
Corpses.Clear();
Helicopters.Clear();
MiniCopter.Clear();
NPCPlayers.Clear();
Ores.Clear();
RHIB.Clear();
RidableHorse.Clear();
SupplyDrops.Clear();
Turrets.Clear();
Zombies.Clear();
}
}
private class StoredData {
public readonly List<string> Extended = new List<string>();
public readonly Dictionary<string, List<string>> Filters = new Dictionary<string, List<string>>();
public readonly List<string> Hidden = new List<string>();
public readonly List<string> OnlineBoxes = new List<string>();
public readonly List<string> Visions = new List<string>();
public readonly List<string> Active = new List<string>();
public StoredData() {
}
}
private class CachedInfo {
public object Info;
public string Name;
public float Size;
}
public enum EntityType {
Active, Airdrops, Animals, Bags, Backpacks, Boats, Bradley, Cars, CargoPlanes, CargoShips, CCTV, CH47Helicopters, Containers, Collectibles, Cupboards, CupboardsArrow, Dead, GroupLimit, Heli, MiniCopter, Npc, Ore, RidableHorses, RigidHullInflatableBoats, Sleepers, Source, Turrets, Zombies
}
public static class Coroutines // Credits to Jake Rich
{
private static Dictionary<float, YieldInstruction> _waitForSecondDict;
public static YieldInstruction WaitForSeconds(float delay) {
if (_waitForSecondDict == null) {
_waitForSecondDict = new Dictionary<float, YieldInstruction>();
}
YieldInstruction yield;
if (!_waitForSecondDict.TryGetValue(delay, out yield)) {
//Cache the yield instruction for later
yield = new WaitForSeconds(delay);
_waitForSecondDict.Add(delay, yield);
}
return yield;
}
public static void Clear() {
if (_waitForSecondDict != null) {
_waitForSecondDict.Clear();
_waitForSecondDict = null;
}
}
}
public string PositionToGrid(Vector3 position) // Rewrite from yetzt implementation
{
var r = new Vector2(World.Size / 2 + position.x, World.Size / 2 + position.z);
var x = Mathf.Floor(r.x / 146.3f) % 26;
var z = Mathf.Floor(World.Size / 146.3f) - Mathf.Floor(r.y / 146.3f);
return $"{(char)('A' + x)}{z - 1}";
}
private void AdminRadarDiscordMessage(string playerName, string playerId, bool state, Vector3 position) {
if (!_sendDiscordMessages || DiscordMessages == null || !DiscordMessages.IsLoaded) {
return;
}
if (Time.realtimeSinceStartup - startupTime < 5f || isUnloading) {
return;
}
string text = state ? _discordMessageToggleOn : _discordMessageToggleOff;
string grid = PositionToGrid(position);
string message = $"[{DateTime.Now}] {playerName} ({playerId} @ {grid}): {text}";
var chatEntry = new ConVar.Chat.ChatEntry {
Message = message, UserId = playerId, Username = playerName, Time = Facepunch.Math.Epoch.Current
}
;
LogToFile("toggles", message, this, false);
RCon.Broadcast(RCon.LogType.Chat, chatEntry);
string steam = $"[{playerName}](https://steamcommunity.com/profiles/{playerId})";
string server = $"steam://connect/{ConVar.Server.ip}:{ConVar.Server.port}";
object fields = new[] {
new {
name = _embedMessagePlayer, value = steam, inline = true
}
, new {
name = _embedMessageMessage, value = text, inline = false
}
, new {
name = _embedMessageServer, value = server, inline = false
}
, new {
name = _embedMessageLocation, value = grid, inline = false
}
}
;
string json = Newtonsoft.Json.JsonConvert.SerializeObject(fields);
Interface.CallHook("API_SendFancyMessage", _webhookUrl, _embedMessageTitle, _messageColor, json, null, this);
}
private class Radar : FacepunchBehaviour {
private EntityType entityType;
private int _inactiveSeconds;
private int activeSeconds;
public float invokeTime {
get;
set;
}
public float maxDistance;
public BasePlayer player;
private Vector3 position;
private float currDistance;
private int checks;
private bool setSource = True;
public bool showBags;
public bool showBoats;
public bool showBox;
public bool showBradley;
public bool showCars;
public bool showCCTV;
public bool showCargoPlanes;
public bool showCargoShips;
public bool showCH47;
public bool showCollectible;
public bool showDead;
public bool showHeli;
public bool showHT;
public bool showLoot;
public bool showMiniCopter;
public bool showNPC;
public bool showOre;
public bool showRidableHorses;
public bool showRHIB;
public bool showSleepers;
public bool showStash;
public bool showTC;
public bool showTCArrow;
public bool showTurrets;
public bool showAll;
private BaseEntity source;
public bool barebonesMode;
private class Ping {
public int AveragePing;
public float Time;
}
private class PrivInfo {
public float ProtectedMinutes;
public float LastTime = float.MaxValue;
public PrivInfo() {
}
}
private Dictionary<BuildingPrivlidge, PrivInfo> tcs;
private Dictionary<ulong, Ping> pings;
private Dictionary<int, List<BasePlayer>> groupedPlayers;
private List<BasePlayer> nearbyPlayers;
private List<BasePlayer> distantPlayers;
private List<BasePlayer> removePlayers;
private bool limitFlag;
private int limitIndex;
public string playerName;
private string playerId;
private Vector3 lastPosition;
private bool canBypassOverride;
private bool hasPermAllowed;
private void Awake() {
removePlayers = new List<BasePlayer>();
groupedPlayers = new Dictionary<int, List<BasePlayer>>();
nearbyPlayers = new List<BasePlayer>();
distantPlayers = new List<BasePlayer>();
tcs = new Dictionary<BuildingPrivlidge, PrivInfo>();
pings = new Dictionary<ulong, Ping>();
ins.activeRadars.Add(this);
if (ins.activeRadars.Count == 1 && (blockDamageAnimals || blockDamageBuildings || blockDamageNpcs || blockDamagePlayers || blockDamageOther)) {
ins.Subscribe(nameof(OnEntityTakeDamage));
}
player = GetComponent<BasePlayer>();
source = player;
position = player.transform.position;
playerName = player.displayName;
playerId = player.UserIDString;
lastPosition = position;
canBypassOverride = ins.permission.UserHasPermission(playerId, permBypassOverride);
hasPermAllowed = ins.permission.UserHasPermission(playerId, permAllowed);
if (inactiveSeconds > 0f || inactiveMinutes > 0) {
InvokeRepeating(Activity, 0f, 1f);
}
ins.AdminRadarDiscordMessage(player.displayName, player.UserIDString, true, player.transform.position);
Interface.CallHook("OnRadarActivated", player);
}
public void StopAll() {
if (_routine != null) {
StopCoroutine(_routine);
_routine = null;
}
CancelInvoke();
}
private void OnDestroy() {
Interface.CallHook("AdminRadarDiscordMessage", playerName, playerId, false, lastPosition);
Interface.CallHook("OnRadarDeactivated", player);
StopAll();
nearbyPlayers.Clear();
groupedPlayers.Clear();
distantPlayers.Clear();
tcs.Clear();
pings.Clear();
if (radarUI != null && radarUI.Contains(player.UserIDString)) DestroyUI(player);
if (ins == null) {
Destroy(this);
return;
}
ins.activeRadars.Remove(this);
if (ins.activeRadars.Count == 0 && !ins.isUnloading) ins.Unsubscribe(nameof(OnEntityTakeDamage));
if (player != null && player.IsConnected) {
if (coolDown > 0f) {
if (!ins.cooldowns.ContainsKey(player.userID)) ins.cooldowns.Add(player.userID, Time.realtimeSinceStartup + coolDown);
else ins.cooldowns[player.userID] = Time.realtimeSinceStartup + coolDown;
}
if (ins.showToggleMessage) {
Message(player, ins.msg("Deactivated", player.UserIDString));
}
}
Destroy(this);
}
public bool GetBool(string value) {
switch (value) {
case "All" : return showAll;
case "Bags" : return showBags;
case "Boats" : return showBoats;
case "Box" : return showBox;
case "Bradley" : return showBradley;
case "CargoPlanes" : return showCargoPlanes;
case "CargoShips" : return showCargoShips;
case "Cars" : return showCars;
case "CCTV" : return showCCTV;
case "CH47" : return showCH47;
case "Collectibles" : return showCollectible;
case "Dead" : return showDead;
case "Heli" : return showHeli;
case "Horse" : case "Horses" : case "RidableHorses" : return showRidableHorses;
case "Loot" : return showLoot;
case "MiniCopter" : return showMiniCopter;
case "NPC" : return showNPC;
case "Ore" : return showOre;
case "RHIB" : return showRHIB;
case "Sleepers" : return showSleepers;
case "Stash" : return showStash;
case "TCArrows" : return showTCArrow;
case "TC" : return showTC;
case "Turrets" : return showTurrets;
default : return False;
}
}
private void Activity() {
if (source != player) {
_inactiveSeconds = 0;
return;
}
_inactiveSeconds = position == player.transform.position ? _inactiveSeconds + 1 : 0;
position = player.transform.position;
if (inactiveMinutes > 0 && ++activeSeconds / 60 > inactiveMinutes) Destroy(this);
else if (inactiveSeconds > 0 && _inactiveSeconds > inactiveSeconds) Destroy(this);
}
Coroutine _routine;
public void Start() {
isAdmin = player.IsAdmin;
if (_routine != null) {
StopCoroutine(_routine);
_routine = null;
}
_routine = StartCoroutine(barebonesMode ? DoBareRadarRoutine() : DoRadarRoutine());
}
bool isAdmin {
get;
set;
}
IEnumerator DoBareRadarRoutine() {
do {
if (!player || !player.IsConnected || ins == null || ins.isUnloading) {
Destroy(this);
yield break;
}
if (!isAdmin && hasPermAllowed) {
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, True);
player.SendNetworkUpdateImmediate();
}
if (!SetSource()) {
yield return Coroutines.WaitForSeconds(0.1f);
continue;
}
lastPosition = source.transform.position;
if (ShowActive() >= 50) {
checks = 0;
yield return null;
}
ShowSleepers();
if (!isAdmin && player.HasPlayerFlag(BasePlayer.PlayerFlags.IsAdmin)) {
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, False);
player.SendNetworkUpdateImmediate();
}
checks = 0;
yield return Coroutines.WaitForSeconds(invokeTime);
}
while (player.IsValid() && player.IsConnected);
}
IEnumerator DoRadarRoutine() {
do {
if (!player || !player.IsConnected || ins == null || ins.isUnloading) {
Destroy(this);
yield break;
}
if (!isAdmin && hasPermAllowed) {
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, True);
player.SendNetworkUpdateImmediate();
}
if (!SetSource()) {
yield return Coroutines.WaitForSeconds(0.1f);
continue;
}
if (ShowActive() >= 300) {
checks = 0;
yield return null;
}
if (ShowSleepers() >= 300) {
checks = 0;
yield return null;
}
if (ShowEntity(EntityType.Cars, showCars, "C", cache.Cars) >= 300) {
checks = 0;
yield return null;
}
if (ShowEntity(EntityType.CargoPlanes, showCargoPlanes, "CP", cache.CargoPlanes) >= 300) {
checks = 0;
yield return null;
}
if (ShowEntity(EntityType.CargoShips, showCargoShips, "CS", cache.CargoShips) >= 300) {
checks = 0;
yield return null;
}
if (ShowHeli() >= 300) {
checks = 0;
yield return null;
}
if (ShowBradley() >= 300) {
checks = 0;
yield return null;
}
if (ShowLimits() >= 300) {
checks = 0;
yield return null;
}
if (ShowTC() >= 300) {
checks = 0;
yield return null;
}
if (ShowContainers() >= 300) {
checks = 0;
yield return null;
}
if (ShowBags() >= 300) {
checks = 0;
yield return null;
}
if (ShowTurrets() >= 300) {
checks = 0;
yield return null;
}
if (ShowDead() >= 300) {
checks = 0;
yield return null;
}
if (ShowNPC() >= 300) {
checks = 0;
yield return null;
}
if (ShowOre() >= 300) {
checks = 0;
yield return null;
}
if (ShowCCTV() >= 300) {
checks = 0;
yield return null;
}
if (ShowEntity(EntityType.CH47Helicopters, showCH47, "CH47", cache.CH47) >= 300) {
checks = 0;
yield return null;
}
if (ShowEntity(EntityType.RigidHullInflatableBoats, showRHIB, "RHIB", cache.RHIB) >= 300) {
checks = 0;
yield return null;
}
if (ShowEntity(EntityType.Boats, showBoats, "RB", cache.Boats) >= 300) {
checks = 0;
yield return null;
}
if (ShowEntity(EntityType.MiniCopter, showMiniCopter, "MC", cache.MiniCopter) >= 300) {
checks = 0;
yield return null;
}
if (ShowEntity(EntityType.RidableHorses, showRidableHorses, "RH", cache.RidableHorse) >= 300) {
checks = 0;
yield return null;
}
ShowCollectables();
if (!isAdmin && player.HasPlayerFlag(BasePlayer.PlayerFlags.IsAdmin)) {
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, False);
player.SendNetworkUpdateImmediate();
}
checks = 0;
yield return Coroutines.WaitForSeconds(invokeTime);
}
while (player.IsValid() && player.IsConnected);
}
private void HandleException(Exception ex) {
if (!isAdmin && player.HasPlayerFlag(BasePlayer.PlayerFlags.IsAdmin)) {
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, False);
player.SendNetworkUpdateImmediate();
}
ins.Puts("Error @{0}: {1} --- {2}", Enum.GetName(typeof(EntityType), entityType), ex.Message, ex.StackTrace);
Message(player, ins.msg("Exception", player.UserIDString));
switch (entityType) {
case EntityType.Active : {
trackActive = False;
}
break;
case EntityType.Airdrops : {
trackSupplyDrops = False;
cache.SupplyDrops.Clear();
}
break;
case EntityType.Animals : case EntityType.Npc : case EntityType.Zombies : {
trackNPC = False;
showNPC = False;
uiBtnNPC = False;
cache.Animals.Clear();
cache.Zombies.Clear();
cache.NPCPlayers.Clear();
}
break;
case EntityType.Bags : {
trackBags = False;
showBags = False;
uiBtnBags = False;
cache.Bags.Clear();
}
break;
case EntityType.Backpacks : {
trackLoot = False;
showLoot = False;
uiBtnLoot = False;
cache.Backpacks.Clear();
}
break;
case EntityType.Bradley : {
showBradley = False;
uiBtnBradley = False;
trackBradley = False;
cache.BradleyAPCs.Clear();
}
break;
case EntityType.Cars : {
showCars = False;
uiBtnCars = False;
trackCars = False;
cache.Cars.Clear();
}
break;
case EntityType.CargoPlanes : {
uiBtnCargoPlanes = False;
trackCargoPlanes = False;
showCargoPlanes = False;
cache.CargoPlanes.Clear();
}
break;
case EntityType.CargoShips : {
trackCargoShips = False;
showCargoShips = False;
uiBtnCargoShips = False;
cache.CargoShips.Clear();
}
break;
case EntityType.CCTV : {
trackCCTV = False;
showCCTV = False;
uiBtnCCTV = False;
cache.CCTV.Clear();
}
break;
case EntityType.CH47Helicopters : {
showCH47 = False;
uiBtnCH47 = False;
trackCH47 = False;
cache.CH47.Clear();
}
break;
case EntityType.Containers : {
showBox = False;
showLoot = False;
showStash = False;
uiBtnBox = False;
uiBtnLoot = False;
uiBtnStash = False;
trackBox = False;
trackLoot = False;
trackStash = False;
cache.Containers.Clear();
}
break;
case EntityType.Collectibles : {
trackCollectibles = False;
showCollectible = False;
uiBtnCollectible = False;
cache.Collectibles.Clear();
}
break;
case EntityType.Cupboards : {
trackTC = False;
showTC = False;
uiBtnTC = False;
cache.Cupboards.Clear();
}
break;
case EntityType.CupboardsArrow : {
showTCArrow = False;
uiBtnTCArrow = False;
}
break;
case EntityType.Dead : {
trackDead = False;
showDead = False;
uiBtnDead = False;
cache.Corpses.Clear();
}
break;
case EntityType.GroupLimit : {
drawX = False;
}
break;
case EntityType.Heli : {
showHeli = False;
uiBtnHeli = False;
trackHeli = False;
cache.Helicopters.Clear();
}
break;
case EntityType.MiniCopter : {
showMiniCopter = False;
uiBtnMiniCopter = False;
trackMiniCopter = False;
cache.MiniCopter.Clear();
}
break;
case EntityType.Ore : {
trackOre = False;
showOre = False;
uiBtnOre = False;
cache.Ores.Clear();
}
break;
case EntityType.RidableHorses : {
showRidableHorses = False;
uiBtnRidableHorses = False;
trackRidableHorses = False;
cache.RidableHorse.Clear();
}
break;
case EntityType.RigidHullInflatableBoats : {
showRHIB = False;
uiBtnRHIB = False;
trackRigidHullInflatableBoats = False;
cache.RHIB.Clear();
}
break;
case EntityType.Boats : {
showBoats = False;
uiBtnBoats = False;
trackBoats = False;
cache.Boats.Clear();
}
break;
case EntityType.Sleepers : {
trackSleepers = False;
showSleepers = False;
uiBtnSleepers = False;
}
break;
case EntityType.Source : {
setSource = False;
}
break;
case EntityType.Turrets : {
trackTurrets = False;
showTurrets = False;
uiBtnTurrets = False;
cache.Turrets.Clear();
}
break;
}
uiBtnNames = new string[0];
uiButtons = null;
}
private Vector3 GetNearestCupboard(BasePlayer target) {
var positions = new List<Vector3>();
float distance = 0f;
foreach (var tc in cache.Cupboards) {
if (tc.IsAuthed(target)) {
distance = (target.transform.position - tc.transform.position).magnitude;
if (distance >= 5f && distance <= tcArrowsDistance) {
positions.Add(tc.transform.position);
}
}
}
if (positions.Count == 0) {
return Vector3.zero;
}
if (positions.Count > 1) {
positions.Sort((x, y) => ((x - target.transform.position).magnitude).CompareTo(((y - target.transform.position).magnitude)));
}
return positions[0];
}
private int GetAveragePing(BasePlayer target) {
Ping ping;
if (!pings.TryGetValue(target.userID, out ping)) {
pings[target.userID] = ping = new Ping();
}
if (ping.Time == 0f || Time.realtimeSinceStartup - ping.Time >= averagePingInterval) {
ping.Time = Time.realtimeSinceStartup;
ping.AveragePing = Network.Net.sv.GetAveragePing(target.Connection);
}
return ping.AveragePing;
}
private bool IsLetters(string value) {
if (string.IsNullOrEmpty(value)) {
return False;
}
foreach (char c in value) {
if (!char.IsLetter(c)) {
return False;
}
}
return True;
}
private bool IsNumeric(string value) {
if (string.IsNullOrEmpty(value)) {
return False;
}
foreach (char c in value) {
if (!char.IsDigit(c)) {
return False;
}
}
return True;
}
private bool SetSource() {
if (!setSource) {
source = player;
return True;
}
entityType = EntityType.Source;
source = player;
if (player.IsSpectating()) {
var parentEntity = player.GetParentEntity();
if (parentEntity as BasePlayer != null) {
var target = parentEntity as BasePlayer;
if (target.IsDead() && !target.IsConnected) player.StopSpectating();
else source = parentEntity;
}
}
if (player == source && (player.IsDead() || player.IsSleeping() || player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot))) return False;
return True;
}
private void DrawVision(BasePlayer target) {
RaycastHit hit;
if (Physics.Raycast(target.eyes.HeadRay(), out hit, Mathf.Infinity)) {
DrawArrow(Color.red, target.eyes.position + new Vector3(0f, 0.115f, 0f), hit.point, 0.15f, true);
}
}
private void DrawArrow(Color color, Vector3 from, Vector3 to, float size, bool bypass) {
if (drawArrows || bypass) player.SendConsoleCommand("ddraw.arrow", invokeTime + flickerDelay, color, from, to, size);
}
private void DrawText(Color color, Vector3 position, string text, bool @override = false) {
if (drawText || @override) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, color, position, text);
}
private void DrawBox(Color color, Vector3 position, float size, bool @override = false) {
if (drawBox || @override) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, color, position, size);
}
private int ShowActive() {
if (!trackActive) return checks;
entityType = EntityType.Active;
Color color;
try {
foreach (var target in BasePlayer.activePlayerList) {
if (target == null || target.transform == null || !target.IsConnected) {
continue;
}
currDistance = (target.transform.position - source.transform.position).magnitude;
if (player == target || currDistance > maxDistance) {
continue;
}
if (ins.permission.UserHasPermission(target.UserIDString, permBypass) && !canBypassOverride) {
continue;
}
color = __(target.IsAlive() ? activeCC : activeDeadCC);
if ((target.IsAdmin || ins.permission.UserHasPermission(target.UserIDString, "fauxadmin.allowed")) && canBypassOverride) {
color = Color.magenta;
}
if (currDistance < playerDistance) {
if (ins.storedData.Extended.Contains(player.UserIDString) && target.GetActiveItem() != null) {
_cachedStringBuilder.Append(target.GetActiveItem().info.displayName.translated);
var itemList = target.GetActiveItem().contents?.itemList;
if (itemList?.Count > 0) {
_cachedStringBuilder.Append(" (");
for (int index = 0; index < itemList.Count; index++) {
_cachedStringBuilder.Append(itemList[index].info.displayName.translated);
_cachedStringBuilder.Append("|");
}
_cachedStringBuilder.Replace("Weapon ", "");
_cachedStringBuilder.Replace("Simple Handmade ", "");
_cachedStringBuilder.Replace("Muzzle ", "");
_cachedStringBuilder.Replace("4x Zoom Scope", "4x");
_cachedStringBuilder.Append(")");
}
}
string vanished = ins.Vanish != null && ins.Vanish.Call<bool>("IsInvisible", target) ? "<color=#FF00FF>V</color>" : string.Empty;
string health = showHT && target.metabolism != null ? string.Format("{0} <color=#FFA500>{1}</color>:<color=#FFADD8E6>{2}</color>", Math.Floor(target.health), target.metabolism.calories.value.ToString("#0"), target.metabolism.hydration.value.ToString("#0")) : Math.Floor(target.health).ToString("#0");
if (averagePingInterval > 0) {
_cachedStringBuilder.Append(" ");
_cachedStringBuilder.Append(GetAveragePing(target));
_cachedStringBuilder.Append("ms");
}
if (ins.storedData.Visions.Contains(player.UserIDString)) DrawVision(target);
DrawArrow(__(colorDrawArrows), target.transform.position + new Vector3(0f, target.transform.position.y + 10), target.transform.position, 1, false);
DrawText(color, target.transform.position + new Vector3(0f, 2f, 0f), string.Format("{0} <color={1}>{2}</color> <color={3}>{4}</color>{5} {6}", ins.RemoveFormatting(target.displayName) ?? target.userID.ToString(), healthCC, health, distCC, currDistance.ToString("0"), vanished, _cachedStringBuilder.ToString()));
DrawBox(color, target.transform.position + new Vector3(0f, 1f, 0f), target.GetHeight(target.modelState.ducked));
if (ins.voices.ContainsKey(target.userID) && (target.transform.position - player.transform.position).magnitude <= voiceDistance) {
DrawArrow(Color.yellow, target.transform.position + new Vector3(0f, 5f, 0f), target.transform.position + new Vector3(0f, 2.5f, 0f), 0.5f, true);
}
ShowCupboardArrows(target, EntityType.Active);
}
else if (drawX) distantPlayers.Add(target);
else DrawBox(color, target.transform.position + new Vector3(0f, 1f, 0f), 5f, true);
checks++;
}
}
catch (Exception ex) {
HandleException(ex);
}
return checks;
}
private int ShowSleepers() {
if (!showSleepers || !trackSleepers) return checks;
entityType = EntityType.Sleepers;
Color color;
try {
foreach (var sleeper in BasePlayer.sleepingPlayerList) {
if (sleeper == null || sleeper.transform == null) continue;
currDistance = (sleeper.transform.position - source.transform.position).magnitude;
if (currDistance > maxDistance) continue;
if (currDistance < playerDistance) {
string health = showHT && sleeper.metabolism != null ? string.Format("{0} <color=#FFA500>{1}</color>:<color=#FFADD8E6>{2}</color>", Math.Floor(sleeper.health), sleeper.metabolism.calories.value.ToString("#0"), sleeper.metabolism.hydration.value.ToString("#0")) : Math.Floor(sleeper.health).ToString("#0");
color = __(sleeper.IsAlive() ? sleeperCC : sleeperDeadCC);
DrawArrow(__(colorDrawArrows), sleeper.transform.position + new Vector3(0f, sleeper.transform.position.y + 10), sleeper.transform.position, 1, false);
DrawText(color, sleeper.transform.position, string.Format("{0} <color={1}>{2}</color> <color={3}>{4}</color>", ins.RemoveFormatting(sleeper.displayName) ?? sleeper.userID.ToString(), healthCC, health, distCC, currDistance.ToString("0")));
DrawText(color, sleeper.transform.position + new Vector3(0f, 1f, 0f), "X", drawX);
if (!drawX && drawBox) DrawBox(color, sleeper.transform.position, GetScale(currDistance));
ShowCupboardArrows(sleeper, EntityType.Sleepers);
}
else DrawBox(Color.cyan, sleeper.transform.position + new Vector3(0f, 1f, 0f), 5f, true);
checks++;
}
}
catch (Exception ex) {
HandleException(ex);
}
return checks;
}
private void ShowCupboardArrows(BasePlayer target, EntityType lastType) {
try {
if (showTCArrow && uiBtnTCArrow && uiBtnTC) {
entityType = EntityType.CupboardsArrow;
var nearest = GetNearestCupboard(target);
if (nearest != Vector3.zero) {
DrawArrow(__(tcCC), target.transform.position + new Vector3(0f, 0.115f, 0f), nearest, 0.25f, true);
}
entityType = lastType;
}
}
catch (Exception ex) {
HandleException(ex);
}
}
private int ShowHeli() {
if (!showHeli || (!trackHeli && !uiBtnHeli)) return checks;
entityType = EntityType.Heli;
try {
if (cache.Helicopters.Count > 0) {
foreach (var heli in cache.Helicopters) {
if (heli == null || heli.transform == null || heli.IsDestroyed) continue;
currDistance = (heli.transform.position - source.transform.position).magnitude;
string heliHealth = heli.health > 1000 ? Math.Floor(heli.health).ToString("#,##0,K", CultureInfo.InvariantCulture) : Math.Floor(heli.health).ToString("#0");
string info = showHeliRotorHealth ? string.Format("<color={0}>{1}</color> (<color=#FFFF00>{2}</color>/<color=#FFFF00>{3}</color>)", healthCC, heliHealth, Math.Floor(heli.weakspots[0].health), Math.Floor(heli.weakspots[1].health)) : string.Format("<color={0}>{1}</color>", healthCC, heliHealth);
DrawText(__(heliCC), heli.transform.position + new Vector3(0f, 2f, 0f), string.Format("H {0} <color={1}>{2}</color>", info, distCC, currDistance.ToString("0")));
DrawBox(__(heliCC), heli.transform.position + new Vector3(0f, 1f, 0f), GetScale(currDistance));
checks++;
}
}
}
catch (Exception ex) {
HandleException(ex);
}
return checks;
}
private int ShowBradley() {
if (!showBradley || (!uiBtnBradley && !trackBradley)) return checks;
entityType = EntityType.Bradley;
try {
if (cache.BradleyAPCs.Count > 0) {
foreach (var bradley in cache.BradleyAPCs) {
if (bradley == null || bradley.transform == null || bradley.IsDestroyed) continue;
currDistance = (bradley.transform.position - source.transform.position).magnitude;
string info = string.Format("<color={0}>{1}</color>", healthCC, bradley.health > 1000 ? Math.Floor(bradley.health).ToString("#,##0,K", CultureInfo.InvariantCulture) : Math.Floor(bradley.health).ToString());
DrawText(__(bradleyCC), bradley.transform.position + new Vector3(0f, 2f, 0f), string.Format("B {0} <color={1}>{2}</color>", info, distCC, currDistance.ToString("0")));
// ... [Code preview truncated due to length. Full source in attached file] ...