C#:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using Random = UnityEngine.Random;
// Fixed NullReferenceException in HasAccess @maxaki
// Reduced map marker radius size due to map update @darkzen
// Removed CSS from player names @casualrussian
// Added config option 'Color-Hex Codes > Player Arrows > #f000000' (black) @ForGx3
// adminradar.allowed now allows full radar functionality without requiring FauxAdmin.This temporarily grants the player the admin flag.USE AT YOUR OWN RISK.@Covfefe
namespace Oxide.Plugins {
[Info("Admin Radar", "nivex", "4.5.5")]
[Description("Radar tool for Admins and Developers.")]
public class AdminRadar : RustPlugin {
public enum CupboardAction {
Authorize, Clear, Deauthorize
}
private class Cache {
public readonly List<BaseEntity> Entities = new List<BaseEntity>();
public readonly List<BaseNpc> Animals = new List<BaseNpc>();
public readonly List<DroppedItemContainer> Backpacks = new List<DroppedItemContainer>();
public readonly Dictionary<Vector3, CachedInfo> Bags = new Dictionary<Vector3, CachedInfo>();
public readonly List<BradleyAPC> BradleyAPCs = new List<BradleyAPC>();
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<BasePlayer> NPCPlayers = new List<BasePlayer>();
public readonly Dictionary<Vector3, CachedInfo> Ores = new Dictionary<Vector3, CachedInfo>();
public readonly List<SupplyDrop> SupplyDrops = new List<SupplyDrop>();
public readonly Dictionary<Vector3, CachedInfo> Turrets = new Dictionary<Vector3, CachedInfo>();
public readonly List<Zombie> Zombies = new List<Zombie>();
}
public class Marker : FacepunchBehaviour {
public BaseEntity entity;
public BasePlayer player;
public BuildingPrivlidge privilege;
public MapMarkerGenericRadius generic;
public VendingMachineMapMarker vending, personal;
public Vector3 lastPosition;
public string markerName, uid;
public bool IsPrivilegeMarker {
get {
return privilege != null;
}
}
private string Scientist() {
var player = entity as BasePlayer;
return entity is Scientist || entity is HTNPlayer || (player != null && player.displayName == player.userID.ToString()) ? ins.msg("scientist") : null;
}
private string MurdererOrScarecrow() {
return entity.ShortPrefabName == "scarecrow" || entity.ShortPrefabName == "murderer" ? ins.msg(entity.ShortPrefabName) : null;
}
private void Awake() {
privilege = GetComponent<BuildingPrivlidge>();
player = GetComponent<BasePlayer>();
entity = gameObject.ToBaseEntity();
uid = player?.UserIDString ?? Guid.NewGuid().ToString();
markerName = MurdererOrScarecrow() ?? Scientist() ?? player?.displayName ?? ins.msg(entity.ShortPrefabName);
lastPosition = transform.position;
markers[uid] = this;
if (IsPrivilegeMarker) {
return;
}
CreateMarker();
if (!useNpcUpdateTracking && entity != null && entity.IsNpc) {
return;
}
InvokeRepeating(new Action(RefreshMarker), 1f, 1f);
}
private void OnDestroy() {
CancelInvoke(new Action(RefreshMarker));
RemoveMarker();
markers.Remove(uid);
Destroy(this);
}
public static bool HasMarker(BaseEntity entity) {
return markers.Values.Any(e => e.vending == entity || e.personal == entity || e.generic == entity);
}
public void RefreshMarker() {
if (entity == null || entity.transform == null || entity.IsDestroyed) {
Destroy(this);
return;
}
if (Vector3.Distance(entity.transform.position, lastPosition) <= markerOverlapDistance) {
return;
}
lastPosition = entity.transform.position;
if (vending != null && vending.transform != null && !vending.IsDestroyed) {
if (generic != null && generic.transform != null && !generic.IsDestroyed) {
vending.markerShopName = GetMarkerShopName();
vending.transform.position = lastPosition;
vending.transform.hasChanged = true;
generic.transform.position = lastPosition;
generic.transform.hasChanged = true;
generic.SendUpdate();
vending.SendNetworkUpdate();
generic.SendNetworkUpdate();
return;
}
}
CreateMarker();
}
public void CreateMarker() {
RemoveMarker();
vending = GameManager.server.CreateEntity(vendingPrefab, lastPosition) as VendingMachineMapMarker;
if (vending != null) {
vending.markerShopName = GetMarkerShopName();
vending.enabled = false;
vending.Spawn();
}
generic = GameManager.server.CreateEntity(genericPrefab, lastPosition) as MapMarkerGenericRadius;
if (generic != null) {
var color1 = entity.IsNpc ? GetNpcColor() : player != null && player.IsAdmin ? adminColor : player != null && !player.IsConnected ? sleeperColor : onlineColor;
generic.alpha = 1f;
generic.color1 = color1;
generic.color2 = entity.IsNpc ? defaultNpcColor : privilegeColor2;
generic.radius = 0.1f;
generic.enabled = true;
generic.Spawn();
generic.SendUpdate();
}
}
public void CreatePrivilegeMarker(string newMarkerName) {
if (privilege == null || privilege.transform == null || privilege.IsDestroyed) {
Destroy(this);
return;
}
RemoveMarker();
markerName = string.Format("{0}{1}{2}", ins.msg("TC"), Environment.NewLine, newMarkerName);
vending = GameManager.server.CreateEntity(vendingPrefab, privilege.transform.position) as VendingMachineMapMarker;
if (vending != null) {
vending.markerShopName = GetMarkerShopName();
vending.enabled = false;
vending.Spawn();
}
if (usePersonalMarkers) {
personal = GameManager.server.CreateEntity(vendingPrefab, privilege.transform.position) as VendingMachineMapMarker;
if (personal != null) {
personal.markerShopName = ins.msg("My Base");
personal.enabled = false;
personal.Spawn();
}
}
generic = GameManager.server.CreateEntity(genericPrefab, privilege.transform.position) as MapMarkerGenericRadius;
if (generic != null) {
generic.alpha = 1f;
generic.color1 = privilegeColor1;
generic.color2 = privilegeColor2;
generic.radius = 0.1f;
generic.enabled = true;
generic.Spawn();
generic.SendUpdate();
}
}
public void RemoveMarker() {
if (generic != null && !generic.IsDestroyed) {
generic.Kill();
}
if (personal != null && !personal.IsDestroyed) {
personal.Kill();
}
if (vending != null && !vending.IsDestroyed) {
vending.Kill();
}
}
private Color GetNpcColor() {
switch (entity.ShortPrefabName) {
case "bear" : return bearColor;
case "boar" : return boarColor;
case "chicken" : return chickenColor;
case "wolf" : return wolfColor;
case "stag" : return stagColor;
case "horse" : return horseColor;
case "murderer" : return __(murdererCC);
case "bandit_guard" : case "bandit_shopkeeper" : case "scientist" : case "scientistjunkpile" : case "scientiststationary" : return __(scientistCC);
case "scientistpeacekeeper" : return __(peacekeeperCC);
case "scientist_astar_full_any" : case "scientist_full_any" : case "scientist_full_lr300" : case "scientist_full_mp5" : case "scientist_full_pistol" : case "scientist_full_shotgun" : case "scientist_turret_any" : case "scientist_turret_lr300" : case "scarecrow" : return __(htnscientistCC);
default : return defaultNpcColor;
}
}
private string GetMarkerShopName() {
var sb = new StringBuilder();
sb.AppendLine(markerName);
foreach (var marker in markers.Values.Where(t => t != this && !string.IsNullOrEmpty(t.markerName) && Vector3.Distance(t.lastPosition, lastPosition) <= markerOverlapDistance).ToList()) {
if (marker.IsPrivilegeMarker) {
sb.AppendLine(ins.msg("TC"));
sb.AppendLine($"> {marker.markerName}");
}
else sb.AppendLine(marker.markerName);
}
sb.Length--;
return sb.ToString();
}
}
private class PlayerTracker : FacepunchBehaviour {
private BasePlayer player;
private ulong uid;
private void Awake() {
player = GetComponent<BasePlayer>();
uid = player.userID;
InvokeRepeating(UpdateMovement, 0f, trackerUpdateInterval);
UpdateMovement();
}
private void UpdateMovement() {
if (!player || !player.IsConnected) {
Destroy(this);
return;
}
if (!trackers.ContainsKey(uid)) trackers.Add(uid, new SortedDictionary<float, Vector3>());
float time = Time.realtimeSinceStartup;
foreach (float stamp in trackers[uid].Keys.ToList()) // keep the dictionary from becoming enormous by removing entries which are too old
if (time - stamp > trackerAge) trackers[uid].Remove(stamp);
if (trackers[uid].Count > 1) {
var lastPos = trackers[uid].Values.ElementAt(trackers[uid].Count - 1);
// get the last position the player was at
if (Vector3.Distance(lastPos, transform.position) <= 1f) // check the distance against the minimum requirement.without this the dictionary will accumulate thousands of entries
return;
}
trackers[uid][time] = transform.position;
UpdateTimer();
}
private void UpdateTimer() {
if (trackerTimers.ContainsKey(uid)) {
if (trackerTimers[uid] != null) {
trackerTimers[uid].Reset();
return;
}
trackerTimers.Remove(uid);
}
trackerTimers.Add(uid, ins.timer.Once(trackerAge, () => {
trackers.Remove(uid);
trackerTimers.Remove(uid);
}
));
}
private void OnDestroy() {
CancelInvoke(UpdateMovement);
UpdateTimer();
Destroy(this);
}
}
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 StoredData() {
}
}
private class CachedInfo {
public object Info;
public string Name;
public double Size;
}
private class Radar : FacepunchBehaviour {
private readonly List<BasePlayer> distantPlayers = new List<BasePlayer>();
private int drawnObjects;
private EntityType entityType;
private int _inactiveSeconds;
private int activeSeconds;
public float invokeTime;
public float maxDistance;
public BasePlayer player;
private Vector3 position;
private bool setSource = true;
private bool showActive = true;
public bool showBags;
public bool showBox;
public bool showCollectible;
public bool showDead;
public bool showHT;
private bool showLimits = true;
public bool showLoot;
public bool showNPC;
public bool showOre;
public bool showSleepers;
public bool showStash;
public bool showTC;
public bool showTurrets;
private BaseEntity source;
private enum EntityType {
Active, Airdrops, Animals, Bags, Backpacks, Boats, Bradley, Cars, CargoShips, CH47Helicopters, Containers, Collectibles, Cupboards, Dead, GroupLimitHightlighting, Heli, Npc, Ore, RigidHullInflatableBoats, Sleepers, Source, Turrets, Zombies
}
private void Awake() {
activeRadars.Add(this);
player = GetComponent<BasePlayer>();
source = player;
position = player.transform.position;
if (inactiveSeconds > 0f || inactiveMinutes > 0) InvokeRepeating(Activity, 0f, 1f);
}
public void Start() {
CancelInvoke(DoRadar);
Invoke(DoRadar, invokeTime);
InvokeRepeating(DoRadar, 0f, invokeTime);
}
private void OnDestroy() {
if (radarUI.Contains(player.UserIDString)) ins.DestroyUI(player);
if (inactiveSeconds > 0 || inactiveMinutes > 0) CancelInvoke(Activity);
CancelInvoke(DoRadar);
activeRadars.Remove(this);
player.ChatMessage(ins.msg("Deactivated", player.UserIDString));
Destroy(this);
}
private bool LatencyAccepted(DateTime tick) {
if (latencyMs > 0) {
double ms = (DateTime.Now - tick).TotalMilliseconds;
if (ms > latencyMs) {
player.ChatMessage(ins.msg("DoESP", player.UserIDString, ms, latencyMs));
return false;
}
}
return true;
}
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);
}
private void DoRadar() {
var tick = DateTime.Now;
bool isAdmin = player.IsAdmin;
try {
if (!player.IsConnected) {
Destroy(this);
return;
}
drawnObjects = 0;
if (!isAdmin && ins.permission.UserHasPermission(player.UserIDString, permName)) {
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
player.SendNetworkUpdateImmediate();
}
if (!SetSource()) return;
if (!ShowActive(tick)) return;
if (!ShowSleepers(tick)) return;
if (barebonesMode) return;
if (!ShowEntity(tick, EntityType.Cars, trackCars)) return;
if (!ShowEntity(tick, EntityType.CargoShips, trackCargoShips)) return;
if (!ShowHeli(tick)) return;
if (!ShowBradley(tick)) return;
if (!ShowLimits(tick)) return;
if (!ShowTC(tick)) return;
if (!ShowContainers(tick)) return;
if (!ShowBags(tick)) return;
if (!ShowTurrets(tick)) return;
if (!ShowDead(tick)) return;
if (!ShowNPC(tick)) return;
if (!ShowOre(tick)) return;
if (!ShowEntity(tick, EntityType.CH47Helicopters, trackCH47)) return;
if (!ShowEntity(tick, EntityType.RigidHullInflatableBoats, trackRigidHullInflatableBoats)) return;
if (!ShowEntity(tick, EntityType.Boats, trackBoats)) return;
ShowCollectables(tick);
}
catch (Exception ex) {
ins.Puts("Error @{0}: {1} --- {2}", Enum.GetName(typeof(EntityType), entityType), ex.Message, ex.StackTrace);
player.ChatMessage(ins.msg("Exception", player.UserIDString));
switch (entityType) {
case EntityType.Active : {
showActive = false;
}
break;
case EntityType.Airdrops : {
showBox = false;
}
break;
case EntityType.Animals : case EntityType.Npc : case EntityType.Zombies : {
showNPC = false;
}
break;
case EntityType.Bags : {
showBags = false;
}
break;
case EntityType.Backpacks : {
showLoot = false;
}
break;
case EntityType.Bradley : {
trackBradley = false;
}
break;
case EntityType.Cars : {
trackCars = false;
}
break;
case EntityType.CargoShips : {
trackCargoShips = false;
}
break;
case EntityType.CH47Helicopters : {
trackCH47 = false;
}
break;
case EntityType.Containers : {
showBox = false;
showLoot = false;
showStash = false;
}
break;
case EntityType.Collectibles : {
showCollectible = false;
}
break;
case EntityType.Cupboards : {
showTC = false;
}
break;
case EntityType.Dead : {
showDead = false;
}
break;
case EntityType.GroupLimitHightlighting : {
showLimits = false;
}
break;
case EntityType.Heli : {
trackHeli = false;
}
break;
case EntityType.Ore : {
showOre = false;
}
break;
case EntityType.RigidHullInflatableBoats : {
trackRigidHullInflatableBoats = false;
}
break;
case EntityType.Boats : {
trackBoats = false;
}
break;
case EntityType.Sleepers : {
showSleepers = false;
}
break;
case EntityType.Source : {
setSource = false;
}
break;
case EntityType.Turrets : {
showTurrets = false;
}
break;
}
}
finally {
if (!isAdmin && player.HasPlayerFlag(BasePlayer.PlayerFlags.IsAdmin)) {
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, false);
player.SendNetworkUpdateImmediate();
}
if (!LatencyAccepted(tick)) {
double ms = (DateTime.Now - tick).TotalMilliseconds;
string message = ins.msg("DoESP", player.UserIDString, ms, latencyMs);
ins.Puts("{0} for {1} ({2})", message, player.displayName, player.UserIDString);
Destroy(this);
}
}
}
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 bool ShowActive(DateTime tick) {
if (!showActive) return true;
entityType = EntityType.Active;
foreach (var target in BasePlayer.activePlayerList.Where(target => target != null && target.transform != null && target.IsConnected)) {
double currDistance = Math.Floor(Vector3.Distance(target.transform.position, source.transform.position));
if (player == target || currDistance > maxDistance || useBypass && ins.permission.UserHasPermission(target.UserIDString, permBypass)) continue;
var color = __(target.IsAlive() ? activeCC : activeDeadCC);
if (currDistance < playerDistance) {
string extText = string.Empty;
if (storedData.Extended.Contains(player.UserIDString)) {
extText = target.GetActiveItem()?.info.displayName.translated ?? string.Empty;
if (!string.IsNullOrEmpty(extText)) {
var itemList = target.GetHeldEntity()?.GetComponent<BaseProjectile>()?.GetItem()?.contents?.itemList;
if (itemList?.Count > 0) {
string contents = string.Join("|", itemList.Select(item => item.info.displayName.translated.Replace("Weapon ", "").Replace("Simple Handmade ", "").Replace("Muzzle ", "").Replace("4x Zoom Scope", "4x")).ToArray());
if (!string.IsNullOrEmpty(contents)) {
extText = string.Format("{0} ({1})", extText, contents);
}
}
}
}
string vanished = ins.Vanish != null && target.IPlayer.HasPermission("vanish.use") && (bool)ins.Vanish.Call("IsInvisible", target) ? "<color=magenta>V</color>" : string.Empty;
string health = showHT && target.metabolism != null ? string.Format("{0} <color=orange>{1}</color>:<color=lightblue>{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 (storedData.Visions.Contains(player.UserIDString)) DrawVision(player, target, invokeTime);
if (drawArrows) player.SendConsoleCommand("ddraw.arrow", invokeTime + flickerDelay, __(colorDrawArrows), target.transform.position + new Vector3(0f, target.transform.position.y + 10), target.transform.position, 1);
if (drawText) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, 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, vanished, extText));
if (drawBox) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, color, target.transform.position + new Vector3(0f, 1f, 0f), target.GetHeight(target.modelState.ducked));
if (voices.ContainsKey(target.userID) && Vector3.Distance(target.transform.position, player.transform.position) <= voiceDistance) {
player.SendConsoleCommand("ddraw.arrow", invokeTime + flickerDelay, Color.yellow, target.transform.position + new Vector3(0f, 2.5f, 0f), target.transform.position, 1);
}
}
else if (drawX) distantPlayers.Add(target);
else player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, color, target.transform.position + new Vector3(0f, 1f, 0f), 5f);
if (objectsLimit > 0 && ++drawnObjects > objectsLimit) return false;
}
return LatencyAccepted(tick);
}
private bool ShowSleepers(DateTime tick) {
if (!showSleepers) return true;
entityType = EntityType.Sleepers;
foreach (var sleeper in BasePlayer.sleepingPlayerList.Where(target => target != null && target.transform != null)) {
double currDistance = Math.Floor(Vector3.Distance(sleeper.transform.position, source.transform.position));
if (currDistance > maxDistance) continue;
if (currDistance < playerDistance) {
string health = showHT && sleeper.metabolism != null ? string.Format("{0} <color=orange>{1}</color>:<color=lightblue>{2}</color>", Math.Floor(sleeper.health), sleeper.metabolism.calories.value.ToString("#0"), sleeper.metabolism.hydration.value.ToString("#0")) : Math.Floor(sleeper.health).ToString("#0");
var color = __(sleeper.IsAlive() ? sleeperCC : sleeperDeadCC);
if (drawArrows) player.SendConsoleCommand("ddraw.arrow", invokeTime + flickerDelay, __(colorDrawArrows), sleeper.transform.position + new Vector3(0f, sleeper.transform.position.y + 10), sleeper.transform.position, 1);
if (drawText) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, 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));
if (drawX) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, color, sleeper.transform.position + new Vector3(0f, 1f, 0f), "X");
else if (drawBox) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, color, sleeper.transform.position, GetScale(currDistance));
}
else player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, Color.cyan, sleeper.transform.position + new Vector3(0f, 1f, 0f), 5f);
if (objectsLimit > 0 && ++drawnObjects > objectsLimit) return false;
}
return LatencyAccepted(tick);
}
private bool ShowHeli(DateTime tick) {
if (!trackHeli) return true;
entityType = EntityType.Heli;
if (cache.Helicopters.Count > 0) {
foreach (var heli in cache.Helicopters.Where(target => target != null && target.transform != null && !target.IsDestroyed)) {
double currDistance = Math.Floor(Vector3.Distance(heli.transform.position, source.transform.position));
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=yellow>{2}</color>/<color=yellow>{3}</color>)", healthCC, heliHealth, Math.Floor(heli.weakspots[0].health), Math.Floor(heli.weakspots[1].health)) : string.Format("<color={0}>{1}</color>", healthCC, heliHealth);
if (drawText) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, __(heliCC), heli.transform.position + new Vector3(0f, 2f, 0f), string.Format("H {0} <color={1}>{2}</color>", info, distCC, currDistance));
if (drawBox) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, __(heliCC), heli.transform.position + new Vector3(0f, 1f, 0f), GetScale(currDistance));
if (objectsLimit > 0 && ++drawnObjects > objectsLimit) return false;
}
}
return LatencyAccepted(tick);
}
private bool ShowBradley(DateTime tick) {
if (!trackBradley) return true;
entityType = EntityType.Bradley;
if (cache.BradleyAPCs.Count > 0) {
foreach (var bradley in cache.BradleyAPCs.Where(target => target != null && target.transform != null && !target.IsDestroyed)) {
double currDistance = Math.Floor(Vector3.Distance(bradley.transform.position, source.transform.position));
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());
if (drawText) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, __(bradleyCC), bradley.transform.position + new Vector3(0f, 2f, 0f), string.Format("B {0} <color={1}>{2}</color>", info, distCC, currDistance));
if (drawBox) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, __(bradleyCC), bradley.transform.position + new Vector3(0f, 1f, 0f), GetScale(currDistance));
if (objectsLimit > 0 && ++drawnObjects > objectsLimit) return false;
}
}
return LatencyAccepted(tick);
}
private bool ShowLimits(DateTime tick) {
if (!showLimits) return true;
entityType = EntityType.GroupLimitHightlighting;
if (distantPlayers.Count > 0) {
var dict = new Dictionary<int, List<BasePlayer>>();
foreach (var target in distantPlayers.ToList()) {
var list = distantPlayers.Where(x => Vector3.Distance(x.transform.position, target.transform.position) < groupRange && !dict.Any(y => y.Value.Contains(x))).ToList();
if (list.Count() >= groupLimit) {
int index = 0;
while (dict.ContainsKey(index)) index++;
dict.Add(index, list);
distantPlayers.RemoveAll(x => list.Contains(x));
}
}
foreach (var target in distantPlayers) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, target.IsAlive() ? Color.green : Color.red, target.transform.position + new Vector3(0f, 1f, 0f), "X");
foreach (var entry in dict) {
foreach (var target in entry.Value) {
player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, __(target.IsAlive() ? GetGroupColor(entry.Key) : groupColorDead), target.transform.position + new Vector3(0f, 1f, 0f), "X");
}
if (groupCountHeight > 0f) {
player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, Color.magenta, entry.Value.First().transform.position + new Vector3(0f, groupCountHeight, 0f), entry.Value.Count.ToString());
}
}
distantPlayers.Clear();
dict.Clear();
}
return LatencyAccepted(tick);
}
private bool ShowTC(DateTime tick) {
if (!showTC) return true;
entityType = EntityType.Cupboards;
foreach (var tc in cache.Cupboards.Where(target => target != null && target.transform != null && !target.IsDestroyed)) {
double currDistance = Math.Floor(Vector3.Distance(tc.transform.position, source.transform.position));
if (currDistance < tcDistance && currDistance < maxDistance) {
if (drawText) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, __(tcCC), tc.transform.position + new Vector3(0f, 0.5f, 0f), string.Format("TC <color={0}>{1}</color>", distCC, currDistance));
if (drawBox) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, __(tcCC), tc.transform.position + new Vector3(0f, 0.5f, 0f), 3f);
if (objectsLimit > 0 && ++drawnObjects > objectsLimit) return false;
}
}
return LatencyAccepted(tick);
}
private bool ShowContainers(DateTime tick) {
if (!showBox && !showLoot && !showStash) {
return true;
}
if (showLoot) {
entityType = EntityType.Backpacks;
foreach (var backpack in cache.Backpacks.Where(target => target != null && target.transform != null && !target.IsDestroyed)) {
double currDistance = Math.Floor(Vector3.Distance(backpack.transform.position, source.transform.position));
if (currDistance > maxDistance || currDistance > lootDistance) continue;
string contents = backpack.inventory?.itemList != null ? string.Format("({0}) ", backpackContentAmount > 0 && backpack.inventory.itemList.Count > 0 ? string.Join(", ", backpack.inventory.itemList.Take(backpackContentAmount).Select(item => string.Format("{0} ({1})", item.info.displayName.translated.ToLower(), item.amount)).ToArray()) : backpack.inventory.itemList.Count().ToString()) : string.Empty;
if (drawText) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, __(backpackCC), backpack.transform.position + new Vector3(0f, 0.5f, 0f), string.Format("{0} <color={1}>{2}</color><color={3}>{4}</color>", string.IsNullOrEmpty(backpack._playerName) ? ins.msg("backpack", player.UserIDString) : backpack._playerName, backpackCC, contents, distCC, currDistance));
if (drawBox) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, __(backpackCC), backpack.transform.position + new Vector3(0f, 0.5f, 0f), GetScale(currDistance));
if (objectsLimit > 0 && ++drawnObjects > objectsLimit) return false;
}
}
if (showBox) {
entityType = EntityType.Airdrops;
foreach (var drop in cache.SupplyDrops.Where(target => target != null && target.transform != null && !target.IsDestroyed)) {
double currDistance = Math.Floor(Vector3.Distance(drop.transform.position, source.transform.position));
if (currDistance > maxDistance || currDistance > adDistance) continue;
string contents = showAirdropContents && drop.inventory.itemList.Count > 0 ? string.Format("({0}) ", string.Join(", ", drop.inventory.itemList.Select(item => string.Format("{0} ({1})", item.info.displayName.translated.ToLower(), item.amount)).ToArray())) : string.Format("({0}) ", drop.inventory.itemList.Count());
if (drawText) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, __(airdropCC), drop.transform.position + new Vector3(0f, 0.5f, 0f), string.Format("{0} {1}<color={2}>{3}</color>", _(drop.ShortPrefabName), contents, distCC, currDistance));
if (drawBox) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, __(airdropCC), drop.transform.position + new Vector3(0f, 0.5f, 0f), GetScale(currDistance));
}
}
entityType = EntityType.Containers;
foreach (var container in cache.Containers.Where(target => target != null && target.transform != null && !target.IsDestroyed)) {
double currDistance = Math.Floor(Vector3.Distance(container.transform.position, source.transform.position));
if (currDistance > maxDistance) continue;
bool isBox = container.ShortPrefabName.Contains("box") || container.ShortPrefabName.Equals("heli_crate");
bool isLoot = container.ShortPrefabName.Contains("loot") || container.ShortPrefabName.Contains("crate_") || container.ShortPrefabName.Contains("trash") || container.ShortPrefabName.Contains("hackable") || container.ShortPrefabName.Contains("oil");
if (isBox) {
if (!showBox || currDistance > boxDistance) continue;
}
if (isLoot) {
if (!showLoot || currDistance > lootDistance) continue;
}
if (container.ShortPrefabName.Contains("stash")) {
if (!showStash || currDistance > stashDistance) continue;
}
else if (!isBox && !isLoot && currDistance > boxDistance) continue;
string colorHex = isBox ? boxCC : isLoot ? lootCC : stashCC;
string contents = string.Empty;
if (storedData.OnlineBoxes.Contains(player.UserIDString) && container.name.Contains("box")) {
var owner = BasePlayer.activePlayerList.Find(x => x.userID == container.OwnerID);
if (owner == null || !owner.IsConnected) {
continue;
}
}
if (container.inventory?.itemList?.Count > 0) {
if (isLoot && showLootContents || container.ShortPrefabName.Contains("stash") && showStashContents) contents = string.Format("({0}) ", string.Join(", ", container.inventory.itemList.Select(item => string.Format("{0} ({1})", item.info.displayName.translated.ToLower(), item.amount)).ToArray()));
else contents = string.Format("({0}) ", container.inventory.itemList.Count());
}
if (string.IsNullOrEmpty(contents) && !drawEmptyContainers) continue;
if (drawText) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, __(colorHex), container.transform.position + new Vector3(0f, 0.5f, 0f), string.Format("{0} {1}<color={2}>{3}</color>", _(container.ShortPrefabName), contents, distCC, currDistance));
if (drawBox) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, __(colorHex), container.transform.position + new Vector3(0f, 0.5f, 0f), GetScale(currDistance));
if (objectsLimit > 0 && ++drawnObjects > objectsLimit) return false;
}
return LatencyAccepted(tick);
}
private bool ShowBags(DateTime tick) {
if (!showBags) return true;
entityType = EntityType.Bags;
foreach (var bag in cache.Bags) {
var currDistance = Math.Floor(Vector3.Distance(bag.Key, source.transform.position));
if (currDistance < bagDistance && currDistance < maxDistance) {
if (drawText) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, __(bagCC), bag.Key, string.Format("bag <color={0}>{1}</color>", distCC, currDistance));
if (drawBox) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, __(bagCC), bag.Key, bag.Value.Size);
if (objectsLimit > 0 && ++drawnObjects > objectsLimit) return false;
}
}
return LatencyAccepted(tick);
}
private bool ShowTurrets(DateTime tick) {
if (!showTurrets) return true;
entityType = EntityType.Turrets;
foreach (var turret in cache.Turrets) {
var currDistance = Math.Floor(Vector3.Distance(turret.Key, source.transform.position));
if (currDistance < turretDistance && currDistance < maxDistance) {
if (drawText) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, __(atCC), turret.Key + new Vector3(0f, 0.5f, 0f), string.Format("AT ({0}) <color={1}>{2}</color>", turret.Value.Info, distCC, currDistance));
if (drawBox) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, __(atCC), turret.Key + new Vector3(0f, 0.5f, 0f), turret.Value.Size);
if (objectsLimit > 0 && ++drawnObjects > objectsLimit) return false;
}
}
return LatencyAccepted(tick);
}
private bool ShowDead(DateTime tick) {
if (!showDead) return true;
entityType = EntityType.Dead;
foreach (var corpse in cache.Corpses.Where(kvp => kvp.Key != null && kvp.Key.transform != null)) {
double currDistance = Math.Floor(Vector3.Distance(source.transform.position, corpse.Key.transform.position));
if (currDistance < corpseDistance && currDistance < maxDistance) {
if (drawText) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, __(corpseCC), corpse.Key.transform.position + new Vector3(0f, 0.25f, 0f), string.Format("{0} ({1})", corpse.Value.Name, corpse.Value.Info));
if (drawBox) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, __(corpseCC), corpse.Key, GetScale(currDistance));
if (objectsLimit > 0 && ++drawnObjects > objectsLimit) return false;
}
}
return LatencyAccepted(tick);
}
private bool ShowNPC(DateTime tick) {
if (!showNPC) return true;
entityType = EntityType.Zombies;
foreach (var zombie in cache.Zombies.Where(target => target != null && target.transform != null && !target.IsDestroyed)) {
double currDistance = Math.Floor(Vector3.Distance(zombie.transform.position, source.transform.position));
if (currDistance > maxDistance) continue;
if (currDistance < playerDistance) {
if (drawArrows) player.SendConsoleCommand("ddraw.arrow", invokeTime + flickerDelay, __(zombieCC), zombie.transform.position + new Vector3(0f, zombie.transform.position.y + 10), zombie.transform.position, 1);
if (drawText) player.SendConsoleCommand("ddraw.text", invokeTime + flickerDelay, __(zombieCC), zombie.transform.position + new Vector3(0f, 2f, 0f), string.Format("{0} <color={1}>{2}</color> <color={3}>{4}</color>", ins.msg("Zombie", player.UserIDString), healthCC, Math.Floor(zombie.health), distCC, currDistance));
if (drawBox) player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, __(zombieCC), zombie.transform.position + new Vector3(0f, 1f, 0f), GetScale(currDistance));
}
else player.SendConsoleCommand("ddraw.box", invokeTime + flickerDelay, __(zombieCC), zombie.transform.position + new Vector3(0f, 1f, 0f), 5f);
if (objectsLimit > 0 && ++drawnObjects > objectsLimit) return false;
}
float k = TerrainMeta.HeightMap.GetHeight(source.transform.position);
entityType = EntityType.Npc;
foreach (var target in cache.NPCPlayers.Where(target => target != null && target.transform != null &&
// ... [Code preview truncated due to length. Full source in attached file] ...