# Relationships, Progression & Creator Suite

```mermaid
erDiagram
  ACCOUNT ||--o{ FIGHTER_MASTERY : earns
  FIGHTER ||--o{ FIGHTER_MASTERY : tracks
  FIGHTER }o--o{ RELATIONSHIP : participates
  RELATIONSHIP ||--o{ TIMELINE_EVENT : records
  ACCOUNT ||--o{ CREATED_FIGHTER : authors
  CREATED_FIGHTER ||--o{ APPEARANCE_VERSION : versions
  CREATED_FIGHTER ||--o{ MOVESET_LOADOUT : equips
  ACCOUNT ||--o{ PROFILE_CARD : owns
  MATCH ||--o{ PROGRESSION_EVENT : produces
  PROGRESSION_EVENT }o--o{ FIGHTER_MASTERY : advances
  TIMELINE_EVENT }o--o{ CODEX_ENTRY : unlocks
```

Roster lore, authored fighter versions, account/fighter mastery, match-derived
progression, and codex unlocks are related but independently governed. Creator
customization cannot rewrite canonical fighter or competitive data.

This is the product-side view of everything that wraps _around_ the fight: who
these 60 fighters are to each other, what a player earns by playing them, and
the authoring surface that lets a player build their own. A fighting game lives
or dies on its moment-to-moment combat — but it _retains_ on the connective
tissue: the rival you keep meeting on the Arcade ladder, the mastery bar that
ticks toward a signature finisher, the wrestler you sculpted slider-by-slider
and gave your own theme. This page inventories three systems as **features** —
the per-fighter rivals / relationship matrix / cross-character timeline (the
story layer), fighter and account progression with the codex and encyclopedia,
and the Creator Suite plus the personalization layer of profile cards,
championships, and match history — and points at the exact data, C++, contracts,
and CI gates that back each one.

The throughline here is V2's quieter discipline: **narrative, progression, and
authoring are data, validated by real gates, not prose in a design doc.** The
relationships between fighters are a typed CSV the build can prove is
consistent; mastery curves are a spreadsheet a designer edits; the Creator Suite
is a family of `UBlueprintFunctionLibrary` validators with fail-loud rejection
tags, the same pattern the combat resolver uses. For the full mode taxonomy,
roster, and the rest of the scope this slots into, start at the feature hub:
[../V2_features.md](../V2_features.md).

## What ships, honestly

Three honest layers, labeled. **First, the story/relationship layer is data plus
gates.** The rivalries, the relationship matrix, the cross-character timeline,
the faction map, and the convergent endings are authored as CSV and Markdown
under `V2/balance/lore/`, described by a JSON contract at
`V2/ue/Content/V2/Lore/RelationshipTimeline_V2_Contract.json`, and held
consistent by a **422-line Python CI checker**
(`check-v2-relationship-timeline.py`) that fails the build on any inconsistency.
The _narrative itself_ — the voice-over, cinematics, comic art — is not in the
repo; per the contract's `sourceBoundary`, the authoring source lives in a
sister monorepo (`apps/hathor/studio-web/`, via `@hathor/lore-compiler`) and V2
owns the launch-roster ids, the compiled artifact ids, the profile-timeline
presentation, and the V2Editor tooling.

**Second, progression is a real spreadsheet-of-truth plus real save logic.** The
mastery curves, account-level rewards, prestige tiers, codex entries, quest
catalog, and reward-inbox rules live under `V2/balance/progression/` and
`V2/balance/codex/`, gated by a **412-line checker**
(`check-v2-player-progression-codex-quest-inbox.py`); the runtime side is real
C++ — `FV2ProgressionTrack::AddXP` is a genuine level-up loop, and the
`FV2MatchHistoryArchive` actually dedups, sorts, and caps history.

