using System; using ai.behaviours; using HarmonyLib; namespace IdleSpectator; /// Relationship lifecycle patches from mutation discovery. [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)); } }