Open-World Narrative · Features

Shared Cross-Cell Systems

A focused page within the Open-World Narrative Features documentation. The full map and every sibling page live in the Features hub.

6sections12 minread1diagram

On this page

V5 sells the same impossible-sounding promise V4 did, moved into an open world: one Unreal Engine 5.5 game that has to feel like six — a Hong Kong triad brawl, a 1947 noir interrogation, an 1899 outlaw chase, a Witcher contract hunt, a Mass-Effect squad firefight, and a Newtonian two-ship duel — yet ship in one executable, share one roster, and read as one coherent narrative universe. The ruleset cells are the thing that makes those six feel different. This page is about the opposite force: the systems that make them feel like one game no matter which cell you stand in. When a thug you gun down in modern Hong Kong, a witness you spare in 1899, and a renegade choice you make in orbit all bend the same moral compass; when the gunplay, the melee, and the parkour obey one shared rule set across seven eras; and when the street under your feet streams, populates, and weathers itself by one open-world simulation — that shared spine is what this page inventories, grounded in the actual Unreal C++ that backs it, with the seams between real code and production-gated content called out honestly. For the full per-cell catalogue and the scope this slots into, start at the hub: ../V5_features.md.

What ships, honestly#

The shared core is real, compiled, and value-tested. Every system on this page is in-tree C++ that the linker has actually produced as a Linux editor module on this box — libUnrealEditor-V5Core.so, -V5Combat.so, -V5Honor.so, -V5Open.so, -V5Crowd.so, -V5Perception.so, and -V5Wanted.so all exist under V5/ue/Binaries/Linux/. The algorithms are domain-specific, not renamed CRUD, and the colocated automation specs assert computed values rather than shapes: that an assault-then-loot-then-help sequence on a fresh honor meter lands at exactly -8 → -11 → -7, that a 1.5× train-robbery charge stacked on a murder posts a $240 bounty, that an all-light-side bridge input produces a moral compass > 0.9, that the weapon catalog expands to 197 authored entries with per-cell counts of 65 / 40 / 22 / 32 / 38. Those tests would collapse instantly against placeholders.

Two honest qualifications carry through everything below. First, V5 is a logic-and-manifest skeleton: V5/ue/Content/ holds 0 .uasset and 1 .umap against ~393 JSON authoring sidecars. So the weapon a reload references (FV5CombatWeaponDefinition::ReloadAnimationPath), the montage a reload plays (FV5CombatReloadState::MontagePath), the parkour clips a vault selects, and the actor classes the traffic spawner instances are all FSoftObjectPaths or TSubclassOf slots — described, not baked. The systems are real; the meshes, mocap, VO and cinematics that would dress them are production-gated and absent.

Second, the shared systems split into two honest design postures, and it is worth being precise about which is which. The morality, perception, crowd, wanted, parkour, and combat-rules layers are pure stateless librariesUBlueprintFunctionLibrary classes of static functions over USTRUCT value types, where the caller holds the state. But combat and the open world also ship genuine stateful runtime: UV5_Combat_StanceSubsystem, UV5_Open_TrafficSpawner, and UV5_Open_PedSpawner are real UWorldSubsystems that own live actor tables and call World->SpawnActor, and the weapon, cover, ADS, and reload classes are stateful UObjects. So this layer is further along the runtime spectrum than the pure perception/honor cores — but there is still no single orchestration loop that chains perception → crowd → honor → wanted into one tick. Each block is proven by its spec and agrees with its neighbours by construction; assembling them into a live world loop is the named gap, traced in full by the architecture companion ../architecture/perception-crowd-and-morality.md.

The morality system: one compass, five local axes#

V5Honor is V5's signature open-world-narrative system — a persistent reputation/morality core whose effects ripple through greetings, prices, encounters, and law enforcement, and whose meta-axis every cell feeds. Each cell measures right-and-wrong on its own local scale (Cop/Triad in the urban cell, Family/Outsider in the period cell, Honor/Bounty out west, Humanity in the hunter cell, Paragon/Renegade in orbit), and the system's job is to keep all of them honest under one number.

The honor meter and its bands#

