Tactical Action · Features

The Tactical FPS Cell

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

5sections11 minread2diagrams

On this page

This is V4's gunfight. The Tactical FPS cell is the Rainbow-Six / Call-of-Duty surface where the moment-to-moment loop is aim, fire, take cover, lean, breach, revive — the genre that lives or dies on sub-frame numbers: how long the gun takes to come up to the sight, whether a recoil pattern is memorizable or a slot-machine spray, whether a peek clears the corner or exposes your head. It is the fattest of V4's six genre modules and the one carrying the server-authoritative competitive backbone, because everything from a 5v5 ranked breach to a 100-player drop runs on the same aim, recoil, stance, and cover math.

V4 markets this cell across five sub-rulesets — Raven-Shield planning, R6 Siege-era attack/defense, a CoD cinematic campaign, a 6v6 multiplayer suite, and a 100-player battle royale — each shipped as its own hot-swappable GameFeatures plugin on top of one shared C++ core. The promise is per-ruleset feel from one gunplay engine: a deliberate Raven-Shield room-clear and a frantic Warzone third-circle firefight read completely differently to the player, yet both consume the same UV4AimComponent interpolation and the same sampled recoil curve. The aim of this page is to inventory what that core actually does, on the player's side of the screen, and to point at the exact Unreal C++ that backs each feature. For the full mode taxonomy, roster, and the scope this slots into, start at the hub: ../V4_features.md.

What ships, honestly#

The gunplay core is real, compiled, and tested. The cell module V4/ue/Source/V4Tactical carries 12 .cpp / 12 .h of domain logic — an aim-state machine, a curve-sampling recoil asset, cover/lean/stance components, weapon and attachment data layers, a ballistic grenade preview, and a downed/revive state machine — wired into GAS through eight cell-gated abilities in V4TacticalAbilities. The signature systems are sub-frame and designer-editable, not stat-sheet placeholders: ADS timings of HipToADSSeconds = 0.18 / ADSToHipSeconds = 0.12, a 1×–8× zoom band, a recoil curve scaled by per-stance and movement multipliers. Most are pinned by dedicated automation specs under V4/ue/Source/V4TestsRecoilSpec, CoverSpec, WeaponLibrarySpec, plus the per-plugin RavenShieldSpec, R6ModernSpec, CoDCampaignSpec, CoDMultiplayerSpec, and CoDWarzoneSpec.

Three honest qualifications, in the spirit of the architecture companion. First, "cell" here means the mechanic module V4Tactical. The features catalogue also files three stealth-leaning FPS sub-rulesets — Splinter Cell, Spies-vs-Mercs, and Hitman — under the Tactical-FPS banner because they share the first-person camera, but on disk those run on V4Stealth, not V4Tactical (their plugins are even namespaced V4Mode_Stealth_*). They are covered on the sibling page, ./cell-stealth-and-real-time-tactics.md. This page is the loud tactical surface: gunfights, breaches, and destruction. Second, the logic is in-tree C++ but the content is not — V4 ships JSON sidecars, not cooked .uasset binaries, so a recoil-curve sampler is real code while the specific recoil-curve assets, weapon meshes, and MetaHuman principals are described, not baked. Weapon balance numbers live in soft-pathed data, surfaced through UV4WeaponLibraryCatalog. Third, network authority and lag compensation are not in this module: V4Tactical.Build.cs deliberately does not depend on V4Netcode; hit-registration authority sits one layer down, covered in ./shared-cross-cell-engine.md. What follows is the gunplay engine on its own terms.

The tactical FPS experience — what a fight feels like#

Strip the five sub-rulesets away and the shared verb set is small and tactile: bring the gun up, control the climb, slice a corner from cover, manage a 30-round magazine, cook a grenade onto an arc, and drag a downed teammate back into the fight. Each verb is a component on the operator pawn, and each carries the specific tuning a tactical shooter argues about.

Aim and the time-to-kill economy#

