Tactical Action · Architecture

Per-Cell Architecture Deep-Dives

A focused page within the Tactical Action Architecture documentation. The full map and every sibling page live in the Architecture hub.

8sections10 minread6diagrams

On this page

V4 is not one game with five skins; it is six genuinely different games that happen to share a roster, a perception model, and an online backbone. A Rainbow-Six breach, a Hitman crowd assassination, a Commandos squad infiltration, a Black-Myth-Wukong boss duel, an Age-of-Empires ladder match, and a two-player Contra couch run each demand mechanics the others never touch — sub-frame recoil curves, lux-based shadow detection, time-dilated command queues, posture-break counters, fixed-point lockstep pathfinding, screen-edge co-op tethering. The architecture answers that by giving each genre its own C++ cell-mechanic module under V4/ue/Source/, then layering ruleset GameFeature plugins on top of it (the hosting model — how a plugin activates a cell at runtime — is the subject of ./high-level-architecture.md).

The unifying seam underneath all six is the Gameplay Ability System: every cell module's Build.cs links GameplayAbilities and the shared V4Gameplay spine, so attributes, abilities, and gameplay tags are common currency while the genre-specific feel lives in the cell's own components. What follows opens each of those six modules in turn — what the cell is, the systems unique to it, and how mature it is on disk, ending each with the dependency or state diagram that the code actually encodes. It is the genre-by-genre companion to the catalogue index in ../V4_ARCHITECTURE.md.

What ships, honestly#

All six cell modules are real and compiled. Each exists as a directory with a Public//Private/ split and a *.Build.cs, and each has a compiled Binaries/Linux/libUnrealEditor-*.so sitting next to its source — V4Tactical, V4Stealth, V4Tactics, V4ActionRPG, V4RTS, and V4Arcade have all been through the linker on this box, as have roughly thirty of the V4Mode_* ruleset plugins on top of them. The genre cores are substantial, not skeletal: V4Tactical carries 12 .cpp/12 .h, V4ActionRPG and V4RTS 11 each, V4Arcade 9, V4Stealth and V4Tactics 8 each. The mechanics are domain-specific — a 6-frame parry window, a 0.125× Showdown time-dilation, a 32.32 fixed-point A* — not renamed CRUD, and most are pinned by dedicated automation specs under V4Tests (WukongSpec, ParrySpec, RecoilSpec, ContraSpec, LockstepSpec, FogSpec, LightGaugeSpec, DisguiseSpec, CommandosSpec, DesperadosSpec, ShowdownSpec).

Two honest qualifications. First, "cell" means the mechanic module, not a one-to-one game: a single ruleset plugin can compose several cells. Commandos pulls V4Tactical and V4Stealth and V4Tactics; Desperados pulls V4Perception + V4Stealth + V4Tactics; Hitman pulls V4Stealth + V4Perception + V4Schedules. The genre families the monolith markets ("five cells") and the six engine modules are both true descriptions at different layers. Second, the logic of every cell is in-tree C++ but the hand-authored art is not: V4's content is JSON sidecars (*.v4asset.json), not cooked .uasset binaries (see ./high-level-architecture.md for the 0-binary-asset accounting). So a recoil curve sampler is real code; the specific recoil curve assets, MetaHuman meshes, and Paper2D flipbooks are described, not baked. Where a claim leans on art, this page says so.

The Tactical FPS cell — V4Tactical#

This is the Rainbow-Six / Call-of-Duty surface: aim-down-sights, recoil, stance, lean, cover, weapon attachments, grenades, and downed-teammate revives. It is the fattest cell module (12 .cpp/12 .h) and the one whose plugins (R6Modern, CoDMultiplayer, CoDWarzone, RavenShield, CoDCampaign) carry the server-authoritative netcode.

