worldbox-observer-mod/IdleSpectator/Events/Feeds/RelationshipInterestFeed.cs
2026-07-16 00:40:53 -05:00

188 lines
6.1 KiB
C#

using UnityEngine;
namespace IdleSpectator;
/// <summary>Registers relationship lifecycle interest candidates under the ownership contract.</summary>
public static class RelationshipInterestFeed
{
public static void Emit(string eventId, Actor subject, Actor related, string labelOverride = null)
{
if (AgentHarness.Busy || subject == null || !subject.isAlive())
{
return;
}
DiscreteEventEntry entry = EventCatalog.Relationship.GetOrFallback(eventId);
if (!entry.CreatesInterest)
{
return;
}
Actor relatedAlive = related != null && related.isAlive() ? related : null;
bool claimsPeer = eventId == "family_group_new"
|| eventId == "family_group_join"
|| eventId == "family_group_leave"
|| eventId == "set_lover"
|| eventId == "add_child";
if (claimsPeer && relatedAlive == null)
{
relatedAlive = ActorRelation.ResolvePackRelated(subject);
}
string label = !string.IsNullOrEmpty(labelOverride)
? labelOverride
: TypedLabel(eventId, subject, relatedAlive);
if (claimsPeer && relatedAlive == null)
{
string soloKey = "rel:" + entry.Id + ":" + EventFeedUtil.SafeId(subject) + ":solo";
EventFeedUtil.Register(
soloKey,
"relationship",
entry.Category,
label,
entry.Id,
Mathf.Min(entry.EventStrength, 40f),
subject.current_position,
subject);
return;
}
string key = "rel:" + entry.Id + ":" + EventFeedUtil.SafeId(subject) + ":" + EventFeedUtil.SafeId(relatedAlive);
EventFeedUtil.Register(
key,
"relationship",
entry.Category,
label,
entry.Id,
entry.EventStrength,
subject.current_position,
subject,
related: relatedAlive);
}
public static void EmitFamily(string eventId, object family, Actor anchor)
{
if (AgentHarness.Busy)
{
return;
}
DiscreteEventEntry entry = EventCatalog.Relationship.GetOrFallback(eventId);
Actor follow = anchor != null && anchor.isAlive() ? anchor : null;
if (follow == null)
{
follow = FirstFamilyMember(family);
}
if (follow == null)
{
return;
}
Actor related = ActorRelation.FirstFamilyPeer(follow);
string label = TypedLabel(eventId, follow, related);
string key = "rel:" + entry.Id + ":" + EventFeedUtil.SafeId(follow);
EventFeedUtil.Register(
key,
"relationship",
entry.Category,
label,
entry.Id,
entry.EventStrength,
follow.current_position,
follow,
related: related);
}
private static string TypedLabel(string eventId, Actor subject, Actor related)
{
switch (eventId)
{
case "set_lover":
return EventReason.Lovers(subject, related);
case "clear_lover":
return EventReason.LoverParted(subject);
case "find_lover":
return EventReason.SeekingLover(subject);
case "add_child":
return EventReason.NewChild(subject, related);
case "baby_created":
return EventReason.BabyBorn(subject);
case "new_family":
return EventReason.NewFamily(subject);
case "family_removed":
return EventReason.FamilyEnded(subject);
case "family_group_new":
return EventReason.FamilyPack(subject, related, "form");
case "family_group_join":
return EventReason.FamilyPack(subject, related, "join");
case "family_group_leave":
return EventReason.FamilyPack(subject, related, "leave");
default:
return EventReason.Apply(
EventCatalog.Relationship.GetOrFallback(eventId).LabelTemplate,
subject,
related,
eventId);
}
}
private static Actor FirstFamilyMember(object family)
{
if (family == null)
{
return null;
}
try
{
foreach (Actor member in ActorRelation.EnumerateFamilyMembers(
ActorRelation.ResolveActor(
family.GetType().GetField("founder")?.GetValue(family)
?? family.GetType().GetProperty("founder")?.GetValue(family, null))
?? null,
max: 1))
{
return member;
}
}
catch
{
// fall through
}
try
{
object list = family.GetType().GetField("units")?.GetValue(family)
?? family.GetType().GetProperty("units")?.GetValue(family, null)
?? family.GetType().GetMethod("getUnits")?.Invoke(family, null)
?? family.GetType().GetMethod("getSimpleList")?.Invoke(family, null);
if (list is System.Collections.IEnumerable enumerable)
{
foreach (object raw in enumerable)
{
Actor a = ActorRelation.ResolveActor(raw);
if (a != null && a.isAlive())
{
return a;
}
}
}
Actor founder = family.GetType().GetField("founder")?.GetValue(family) as Actor
?? family.GetType().GetProperty("founder")?.GetValue(family, null) as Actor;
if (founder != null && founder.isAlive())
{
return founder;
}
}
catch
{
// ignore
}
return null;
}
}