UV4AimComponent (V4/ue/Source/V4Tactical/Public/V4AimComponent.h) is a four-state machine — Hipfire → EnteringADS → ADS → ExitingADS — that drives an ADSAlpha interpolation every tick. The two transition times are deliberately asymmetric: raising the sight takes HipToADSSeconds = 0.18 while dropping back to the hip takes only ADSToHipSeconds = 0.12, so committing to a scope is slower than bailing out of one — exactly the risk/reward a competitive shooter tunes. TickComponent advances ADSAlpha by DeltaTime / HipToADSSeconds on the way up and clamps at 1.0 before flipping to the steady ADS state, with a zero-time fast path that snaps instantly. BeginAimDownSights clamps the requested zoom into the MinZoomLevel = 1.0MaxZoomLevel = 8.0 band, so the same component serves a red-dot and an 8× marksman optic. Per-weapon ADSSeconds and per-attachment ADSTimeModifierSeconds (a heavy barrel slows the raise; a lightweight stock speeds it) feed the same number, which is how an attachment loadout changes the gun's handling and not just its damage.

Recoil you can learn#

The property that separates a tactical shooter from a spray simulator is a recoil pattern you can memorize and counter, and V4 implements it as sampled interpolation rather than a random kick. UV4WeaponRecoilCurveAsset (V4/ue/Source/V4Tactical/Private/V4WeaponRecoilCurveAsset.cpp) holds a TArray<FV4WeaponRecoilSample> of {TimeSeconds, Offset} keys; SampleRecoil() finds the bracketing pair for the current shot time and FMath::Lerps between them, clamping to the first sample before the curve starts and the last sample after it ends. The interpolated offset is then scaled by a stance multiplier (Standing 1.0, Crouch 0.8, Prone 0.6) and a MovingMultiplier = 1.3, so going prone tightens your pattern by 40% while moving blooms it by 30%. RecoilSpec pins the exact arithmetic: a mid-curve standing shot interpolates to (1.0, 2.0), a crouched-and-moving shot at the second key resolves to a pitch of 4.16 (4.0 × 0.8 × 1.3), and a late prone shot clamps to 4.8 (8.0 × 0.6) — a test that would fail instantly against a Math.random() kick. Because the weapon library also carries a DeterministicRecoilSeed, the pattern is reproducible shot-for-shot, which is what makes recoil both learnable for players and auditable for anti-cheat.

flowchart LR Input["V4Input · Enhanced Input"] --> Abilities subgraph Abilities["V4TacticalAbilities · GAS (cell-gated)"] Fire[UGA_Fire] ADS[UGA_ADS] Lean[UGA_Lean] Nade[UGA_ThrowGrenade] Revive[UGA_Revive] end subgraph Tac["V4Tactical — gunplay components"] Aim["UV4AimComponent<br/><sub>ADS 0.18s / hip 0.12s · 1–8×</sub>"] Recoil["UV4WeaponRecoilCurveAsset<br/><sub>sampled curve × stance × move</sub>"] Cover["UV4CoverComponent<br/><sub>snap · lean · project</sub>"] Stance["UV4StanceComponent<br/><sub>speed × sound footprint</sub>"] Wpn["UV4WeaponBase / Library / Attachments"] Gren[UV4GrenadeComponent] end ADS --> Aim Fire --> Wpn Lean --> Cover Nade --> Gren Wpn --> Recoil Wpn --> Attr["UV4Attr_Tactical<br/><sub>Health · Armor · Ammo · Suppression</sub>"] Revive --> Attr Tac --> Net["V4Netcode<br/><sub>server-authoritative hit-reg (one layer down)</sub>"]

Stance, cover, and lean — the defensive vocabulary#

UV4StanceComponent ties posture to two outputs at once: a movement-speed multiplier (Crouch 0.7, Prone 0.45) and a sound footprint radius scaled off a BaseFootstepRadius = 600 by stance (Crouch 0.65, Prone 0.35) and a per-surface TMap multiplier, broadcasting an OnSoundFootprintEmitted event that the shared perception model can hear. Crouching is therefore both slower and quieter — the genre's core stealth/speed trade made into one number.

Cover is geometric, not a binary flag. UV4CoverComponent (V4/ue/Source/V4Tactical/Private/V4CoverComponent.cpp) stores a list of FV4CoverAnchors (location, surface normal, width, and per-side peek permissions); FindBestCoverAnchor does a squared-distance search inside SnapRadius, SetLeanSide refuses a peek the anchor doesn't support, CalculatePeekLocation offsets along the cover tangent with a 15-unit forward clearance, and ProjectMovementAlongCover clamps lateral movement to ±Width/2 so you slide along a wall instead of through it. CoverSpec verifies the geometry to the millimetre: snapping near a 240-wide anchor and leaning right yields a peek at (115, 50, 0), and a 500-unit lateral push clamps to (0, 120, 0). That is real corner-slicing math, the spatial grammar a breach is built on.

