feat(bridge): map.live names RunicNPC's NPCs, marks bosses and adds (runicnpc stage 8) #26
@@ -13076,6 +13076,73 @@ namespace Oxide.Plugins
|
||||
return e == null || e.IsDestroyed || e.transform == null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main thread. RunicNPC's NPCs keyed by net id as text (a ledger entry's id), from
|
||||
/// `RunicNpc_List`; empty when RunicNPC is not loaded or answers anything else.
|
||||
/// </summary>
|
||||
private Dictionary<string, Dictionary<string, object>> RunicNpcsForMap()
|
||||
{
|
||||
var byId = new Dictionary<string, Dictionary<string, object>>();
|
||||
Plugin npc = RunicNpcPlugin();
|
||||
|
||||
if (npc == null)
|
||||
return byId;
|
||||
|
||||
var listed = npc.Call("RunicNpc_List", (string)null) as List<Dictionary<string, object>>;
|
||||
|
||||
if (listed == null)
|
||||
return byId;
|
||||
|
||||
foreach (Dictionary<string, object> d in listed)
|
||||
{
|
||||
object id;
|
||||
|
||||
if (d != null && d.TryGetValue("netId", out id) && id != null)
|
||||
byId[id.ToString()] = d;
|
||||
}
|
||||
|
||||
return byId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A RunicNPC NPC's name, and for a boss `boss` and its health as a fraction. The health is
|
||||
/// for the event page's progress line; the site's map does not show it (D303).
|
||||
/// </summary>
|
||||
private static void MapNpcFields(Dictionary<string, object> row, Dictionary<string, object> npc)
|
||||
{
|
||||
object value;
|
||||
|
||||
if (npc.TryGetValue("name", out value) && value is string)
|
||||
row["name"] = value;
|
||||
|
||||
if (!npc.TryGetValue("boss", out value) || value == null)
|
||||
return;
|
||||
|
||||
row["boss"] = true;
|
||||
|
||||
object health, max;
|
||||
|
||||
if (npc.TryGetValue("health", out health) && npc.TryGetValue("maxHealth", out max))
|
||||
{
|
||||
double h = Convert.ToDouble(health), m = Convert.ToDouble(max);
|
||||
|
||||
if (m > 0)
|
||||
row["health"] = Math.Round(Math.Max(0, Math.Min(1, h / m)), 3);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Where one of RunicNPC's NPCs stands, from its `RunicNpc_List` row.</summary>
|
||||
private static Dictionary<string, object> MapNpcAt(Dictionary<string, object> npc)
|
||||
{
|
||||
object value;
|
||||
var p = npc.TryGetValue("position", out value) ? value as Dictionary<string, object> : null;
|
||||
|
||||
if (p == null)
|
||||
return At(UnityEngine.Vector3.zero);
|
||||
|
||||
return At(new UnityEngine.Vector3(Convert.ToSingle(p["x"]), 0f, Convert.ToSingle(p["z"])));
|
||||
}
|
||||
|
||||
private static Dictionary<string, object> At(UnityEngine.Vector3 p)
|
||||
{
|
||||
return new Dictionary<string, object>
|
||||
@@ -13140,6 +13207,10 @@ namespace Oxide.Plugins
|
||||
|
||||
var events = new List<object>();
|
||||
|
||||
// RunicNPC's own NPCs by net id, for their names, bosses and a boss's adds (runicnpc
|
||||
// stage 8, D302, D303). Empty without RunicNPC.
|
||||
Dictionary<string, Dictionary<string, object>> runic = RunicNpcsForMap();
|
||||
|
||||
foreach (WorldEntry w in _world.Values)
|
||||
{
|
||||
Dictionary<string, object> row;
|
||||
@@ -13162,6 +13233,17 @@ namespace Oxide.Plugins
|
||||
|
||||
row = At(found.transform.position);
|
||||
row["prefab"] = w.Prefab;
|
||||
|
||||
// The step that placed it, so a step's NPCs still standing can be counted.
|
||||
row["key"] = w.Key;
|
||||
|
||||
Dictionary<string, object> npc;
|
||||
|
||||
if (runic.TryGetValue(w.Id, out npc))
|
||||
{
|
||||
MapNpcFields(row, npc);
|
||||
runic.Remove(w.Id);
|
||||
}
|
||||
}
|
||||
|
||||
row["kind"] = w.Kind;
|
||||
@@ -13169,6 +13251,37 @@ namespace Oxide.Plugins
|
||||
events.Add(row);
|
||||
}
|
||||
|
||||
// What is left of RunicNPC's list was placed by no step. A boss's adds are owned by its
|
||||
// run (`run:<id>`) and join the events layer under it; any other boss is in the open
|
||||
// world, as cargo or a helicopter is. A placement's ordinary NPCs are not on the map.
|
||||
foreach (Dictionary<string, object> npc in runic.Values)
|
||||
{
|
||||
object value;
|
||||
string owner = npc.TryGetValue("owner", out value) ? value as string : null;
|
||||
bool boss = npc.TryGetValue("boss", out value) && value != null;
|
||||
Dictionary<string, object> row;
|
||||
|
||||
if (owner != null && owner.StartsWith("run:", StringComparison.Ordinal))
|
||||
{
|
||||
row = MapNpcAt(npc);
|
||||
MapNpcFields(row, npc);
|
||||
row["kind"] = WorldKindNpc;
|
||||
row["runId"] = owner.Substring(4);
|
||||
row["add"] = true;
|
||||
events.Add(row);
|
||||
}
|
||||
else if (boss)
|
||||
{
|
||||
row = MapNpcAt(npc);
|
||||
row["kind"] = "boss";
|
||||
|
||||
if (npc.TryGetValue("name", out value) && value is string)
|
||||
row["name"] = value;
|
||||
|
||||
world.Add(row);
|
||||
}
|
||||
}
|
||||
|
||||
var players = new List<object>();
|
||||
|
||||
foreach (BasePlayer p in BasePlayer.activePlayerList)
|
||||
|
||||
Reference in New Issue
Block a user