C#:
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("AlphaAnimals Map" , "Krungh Crow" , "1.0.1")]
[Description("Shows AlphaAnimals on the map with moving icon markers.")]
public class AlphaAnimalsMap : RustPlugin
{
private const string VENDING_PREFAB = "assets/prefabs/deployable/vendingmachine/vending_mapmarker.prefab";
private const string RADIUS_PREFAB = "assets/prefabs/tools/map/genericradiusmarker.prefab";
private readonly Dictionary<NetworkableId , AnimalMarkerTracker> activeTrackers =
new Dictionary<NetworkableId , AnimalMarkerTracker>();
private PluginConfig configData;
private class PluginConfig
{
[JsonProperty(PropertyName = "Marker Settings")]
public MarkerSettings Marker = new MarkerSettings();
}
private class MarkerSettings
{
[JsonProperty(PropertyName = "Primary Color (Hex)")]
public string PrimaryColor = "#00FF00";
[JsonProperty(PropertyName = "Secondary Color (Hex)")]
public string SecondaryColor = "#000000";
[JsonProperty(PropertyName = "Alpha")]
public float Alpha = 0.45f;
[JsonProperty(PropertyName = "Radius")]
public float Radius = 0.2f;
}
private readonly Dictionary<string , string> prettyNames = new Dictionary<string , string>
{
["bear"] = "Bear" ,
["polarbear"] = "Polar Bear" ,
["wolf"] = "Wolf" ,
["wolf2"] = "Wolf" ,
["crocodile"] = "Crocodile" ,
["panther"] = "Panther" ,
["tiger"] = "Tiger" ,
};
private void Init()
{
LoadConfigVariables();
}
private bool LoadConfigVariables()
{
try
{
configData = Config.ReadObject<PluginConfig>();
}
catch
{
PrintWarning("Config file issue detected. Loading default values.");
LoadDefaultConfig();
}
if (configData == null)
configData = new PluginConfig();
if (configData.Marker == null)
configData.Marker = new MarkerSettings();
SaveConfig();
return true;
}
protected override void LoadDefaultConfig()
{
configData = new PluginConfig();
SaveConfig();
}
protected override void SaveConfig()
{
Config.WriteObject(configData , true);
}
private Color GetConfiguredColor(string value , Color fallback)
{
Color color;
if (!string.IsNullOrEmpty(value) && ColorUtility.TryParseHtmlString(value , out color))
return color;
return fallback;
}
private void OnServerInitialized()
{
NextTick(() =>
{
foreach (var entity in BaseNetworkable.serverEntities)
{
var combat = entity as BaseCombatEntity;
if (combat == null || combat.net == null) continue;
if (activeTrackers.ContainsKey(combat.net.ID)) continue;
if (!IsAlphaTarget(combat)) continue;
var label = BuildLabel(combat);
SpawnMarkers(combat , label);
}
});
}
private void OnEntitySpawned(BaseNetworkable entity)
{
var combat = entity as BaseCombatEntity;
if (combat == null || combat.net == null) return;
if (!(combat is BaseAnimalNPC) && !(combat is BaseNpc)) return;
if (activeTrackers.ContainsKey(combat.net.ID)) return;
NextTick(() =>
{
if (combat == null || combat.net == null || combat.IsDestroyed) return;
if (activeTrackers.ContainsKey(combat.net.ID)) return;
if (!IsAlphaTarget(combat)) return;
var label = BuildLabel(combat);
SpawnMarkers(combat , label);
});
}
private bool IsAlphaTarget(BaseCombatEntity ent)
{
if (ent == null) return false;
var n = ent.name;
if (string.IsNullOrEmpty(n)) return false;
if (n.IndexOf("Omega" , System.StringComparison.OrdinalIgnoreCase) >= 0) return false;
return n.IndexOf("Alpha" , System.StringComparison.OrdinalIgnoreCase) >= 0;
}
private string BuildLabel(BaseCombatEntity ent)
{
var be = ent as BaseEntity;
if (be != null)
{
var prefab = be.ShortPrefabName;
if (!string.IsNullOrEmpty(prefab))
{
string pretty;
if (prettyNames.TryGetValue(prefab , out pretty))
return $"Alpha {pretty}";
}
}
return (ent.name ?? "Alpha").Replace("(Clone)" , "").Trim();
}
private void SpawnMarkers(BaseCombatEntity ent , string label)
{
var pos = ent.transform.position;
var iconMarker = GameManager.server.CreateEntity(VENDING_PREFAB , pos) as VendingMachineMapMarker;
if (iconMarker == null) return;
iconMarker.markerShopName = label;
iconMarker.globalBroadcast = true;
iconMarker.Spawn();
using (var flags = iconMarker.StartSetFlags(BaseEntity.FlagsUpdateMode.SendNetworkUpdate))
{
flags.Set(BaseEntity.Flags.On , true);
}
var radiusMarker = GameManager.server.CreateEntity(RADIUS_PREFAB , pos) as MapMarkerGenericRadius;
if (radiusMarker != null)
{
radiusMarker.alpha = Mathf.Clamp01(configData.Marker.Alpha);
radiusMarker.color1 = GetConfiguredColor(configData.Marker.PrimaryColor , Color.green);
radiusMarker.color2 = GetConfiguredColor(configData.Marker.SecondaryColor , Color.black);
radiusMarker.radius = Mathf.Max(0.01f , configData.Marker.Radius);
radiusMarker.enabled = true;
radiusMarker.Spawn();
radiusMarker.SendUpdate();
}
var tracker = ent.gameObject.AddComponent<AnimalMarkerTracker>();
tracker.Setup(this , ent , iconMarker , radiusMarker);
activeTrackers[ent.net.ID] = tracker;
}
private void CleanupFor(BaseCombatEntity ent)
{
if (ent == null || ent.net == null) return;
AnimalMarkerTracker tracker;
if (activeTrackers.TryGetValue(ent.net.ID , out tracker))
tracker.Cleanup();
}
private void OnEntityKill(BaseNetworkable entity)
{
var combat = entity as BaseCombatEntity;
if (combat == null) return;
CleanupFor(combat);
}
private void OnEntityDeath(BaseCombatEntity entity , HitInfo info)
{
if (entity == null) return;
CleanupFor(entity);
}
private void Unload()
{
var trackers = new List<AnimalMarkerTracker>(activeTrackers.Values);
foreach (var tracker in trackers)
{
if (tracker != null) tracker.Cleanup();
}
activeTrackers.Clear();
}
public class AnimalMarkerTracker : MonoBehaviour
{
private AlphaAnimalsMap plugin;
private BaseCombatEntity ent;
private VendingMachineMapMarker iconMarker;
private MapMarkerGenericRadius radiusMarker;
public void Setup(AlphaAnimalsMap pluginInstance , BaseCombatEntity entity , VendingMachineMapMarker icon , MapMarkerGenericRadius radius)
{
plugin = pluginInstance;
ent = entity;
iconMarker = icon;
radiusMarker = radius;
InvokeRepeating(nameof(UpdatePosition) , 1.0f , 1.0f);
}
private void UpdatePosition()
{
if (ent == null || ent.IsDestroyed || ent.IsDead())
{
Cleanup();
return;
}
var pos = ent.transform.position;
if (iconMarker != null && !iconMarker.IsDestroyed)
{
iconMarker.transform.position = pos;
iconMarker.TransformChanged();
iconMarker.SendNetworkUpdate();
}
if (radiusMarker != null && !radiusMarker.IsDestroyed)
{
radiusMarker.transform.position = pos;
radiusMarker.TransformChanged();
radiusMarker.SendNetworkUpdate();
radiusMarker.SendUpdate();
}
}
public void Cleanup()
{
CancelInvoke();
if (ent != null && ent.net != null && plugin != null)
plugin.activeTrackers.Remove(ent.net.ID);
if (iconMarker != null && !iconMarker.IsDestroyed)
iconMarker.Kill();
if (radiusMarker != null && !radiusMarker.IsDestroyed)
radiusMarker.Kill();
Destroy(this);
}
}
}
}