Fighting Game · Features

Relationships, Progression & Creator Suite

A focused page within the Fighting Game Features documentation. The full map and every sibling page live in the Features hub.

6sections13 minread1diagram

On this page
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.

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 eventTypespre-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).

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.

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.

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; and the Creator Suite produces the fighters, movesets, arenas, and cosmetics that the roster and presentation layer renders and the community, store & support 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.