The cell's signature subsystems are sub-frame, not stat-sheet. UV4AimComponent is a state machine (EV4AimState::HipfireADS) that drives an ADSAlpha interpolation with asymmetric timings — HipToADSSeconds = 0.18, ADSToHipSeconds = 0.12 — and a 1×–8× zoom band, so the exact time-to-ADS that competitive shooters tune is a first-class, designer-editable property. Recoil is a sampled curve, not a random kick: UV4WeaponRecoilCurveAsset holds a TArray<FV4WeaponRecoilSample> of {TimeSeconds, Offset} keys, and SampleRecoil() lerps between them, then scales the result by a stance multiplier (Standing 1.0, Crouch 0.8, Prone 0.6) and a MovingMultiplier = 1.3. That is a learnable, memorizable recoil pattern — the property that separates a tactical shooter from a spray simulator — implemented as real interpolation math. Around those sit UV4CoverComponent, UV4StanceComponent, UV4WeaponAttachmentComponent, UV4WeaponSwitchComponent, UV4GrenadeComponent, and UV4ReviveComponent, with UV4WeaponBase/UV4WeaponLibrary as the weapon data layer.

flowchart LR subgraph Tac["V4Tactical — FPS cell"] Aim["UV4AimComponent<br/><sub>ADS 0.18s / hip 0.12s · 1–8× zoom</sub>"] Recoil["UV4WeaponRecoilCurveAsset<br/><sub>sampled curve × stance × move</sub>"] Cover[UV4CoverComponent] Stance[UV4StanceComponent] Wpn["UV4WeaponBase / Library / Attachments"] Revive[UV4ReviveComponent] end GAS["V4Gameplay · GAS"] --> Tac Tac --> Net["V4Netcode<br/><sub>server-authoritative hit-reg</sub>"]

Maturity: high. Real interpolation/curve math, compiled module, RecoilSpec coverage. Authority and lag-compensation live one layer down in V4Netcode (cross-referenced in ./high-level-architecture.md); weapon balance values live in JSON sidecars.

The Stealth cell — V4Stealth#

This is the Splinter Cell / Hitman surface, and its defining trait is that it reads the world's lighting as a gameplay input. UV4LightGaugeComponent implements a lux-based shadow model: CalculateLuxAtCapsule() sums the contribution of every FV4StealthLuxSample light against the player capsule and classifies the result through DarkLuxThreshold = 0.3 and LitLuxThreshold = 0.65 (over an AmbientLux = 0.02 floor) into an EV4LightExposureState. Detection is then gated by exposure: CanSplinterCellSightDetect() is a distinct, stricter path from the generic CanBeSightDetected(), and in true darkness a guard must close to DarkCloseDetectionDistanceCentimeters = 150 to spot you. The companion ApplyLightOut() / RestoreLight() pair makes "shoot out the light" a real state change to the gauge, not a cosmetic.

The Hitman face of the cell is UV4DisguiseComponent, a full disguise economy: BeginDisguisePickupSwap() takes a downed-target body (knocked-out, dragged, or hidden in a container) and times a swap; HasZoneAccess() enforces per-disguise allowed zones; and ComputeSuspicionMultiplier() blends three tuned scalars — AllowedZoneSuspicionMultiplier = 0.3, RestrictedZoneSuspicionMultiplier = 1.75, EnforcerSuspicionMultiplier = 2.0 — against suspicious actions and visible weapons. ComputeEnforcerDetectionTimeSeconds() models the Hitman "enforcer" NPC who can see through your specific disguise faster. Rounding out the module are UV4SoundFootprintComponent (movement noise), UV4BodyDragComponent (move and hide bodies), UV4StealthGadgetComponent, and UV4MarkAndExecuteComponent (the Conviction-style tag-then-execute chain). Critically, V4Stealth.Build.cs depends on V4Perception — the gauges feed the shared suspicion model that every NPC reads, detailed in ./ai-perception-stealth.md.

