# Game Modes: Campaign, Co-op, PvP & Horde

This is the answer to "what do I actually press play on?" V4 advertises a
sprawling catalogue — an eleven-row campaign table that runs from a 16-mission
Raven-Shield breach to a couch-co-op Contra run, a cross-cell co-op ladder, a
5v5 ranked attack/defense, a 6v6 suite, a 100-player drop, and a six-cell horde
mode — but the product only holds together if every one of those surfaces
bottoms out in the same orchestration seam instead of forking the engine per
genre. They do. A "mode" in V4 is **a thin data record plus a load plan**,
registered in one game-instance subsystem, and the four families this page
covers — single-player **campaigns**, drop-in **co-op**, competitive **PvP**,
and wave-based **horde** — are differentiated not by separate runtimes but by
the per-plugin component that runs _after_ the registry hands off. This page
tours those four families on the player's side of the menu: what each is, what
you do in it, and which parts are shipped, compiled, tested C++ versus content
that is named-but-uncooked. The engine-side treatment of the registry, discovery
pipeline, and live-service backbone is the architecture companion,
[../architecture/game-modes-live-service.md](../architecture/game-modes-live-service.md);
the training, replay, signature-event, and AI-Director surfaces these modes feed
get their own page,
[./modes-training-replay-signature-and-ai-director.md](./modes-training-replay-signature-and-ai-director.md).
For the full scope this slots into, start at the hub:
[../V4_features.md](../V4_features.md).

## What ships, honestly

**The mode machinery is real, compiled, and tested, and so is the per-family
domain logic.** `UV4ModeSubsystem`
(`V4/ue/Source/V4Modes/Private/V4ModeSubsystem.cpp`, 245 lines) implements
registration, a four-result transition, a deterministic weighted quick-play
lottery, and a fail-closed local-multiplayer admission gate as ordinary C++ that
runs headless under automation; `V4ModesTests/ModeSpec.cpp` pins it with 89
assertions. Each mode family then layers its own shipped plugin: the R6 5v5
match machine (`R6ModernSpec.cpp`, 103 assertions), the CoD 6v6 rule catalog and
match component (`CoDMultiplayerSpec.cpp`, 83), the 12-mission CoD campaign
catalog (`CoDCampaignSpec.cpp`, 62), the Shadow War crossover progression
(`ShadowWarSpec.cpp`, 29), the 18-mission Spec Ops co-op model
(`SpecOpsCoopSpec.cpp`, 61), and the six-variant horde wave director
(`HordeDefenseSpec.cpp`, 33). These are not stat-sheet placeholders; they carry
real arithmetic — performance-pressure curves, party-size difficulty scaling,
best-of-N round resolution, mode-specific scoring gates — that a test would fail
on if hardcoded.

Three honest qualifications, in the spirit of the architecture companion.
**First, the content is uncooked.** V4 represents every level and asset as a
JSON descriptor (`*.uasset.v4asset.json` / `*.umap.v4asset.json`), so a horde
wave _director_ is real code while the wave's enemy _meshes_ and the campaign's
MetaHuman principals are described, not baked; the soft map paths each catalog
builds (`/V4Mode_SpecOps_Coop/Maps/L_SpecOps_07.L_SpecOps_07`, …) resolve to
nothing at runtime today. **Second, the catalogue is wider than the shipped
plugins.** The eleven-row campaign table in the features monolith is design
scope; on disk, the two campaign families with fully-shipped C++ mission
catalogs are the CoD campaign and the Shadow War crossover — the Raven-Shield,
Commandos, Desperados, Wukong, Conquest, Civ, and Contra campaigns live under
their own `V4Mode_*` plugins with their own automation specs and are inventoried
on the per-cell pages. **Third, network authority is one layer down.** The PvP
match components below are server-friendly state machines; the dedicated-server
client-server netcode, lag compensation, Glicko-2 matchmaking, and host
migration they assume sit in `V4Netcode` and the Rust `online-services` crate,
covered in [./shared-cross-cell-engine.md](./shared-cross-cell-engine.md).

## How any mode boots

Every family below routes through the same three calls. A mode is one
`FV4ModeDefinition` (`V4Modes/Public/V4ModeTypes.h:17`) — five fields: `ModeId`,
localized `DisplayName`, a `GameFeaturePluginURL`, a soft `EntryMap`, and the
`ActivationAssets` streamed on entry. `RegisterMode` stores it by id (rejecting
an empty id); `TransitionToMode` (`V4ModeSubsystem.cpp:44`) is the switch,
returning `EV4ModeTransitionResult::UnknownMode` for an unregistered id,
`AlreadyActive` when you re-select the current mode, and otherwise `Succeeded`
after setting `CurrentModeId` and broadcasting `OnModeTransitionCompleted` so
HUD and telemetry follow without polling. Quick-play is a **deterministic
weighted lottery** — `SelectQuickPlayMode` (`:193`) sums the `Weight` of every
enabled, registered entry, takes `Roll = FMath::Abs(Seed) % TotalWeight`, and
walks the playlist subtracting weights until `Roll` lands in a band, so the same
seed yields the same mode for the whole community. The diagram shows how the
four families diverge only _after_ the transition:

```mermaid
flowchart TD
    Menu[Player picks a mode or quick-play seed] --> Reg["UV4ModeSubsystem::TransitionToMode(ModeId)"]
    Reg --> Res{EV4ModeTransitionResult}
    Res -->|UnknownMode / AlreadyActive| Stop[delegate broadcast, no state change]
    Res -->|Succeeded| Cur[CurrentModeId set + OnModeTransitionCompleted]
    Cur --> Campaign["Campaign — UV4CoDCampaignMissionCatalog / UV4ShadowWarProgression"]
    Cur --> Coop["Co-op — UV4SpecOpsOnlineCoopModel + UV4LocalMultiplayerPolicyLibrary gate"]
    Cur --> PvP["PvP — UV4R6ModernMatchComponent / UV4CoDMPMatchComponent"]
    Cur --> Horde["Horde — UV4HordeWavePacingDirector"]
    Campaign -->|cross-cell handoff re-enters the registry| Reg
```

## Campaign modes

Campaigns are V4's single-player spine. The flagship shipped catalog is the
**CoD cinematic campaign**:
`UV4CoDCampaignMissionCatalog::BuildLaunchMissions()`
(`V4CoDCampaignMissionCatalog.cpp:64`) returns exactly 12 missions — Helo
Insertion, Spectre Watch, Black Tide, Dune Run, Dam Break, Iron Valley,
Glassfall, Red Sand, Whiteout Chase, Lights Out, Line Control, Skyhook — each
carrying a soft map asset, a 90-second opener `LevelSequence`, an AI squad
(`SquadMemberIds = {Price, Wraith, Hale}`), and a mandatory set-piece. The
set-piece archetype drives a real flag: `MakeSetpiece` (`:26`) marks
`bVehicleSegment` true for the Helicopter, AC-130 gunship, Tank, Dune-Buggy, and
Snowmobile types, so the four-plus advertised vehicle missions are data, not
prose. `ValidateLaunchCampaign` (`:82`) is a genuine gate: it rejects a campaign
without 12 missions, an opener outside the 60–120-second window, fewer than two
branch moments or three squad members, **any branch flagged
`bMajorStoryBranch`** (CoD-lineage campaigns allow only light-dialogue and
optional-objective branches), or a missing entry from the 12 required set-piece
archetypes. The five difficulty tiers (`Recruit`, `Regular`, `Hardened`,
`Veteran`, `Realism`) come from `GetDifficultyTiers`, the from-menu
mission-select with per-mission difficulty tracking from
`BuildMissionReplayMenu` (mission 1 plus any completed mission is unlocked), and
the 30-minute pre-rendered cinematic pool with Movie-Render-Queue cook hook from
`BuildCinematicBudget`.

The **Shadow War crossover** is the unifying arc, and it is the one campaign
that exercises the mode registry as a gameplay verb. It is a six-mission story
in which the same operators recur across cells — a Hitman-cell assassination
sets up a CoD-cell battle that sets up an RTS-cell invasion — and the cell
transitions are _real_. `UV4ShadowWarProgression::ExecuteHandoff`
(`V4ShadowWarCampaign.cpp:476`) does not narrate a handoff; it records the save
point, calls `Modes->TransitionToMode(Handoff->FromModeId)` then
`TransitionToMode(Handoff->ToModeId)` on the live `UV4ModeSubsystem`, carries
the handoff's narrative flags into the save, and sets `bNarrativeStateCarried`
only after confirming every carried flag is present in
`Save.NarrativeStateFlags`. The arc is JSON-loaded (`LoadCampaignMissions` over
`DT_ShadowWar_Missions.json`) and `ValidateCampaign` enforces the §141 contract
— every mission spans ≥2 cells whose mode ids resolve against the discovered
roster, handoffs connect consecutive legs with save points, shared operators
come from the unified §42 roster and recur across the whole arc, and bridge
cinematics consume none of the pre-rendered pool. A JSON save round-trip
(`ExportSave`/`ImportSave`) and sequential unlock gating complete the shell.

## Co-op modes