Weapons, ammo, and the attachment economy#

The weapon data layer is split cleanly. FV4WeaponBase (V4/ue/Source/V4Tactical/Private/V4WeaponBase.cpp) is the runtime instance — MagazineSize = 30, MaxReserveAmmo = 90, Damage = 35, FireRateRoundsPerMinute = 650 — with real ammo bookkeeping against the operator attribute set: ConsumeRound decrements AmmoCurrent only when CanFire passes, ReloadFromReserve computes min(needed, reserve) and moves exactly that many rounds, and CalculateDamageAfterArmor resolves max(0, Damage − max(0, Armor − ArmorPiercing)) — a genuine armor-penetration curve, not a flat subtract. Those numbers live on UV4Attr_Tactical (V4/ue/Source/V4Gameplay/Public/V4AttributeSets.h), a replicated GAS attribute set carrying Health, Armor, Suppression, StaminaSprint, AmmoCurrent, and AmmoReserve. Above the instance, UV4WeaponLibraryCatalog is the authoring layer: ten weapon categories (assault rifle through marksman rifle, LMG, shotgun, pistol), a per-hit-zone FV4WeaponDamageProfile (Head / Chest / Limb / ArmorPiercing), soft-pathed recoil curves and foley, and a ValidateLaunchLibrary linter. Attachments are a six-slot system (Sight, Barrel, Underbarrel, Magazine, Grip, Stock): UV4WeaponAttachmentComponent::ApplyAttachments folds each equipped FV4WeaponAttachmentSpec's recoil, ADS-time, mobility, and magazine modifiers into the base weapon — the Create-a-Class tuning loop expressed as composable data.

Grenades and downed-teammate care#

UV4GrenadeComponent::BuildArcPreview integrates real projectile motion — Start + Velocity·t + ½·g·t² sampled over PreviewSteps = 16 at 0.1 s — so the throw arc the HUD draws is the path the grenade actually flies, and ThrowGrenade decrements a real two-grenade count. Revive is a proper state machine: UV4ReviveComponent runs Alive → Downed → Reviving → Dead with a ticking bleed-out timer, a cancelable revive progress bar, and ApplyRevivedHealth restoring exactly RevivedHealth = 25 on completion — the "knocked, not killed" loop that anchors squad play and the CoD campaign's reviving AI teammates.

The systems behind the sub-rulesets#

Each ruleset is a GameFeatures plugin under V4/ue/Plugins/ that composes the gunplay core above with its own mode logic, content root, and test spec. The two most mechanically distinctive are real and spec-covered today.

Raven Shield — the planning phase and the breach#

V4Mode_Tactical_RavenShield is the "you plan it, the squad executes it" doctrine. UV4RavenShieldPlanningComponent builds a top-down tactical map, accepts two squads (Red, Gold) capped at three operators each, and authors a verb-typed waypoint list — MoveTo, StackOnDoor, BreachFlash, WaitFor (with a seconds/sound/hostage condition), MoveOnGo — that ValidatePlan must accept before the mission can start. BuildRehearsalPreview replays the plan at a slowdown, FindConflictHighlights flags crossfire and friendly-fire paths in red, and PauseAndEnterLiveOverride / CommitLiveOverride let the player re-author waypoints mid-mission. Execution is UV4RavenShieldExecutionComponent: doors with lock states, breach tools where a Kick cannot defeat a Locked door but Thermite can (and emits a noise event), a stack that caps at three with the point operator held first, a four-color threat-ID system (Red hostile, Blue hostage), and a room-clear state machine (Breach → ThreatAssessment → SecureHostages → Cuffing → Cleared) with Suppress/Cuff verbs gated by threat color. RavenShieldSpec drives the whole loop end-to-end across a validated 16-mission campaign, and registers a feel-test gate asserting the planning-to-breach loop stays under 75 seconds.

stateDiagram-v2 [*] --> Plan Plan --> Plan: AuthorWaypoint() · ValidatePlan() Plan --> Rehearse: BuildRehearsalPreview() (4× slow) Rehearse --> Execute: BeginExecution() Execute --> Override: PauseAndEnterLiveOverride() Override --> Execute: CommitLiveOverride() Execute --> RoomClear: stack · breach tool RoomClear --> RoomClear: Suppress / Cuff by threat color RoomClear --> Cleared

