V2 does not author Story, Side Story, Krypt, Chronicles, or DJ Story source
content in the Unreal editor. Hathor owns the source in
apps/hathor/studio-web/; V2 consumes only compiled artifacts emitted by
@hathor/lore-compiler and cooked by Bellona into generated UE assets.
Ownership Boundary#
| Surface | Source owner | V2 input |
|---|---|---|
| Cinematic Story | apps/hathor/studio-web/ |
compiled dialogue, Sequencer outlines, quests |
| Per-fighter Side Stories | apps/hathor/studio-web/ |
compiled timelines, rivalry edges, endings |
| Krypt / reward-vault lore | apps/hathor/studio-web/ |
compiled codex, quest graph, localization |
| Chronicles / Weapon Master campaign | apps/hathor/studio-web/ |
compiled quest graph and strategy scenes |
| DJ Story / street career | apps/hathor/studio-web/ |
compiled crew/faction arcs and cinematics |
V2 may request a published Hathor world by immutable worldId and
versionHash, but it must not ingest mutable authoring metadata into rollback
or gameplay snapshots.
Required Authoring Records#
FighterTimeline#
Every launch fighter has one canonical per-fighter timeline record. Required fields:
| Field | Meaning |
|---|---|
fighterId |
Stable roster id matching the V2 fighter data asset id |
canonEvents |
Shared-canon events used by Story, intros, codex, and sequencer refs |
storyChapters |
Main Story chapter ids where the fighter appears |
sideStoryArcs |
Non-canonical or branchable character episodes |
arcadeEndingIds |
Ending graphs this fighter can resolve to |
careerForkInputs |
MyRISE / MyCAREER branch seeds that can fork player-specific history |
compiledOutputKey |
V2/ue/Content/Generated/Timelines/<fighter>.uasset target key |
Validation:
fighterIdmust resolve to a V2 roster id.- Every
storyChaptersentry must exist in the Story content pack. - Every
arcadeEndingIdsentry must resolve to aLadderEndingGraph. - Canon events are append-only once a Hathor world version is published.
RivalryMatrix#
The rivalry matrix is a roster-level relationship graph. Each edge contains:
| Field | Meaning |
|---|---|
a, b |
Fighter ids; unordered for symmetric relationships |
type |
nemesis, rival, friendly-rival, mentor, student, family-ally, family-nemesis, love-interest, respect, neutral |
intensity |
0.0 to 1.0 value used by intros, Story branches, and barks |
motif |
Short stable motif key, such as ice-vs-fire |
canonScope |
canon, what-if, career-fork, or post-launch-crossover |
Validation:
- No duplicate unordered pair exists in the same
canonScope. intensitymust be numeric and clamped to[0.0, 1.0].- A non-neutral edge must reference at least one dialogue bank or Sequencer beat.
- Cross-franchise edges must be gated by a release flag.
FactionMatrix#
The faction matrix maps fighters, crews, realms, stables, gyms, labels, and Chronicles kingdoms into relationship edges. Each edge contains:
| Field | Meaning |
|---|---|
sourceFactionId |
Stable Hathor faction id |
targetFactionId |
Stable Hathor faction id |
stance |
ally, tense-ally, neutral, rival, war, or vassal |
modeScopes |
V2 modes where the stance is active |
unlockConditions |
Optional quest, timeline, or player-career gates |
compiledOutputKey |
V2/ue/Content/Generated/Rivalry/FactionMatrix.uasset target |
Validation:
- Every faction referenced by Story, Krypt, Chronicles, or DJ Story appears in at least one matrix edge.
- Directed stances such as
vassalmust declare direction explicitly. - Player-mutated career forks are emitted as save-scoped overlays, not changes to the published canonical matrix.
LadderEndingGraph#
Every fighter has at least one ladder ending graph. Required fields:
| Field | Meaning |
|---|---|
endingGraphId |
Stable graph id |
fighterId |
Fighter this graph belongs to |
encounterNodes |
Ordered or branched fight nodes |
bossNodeId |
Required final boss encounter |
endingCinematicId |
Required Sequencer outline id |
canonScope |
canon, what-if, joke, crossover, or career |
compiledOutputKey |
V2/ue/Content/Generated/Quests/Arcade/<fighter>.json |
Validation:
- The graph is acyclic except for explicit challenge-loop nodes.
- Every terminal path reaches
bossNodeIdand thenendingCinematicId. - Non-canonical endings are tagged so Story Theater and codex do not present them as canon.
SideStorySequencerOutline#
Side Story cinematics are authored as Hathor Sequencer outlines, not UE Level Sequence source assets. Required fields:
| Field | Meaning |
|---|---|
outlineId |
Stable scene outline id |
surface |
story, side_story, krypt, chronicles, or dj_story |
participants |
Fighter, NPC, faction, or venue ids |
shots |
Ordered shot ids with camera intent, dialogue ids, and timing |
branchHooks |
Optional player-choice or career-fork hook ids |
localizationKeys |
String-table keys emitted with the compiled package |
compiledOutputKey |
V2/ue/Content/Generated/Sequencer/<outline>.uasset target |
Validation:
- Each shot has a deterministic order, stable id, and non-empty camera intent.
- Dialogue ids resolve to Hathor dialogue-bank records.
- Branch hooks name authored branches only; V2 does not invent branches in UE.
Compiler Handoff#
@hathor/lore-compiler emits:
V2/ue/Content/Generated/Dialogue/<surface>/V2/ue/Content/Generated/Sequencer/<outline>.uassetV2/ue/Content/Generated/Quests/<mode>/V2/ue/Content/Generated/Timelines/<fighter>.uassetV2/ue/Content/Generated/Rivalry/Matrix.uassetV2/ue/Content/Generated/Rivalry/FactionMatrix.uassetV2/ue/Content/Generated/Codex/- UE localization string-table exports
The compiler package must include a content-addressed manifest with worldId,
versionHash, compiler package version, artifact hashes, and Bellona cook
lineage ids. V2 stores only immutable ids and hashes in gameplay-facing
snapshots.
Reciprocal Hathor Work#
The reciprocal Hathor backlog lives in
docs/domains/hathor/deep-dive/specifications.md § 9.6. At minimum, Hathor must
extend @hathor/domain-models, @hathor/narrative, and @hathor/lore-compiler
with FighterTimeline, RivalryMatrix, FactionMatrix, LadderEndingGraph,
and SideStorySequencerOutline before V2 Story Mode, Side Stories, Krypt,
Chronicles, or DJ Story can ship.