worldbox-observer-mod/IdleSpectator/RelationshipEventPatches.cs
2026-07-15 22:16:24 -05:00

186 lines
5.4 KiB
C#

using System;
using ai.behaviours;
using HarmonyLib;
namespace IdleSpectator;
/// <summary>Relationship lifecycle patches from mutation discovery.</summary>
[HarmonyPatch]
public static class RelationshipEventPatches
{
[HarmonyPatch(typeof(Actor), nameof(Actor.setLover))]
[HarmonyPostfix]
public static void PostfixSetLover(Actor __instance, Actor pActor)
{
if (__instance == null || !__instance.isAlive())
{
return;
}
if (pActor == null)
{
RelationshipInterestFeed.Emit("clear_lover", __instance, null);
return;
}
RelationshipInterestFeed.Emit("set_lover", __instance, pActor);
}
[HarmonyPatch(typeof(Actor), nameof(Actor.addChild))]
[HarmonyPostfix]
public static void PostfixAddChild(Actor __instance, object pObject)
{
Actor child = ResolveRelatedActor(pObject);
if (__instance == null || child == null)
{
return;
}
RelationshipInterestFeed.Emit("add_child", __instance, child);
}
[HarmonyPatch(typeof(Actor), "addChildSimple")]
[HarmonyPostfix]
public static void PostfixAddChildSimple(Actor __instance, object pObject)
{
Actor child = ResolveRelatedActor(pObject);
if (__instance == null || child == null)
{
return;
}
RelationshipInterestFeed.Emit("add_child", __instance, child);
}
private static Actor ResolveRelatedActor(object raw)
{
if (raw == null)
{
return null;
}
if (raw is Actor actor)
{
return actor;
}
try
{
if (raw is BaseSimObject sim && sim.isActor())
{
return sim.a;
}
}
catch
{
// fall through
}
try
{
var type = raw.GetType();
foreach (string name in new[] { "actor", "Actor", "a", "parent" })
{
var prop = type.GetProperty(name);
if (prop != null && typeof(Actor).IsAssignableFrom(prop.PropertyType))
{
return prop.GetValue(raw, null) as Actor;
}
var field = type.GetField(name);
if (field != null && typeof(Actor).IsAssignableFrom(field.FieldType))
{
return field.GetValue(raw) as Actor;
}
}
var getActor = type.GetMethod("getActor", Type.EmptyTypes)
?? type.GetMethod("GetActor", Type.EmptyTypes);
if (getActor != null && typeof(Actor).IsAssignableFrom(getActor.ReturnType))
{
return getActor.Invoke(raw, null) as Actor;
}
}
catch
{
// ignore
}
return null;
}
[HarmonyPatch(typeof(FamilyManager), nameof(FamilyManager.newFamily))]
[HarmonyPostfix]
public static void PostfixNewFamily(Family __result, Actor pActor)
{
Actor anchor = pActor != null && pActor.isAlive() ? pActor : null;
RelationshipInterestFeed.EmitFamily("new_family", __result, anchor);
}
[HarmonyPatch(typeof(FamilyManager), "removeObject", new Type[] { typeof(Family) })]
[HarmonyPostfix]
public static void PostfixRemoveFamily(Family pObject)
{
RelationshipInterestFeed.EmitFamily("family_removed", pObject, null);
}
[HarmonyPatch(typeof(ActorManager), "createBabyActorFromData")]
[HarmonyPostfix]
public static void PostfixCreateBaby(Actor __result)
{
if (__result == null || !__result.isAlive())
{
return;
}
RelationshipInterestFeed.Emit("baby_created", __result, null);
}
[HarmonyPatch(typeof(BehFindLover), nameof(BehFindLover.execute))]
[HarmonyPostfix]
public static void PostfixFindLover(Actor pActor, BehResult __result)
{
if (pActor == null || !pActor.isAlive() || __result == BehResult.Stop)
{
return;
}
RelationshipInterestFeed.Emit("find_lover", pActor, null);
}
[HarmonyPatch(typeof(BehFamilyGroupNew), nameof(BehFamilyGroupNew.execute))]
[HarmonyPostfix]
public static void PostfixFamilyNew(Actor pActor, BehResult __result)
{
if (pActor == null || !pActor.isAlive() || __result == BehResult.Stop)
{
return;
}
RelationshipInterestFeed.Emit("family_group_new", pActor, ActorRelation.ResolvePackRelated(pActor));
}
[HarmonyPatch(typeof(BehFamilyGroupJoin), nameof(BehFamilyGroupJoin.execute))]
[HarmonyPostfix]
public static void PostfixFamilyJoin(Actor pActor, BehResult __result)
{
if (pActor == null || !pActor.isAlive() || __result == BehResult.Stop)
{
return;
}
RelationshipInterestFeed.Emit("family_group_join", pActor, ActorRelation.ResolvePackRelated(pActor));
}
[HarmonyPatch(typeof(BehFamilyGroupLeave), nameof(BehFamilyGroupLeave.execute))]
[HarmonyPostfix]
public static void PostfixFamilyLeave(Actor pActor, BehResult __result)
{
if (pActor == null || !pActor.isAlive() || __result == BehResult.Stop)
{
return;
}
RelationshipInterestFeed.Emit("family_group_leave", pActor, ActorRelation.ResolvePackRelated(pActor));
}
}