HonorScore lives in [-100, 100]. HonorDeltaForAction (V5/ue/Source/V5Honor/Private/V5HonorSystems.cpp) is the authored consequence table — AssaultCivilian -8, LootBodyInTown -3, HelpStranger +4, StoryMercy +12, StoryCruelty -12, with a deliberate CleanAnimalKill 0 so a clean hunt costs nothing — and GetHonorBand buckets the score into VeryLow (≤ -60), Low (< -20), Neutral (≤ 20), High (< 60), and VeryHigh (≥ 60). ApplyHonorChange accepts an OverrideDelta so a scripted story beat can post a bespoke swing while ordinary actions read the table. The honor value round-trips through the GAS attribute set UV5_AttributeSet_Honor (V5/ue/Source/V5Gameplay/Public/V5AttributeSets.h) via ReadHonorAttributes / WriteHonorAttributes, which is also where the CopRep, TriadRep, FamilyRep, OutsiderRep, ParagonScore, RenegadeScore, and WitcherHumanity sub-axes that feed the bridge live. V5HonorTests walks the canonical sequence — assault (-8), then loot in town (-11), then help a stranger (-7) — pinning the exact arithmetic.

Bounty, witnesses, and the cost of being seen#

GetBaseBounty prices crimes — Trespass $5, Theft $10, Assault $15, Murder $60, TrainRobbery $120 — and ApplyBountyCharge enforces the most important rule in the morality system: an unwitnessed crime adds nothing. If FV5HonorBountyCharge::bWitnessed is false the state passes through unchanged, so a clean kill genuinely leaves no trail; otherwise the base price scales by a StateMultiplier (the spec stacks a witnessed murder to $60, then a 1.5× train-robbery on top to reach $240). BuildWitnessReport is the tension mechanic: a witness reports only when there is a witness id, an authority id, and a bounty at stake, and the time-to-report is

text
clamp(90 + DistanceToAuthority × 0.6 − max(0,−honor) × 0.35 + max(0,honor) × 0.15, 15, 180)

so an infamous (very-low-honor) player is reported faster and a respected one gets a grace delay — the spec confirms the low-honor report fires sooner at the same distance, and that advancing past the timer transitions the report Fleeing → Reported. That witnessed bounty is exactly what escalates into V5Wanted's star-rated, era-scaled law-enforcement response (Marshal and PosseRider in 1899, LAPD up to attack-helo in the modern city), detailed in the architecture companion.

Lived-in NPC reactions#

The honor band drives reactions you can see and hear. BuildGreeting swaps both the line and a ToneTaghostile ("Keep your hands where I can see them.") at VeryLow through admiring ("Town knows what you did for us.") at VeryHigh. BuildDiscount gives shopkeepers a 10 % price cut at High and 20 % at VeryHigh. BuildEncounterFlavor reweights the encounter director: high honor biases the world toward help-needed events (weights up to 2.0 help / 0.5 ambush), low honor toward ambushes (0.5 / 2.0), and a standing bounty adds bounty-hunter pressure proportional to dollars owed (clamp(bounty / 100, 0, 2)). None of this branches on the cell — it is one reputation surface every open-world cell reads.

The cross-cell bridge and the moral compass#

ComputeMoralCompass (UV5_Honor_KarmaParagonBridge) is the meta-axis that makes "one moral universe" literally true. It folds every cell's local axis into a LightScore and a DarkScoremax(0, CopRep) and the case-rating average on the light side, TriadRep/OutsiderRep/RenegadeScore and inverted case-rating on the dark — each term scaled by a per-cell weight, then normalizes the difference into a MoralCompass in [-1, 1]. GetBureauXPMultiplier rewards conviction in either direction: 1.5× at magnitude ≥ 0.7, 1.25× at ≥ 0.4, 1.0× near zero, so a committed saint and a committed villain both out-earn a fence-sitter. The spec proves an all-light input lands > 0.9 and an all-dark one < -0.9, both earning the 1.5× modifier. One documented approximation lives here, called out so it is not mistaken for drift: the monolith design lists two separate period weights, but the shipped code collapses them into a single PeriodWeight applied to both the Family-rep and case-rating terms, with the normalizer using PeriodWeight × 2. The compass is real and tested; this is the single place the code simplifies the spec. That compass is also what the cross-cell Mind Palace reads to gate its deductions — evidence gathered as a saint and as a villain weighs differently — which is the morality system reaching across the whole roster.

Shared combat and traversal: one rule set, seven eras#

