Five ruleset cells on one Unreal Engine 5 spine is an engineering achievement;
making a player invest in a Bureau operator across all five is a progression
problem; building a 1947 noir city, a frontier of five biomes, and 32 star
systems that each feel inhabited is a world problem; and capturing the faces,
voices, and scores that dress all of it is a production problem the size of a
studio. This page is the production-and-platform leg of V5's "Platform,
Compliance & Production" group: the studio-ops capacity behind the content, the
two-track progression that carries a player across cells, the open-world systems
that make the maps live, and the single machine-checked gate that decides
whether the result is allowed to ship. The honest distinction that governs every
line below is the one the rest of the V5 catalogue carries — V5 ships zero
cooked .uasset binaries; the tree is 74 C++ Source modules, 29
.uplugin manifests, and content-as-data. So the production capacity here is
real logic and authored intent in machine-readable form, backed by real
verification and real C++ systems, while the scanned faces, recorded VO,
composed score, and cooked maps that would fill it are production-gated and not
in-tree. And where some V-products carry a green launch aggregate, V5's is
deliberately, honestly red — 17 of 17 blocking gates pending,
releaseBlocked: true — because a prior revision once fabricated the green and
the remediation tore it out. Each claim below is pinned to the C++ surface, the
JSON manifest, or the Python gate that backs it, or labelled plainly where it is
declared-but-uncooked. The orientation door and stand-in conventions every path
here rides on are ./product-promise.md. The feature hub
this page belongs to is ../V5_features.md.
What ships, honestly#
The progression, world, and production systems are real C++, not contract
scaffolds. V5Persistence (V5/ue/Source/V5Persistence/) implements the
cross-cell save router, the per-cell currency ledger, the New Game+ economy, and
Save-Slot Archaeology as deterministic Blueprint function libraries with a
backing test suite. V5Open implements weather, era-swap data layers,
time-of-day, World Partition streaming, population, and HLOD rules against the
real UDataLayerManager. V5FaceCapture implements the MotionScan-equivalent
facial pipeline — blendshape stacks, MetaHuman binding, take linting, and FACS
calibration — with domain-specific quality math. V5Audio carries the score,
VO, and broadcast production budget as real routing and manifest logic. These
are domain-specific systems a renamed-variable stub could not reproduce.
Three honest qualifications carry through the page. First, every authored
artifact those systems describe — a scanned principal's 52-blendshape face, ~90
minutes of frontier score, a 140 km² Heist City — is declared by data and code
and cooked by nothing; there are 0 .uasset files, so any claim that needs
authored content is forward-looking by construction and labelled as such.
Second, a few builder functions set production-completion booleans
(bRecordingComplete, bCastingTeamAssigned) to true as manifest defaults —
those record planned production capacity, not recorded audio, and the
0-.uasset reality is the cap on them. Third, the launch-readiness gate is
red on purpose, and the machinery is built so the red cannot be forged: the
validator fails closed, and the only verified quality signal to date is a single
on-box automation run (298/298), not a green nightly pipeline.
Production: studio ops, mocap, VO, and composer#
V5's content scale is documented as real studio capacity — 4 body-mocap stages (LA, London, Vancouver, Tokyo), a 12-camera MetaHuman face stage at LA, 28 bespoke-scanned principals, 3 composers one per cell-cluster, and 12 voiced + 4 text-only language SKUs (the Sci-Fi player character fully voiced for both genders, ~38 000 lines each). The in-tree code is the pipeline that capacity would run through.
The facial-capture pipeline#
V5FaceCapture (V5/ue/Source/V5FaceCapture/Private/V5FaceCaptureSystems.cpp)
is the MotionScan-equivalent interrogation rig in code, and its constants are
domain-correct: RequiredMetaHumanBlendshapes = 52 and
RequiredFACSUnits = 16. UV5_FaceCapture_USDLoader::BuildBlendshapeStack
ingests a .usd take at a frame rate, frame count, blendshape-name set, and
FACS-unit set; UV5_FaceCapture_MetaHumanBind::BuildMetaHumanBind then binds it
to a MetaHuman rig and computes a BlendshapeCoverage as the min of
blendshape and FACS coverage, marking the bind bCompatible only when coverage
≥ 0.95 and the stack runs at 60 fps
(IsNearlyEqual(FrameRate, 60.0f, 0.1f)) — exactly the "60 fps .usd
blendshape stacks" the features text promises. The
UV5_FaceCapture_CalibrationTool::BuildCalibrationScript enumerates 8 facial
action units (AU01_BrowInnerUp … AU15_LipCornerDepress) at 120 minutes each,
summing to the 16-hour FACS calibration session the production scope names.
UV5_FaceCapture_RetakePipeline and …_TellTakeLinter score each take by a
weighted rubric (frame-rate 0.25, blendshape coverage 0.35, FACS coverage 0.30,
trim 0.10) and fail any take below the gate, and
UV5_FaceCapture_VOSyncSubsystem::BuildVOSyncPlan only sets bFullLipsync when
the facial/voice offset is within ±0.25 s — the seam between the 4
full-lipsync SKUs and the 8 lipsync-light ones.
The audio production budget#
V5Audio (V5/ue/Source/V5Audio/Private/V5AudioSystems.cpp) carries the score,
VO, and broadcast capacity as routing and budget logic. MakeScoreBudget pins
8 hours of original score per cell with a score.<cell>.8h stem-pack id;
MakeComposerEngagement records the per-cell-cluster composer contracts;
MakePeriodBroadcastBudget declares the period broadcast inventory (18 radio
stations, 140 TV channels); and BuildVoiceRoute emits per-cell MetaSound
voice graphs with cell-tuned attenuation (40 m Sci-Fi, 28 m elsewhere) and
priority (Mind Palace dialogue at 90). The honest seam is
MakeVoLanguageCoverage, which sets bRecordingComplete and
bCastingTeamAssigned to true — those are manifest defaults describing
planned coverage, not proof of recorded sessions; no VO .uasset exists, and
the localization lock is a separate launch gate (it lives with
./accessibility-localization-and-compliance.md).
NIL and IP clearance gate any real-person likeness, trademark, and licensed
music — documented as obligations, enforced at the clearance manifest, not yet
exercised against cooked assets.
Progression: two tracks, account and character#
V5 progression runs on two tracks — per-character inside a cell, and per-account
across cells — and V5Persistence plus the Bureau ledger in V5Core implement
both as real save state, stored per account in Profile_<accountId>.json.
Bureau XP and the tier ladder#
The Cross-Continuum Bureau XP ledger is the account spine.
FV5BureauXPLedger::RecalculateTier
(V5/ue/Source/V5Core/Private/V5Types.cpp:42) computes
CurrentTier = max(1, TotalXP / 2500 + 1) — a tier every 2 500 XP — and grants
idempotent cross-cell unlocks at the exact thresholds the features text
advertises: Tier 1 PhotoMode.AllCells, Tier 5 MindPalace.CrossEraPairs, Tier
10 CompanionApp.FullSync, Tier 20 NewGamePlus, Tier 30
Cosmetic.BureauGear.AllCells. The save router
(UV5_Persist_SaveGameRouter::BuildManifest) enforces cross-cell consistency on
every route: each cell slot must carry the current save version and point at the
right profile slot, a Mind Palace slot must exist, and the Bureau ledger's
account id must match the profile's — the manifest is only
bCrossCellConsistent when all of that holds.
Per-cell currency, fail-closed#
UV5_Persist_CurrencyLedger::BuildStartingLedger seeds the cross-cell economy
with cell-correct currencies — Urban 250 Cash, Period 125 Cash, Frontier 2
Gold, Hunter 80 Crowns, Sci-Fi 500 Credits, plus Bureau scrip in the Mind
Palace — and ApplyTransaction is an append-only journal that rejects any
debit that would drive a balance negative (recording the rejection rather than
silently clamping), tracking LifetimeEarned/LifetimeSpent per balance. The
public side of balance is the balance-ledger service
(apps/v5/balance-ledger/contract.json): an append-only, designer-note-linked,
telemetry-evidenced ledger on Postgres/Redis with a public-export capability —
real contract surface whose publicBalanceLedgerLive flag is honestly false
until the service is deployed, and which is itself a launch gate.
New Game+ and Save-Slot Archaeology#
The deepest progression code is the Year-1 New Game+ plan.
UV5_Persist_NewGamePlus::BuildYear1Plan requires Bureau tier 20 and a
completed campaign, covers all five launch cells, and is validated by
ValidateYear1Plan against hard domain invariants: ≥2 authored story branches
per cell (≥10 total), ≥3 difficulty modifiers per cell (≥15 total), every
modifier scalar ≥ 1.0 so NG+ can only raise challenge, and
bNoPaidPowerCarryover true. Carry-over domains are explicit (bureauXp,
cosmetics, photoMode, mindPalaceOutcomesArchive, codex,
workshopEntitlements); reset domains are equally explicit
(criticalPathMissionState, cellEconomyBalances, wantedHeat, bountyDebt,
factionMissionLocks) — so a second run keeps your identity and loses your
shortcuts. On top sits Save-Slot Archaeology
(UV5_Persist_SaveSlotArchaeology): 10 authored scenarios (two per cell) that
read a prior save's ending flags (ending.urban.low-collateral,
ending.scifi.alliance.independent, …) and, when matched, trigger the matching
NG+ branch — your first ending literally reseeds your second beginning. Imports
must be migrated to the current save version before they validate. Underneath it
all, crash recovery (UV5_Persist_CrashRecovery::BuildPolicy) holds a 90-second
autosave interval, an atomic temp-write, write-before-map-travel, and three save
generations (Current/Previous/Fallback); replay packets carry an exact
binary SHA-256 payload digest plus an externally keyed HMAC-SHA256 signature,
expiry, and single-use nonce over every frame and security-relevant field.
The open world: weather, eras, and streaming that bite#
The maps themselves are content-gated (no cooked geometry exists), but the
systems that make them live are real V5Open code over UE5 World Partition.
The signature maps are declared in the features text — Urban's 16 districts
across ~140 km² Heist City plus the ~22 km² Street Triad world, Period's one
1947 city seen across three eras, Frontier's 5 biomes, Sci-Fi's 32 systems with
~120 bodies (PCG planetary detail), Hunter's 4 regions — and the runtime that
would drive them is implemented now.
Weather is gameplay, not cosmetic#
UV5_Open_Weather (V5/ue/Source/V5Open/Private/V5OpenWeather.cpp) models
seven states — Dry, LightRain, HeavyRain, Snow, Fog, DustStorm,
SolarFlare — each binding to a World Partition data layer activated through
UDataLayerManager::SetDataLayerRuntimeState. Crucially, every state carries
four gameplay modifiers: VisibilityScalar, TractionScalar,
CrowdDensityScalar, and ClueLegibilityScalar. A DustStorm drops visibility
to 0.24 and crowds to 0.35; Fog cuts clue legibility to 0.62; HeavyRain
thins crowds to 0.48 and traction to 0.62 — and GetCurrentGameplayModifiers
lerps between source and target during a transition, so a clearing storm
hands visibility back gradually. This is the "weather affects visibility,
traction, NPC behavior, and sense-mode clue legibility — not purely cosmetic"
promise, implemented as numbers a feel test can assert.
Eras, day-cycle, and streaming#
UV5_Open_DataLayer_Era swaps the Period cell's 1930s/1947/1968 eras by
activating the matching era data layer and unloading the rest — the same
World-Partition mechanism, applied to time instead of weather, so Made Man and
Vice Squad can share one city's geometry. UV5_Open_TimeOfDay pins a
DayLengthRealSeconds = 48.0f * 60.0f constant — the 48-minute in-game day
that drives NPC schedules and shop hours. And UV5_Open_StreamingSubsystem
registers World Partition streaming sources (actor- and location-anchored,
sorted by priority into FWorldPartitionStreamingSources) so a seamless
open-world cell streams around the player; population and HLOD-rule modules sit
beside it. The persistent-world economy that layers over the maps is
deterministic-given-seed save state, simulated coarsely while a cell is
inactive.
Launch readiness and exit criteria (honestly red)#
§90 aggregates the entire product — cells, modes, localization, cert,
compliance, quality, online, and live-service — into one go/no-go, and it is the
page's load-bearing example of fail-loud honesty.
V5/release/launch-readiness-manifest.json (schemaVersion: 2) tracks 17
blocking gates, and today every one reads pending: passedGates: 0,
cellsComplete: 0, languagePacksLocked: 0, platformsCertPassed: 0,
releaseBlocked: true, greenBuildId: null. Its correctionNote is blunt
about why — a prior revision fabricated a shippable game (17/17 gates passed, a
99.72% crash-free rate over 125 000 PS5 sessions, nine cert passes, a completed
accessibility audit) with no build, hardware, sessions, or external engagements
behind any of it. V5/REMEDIATION_2026-06-12.md reset it, moving the backlog
from 905 [x] to 875 [x] and promoting zero marks to done; it records
that "the only verified quality signal to date is the one-off 2026-05-31 on-box
automation run (298/298 after remediation); no green nightly pipeline exists."
The gate cannot be hand-edited green#
V5/tools/release/validate-launch-readiness.py (399 lines) fails closed,
and its core is a require_gate_not_passed helper that refuses a passed
status without backing evidence. releaseBlocked: false requires every gate
passed and a real greenBuildId; a cert-passed platform needs
memoryWithinBudget plus an existing certEvidencePath on disk; a "complete"
accessibility audit needs a real named consultant ("TBD" is rejected); the
crash-free gate needs a cohort ≥ 100 000 with a rate above 99.5%; and a regex
stub-scan walks the runtime tree (V5/ue/Source, V5/ue/Content,
apps/v5/web/src, apps/v5) for
coming soon|not implemented|lorem ipsum|todo|fixme|tbd. It also composes the
cell, performance-budget, and live-service validators, so a regression in any of
them blocks launch. FV5LaunchReadinessManifestTest
(V5.Tests.LaunchReadiness) mirrors the fail-closed logic in C++ — its own
comment records that it once hardcoded the fabricated 17/17 and now validates
internal consistency instead.
Exit criteria vs. the point-in-time gate#
The §"V5 Exit Criteria" list is the standing bar for "done": every § in
V5_TODOS.md checked against real source, a zero-hit adversarial stub-scan
across all modules, the nightly Gauntlet green for 7 consecutive days, all 9
platforms cert-passed, all 16 language packs through localization QA, and the
cross-cell Mind Palace deduction graph validated end-to-end with the cross-era
arc playable to all endings. Launch readiness is the point-in-time gate for
"ready to ship to the public." A build may meet exit criteria before every
operational launch item (event scheduling, marketing) is complete — but it may
not launch before both are satisfied. The day-one event is already authored
(event.s01.day-one.continuum-signal, 30 days, scheduled) and the
cross-validating C++/Python checks are real; what is honestly absent is the
seven-day green nightly, the cooked content, and the external evidence — and the
gate is built to keep saying so.
Where this connects#
- ./accessibility-localization-and-compliance.md
— the WCAG audit, the 16 language-pack lock and per-language QA, the
parental/age-gating and ratings reviews, and the DSAR/privacy flows that
several of this page's launch gates (
localization.*,accessibility.audit.pass,compliance.*) cross-check. - ./product-promise.md — the orientation door, the
74-module / 0-
.uasset/ 29-.upluginconvention, and the spec-vs-disk discipline behind the declared-but-uncooked caveats above. - ../architecture/observability-performance-testing-content-pipeline.md — the architecture companion: the performance-budget gate, the Gauntlet driver and feel-test catalog, the content-as-data accounting, and the same fail-closed launch-readiness validator read in engineering depth.
- The feature hub: ../V5_features.md.