flowchart TB Lights["world lights"] --> Lux["UV4LightGaugeComponent<br/><sub>lux → Dark 0.3 / Lit 0.65</sub>"] Disg["UV4DisguiseComponent<br/><sub>zone × enforcer suspicion</sub>"] Sound[UV4SoundFootprintComponent] Body[UV4BodyDragComponent] Lux --> Perc["V4Perception<br/><sub>shared suspicion state machine</sub>"] Disg --> Perc Sound --> Perc Body --> Disg

Maturity: high for the gauge/disguise math (real formulas, LightGaugeSpec + DisguiseSpec); the perception substrate it feeds is its own cell-shared system.

The RTST cell — V4Tactics (Commandos / Desperados)#

Real-time tactics is the squad-of-specialists genre: you pause-and-queue precise actions for six characters, watch enemy vision cones, and trigger them in unison. V4Tactics is the smallest headline cell by file count (8/8) but the densest in distinctive subsystems. UV4CommandQueueComponent caps each specialist at MaxCommandsPerSpecialist = 2 queued orders. UV4VisionConeComponent is the genre's iconic UI-and-logic primitive: a cone with HalfAngleDegrees = 60 (a 120° field), RangeCentimeters = 1200, a LowLightFalloff = 0.5, and Calm/Alert/Hostile colors (green/yellow/red); ContainsPoint() and GetDetectionWeight() are the detection math, and BuildGroundConeVertices() generates the floor decal.

The defining mechanic is UV4ShowdownModeSubsystem — Desperados' "Showdown Mode." SetShowdownActive() drops ShowdownWorldTimeDilation = 0.125 (one-eighth speed — the code is explicit that the world slows, it does not stop), accepts up to MaxShowdownCommands = 4 queued cross-specialist actions, and ResolveCommandOrder() returns a dependency-resolved firing order plus a list of blocked command GUIDs when a queued action's preconditions fail. Releasing the queue fires the plan in that resolved order. With UV4PartyComponent, UV4SpecialistAbilitiesComponent, and UV4BodyDisposalComponent rounding it out, the cell is a genuine simultaneous-turn planner, not a slow-mo toggle. Honest composition note: the Commandos plugin links V4Tactical + V4Stealth + V4Tactics together, because a WW2 squad mission is stealth + gunplay + tactics fused — the clearest demonstration that a ruleset plugin composes cells.

stateDiagram-v2 [*] --> RealTime RealTime --> Showdown: SetShowdownActive(true)<br/>world × 0.125 Showdown --> Showdown: QueueShowdownCommand()<br/>(≤ 4) Showdown --> Resolve: TriggerShowdown() Resolve --> RealTime: ResolveCommandOrder()<br/>fire ordered · drop blocked GUIDs

Maturity: high for the time-dilation/queue/cone logic (ShowdownSpec, CommandosSpec, DesperadosSpec); see ./ai-perception-stealth.md for how the cones tie into the shared perception model.

The Action-RPG cell — V4ActionRPG (Wukong)#

This is the souls-like / Black-Myth-Wukong combat cell, and it is the most combat-theoretic of the six — closest in spirit to V2's frame-deterministic fighting core (see V2's combat-system-gas-frame-data-and-determinism). Its backbone is an explicit 8-state machine, EV4ARPGCombatState { Neutral, Attacking, Dodging, Parrying, Stunned, Transformed, Casting, Damaged }, with attacks classified Light/Heavy/SuperHeavy and timed by FV4ARPGFrameWindow { StartupFrames, ActiveFrames = 6, RecoveryFrames = 12 } — integer-frame data, the kind a fighting game exposes publicly.