Where morality is the consequence layer, V5Combat and V5Parkour are the verb layer — the moment-to-moment gunplay, melee resolution, and free-running that has to read as a 1947 revolver duel in one cell and a biotic-rifle zero-G firefight in the next, off one shared implementation.

The weapon catalog: 197 guns as validated data#

UV5_Combat_Catalog (V5/ue/Source/V5Combat/Public/V5CombatCatalog.h) loads the arsenal from JSON and expands it to 197 authored weapons, partitioned by cell: 65 modern (Urban), 40 period, 22 frontier, 32 hunter, and 38 sci-fi. Each FV5CombatWeaponDefinition carries its EV5Cell, an EV5CombatEra (one of seven: Frontier1899, Period1930s/1947/1968, Modern, Hunter, SciFi), one of 14 EV5CombatWeaponClass values — from Pistol/Revolver/SMG through SteelSword/SilverSword to BioticRifle/TechRifle — plus a real balance profile (base damage, armor penetration, RPM, magazine, reload seconds, ADS FOV, optimal/max range) and a soft-pathed reload animation. The point is not the count; it is that ValidateWeaponRosterJson is a real linter that rejects malformed data (the spec feeds it a one-field group and asserts it errors), and that the recoil catalog encodes fiction as numbers — the spec asserts the 1899 revolver kicks more than twice as hard vertically as the sci-fi rifle.

The shared rules: penetration, hit-reaction, and friendly fire as a morality hook#

Three UBlueprintFunctionLibrary rule sets back every cell's combat resolution. UV5_Combat_BulletPenetration::ResolvePenetration computes an effective resistance of max(Resistance × Thickness/10 − ArmorPenetration, 0), blocks a shot cold if a hard-cover surface exceeds 0.85, and otherwise passes damage × clamp(1 − resistance) through — the spec proves 40 cm of 1.0-resistance concrete stops a weak round. UV5_Combat_HitReaction::ResolveHitReaction maps damage to one of twelve reaction classes by a real ladder: a headshot ≥ 75 is a KO, an armour break is a WallSlam, a hunter-cell hit ≥ 55 bleeds (KOBleed), then SpinFall (≥ 90), Knockdown (≥ 65), HeavyStagger (≥ 35), down to LightStagger.

The standout is UV5_Combat_FriendlyFire, which is where combat reads the cell enum and feeds the morality system directly. GetPolicyForCell returns a distinct policy per cell — Urban and Frontier apply an HonorPenalty, Period is Blocked, Hunter is Allowed, SciFi is SquadOnly — and GetReputationPenalty turns a bad shot into a number the honor meter consumes: 25 for shooting a civilian, 10 for another non-squad ally under the honor policy, 35 for friendly-firing a squadmate under the sci-fi/paragon policy. So the same trigger pull that the combat layer resolves is the same act the morality bridge later weighs — one join key, two systems.

Stance, cover, ADS, and reload: the stateful runtime#

This is where combat steps past pure libraries into live state. UV5_Combat_StanceSubsystem is a UWorldSubsystem that tracks a per-actor stance and gates it by cell: SetStance accepts ZeroG only in the sci-fi cell and Horseback only on the frontier, and rejects a zero-G stance in the urban cell — the spec verifies all four cases — while GetStanceModifiers returns the accuracy/recoil/profile/movement scalars (prone drops the profile below 0.5). Alongside it, UV5_Combat_Cover, UV5_Combat_AimDownSight, and UV5_Combat_Reload are stateful UObjects with their own tested life-cycles: sticky-cover attach and corner-peek, an ADS that narrows FOV and improves accuracy while stationary and tracks recoil impulse, and a reload that runs a weapon-specific montage and refills the magazine after the weapon's ReloadSeconds.

Traversal: the free-running verb family#

V5Parkour is the shared traversal spine (Sleeping-Dogs lineage), and it mirrors the combat-rules posture: a family of UBlueprintFunctionLibrary evaluators in V5/ue/Source/V5Parkour/Public/V5ParkourSystems.hEvaluateVault, EvaluateClimb, EvaluateWallRun, EvaluateLedgeGrabShimmy, EvaluateFireEscapeSlide, plus awning-bounce and roof-to-roof-drop — each taking an obstacle/surface condition, a Stamina budget, and a list of FV5ParkourAnimationClips, and returning an FV5ParkourMoveResult. A UV5_Parkour_ContextSolver picks the right move for the geometry and a UV5_Parkour_FailureRecovery handles the miss, so the same button-hold traversal grammar drives a fire-escape sprint in the city and a cliffside scramble out west.

