297 lines
8.6 KiB
C#
297 lines
8.6 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Reflection;
|
|
using UnityEngine;
|
|
|
|
namespace IdleSpectator;
|
|
|
|
/// <summary>
|
|
/// Registers plot interest from Harmony hooks and World.plots polling.
|
|
/// Active plots with a target kingdom use sticky PlotCell tips; begin/end stay FixedDwell.
|
|
/// </summary>
|
|
public static class PlotInterestFeed
|
|
{
|
|
public static void Emit(string plotAssetId, Actor subject, string phase)
|
|
{
|
|
if (!AgentHarness.LiveFeedsAllowed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
DiscreteEventEntry entry = EventCatalog.Plot.GetOrFallback(plotAssetId);
|
|
if (!EventCatalog.IsCameraWorthy(entry))
|
|
{
|
|
InterestDropLog.Record("createsInterest=false", "plot");
|
|
return;
|
|
}
|
|
|
|
Actor follow = subject;
|
|
if (follow == null || !follow.isAlive())
|
|
{
|
|
// Plot without a living author: skip rather than invent a stranger.
|
|
return;
|
|
}
|
|
|
|
string label = EventReason.Plot(follow, entry.LabelTemplate, phase, entry.Id);
|
|
string key = "plot:" + entry.Id + ":" + (phase ?? "active") + ":" + EventFeedUtil.SafeId(follow);
|
|
EventFeedUtil.Register(
|
|
key,
|
|
"plot",
|
|
entry.Category,
|
|
label,
|
|
entry.Id,
|
|
entry.EventStrength,
|
|
follow.current_position,
|
|
follow);
|
|
}
|
|
|
|
public static void EmitFromPlot(object plot, string phase)
|
|
{
|
|
if (plot == null || !AgentHarness.LiveFeedsAllowed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
TryRegisterPlot(plot, phase ?? "active");
|
|
}
|
|
|
|
public static void Tick()
|
|
{
|
|
if (!AgentHarness.LiveFeedsAllowed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
IEnumerable plots = ResolvePlotsEnumerable();
|
|
if (plots == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int registered = 0;
|
|
foreach (object plot in plots)
|
|
{
|
|
if (plot == null || registered >= 8)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (TryRegisterPlot(plot, "active"))
|
|
{
|
|
registered++;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static bool TryRegisterPlot(object plot, string phase)
|
|
{
|
|
string assetId = ReadPlotAssetId(plot);
|
|
DiscreteEventEntry entry = EventCatalog.Plot.GetOrFallback(assetId);
|
|
if (!EventCatalog.IsCameraWorthy(entry))
|
|
{
|
|
InterestDropLog.Record("createsInterest=false", "plot:" + (assetId ?? ""));
|
|
return false;
|
|
}
|
|
|
|
string phaseKey = string.IsNullOrEmpty(phase) ? "active" : phase;
|
|
LiveEnsemble ensemble = null;
|
|
if (plot is Plot typedPlot && phaseKey == "active")
|
|
{
|
|
LiveEnsemble.TryBuildPlot(typedPlot, out ensemble);
|
|
}
|
|
|
|
Actor follow = ensemble?.Focus ?? ReadPlotAuthor(plot);
|
|
Actor related = ensemble?.Related;
|
|
if (follow == null || !follow.isAlive())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Vector3 position = Vector3.zero;
|
|
try
|
|
{
|
|
position = follow.current_position;
|
|
}
|
|
catch
|
|
{
|
|
position = Vector3.zero;
|
|
}
|
|
|
|
string plotId = "";
|
|
if (plot is Plot pId)
|
|
{
|
|
try
|
|
{
|
|
plotId = pId.getID().ToString();
|
|
}
|
|
catch
|
|
{
|
|
plotId = "";
|
|
}
|
|
}
|
|
|
|
string key = "plot:" + phaseKey + ":" + (plotId ?? "") + ":" + (entry.Id ?? assetId ?? "plot")
|
|
+ ":" + EventFeedUtil.SafeId(follow);
|
|
string label;
|
|
InterestCompletionKind completion = InterestCompletionKind.FixedDwell;
|
|
float minWatch = 6f;
|
|
float maxWatch = 28f;
|
|
string registerAsset = entry.Id;
|
|
float strength = entry.EventStrength;
|
|
|
|
if (ensemble != null && phaseKey == "active")
|
|
{
|
|
label = EventReason.PlotCell(ensemble);
|
|
if (string.IsNullOrEmpty(label))
|
|
{
|
|
label = EventReason.Ensemble(ensemble);
|
|
}
|
|
|
|
completion = InterestCompletionKind.PlotActive;
|
|
registerAsset = "live_plot";
|
|
minWatch = 8f;
|
|
maxWatch = 40f;
|
|
strength = Mathf.Max(strength, 86f);
|
|
}
|
|
else
|
|
{
|
|
label = EventReason.Plot(follow, entry.LabelTemplate, phaseKey, entry.Id);
|
|
}
|
|
|
|
InterestCandidate registered = EventFeedUtil.Register(
|
|
key,
|
|
"plot",
|
|
entry.Category,
|
|
label,
|
|
registerAsset,
|
|
strength,
|
|
position,
|
|
follow,
|
|
related: related,
|
|
minWatch: minWatch,
|
|
maxWatch: maxWatch,
|
|
completion: completion);
|
|
if (registered == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (ensemble != null)
|
|
{
|
|
registered.CorrelationKey = key;
|
|
StickyScoreboard.TryLockFromEnsemble(registered.Sticky, ensemble);
|
|
StickyScoreboard.Refresh(
|
|
registered,
|
|
ensemble,
|
|
position,
|
|
StickyScoreboard.PlotTheaterRadius);
|
|
registered.Label = EventReason.PlotCell(ensemble);
|
|
if (string.IsNullOrEmpty(registered.Label))
|
|
{
|
|
registered.Label = label;
|
|
}
|
|
|
|
registered.ParticipantCount = ensemble.ParticipantCount;
|
|
registered.AssetId = "live_plot";
|
|
InterestScoring.ScoreCheap(registered);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private static IEnumerable ResolvePlotsEnumerable()
|
|
{
|
|
try
|
|
{
|
|
object world = World.world;
|
|
if (world == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
object plots = world.GetType().GetField("plots")?.GetValue(world)
|
|
?? world.GetType().GetProperty("plots")?.GetValue(world, null);
|
|
if (plots is IEnumerable direct)
|
|
{
|
|
return direct;
|
|
}
|
|
|
|
object manager = world.GetType().GetField("plots_manager")?.GetValue(world)
|
|
?? world.GetType().GetProperty("plots_manager")?.GetValue(world, null)
|
|
?? typeof(PlotManager);
|
|
if (manager is Type)
|
|
{
|
|
manager = null;
|
|
}
|
|
|
|
object mapBox = MapBox.instance;
|
|
if (manager == null && mapBox != null)
|
|
{
|
|
manager = mapBox.GetType().GetField("plots")?.GetValue(mapBox)
|
|
?? mapBox.GetType().GetProperty("plots")?.GetValue(mapBox, null);
|
|
}
|
|
|
|
if (manager == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
MethodInfo getAll = manager.GetType().GetMethod("getSimpleList")
|
|
?? manager.GetType().GetMethod("getList")
|
|
?? manager.GetType().GetMethod("getPlots");
|
|
if (getAll != null)
|
|
{
|
|
return getAll.Invoke(manager, null) as IEnumerable;
|
|
}
|
|
|
|
return manager as IEnumerable;
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static string ReadPlotAssetId(object plot)
|
|
{
|
|
try
|
|
{
|
|
object asset = plot.GetType().GetField("asset")?.GetValue(plot)
|
|
?? plot.GetType().GetProperty("asset")?.GetValue(plot, null)
|
|
?? plot.GetType().GetMethod("getAsset")?.Invoke(plot, null);
|
|
if (asset != null)
|
|
{
|
|
object id = asset.GetType().GetField("id")?.GetValue(asset)
|
|
?? asset.GetType().GetProperty("id")?.GetValue(asset, null);
|
|
if (id != null)
|
|
{
|
|
return id.ToString();
|
|
}
|
|
}
|
|
|
|
object typeId = plot.GetType().GetField("type")?.GetValue(plot)
|
|
?? plot.GetType().GetProperty("type")?.GetValue(plot, null);
|
|
return typeId?.ToString() ?? "unknown";
|
|
}
|
|
catch
|
|
{
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
private static Actor ReadPlotAuthor(object plot)
|
|
{
|
|
try
|
|
{
|
|
object author = plot.GetType().GetField("author")?.GetValue(plot)
|
|
?? plot.GetType().GetProperty("author")?.GetValue(plot, null)
|
|
?? plot.GetType().GetMethod("getAuthor")?.Invoke(plot, null)
|
|
?? plot.GetType().GetField("founder")?.GetValue(plot);
|
|
return author as Actor;
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|