The frame constants are precise and match the design intent: UV4ParryComponent ships a ParryWindowFrames = 6 window with IsFrameInsideParryWindow() and a perfect-parry counter prompt; UV4DodgeComponent grants InvincibilityFrames = 9 of roll i-frames via IsInvincibleAtFrame(). Health is split from poise: UV4PostureComponent carries MaxPosture = 200 with a DecaySeconds = 3.0 regen and an OnPostureBroken delegate that fires the cinematic counter. UV4TransformationComponent implements Wukong's form changes — FV4TransformationForm { HitPoints = 300, DurationSeconds = 12, WillCost } with a CurrentWillCharges = 3 budget refilled by parries and posture breaks. UV4HeroComboComponent (LightComboLength = 4, HeavyComboLength = 3), UV4SpellCraftComponent (the Pillar Stance / Cloud Step / Body Double / Hair-Splitting verbs), UV4StaminaComponent, and UV4CharmComponent (FV4CharmSpec granting +ParryWindowFrameBonus, stamina-regen, and posture-damage multipliers) complete the kit. The cell even hosts a P3 duel sub-mode: UV4SpecialtyCombatModeCatalog validates a UFC-style BoxingSimulator (uses stamina/posture/parry, KnockoutPostureThreshold = 100, RoundSeconds = 180, PerfectGuardWindowFrames = 6) and a OneHitSwordDuel (bOneHitKill, bWeaponNormalized, bRequiresMutualConsent) by reusing the same backbone components.

stateDiagram-v2 Neutral --> Attacking: Light/Heavy combo Attacking --> Neutral: recovery (12f) Neutral --> Dodging: roll (9 i-frames) Neutral --> Parrying: parry (6f window) Parrying --> Attacking: counter prompt Neutral --> Transformed: Will charge (cost ≤ 3) Transformed --> Neutral: form HP/duration end Attacking --> Stunned: posture break (200) Neutral --> Casting: spell-craft verb

Maturity: high. Real integer-frame logic with ParrySpec + WukongSpec; the souls-like math is in-tree, while move montages and form meshes are JSON-described art.

The RTS cell — V4RTS#

This is the Age-of-Empires / StarCraft cell, and it is the one whose determinism is load-bearing, because RTS networking is deterministic lockstep — every client re-simulates the same inputs and any float divergence desyncs the match. V4RTS takes that seriously at the type level: FV4RTSFixed32 is a 32.32 fixed-point number (FractionalBits = 32, OneRaw = 1 << 32) with integer add/subtract and ordering operators, used wherever the simulation must be bit-identical across machines. UV4PathfindingSubsystem::FindPath() is a real A* over an FV4RTSGrid using fixed-point G/F scores and a Manhattan-distance heuristic, with a seed-hashed tiebreak (V4CellSortKey combines the cell hash with the match seed) so the open-set ordering is reproducible rather than pointer-dependent. AuditDeterministicPathfinding() is a built-in self-test: it runs the same query twice under seed 314 and asserts the paths match step-for-step, and checks the heuristic for (0,0)→(3,4) equals exactly 7 cells — determinism verified in code, not asserted in prose.

On top of that deterministic floor sits a complete economy: FV4RTSResourceCost (Ore + Crystal), UV4ResourceComponent over FV4RTSResourcePatch (GatherPerSecond = 8), UV4BuildComponent (FV4RTSBuildOrder, BuildSeconds = 10, grid footprints), UV4TrainComponent (FV4RTSProductionOrder, TrainSeconds = 5), UV4TechTreeComponent (FV4RTSTechNode with prerequisite tags), UV4AgeUpComponent (EV4RTSAge { Dark, Feudal, Castle, Imperial }), UV4FogOfWarComponent (EV4RTSFogState { Unexplored, Explored, Visible }), UV4UnitGroupComponent, and UV4WonderComponent. The lockstep transport (V4RTSLockstepSubsystem, 25 Hz, replay) lives in V4Netcode; V4RTS provides the deterministic simulation it drives.