Co-op spans online drop-in missions and local couch/LAN play, and both halves
are shipped C++. The online surface is **Spec Ops**:
`UV4SpecOpsMissionCatalog::BuildLaunchMissions()`
(`V4SpecOpsCoopSystems.cpp:177`) builds exactly 18 cross-cell missions, each
1–4-player and each carrying at least two `CrossCellLoadouts` whose cells are
validated to be listed as supported — so an Embassy Breakpoint flows Tactical →
Stealth and a Citadel All-Cell mission spans four cells. The difficulty model is
the feature doc's headline numbers, computed not transcribed:
`UV4SpecOpsDifficultyModel::BuildDifficultyProfile` (`:262`) sets
`EnemyScalar = 1.0 + (PlayerCount-1) × 0.45`, yielding exactly **1.0× / 1.45× /
1.90× / 2.35×** for 1–4 players, alongside
`ReviveTokenCount = max(0, 5 - players)` and a friendly-fire scale that loosens
with party size. The post-launch online model `UV4SpecOpsOnlineCoopModel` is
dense: **Marathon** chains the full 18-mission ladder into one timed
host-authoritative run (`BuildMarathonRunConfig` pulls all 18 mission ids;
`AdvanceMarathonRun` only completes after the last mission while preserving
elapsed time; the leaderboard score is
`difficultyFloor × 100000 − timePenalty`); **Endurance** is endless with
deliberately diminishing supply (`BuildEnduranceWaveState` shrinks the ammo pool
by `ResourceScalar = clamp(1 - (wave-1)×0.08, 0.1, 1.0)` and drops a heal flask
every two waves); a **six-card modifier deck** (Vampiric Heal, Speed Demons,
Iron Armour, Inverted Vision Cones, Low Visibility, Scarce Munitions) feeds a
deterministic `SelectModifierStackAtMissionStart` that combines enemy and reward
scalars per weekly featured contract; the **matchmaking queue** matches on
shared region and intersecting preferred cells with skill averaging
(`UV4SpecOpsMatchmakingQueue::FindMatch`); and the **Temple Breach crossover**
puts a Tactical-FPS player and a Wukong player in the same room with asymmetric
objectives. `BuildDropInPolicy` pins the seam honestly: host-authoritative,
drop-in and drop-out enabled, **host migration disabled** for the mission.

Local co-op rides the **`UV4LocalMultiplayerPolicyLibrary`** policy gate. The
five shipped split-screen policies (`BuildLaunchPolicies`,
`V4LocalMultiplayer.cpp:81`) cover Tactical Co-op, Wukong Two-Tail, Contra Co-op
(screen-edge tethering on), RTS Team (deterministic lockstep at 25 Hz), and the
1–4-player Spec Ops experience, plus an RTST **hot-seat** policy
(single-keyboard alternation) and an 8-player **LAN skirmish** (backend-free
deterministic lockstep, broadcast port 7777). Admission is a real fail-closed
predicate: `CanStartLocalMultiplayerSession` (`V4ModeSubsystem.cpp:112`) rejects
an unknown experience, an unsupported player count, the wrong platform class, or
— the honest seam between couch and cloud — a backend-required session when the
backend is unavailable, so a LAN skirmish that needs matchmaking refuses to
start offline rather than fake a connection. `ValidateLaunchPolicies`
independently asserts each of those invariants (screen-edge tethering for
Contra, single-keyboard for hot-seat, backend-free lockstep for LAN).

## PvP modes

Competitive PvP ships as per-mode match state machines that a dedicated server
drives. The **R6-style 5v5** is `UV4R6ModernMatchComponent`
(`V4R6ModernMatchComponent.cpp`): two rosters (Attackers/Defenders) capped at
five operators each, a `ConfigureMatch` that sets `RankedBestOf9` to 9 rounds /
5 to win (or `CasualBestOf7` to 7 / 4), a 60-second setup phase, and a real
phase machine `Setup → Action → RoundEnd → MatchEnd` advanced by `AdvancePhase`.
`CompleteObjective` resolves the round per objective type — `Bomb` plant and
`Hostage` extraction award the attackers immediately, `SecureArea` accrues
clamped progress until 1.0 — and `RecordRoundWin` flips the match to `MatchEnd`
the instant a team reaches `RoundsToWin` or the round count hits `MaxRounds`.
The attacker and defender gadget vocabulary is a 16-value `EV4R6GadgetType` enum
(hard/soft breach, drone, EMP, smoke, flash, frag, claymore, heartbeat scanner;
reinforced wall, barbed wire, deployable shield, bulletproof camera, proximity
alarm, trap mine, jammer), with structural destruction carried by a separate
`V4R6ModernDestructionComponent`.

