using System; using HarmonyLib; namespace IdleSpectator; /// Actor trait add/remove interest patches from mutation discovery. [HarmonyPatch] public static class TraitEventPatches { [HarmonyPatch(typeof(Actor), nameof(Actor.addTrait), new Type[] { typeof(string), typeof(bool) })] [HarmonyPostfix] public static void PostfixAddTraitString(Actor __instance, string pTraitID, bool __result) { if (!__result || __instance == null || !__instance.isAlive() || string.IsNullOrEmpty(pTraitID)) { return; } Emit(pTraitID, __instance, gained: true); } [HarmonyPatch(typeof(Actor), nameof(Actor.addTrait), new Type[] { typeof(ActorTrait), typeof(bool) })] [HarmonyPostfix] public static void PostfixAddTraitAsset(Actor __instance, ActorTrait pTrait, bool __result) { if (!__result || __instance == null || !__instance.isAlive() || pTrait == null) { return; } string id = ""; try { id = pTrait.id ?? ""; } catch { id = ""; } if (string.IsNullOrEmpty(id)) { return; } Emit(id, __instance, gained: true); } [HarmonyPatch(typeof(Actor), nameof(Actor.removeTrait), new Type[] { typeof(string) })] [HarmonyPostfix] public static void PostfixRemoveTraitString(Actor __instance, string pTraitID) { if (__instance == null || !__instance.isAlive() || string.IsNullOrEmpty(pTraitID)) { return; } Emit(pTraitID, __instance, gained: false); } [HarmonyPatch(typeof(Actor), nameof(Actor.removeTrait), new Type[] { typeof(ActorTrait) })] [HarmonyPostfix] public static void PostfixRemoveTraitAsset(Actor __instance, ActorTrait pTrait, bool __result) { if (!__result || __instance == null || !__instance.isAlive() || pTrait == null) { return; } string id = ""; try { id = pTrait.id ?? ""; } catch { id = ""; } if (string.IsNullOrEmpty(id)) { return; } Emit(id, __instance, gained: false); } private static void Emit(string traitId, Actor actor, bool gained) { if (AgentHarness.Busy) { return; } DiscreteEventEntry entry = TraitInterestCatalog.GetOrFallback(traitId); if (!entry.CreatesInterest) { return; } InterestOwnership owns = entry.OwnsCamera; if (!gained && owns == InterestOwnership.Signal) { owns = InterestOwnership.Ambient; } string phase = gained ? "gains" : "loses"; string label = EventFeedUtil.SafeName(actor) + " " + phase + " " + entry.Id; string key = "trait:" + entry.Id + ":" + phase + ":" + EventFeedUtil.SafeId(actor); EventFeedUtil.Register( key, "trait", entry.Category, label, entry.Id, entry.EventStrength, owns, actor.current_position, actor); } }