**Third, the Creator Suite is substantive, tested C++.** CAW/Create-a-Soul, the
Move Editor, the variation system, profile cards, and save integrity are real
`USTRUCT`/`UBlueprintFunctionLibrary` code in `V2Gameplay`, `V2Combat`, and
`V2Persistence`, exercised by automation specs under `V2/ue/Source/V2Tests`
(`Gameplay.Module`, `Persistence.Module`, `MorphTargetRig`, `MovesetDataAsset`,
`ProfileSave`, …) and gated by a fleet of `check-v2-create-*.py` scripts. The
honest qualification: there are **no `.uasset` binaries** in the repo — this is
a logic-and-data skeleton, the editor _authoring UI_ is modeled as descriptor
types rather than shipped Slate panels, and `face-from-photo` via MetaHuman is
**license-gated** (manual sculpt always works). What exists is real; what's
absent (art, audio, the interactive editor chrome) is absent honestly.

## Rivals, the relationship matrix & the cross-character timeline

V2 models its roster as a _graph_, not a cast list. Three datasets describe who
fighters are to each other, and a fourth ties their history into a single canon.

### Rivals — reciprocal primaries, 2–3 secondaries

`V2/balance/lore/rivals.csv` gives all **60** launch fighters a `primary_rival`
and a pipe-delimited `secondary_rivals` list. The primary rivalry is the spine
of the Arcade mid-ladder rival fight, the Story banter, and the lore-page
cross-references; secondaries seed Side Stories, Konquest, and per-matchup
banter. The checker enforces the rules that make a rivalry _mean_ something:
`Fighter.Asha`'s primary is `Fighter.Mara`, and Mara's primary must be Asha
(reciprocity), no fighter may rival itself, every named rival must be a real
roster id, and each fighter carries exactly **2–3** secondaries that don't
duplicate self or primary. A one-directional or dangling rivalry fails CI.

### The relationship matrix — typed, drive-tagged, asymmetric

`relationship-matrix.csv` is the richer structure: **78 directed edges**, each
typed from the canonical set the contract pins — `Ally`, `Friend`, `Rival`,
`Enemy`, `Mentor`, `Student`, `Mentor-Betrayed`, `Family`, `Romantic`,
`Cordial`, `Indifferent` (default `Indifferent`) — and each carrying a `drives`
list naming what it feeds (`arcade-rival`, `story-banter`, `mygm-feud`,
`side-story`, `profile-timeline`, …). Because the edges are _directed_, the
matrix supports **asymmetric relationships**, and the data uses them
deliberately: `Fighter.Cassia → Fighter.ChunLi` is a `Friend`, while
`Fighter.ChunLi → Fighter.Cassia` is a `Rival` — one fighter's mentor is the
other's betrayer (`Fighter.Orin`/`Fighter.Thorne` as `Mentor-Betrayed`/`Enemy`;
`Fighter.Ryu`/`Fighter.Nova` as `Mentor`/`Student`). The checker is adversarial
about this: it requires **every one of the 11 types to appear**, every launch
fighter to participate in at least one edge, every primary rivalry to have a
matching `Rival` edge, and — pointedly — that **at least one asymmetric
reciprocal pair exists with genuinely different views** in each direction, so
"asymmetric relationships supported" is a proven property, not a claim. The
contract names the runtime target as a DataTable, `URV2_RelationshipMatrix`,
indexed by fighter pair, driving per-matchup banter, Side-Story eligibility,
Konquest faction-master assignment, crew-formation suggestions, and MyGM AI feud
generation.

### The master cross-character timeline & convergent endings

`timeline.csv` (with a companion `timeline.md`) is the canon spine: **14
events** spanning the contract's six `eventTypes` — `pre-story`, `story-major`,
`side-story`, `arcade-ending`, `post-credits`, `dlc-future` — from
`TL.PreStormArchive` (Ancient era, Raiden/Liu Kang) through
`TL.OpeningTournament` (Story Ch01) to branch-canon side stories and `what-if`
arcade endings like `TL.BloodMoonEnding`. Every event carries its participants
(roster-checked), its `linked_lore_pages`, `side_story_refs`,
`audio_diary_refs`, and `codec_refs` — and the checker requires _all four_
reference fields to be non-empty on every row, plus the presence of
arcade-branch and DLC hooks, so the timeline can never ship an event with no
lore behind it. This is the data the per-fighter **profile timeline view**
reads.