flowchart TB Fixed["FV4RTSFixed32<br/><sub>32.32 fixed-point</sub>"] --> Path["UV4PathfindingSubsystem<br/><sub>seeded A* · self-audited</sub>"] Econ["Resource → Build → Train<br/><sub>Ore/Crystal · 10s/5s</sub>"] Tech["TechTree → AgeUp<br/><sub>Dark→Feudal→Castle→Imperial</sub>"] Fog[FogOfWar · UnitGroups · Wonder] Path --> Sim["deterministic sim"] Econ --> Sim Tech --> Sim Fog --> Sim Sim --> Lockstep["V4Netcode · 25 Hz lockstep"]

Maturity: high. The fixed-point determinism, A*, and economy are real and covered by LockstepSpec + FogSpec + AsymmetricRTSSpec/HistoricalRTSSpec.

The 2D run-and-gun & arcade cell — V4Arcade#

The arcade cell wears two faces from one module. The first is Contra: a 2D side-scrolling run-and-gun. UV4SideScrollComponent is the camera brain — CalculateCameraLocation() follows a single player or the midpoint of two for couch co-op, applies a CameraOffset = (-900, 0, 250), and ClampPlayerToScreen() keeps both players inside a HalfScreenWidth = 650 frame with a CoOpSeparationCap = 900 tether — the exact "you can't run off and leave player two behind" constraint the genre lives on. UV4WeaponPickupComponent swaps the held FV4ArcadeWeaponSpec and drops the previous one, and the weapon roster is unmistakably Contra: EV4ArcadeWeaponType { Spread, Laser, MachineGun, Fire, Crush, Homing, Barrier } — the literal S/L/M/F/C/H/B power-up letters, each with its own FireRatePerSecond, ProjectileCount, and Damage. UV4LivesComponent enforces true arcade economy (StartingLives = 3, StartingContinues = 2, IsGameOver()), alongside UV4LadderClimbComponent, UV4DropPlatformComponent, and UV4PowerUpComponent.

The second face is the Battle-Hub arcade cabinets: UV4ArcadeMiniGameCatalog defines FV4ArcadeMiniGameDefinition rows for Pinball, AirHockey, MiniGolf, Darts, Pool, Cooking with score targets and player caps — the social-space minigames. V4Arcade.Build.cs honestly links Paper2D (plus GameplayAbilities and V4Animation), so the 2D pipeline the monolith promises is wired at the dependency level; the flipbook sprites, tilemaps, parallax materials, and Niagara 2D projectiles it references are JSON-described content, not cooked binaries in-tree.

flowchart LR subgraph Arc["V4Arcade — two faces"] Scroll["UV4SideScrollComponent<br/><sub>midpoint cam · 900 co-op tether</sub>"] Wpn["UV4WeaponPickupComponent<br/><sub>S/L/M/F/C/H/B</sub>"] Lives["UV4LivesComponent<br/><sub>3 lives · 2 continues</sub>"] Mini["UV4ArcadeMiniGameCatalog<br/><sub>Pinball · Pool · Darts …</sub>"] end Paper["Paper2D"] --> Arc GAS["V4Gameplay · GAS"] --> Arc

Maturity: high for the run-and-gun and lives/weapon logic (ContraSpec); the 2D art (flipbooks, parallax, Niagara sprites) is described, not baked.

Where the cells meet#

Three things keep six genres from fragmenting into six engines. They all sit on the same GAS spine (V4Gameplay), so an operator's attributes carry across cells. The stealth and RTST cells both feed the same perception model (V4Perception, with the Mass-based V4Crowd and V4Schedules above it) — a Hitman guard, a Commandos patrol, and a Splinter Cell mercenary read stimuli through one suspicion state machine, dissected in ./ai-perception-stealth.md. And they are all activated, gated, and live-serviced by the same mode machinery — quick-play playlists, per-cell ruleset gating, seasons, and cross-cell crossovers — covered in ./game-modes-live-service.md. The cell modules are where each genre earns its feel; those three shared layers are why it is one game. For the full catalogue, return to ../V4_ARCHITECTURE.md.