R6 Modern — gadgets, destruction, and two-sided rounds#

V4Mode_Tactical_R6Modern is the Siege-era asymmetric surface. UV4R6ModernMatchComponent runs 5v5 (the roster rejects a sixth player and duplicate ids), a Setup → Action phase clock that flips at 60 seconds, and objective formats (RankedBestOf9 to 5 round wins, CasualBestOf7 to 4) over Bomb, Hostage, and SecureArea win conditions with stored partial progress. Its gadget catalogue is fully authored — 9 attacker gadgets (hard breach, soft breach, drone, EMP, smoke, flash, frag, claymore, heartbeat scanner), 7 defender gadgets (reinforced wall through jammer), and 40 launch operators, 20 per side. The standout is UV4R6ModernDestructionComponent, which is not a cosmetic: it classifies wall materials (drywall and plywood soft, concrete and brick hard, plus floors and ceilings for vertical attack vectors), gates each destruction tool correctly (frag and shotgun open soft walls but bounce off concrete; thermite and hard-breach open hard walls), and restricts reinforcement to the defender side during setup only. R6ModernSpec proves the integration is real by binding an actual Chaos UGeometryCollectionComponent in a live test world and asserting a hard breach drives a genuine fracture (bChaosFractureApplied) whose replication debits a byte-budgeted band — real physics, server-authoritative, measured rather than asserted.

CoD — campaign, 6v6, and battle royale#

The Call-of-Duty trio (V4Mode_Tactical_CoDCampaign, V4Mode_Tactical_CoDMultiplayer, V4Mode_Tactical_CoDWarzone) leans hardest on the shared gunplay core: a 12-mission cinematic campaign with reviving AI squad teammates, a 6v6 suite (TDM, Domination, Hardpoint, Search-&-Destroy, Kill Confirmed and more) with a Create-a-Class / Pick-10 loadout economy and killstreaks, and a 100-player battle royale with the Gulag, buy stations, and loadout drops. Each is its own plugin with its own *Spec, and each consumes the same UV4AimComponent, recoil curve, and UV4Attr_Tactical ammo math described above — which is precisely why a weapon tuned once behaves consistently from the campaign to the third circle of Warzone. As with all V4 cells, the mode logic is in-tree C++ and the maps, cinematics, and weapon art are JSON-described content, not baked binaries.

How gunplay ties to GAS and the shared engine#

Every player action routes through the Gameplay Ability System, and V4's abilities are cell-gated so a tactical ability cannot fire on a non-tactical pawn. UV4GameplayAbilityBase (V4/ue/Source/V4Gameplay/Public/V4GameplayAbilities.h) overrides CanActivateAbility to check IsAbilityCellCompatible, then funnels real work into a protected ExecuteV4Ability that records a bLastActivationSuccessful flag and a LastActivationReason string. The eight tactical abilities in V4TacticalAbilities.cpp each set RequiredCell = EV4RulesetCell::Tactical and delegate to the components rather than reimplementing them: UGA_Fire calls Weapon.ConsumeRound and fails loud with "no-ammo"; UGA_Reload returns "reload-empty" when the reserve is dry; UGA_ADS drives the aim component; UGA_Lean is refused with "lean-blocked" if you are not in cover; UGA_ThrowGrenade, UGA_BreachStack, UGA_Revive, and UGA_Heal each thread through their component and report a precise rejection tag on failure. This is the fail-loud seam the project favors: the ability honestly reports what it could not do instead of faking success.

Two shared V4Core libraries back the cell's content without belonging to it. UV4GadgetLibraryCatalog (V4/ue/Source/V4Core/Public/V4GadgetLibrary.h) defines a cross-cell gadget vocabulary with a balance profile per entry (Charges, CooldownSeconds, RadiusMeters, NoiseMeters, PickCost, a CounterplayWindowSeconds) and a published balance ledger so nerfs and buffs are auditable — the same TacticalFPS domain that the R6 gadget catalogue draws from. UV4TakedownLibraryCatalog authors melee/takedown verbs (sneak choke, garrote, and the rest) with motion-warped animation pairs and per-takedown sound profiles, shared with the stealth cell. The throughline is the architecture's unifying claim: six genres stay one game because they sit on the same GAS spine, the same shared V4Core libraries, and the same mode machinery. For the engine-side treatment — netcode authority, the GAS layout, and the cross-cell seams named here — read the architecture companion, ../architecture/per-cell-deep-dives.md.