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 for Rust update
Fixed boat and horse filters UI
Prevent discord messages during plugin reload
Radar is no longer automatically activated for users when the plugin loads, unless radar was activated prior to the unload
- Users that want radar activated automatically must use the adminradar.auto permission
*/
namespace Oxide.Plugins {
[Info("Admin Radar", "nivex", "5.0.9")]
[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 string genericPrefab = "assets/prefabs/tools/map/genericradiusmarker.prefab";
private const string vendingPrefab = "assets/prefabs/deployable/vendingmachine/vending_mapmarker.prefab";
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
}
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" : return showRidableHorses;
case "Loot" : return showLoot;
case "MiniCopter" : return showMiniCopter;
case "NPC" : return showNPC;
case "Ore" : return showOre;
case "RidableHorses" : return showRidableHorses;
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 (!barebonesMode && 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.T
// ... [Code preview truncated due to length. Full source in attached file] ...