The open-world simulation: one streaming world, per-cell density#

V5Open is the simulation layer the cells share to make their worlds feel inhabited — and unlike most of this page it depends on only V5Core plus engine World-Partition, which is exactly what a foundation should look like.

FV5OpenStreamingSourceDescriptor wraps Unreal's World-Partition streaming around the V5 vocabulary: a source is a Player, Companion, or MissionMarker, tagged with its EV5Cell, with a 768 m default load radius and a real EStreamingSourcePriority. FV5OpenWeatherGameplayModifiers makes weather more than cosmetic — its VisibilityScalar, TractionScalar, CrowdDensityScalar, and a ClueLegibilityScalar mean a downpour both thins the crowd and degrades the evidence the detective cells read, across seven weather states from Dry to DustStorm and SolarFlare. Data-layer era bundles (1930s / 1947 / 1968) let one period map re-dress itself across decades.

The simulation's heart is density-driven population. UV5_Open_TrafficSpawner and UV5_Open_PedSpawner are UWorldSubsystems that author per-cell, per-era density profiles and turn them into real spawned actors. Traffic density is the fiction in numbers — 260/km² in the modern city, 85 / 120 / 165 across the three period decades, 18 on the frontier, 6 in the hunter wilds, and 0 in the sci-fi cell (no cars in orbit). Pedestrian density reads as "people within 100 m" — 250 urban, 120 period, and a settlement/wilderness split out west and in monster country (40 vs 6 frontier, 60 vs 10 hunter). CalculateCountFromDensity multiplies density by the circle area and clamps to MaxActors; the spawner places actors area-uniformly (a sqrt-distributed radius) from a seeded FRandomStream so a given seed reproduces the same street, and CullOutsideRadius tears down actors that fall out of range. Honestly labelled: with no content classes supplied the spawner instances bare AActor placeholders — the density math, determinism, and spawn/cull life-cycle are real; the citizens are content-gated.

flowchart TB Enum["EV5Cell (V5Core) — the join key<br/><sub>Urban · Period · Frontier · Hunter · SciFi · Steampunk · MindPalace</sub>"] subgraph SHARED["Shared cross-cell systems (write once, tune per cell)"] Combat["V5Combat<br/><sub>197 weapons · 14 classes · 7 eras<br/>penetration · hit-reaction · stance subsystem</sub>"] Parkour["V5Parkour<br/><sub>vault · climb · wall-run · shimmy<br/>stamina-gated evaluators</sub>"] Open["V5Open<br/><sub>World-Partition streaming · weather<br/>traffic/ped density spawners</sub>"] Honor["V5Honor<br/><sub>honor −100..100 · bounty · witness<br/>moral-compass bridge</sub>"] Perc["V5Perception → V5Crowd → V5Wanted<br/><sub>suspicion · panic · era-scaled law</sub>"] end Enum --> SHARED Combat -->|"friendly-fire penalty"| Honor Perc -->|"witnessed crime"| Honor Honor -->|"bounty"| Perc Honor -->|"moral compass"| Palace["Mind Palace<br/><sub>deduction gating</sub>"] Honor -->|"×1.0 / 1.25 / 1.5"| XP["Bureau XP ledger"] SHARED --> Cells["Six ruleset cells<br/><sub>each supplies one enum value + tuning</sub>"]

How a cell leans on the spine#

Put together, the deal is the same one the ruleset-cells overview describes from the cell's side, seen now from the shared side: a cell does not re-implement gunplay, reputation, or the streaming world — it composes these modules and contributes its narrow slice. To stand up a cell you supply one EV5Cell value, a campaign catalog, and per-cell tuning (a density number, a friendly-fire policy, a stance whitelist, a perception sensitivity), and inherit the combat rules, the parkour grammar, the open-world simulation, and the one moral compass unchanged. That is why a triad enforcer, a 1947 detective, an 1899 outlaw, a Witcher, and a station marine can cohabit one build: the expensive, correctness-critical machinery is written once and tuned per cell, and the cell enum is the single key threading combat, morality, and the open world together. The honest edge remains the one named in What ships, honestly — these are proven, compiled, value-tested blocks, with the content production-gated and the single perception → crowd → honor → wanted runtime loop still unassembled.