The timeline resolves into the payoff system: `convergent-endings.md` defines
**4** convergent endings (`Convergence.Oathbreaker`, `NeonDynasty`,
`AncestorRift`, `FutureEcho`), each a post-credits cinematic that unlocks only
when a _combination_ of inputs is satisfied on one profile — specific Arcade
endings **plus** Story branch states **plus** a Side-Story completion set.
`Oathbreaker`, for instance, needs `Arcade.Ending.DragonCrown`, the
`StormCupMercy` + `BlackIceCompactPreserved` branches, and the `Asha.Rival` /
`SubZero.Compact` side stories — narrative convergence expressed as a boolean
over the player's resolved branch history.

### Factions and the Hathor boundary

`faction-relationships.csv` lifts the same idea to organizations: **16 directed
edges** (8 reciprocal pairs) typed from `Allied` / `Neutral` / `Rival` / `Enemy`
/ `At-War` (Lin Kuei `At-War` with Black Dragon, Soul Temple `Allied` with
Shirai Ryu), each scoped to the modes it drives (`Universe`, `MyGM`, `Konquest`,
`FactionQuests`). The honest seam worth naming: the contract's `sourceBoundary`
makes explicit that this data is a **compiled artifact** — the narrative is
authored upstream in Hathor's studio-web and compiled by
`@hathor/lore-compiler`; V2 owns the launch ids, the presentation, and the
editor tooling, modeled in the real `V2Editor` module (the
`EV2EditorToolSurface` enum carries `RelationshipMatrixEditor` and
`TimelineVisualizer` surfaces). The interactive matrix/timeline editors are
descriptor-and-validation types today, not shipped Slate UI — but the data they
describe is already proven consistent by the CI gate.

## Fighter & account progression, codex, encyclopedia

Progression is two interlocking loops — per-fighter mastery and per-account
level — both authored as CSV and both backed by real save-side C++.

### Per-fighter mastery and the progression track

`fighter-mastery-tracks.csv` gives all **60** fighters a mastery track (max
level **30**, a shared `Curve.Mastery.Standard`, a per-fighter seasonal boost
theme), with the unlock ladder in `mastery-level-rewards.csv`. Def Jam's
per-style mastery is its own dataset (`style-mastery-tracks.csv`: independent
30-level tracks per equipped style). The runtime is the real thing:
`FV2ProgressionTrack` (`V2Persistence/Public/V2PersistenceTypes.h`) carries a
`Domain` (`GlobalPlayerLevel` / `FighterMastery` / `StyleMastery` / `ModeRank`),
a `Level`, an `int64 XP`, and a `Prestige`, and
`AddXP(DeltaXP, XPPerLevel, MaxLevel)` is a genuine level-up loop — it
accumulates XP, advances the level while there's enough to spend and the cap
isn't hit, and _clamps overflow at the cap_ (`XP = XPPerLevel