The **CoD-style 6v6 suite** is data-driven through
`UV4CoDMPModeCatalog::BuildModeRules()` (`V4CoDMPModeCatalog.cpp:35`), which
builds exactly 10 rulesets and sets the mode-specific flags from the type — Team
Deathmatch to 75, Domination to 200, Hardpoint to 250 with `bRotatingObjective`,
Search & Destroy as a one-life best-of-11, Kill Confirmed to 65 with
`bRequiresDogTags`, plus Free-for-All, Gun Game (`bFinalKnifeRequired`), Prop
Hunt, One in the Chamber, and Sticks and Stones (`bBankruptcyMechanic`).
`UV4CoDMPMatchComponent` then _enforces_ those flags: `RecordKill`
(`V4CoDMPMatchComponent.cpp:25`) refuses a kill that lacks a confirmed dog tag
in Kill Confirmed, and gates the winning kill on a final-knife in Gun Game,
while `AdvanceTime` resolves a time-limit win by comparing team scores. The
100-player **Battle Royale** (`V4Mode_Tactical_CoDWarzone`, the largest mode
spec in the suite at 127 assertions) — drop, shrinking circles, Gulag, buy
stations, loadout drops, and the Resurgence/Plunder variants — is inventoried
with the rest of the loud tactical surface on
[./cell-tactical-fps.md](./cell-tactical-fps.md). All PvP modes inherit the same
ranked ladders, MMR, and replay capture described in the architecture
companion's live-service section.

## Horde defense

Horde is one shared wave director with a per-cell verb set.
`UV4HordeVariantCatalog::BuildLaunchVariants()` (`V4HordeDefenseSystems.cpp:49`)
defines exactly six launch variants, one per cell: Tactical Last Stand, Shadow
Evade (`bEvadeOnly` — the waves hunt you), Tactics Stronghold, Wukong Trial
Swarm, RTS Tower Hold (`bUsesTowerDefense`), and Contra Barrage
(`bSideScrolling2D`); `ValidateLaunchContent` asserts all six cells and all six
variant kinds are covered. A single post-launch cross-cell variant, **Fireteam
Stronghold** (`BuildPostLaunchVariants`), lets a Tactical-FPS fireteam defend an
RTST-cell base. The pacing is real domain math, not a difficulty slider:
`UV4HordeWavePacingDirector::BuildWavePlan` (`:244`) multiplies a base spawn
rate by `WaveScalar = 1 + (wave-1)×0.12`, a
`PlayerScalar = 1 + (players-1)×0.18`, a per-variant spawn modifier (evade
0.65×, tower 1.20×, side-scroll 1.35×), and a clamped **performance-pressure**
term — `V4PerformancePressure` (`:40`) reads recent objective success, survival
time, and damage taken into a `[0.75, 1.35]` band so a coordinated party gets
pushed and a struggling one gets relief, the same adaptive discipline the AI
Director uses elsewhere. Elite count scales as `clamp(wave/3 + …, 0, 12)`, and
`BuildWaveSchedule` rolls a full session's curve. The feature spec's "every 5th
wave is a boss wave," the inter-wave build/buy intermission, and the per-cell
leaderboards are the design layer this director's numbers feed.

## Where this connects

The mode registry is the orchestration layer almost everything in this page
hangs off, and it is also the seam to the rest of V4. The shared GAS spine,
perception model, netcode authority, and the registry/discovery internals all
four families ride are in
[./shared-cross-cell-engine.md](./shared-cross-cell-engine.md); the training
ranges, replay theater, per-cell signature modes (R6 Anniversary, CoD Zombies,
Hitman Elusive Targets, Wukong Mirror Veneration), and the PvE-only AI Director
that tunes these modes are on
[./modes-training-replay-signature-and-ai-director.md](./modes-training-replay-signature-and-ai-director.md).
The genre-by-genre engine view — where each campaign's cell, each PvP cell's
gunplay or RTS economy, and each horde variant's verb set actually live — is
split across the per-cell pages
([./cell-tactical-fps.md](./cell-tactical-fps.md) and its siblings). For the
engine-side registry, the GameFeature discovery pipeline, the live-service
subsystem, and the Rust online-services backbone that ranked PvP, co-op
matchmaking, and replay storage read from, read the architecture companion,
[../architecture/game-modes-live-service.md](../architecture/game-modes-live-service.md).

## Related

- The feature hub: [../V4_features.md](../V4_features.md)
- [Modes: Training, Replay, Signature & AI Director](./modes-training-replay-signature-and-ai-director.md)
  — the practice, spectating, evergreen-event, and adaptive-difficulty surfaces
  these modes feed
- [Shared cross-cell engine](./shared-cross-cell-engine.md) — the GAS spine,
  perception model, netcode authority, and mode machinery every family rides
- [Tactical FPS cell](./cell-tactical-fps.md) — the gunplay engine behind the
  PvP families and the 100-player battle royale
- Architecture companion:
  [../architecture/game-modes-live-service.md](../architecture/game-modes-live-service.md)
  — the mode registry, discovery pipeline, live-service subsystem, and Rust
  online-services backbone
