worldbox-observer-mod/docs/event-prose-audit.md

4.1 KiB

Event prose audit (vs game call sites)

Authored IdleSpectator sentences must match what the game actually does when an id fires. Source of truth: Assembly-CSharp apply sites (changeHappiness, relationship patches, status receive), not English guesses from the id string.

Audit date: 2026-07-16. Scope: Happiness (all authored), Relationship (all), Status/WorldLog/Plot/etc. sampled.

Fixed this pass

Id Was Actual Now
just_born "is born into the world" / "first breath" Actor.newCreature spawn; may precede egg form "appears in the world" / "is brought into existence"; strength 48; no hatch strength floor
just_kissed "shares a kiss" Mating afterglow (BehCheckForBabiesFromSexualReproduction) "mates with …" / "shares intimacy …"
just_killed "takes a life" Only with trait bloodlust Explicit bloodlust wording
add_child / EventReason.NewChild "{a} and {b} have a new child" {b} is the child "{a} gains a child, {b}"
baby_created / EventReason.BabyBorn "{a} welcomes a baby" {a} is the baby "{a} is created as a baby"
just_had_child Named newborn {related} Related newborn not wired "has a child" / parenthood only
just_started_war Anyone cheers war Culture trait happiness_from_war "is glad war has started" / culture-loves-war
just_talked Always warm Talk can be good or bad Neutral "finishes talking"
just_inspired Onset of inspiration Status inspired end "comes down from inspiration"
slept_outside Rough night over Sleep start, no house "has to sleep without a house"
just_rebelled Joins / rises Whole city units swept "is swept up as the city rebels"
just_forced_power Vague forced power God force shove "is flung by a god power"
got_caught Shady catch Signal No game caller found Ambient, weak strength
lost_fight Decisive loss Yield / submit mid-fight "is forced to yield"
just_talked_gossip Generic juicy gossip gossip_lovers culture Lover-gossip wording
become_king "crowned king" Any sex ruler "takes the crown" / "becomes ruler"
become_alpha Fight for alpha Oldest living family unit "becomes the family alpha"
Dreams "wakes from …" Dream status on receive "has a … dream"

Policy notes

  • Hatch camera floor (Max(strength, 88)) applies only to just_got_out_of_egg / just_hatched, not just_born.
  • True hatch prose (just_got_out_of_egg → "hatches from an egg") matches Actor.eventHatchFromEgg.
  • Live parent beat is just_had_child, not just_born.

Still clean (sample)

Grief deaths, fallen_in_love, gifts, house find/lose, just_got_out_of_egg, just_became_adult, WorldLog king_new template roles, Status egg / pregnant / drowning prose.

A/B camera policy (2026-07-16)

Interesting = interest candidate. Director ranks by strength.

Happiness Ambient only for true FX: poke, caught stub, tax, ate, pooped. Status CreatesInterest false only for brief FX/cooldowns + egg gain.

Gate helper: EventCatalog.IsCameraWorthy. Drops: InterestDropLog.

Hatch camera path (fixed)

Hatch was Activity-only for many units:

  • Status egg has CreatesInterest=false (becoming an egg is not a camera beat).
  • OnStatusChange previously ignored losses, so "Hatches from an egg" never became interest.
  • Happiness just_got_out_of_egg is often suppressed (!hasEmotions()).
  • Even when a hatch Label existed, dossier identity filter dropped verbs without is (e.g. "Name hatches …").

Fix:

  • Egg status lossInterestFeeds.EmitHatch + EventReason.Hatch, key hatch:{id} shared with happiness.
  • Keep Name verb … EventReason sentences in UnitDossier.OwnedEventReason.

Reasons

EventLed camera candidates always get a Label (orange reason) when ownership + sentence filters pass. Sources: EventReason.*, happiness catalog PlainClause, or discrete catalog templates. Character fill / ambient may show empty reason. Not every Activity line is a camera event (Ambient happiness, status gains with CreatesInterest=false, status losses except egg).