- 1`) so a maxed track can't bank phantom levels. The transparent XP economy is data too (`xp-gain-rates.csv`:
  Win 450, Loss 150, Perfect-round 125, each with a "shown on results screen"
  transparency label the checker requires).

### Account level, prestige, and long-form goals

The account loop runs **1–100** with rewards every **5** levels
(`account-level-rewards.csv`, 20 reward rows) and a **P1–P10** prestige loop
(`prestige-tiers.csv`, 10 tiers from Copper to a top flair, each
`keeps_all_unlocks = true`). The progression contract is gated hard: the checker
fails unless account level is exactly `1–100`, rewards land every `5`, and the
prestige loop has exactly `10` entries. Above both loops sit the marquee
`long-form-goals.csv` chases — Win 1000 across all rulesets, Master rank in 3
rulesets, all 60 Arcade endings, all 60 Side Stories — each granting a unique
title and animated badge.

### Codex / Encyclopedia, quest log, reward inbox

The **Codex** is a browsable encyclopedia spanning **8 categories**
(`codex-categories.csv`: fighter, stage, faction, weapon, special-move, style,
ruleset, historical-event), each pointing at its content source — the
historical-event category, for example, reads `timeline.csv`, so the
encyclopedia and the canon share one dataset. The fighter category is fully
authored: `codex-fighter-entries.csv` carries **60 entries**, and the checker
enforces a real content budget per entry — `word_count` between **200 and 500**,
a present art ref, audio diary, diary entry, an unlock condition that actually
contains "Complete", and a `replay_or_cinematic_link` that resolves to a
`Replay.`/`Cinematic.` id plus cross-links. The **Unified Quest Log**
(`quest-log-catalog.csv`) and **Reward Inbox** (`reward-inbox-rules.csv`, with
claim-all / per-item / auto-claim and `high_value` manual-claim flags for season
and charity rewards) round out the account surface, both type-checked against
the contract's required sets.

## The Creator Suite & personalization

V2's authoring surface is a first-class feature, and unlike the narrative layer
it is mostly _runtime C++ with validation logic_, gated by a dozen
`check-v2-create-*` scripts. The pattern mirrors combat: a
`UBlueprintFunctionLibrary` builds a default catalog, a `HasRequired…` validator
proves it's complete, and resolution functions return fail-loud reason tags.

### Create-a-Fighter / Wrestler / Soul

`UV2FighterCustomizationLibrary` (`V2Gameplay`, 742-line header / 1,345-line
impl) is the CAW/CAF/CAS core. The contract
(`CreateFighterCAW_V2_Contract.json`) pins the depth the catalog must hit and
the checker enforces it: **≥ 50 body-morph sliders** wired to skeleton vertex
deltas, **≥ 100 FACS face-sculpt targets**, ≥ 8 heritage presets, gender
expression independent of body archetype. Sliders are real bindings —
`FV2MorphTargetBinding` carries min/max/default and a `ClampSliderValue` that
clamps to range and falls back to default on non-finite input. The extended
sculpt adds an **11-region bone-scale rig** (Head…Hand), 8 muscle-definition
regions, a layered tattoo painter with blend modes and symmetric mirroring, and
groom hair with per-strand color. The crucial honest seam: `face-from-photo` via
the MetaHuman pipeline is present but **regionally license-gated**
(`faceFromPhotoRequiresRegionalLicenseGate`), and `manualSculptAlwaysAvailable`
guarantees the creator never _depends_ on a gated path — a fail-loud capability
boundary, not a fake feature.

### Create-a-Soul style resolution — the DJ diminishing-returns rule

`ResolveCreateASoulStyleSelection` is the showcase of real domain logic. It
takes a weapon-style catalog, a selection, and rules, and returns an
`FV2CreateASoulStyleResolution` — or one of a family of precise rejection tags
(`SC.CreateASoul.Rejected.WeaponStyleDisciplineMix`,
`…CustomStyleTooManyStyles`, `…UnknownWeaponStyle`). When a player mixes
disciplines in Custom Style, the resolver computes
`ExtraDisciplinePenaltyStacks = max(0, distinctDisciplines − 1)` and applies a
**damage penalty scalar per extra discipline**, floored at a minimum stat scalar
— the "diminishing returns past two styles" (Def Jam logic) expressed as an
actual formula, with the style-assignment config defaulting
`DiminishingReturnScalar = 0.82` over a `StylePointBudget = 100`.

### Color edit, decals, voice

`FV2CreateFighterColorEditConfig` is the Tekken/SC-style palette system: **16
addressable color slots per item**, an HSV picker, a saved-palette gallery,
shareable scheme codes, and per-slot material scalar channels the contract
requires by name (`Metallic`, `Roughness`, `DirtLevel`, `WearLevel`,
`EmissiveIntensity`). The decal editor declares a 32-layer pixel/vector surface
with `Normal`/`Multiply`/`Overlay`/`Mask` blend modes and cylindrical-wrap
projection; the logo painter exposes vector primitives plus a curve tool and a
_moderated_ image upload. CAW also carries a **voice pitch slider** (±12
semitones) and per-locale announcer/commentary pack selection.

### Create-a-Moveset & the Variation System

`UV2MoveEditorLibrary` (`V2Combat/V2MovesetData.h`) is Create-a-Moveset: a
curated catalog keyed to command slots, each move carrying a `CostWeight`,
governed by a `TotalCostBudget` (default **100**). `CalculateMoveSelectionCost`
sums the weights and `IsMoveSelectionWithinBudget` enforces the cap —
balance-by-budget, not by honor system. On top sits the **Variation System**
(MKX/MK11 Kustom Variations): `FV2VariationCardDefinition` cards
(Ability/Passive) with a `CostWeight` and a `MutuallyExclusiveGroupId`, a
`SlotBudget` of **5**, and `ValidateVariationCardSelection`, which rejects an
over-budget pick, a duplicate, an unknown card, **or two cards from the same
mutually-exclusive group** — collecting _all_ errors into an out-list rather
than bailing on the first. Tournament-Edition presets and shareable codes
complete the kit, and the config even names the frame-data export root
(`V2/balance/exports/<branch>/variations/`) so custom variations flow through
the same balance pipeline as the base roster (see the architecture companion,
[../architecture/build-cook-assets-data-and-production.md](../architecture/build-cook-assets-data-and-production.md)).

### Arena, Entrance, Championship, and the personalization layer

The authoring surface extends past the fighter: real contracts and checkers
exist for Create-an-Arena (`CreateArenaStageEditor_V2_Contract.json`),
Create-an-Entrance (`check-v2-create-entrance-theme-authoring.py`), and the
WWE-2K-style Create-a-Championship custom belt
(`check-v2-create-championship-custom-belt.py`). On the persistence side,
`V2PersistenceTypes` backs the personalization layer: `FV2MatchHistoryArchive`
is genuine bookkeeping — `RecordMatch` validates and **dedups by `MatchId`**,
sorts newest-first, and `GetRecentMatches` caps the display list at a default of
**200**, with `FV2MatchHistoryFilter::Matches` filtering by
mode/ruleset/fighter/opponent/outcome. **Save integrity** is real policy too:
`FV2SaveIntegrityPolicy` keeps `MaxAutomaticBackups = 3`
(`bAutoBackupLastThreeSaves`), prompts on corruption detection, and carries a
non-destructive `FV2SaveMigrationPlan` that takes a backup before migrating —
"auto-backup last 3 saves" is a typed, tested guarantee.

### Community gallery & moderation

Every upload path above — decals, arenas, custom variations, championship logos
— is flagged `moderated` in its contract, and the customization-library lifetime
checker (`check-v2-customization-library-lifetime.py`, 340 lines) gates the
end-to-end discipline. The moderation pipeline itself (ML pre-filter,
human-review SLA, per-region content rules, performer protection) is
service-side and is covered in
[./community-store-support-and-ai-services.md](./community-store-support-and-ai-services.md).

## How it connects

These three systems are the glue between the fight and the player's long-term
relationship with the game. The rivalries and relationship matrix feed the
Arcade ladder, Story banter, and the MyGM/Konquest feuds; the codex and timeline
share their dataset with the in-game encyclopedia; mastery and account level
reward the combat covered in
[./combat-systems-defense-and-game-feel.md](./combat-systems-defense-and-game-feel.md);
and the Creator Suite produces the fighters, movesets, arenas, and cosmetics
that the [roster and presentation](./roster-presentation-and-stages.md) layer
renders and the
[community, store & support](./community-store-support-and-ai-services.md) layer
moderates and sells. The data discipline underneath all of it — the
spreadsheet-of-truth, the CSV↔DataTable round-trip, and the CI gates that fail a
build on drift — is the engine-side subject of the architecture companion,
[../architecture/build-cook-assets-data-and-production.md](../architecture/build-cook-assets-data-and-production.md).

## Related

- The feature hub: [../V2_features.md](../V2_features.md)
- [Roster, Presentation & Stages](./roster-presentation-and-stages.md) — the
  fighters, intros, signature libraries, and stages this content describes
- [Community, Store, Support & AI Services](./community-store-support-and-ai-services.md)
  — gallery moderation, storefront, and the live-service surfaces
- [Combat Systems, Defensive Options & Game Feel](./combat-systems-defense-and-game-feel.md)
  — the fight that progression rewards
- Architecture companion:
  [../architecture/build-cook-assets-data-and-production.md](../architecture/build-cook-assets-data-and-production.md)
  — the data pipeline, validators, and gates that hold all of this consistent
