Skip to content

Naval HVT Objectives Atlas

rayswaynl edited this page Jul 7, 2026 · 5 revisions

Naval HVT Objectives (offshore capturable carriers and platforms)

Source-verified 2026-07-07 against claude/build84-cmdcon36 (c3cc5b1, Build 91 / release 1.2.2 candidate). Paths relative to Missions/[55-2hc]warfarev2_073v48co.chernarus/ unless noted. Arma 2 OA 1.64.

Why This Matters

The naval HVT feature adds a whole new objective family to Chernarus: three pre-placed offshore LHD "carrier" objectives off the east coast, each one a real capturable town logic that starts GUER-owned and defends itself with a GUER combat air patrol (a proximity-gated circuit of jets by default). Capturing a carrier is a multi-part payoff: it becomes a friendly deck-spawn for GUER respawns, it carries 2 capturable camp bunkers of its own, and whichever carrier is geometrically the middle one of the three (currently Khe Sanh Charlie) carries the SCUD saturation-strike launcher.

This page is the runtime map for the placement + capture + integration flow. It deliberately does not restate the SCUD strike numbers (warheads, ballistic flight, MIRV) — those live on SCUD Saturation Strike Mechanic. It also distinguishes the naval CAP (defined here) from the unrelated GUER Air Defense Loop, which is a separate town-defender loop in its own file.

The single most important caveat: one part of the post-capture integration in server_town.sqf is still dead code that reads a variable nobody sets (the wfbe_naval_marker recolour); the carrier hangar/aircraft-sell branch that used to be dead is now wired and live (Build 91). The live respawn integration is the deck-spawn in Client_OnRespawnHandler.sqf. The "Dead Vs Live Integration" table below is the load-bearing part of this page — read it before touching the carrier hangar block.

Master Gate

Everything is behind one constant. Set it to 0 for a byte-for-byte vanilla session.

Constant Value Source Meaning
WFBE_C_NAVAL_HVT 1 (default) Common/Init/Init_CommonConstants.sqf:1136 Master gate. 0 = no objects, no logic, no CAP, no SCUD.
WFBE_C_SCUD_COST 25000 Init_CommonConstants.sqf:1139 Funds cost for a SCUD launch (consumed by SCUD page).

The gate is checked in four independent places, all with a default-on fallback of 1:

  • Server/Init/Init_Server.sqf:52 compiles the SCUD strike handler only when on.
  • Server/Init/Init_Server.sqf:852 execVMs Init_NavalHVT.sqf only when on.
  • Server/Init/Init_NavalHVT.sqf:26-28 self-guards and logs a skip line if off.
  • Server/FSM/server_town.sqf:283 guards the post-capture block (combined with the per-location wfbe_is_naval_hvt tag).

The Asset Roster

Despite the orchestrator header comment saying "2 naval logics" (Init_NavalHVT.sqf:103), the code spawns, tags, and registers three LHD HVTs. They are pre-placed game logics in mission.sqm, each calling Init_Town.sqf so they enter towns[] as ordinary town objects.

Asset Town name Sea area Payoff mission.sqm
[A] Khe Sanh Alpha NE sea carrier deck-spawn mission.sqm:55-56
[B] Khe Sanh Bravo SE sea carrier deck-spawn mission.sqm:77-78
[C] Khe Sanh Charlie Skalisty Island sea carrier deck-spawn + SCUD pad mission.sqm:99-100

Each mission.sqm init line is [this,"Khe Sanh X","+",10,50,400,["LargeTown1"]] execVM "Common\Init\Init_Town.sqf" plus this enableSimulation false — so every carrier is a LargeTown1-template town with starting SV 10, max SV 50, town value 400 (mission.sqm:56,78,100). The name variable that the orchestrator matches on is written by Init_Town.sqf:31 (_town setVariable ["name",_townName]).

Default GUER ownership

No starting-mode in Server/Init/Init_Towns.sqf assigns the carriers, so they fall through to the per-town default: Init_Town.sqf:90 sets any logic with no sideID to WFBE_DEFENDER_ID. WFBE_DEFENDER = resistance (Common/Init/Init_Common.sqf:297), so WFBE_DEFENDER_ID resolves to the GUER/resistance side id, which is WFBE_C_GUER_ID = 2 (Init_CommonConstants.sqf:32). The CAP and SCUD-action loops also defensively fall back to WFBE_C_GUER_ID when reading the logic sideID (Init_NavalHVT.sqf:221,303).

Orchestrator Lifecycle

Server/Init/Init_NavalHVT.sqf runs once, server-only, after town init. End-to-end:

Stage Source Behavior
Server + gate guard Init_NavalHVT.sqf:27-31 Exits on client (:27); exits if IS_naval_map == false (:28, e.g. Takistan); exits + logs if WFBE_C_NAVAL_HVT != 1 (:29-31).
Wait for town init Init_NavalHVT.sqf:35-36 waitUntil townInit then waitUntil towns so the pre-placed logics exist in towns[].
Locate the 3 logics Init_NavalHVT.sqf:106-122 Scans towns[], matches getVariable "name" against the three Khe Sanh strings; warns + exits if any is missing.
Force sea level Init_NavalHVT.sqf:125-127 setPosASL each logic to z=0 (sea surface) for accurate capture-radius detection.
Water sanity check Init_NavalHVT.sqf:131-135 diag_log a NAVALHVT-WARN if any logic is not over surfaceIsWater — catches a bad land coordinate server-side.
Derive [x,y] anchors Init_NavalHVT.sqf:139-142 2-element anchors from logic positions for the prop spawners.
Spawn LHD hulls Init_NavalHVT.sqf:152,173,193 Builds each carrier via WFBE_NavalHVT_SpawnLHD, heading 90.
Deck-Z + tags Init_NavalHVT.sqf:160-166,180-186,195-201 Computes top-of-hull Z, stores wfbe_naval_deckz and wfbe_is_naval_hvt=true (both broadcast) on each logic.
SCUD + camp deck props Init_NavalHVT.sqf:277-393,861-1038 Resolves the geometrically-middle carrier, adds its SCUD pad ref + addAction-dispatch loop and an attachTo'd erect MAZ_543_SCUD_TK_EP1; separately builds 2 capturable camp bunkers + reseats the depot on the deck of all 3 carriers.
Register logics Init_NavalHVT.sqf:212,282 Publishes WFBE_NAVAL_HVT_PLATFORMS ([Charlie]) and WFBE_NAVAL_HVT_LOGICS ([A,B,C]).
Start CAP loops Init_NavalHVT.sqf:289-376 One proximity-gated GUER CAP thread per logic.

Anchor / ASL placement rules

The header comments are explicit about the A2-not-A3 placement discipline (Init_NavalHVT.sqf:11-16):

  • setPosASL is used for every sea object (SpawnProp at Init_NavalHVT.sqf:52, hull parts, pads, SCUD, camps). setPos/setPosATL would snap to the seabed.
  • All createVehicle calls are GLOBAL/server-authoritative so AI and collision see them.
  • The hull is built from an 11-part offset list WFBE_C_NAVAL_LHD_OFFSETS (Init_NavalHVT.sqf:81-93): Land_LHD_1..6, Land_LHD_house_1, Land_LHD_house_2, Land_LHD_house_2_CP, Land_LHD_elev_L, Land_LHD_elev_R. All offsets are [0,0,0] (the model geometry holds the ~250m layout internally); house_2_CP and elev_L were previously dropped by an earlier commit and restored (Init_NavalHVT.sqf:76-80).
  • Each prop is enableSimulation false + allowDamage false (SpawnProp:67-68), so the carrier hull is indestructible static scenery — only the underlying town logic's sideID is capturable.
  • The flight deck sits at an engine-verified 15.9 m ASL, not a guessed 16/22 (Init_NavalHVT.sqf:220). Alpha's and Bravo's HeliHCivil heli pads are setPosASL'd explicitly to that height (Init_NavalHVT.sqf:212-213,241-242) — a prior bug placed them at z=0 (sea level, inside the hull); this is fixed, not open.

Capture Lifecycle

A carrier is captured by the ordinary town-capture loop (server_town.sqf) — there is no special naval capture math; the LHD is a LargeTown1 town with a tiny SV (10/50), so it flips like any small town once a side dominates the capture radius. See Towns, camps and capture atlas for the generic capture/SV mechanics.

What is naval-specific is the post-capture block in server_town.sqf:281-316, gated on WFBE_C_NAVAL_HVT == 1 && _location getVariable "wfbe_is_naval_hvt" (:283). On capture of a tagged carrier it:

  1. Resolves the new owner side and broadcasts a "naval-hvt-captured" HandleSpecial to clients (no inbound warning) and logs it (:289-290).
  2. Attempts to recolour a wfbe_naval_marker map marker (:293-296).
  3. If the location is tagged wfbe_is_carrier_hvt, deletes the old owner's hangar and respawns one for the new owner via WFBE_C_HANGAR, writing wfbe_hangar + wfbe_airfield_side on a wfbe_airfield_logic_ref (:300-314).

Item 2 is still dead at this commit; item 3 is now live (Build 91) — see below.

Dead Vs Live Integration

This is the load-bearing accuracy point. The orchestrator tags each carrier logic with exactly wfbe_is_naval_hvt + wfbe_naval_deckz (Init_NavalHVT.sqf:164-165,184-185,199-200), and as of Build 91 also sets wfbe_is_carrier_hvt (Init_NavalHVT.sqf:603). It never sets wfbe_naval_marker — a whole-mission grep confirms zero setVariable writers for it.

server_town.sqf reads Set anywhere? Effect
wfbe_is_naval_hvt (:283) Yes, Init_NavalHVT.sqf:165,185,200 LIVE — the naval post-capture block does run on carrier capture.
wfbe_naval_marker (:293) No setter anywhere DEAD — defaults to "", the marker recolour at :294-296 never fires.
wfbe_is_carrier_hvt (server_town.sqf:411) Yes, Init_NavalHVT.sqf:603 LIVE — the carrier hangar/aircraft-sell respawn branch (server_town.sqf:411-435) now runs on carrier capture.
wfbe_airfield_logic_ref (:301) Yes, Init_NavalHVT.sqf:318 (self-reference) LIVE — set to the carrier logic itself; the hangar-respawn branch executes on carrier capture.

Practical consequence: capturing a carrier flips its sideID, fires the announcement, and now also emits a MATCH|v1|MILESTONE|CARRIER_CAP| telemetry line (server_town.sqf:398-401). Because of the deck-spawn integration below it becomes a friendly respawn, and — no longer aspirational — the carrier hangar / aircraft-sell shop on the deck now respawns for the new owner as part of the B74.2 carrier air-shop wiring (Init_NavalHVT.sqf:585-608; server_town.sqf:411-435). It still does not recolour a dedicated naval marker: wfbe_naval_marker has no setter anywhere, so the marker-recolour branch (server_town.sqf:404-407) remains dead.

Deck-Hangar / Airfield Respawn Integration

There are two airfield-respawn code paths that touch carriers; only one is live.

Live: deck-spawn on GUER respawn

Client_OnRespawnHandler.sqf:58-59 (GUER) and :64-69 (WEST/EAST, B74.2) are the working integration. For a GUER respawn, if the chosen town has wfbe_is_naval_hvt, the player is placed on the deck (:58-59). For WEST/EAST, if the assigned respawn spawn point is a naval-HVT town that side holds, they are also deck-spawned (:64-69). For a resistance/GUER respawn it picks a friendly town _t (honoring the player's selected town when valid, else a random GUER-held/neutral town), then:

  • if _t getVariable "wfbe_is_naval_hvt" is true, it setPosASL the unit to the carrier's deck: [x, y, deckZ + 2] using wfbe_naval_deckz (default 16) (:50-51);
  • otherwise it uses the normal GetRandomPosition ground spawn (:53).

So once a carrier is GUER-held, respawning GUER players land on its deck rather than in the water. This is the real "carrier" payoff at this commit.

Mostly inert: GetClosestAirport gate

Client_GetClosestAirport.sqf:13 scans nearEntities [WFBE_Logic_Airfield, _range] and, for sideJoined == resistance, only accepts an airfield whose wfbe_airfield_side == resistance. This is the GUER airfield-ownership gate that the dead server_town.sqf block was meant to feed (it writes wfbe_airfield_side at :312). Because the carriers are not registered as WFBE_Logic_Airfield (the orchestrator never registers them; grep for airfield in Init_NavalHVT.sqf finds only a TODO comment at :22) and the carrier-hangar branch is dead, carriers never appear here. Treat the wfbe_airfield_side / wfbe_hangar carrier wiring as a designed-but-unwired path, not a live aircraft-sell shop.

The same wfbe_hangar / wfbe_airfield_side variables ARE live for ordinary land airfields via the Task-12 capture block at server_town.sqf:460-557 (:556 sets wfbe_airfield_side) — see Town capture, garrison and airfield rebuild. The naval block was copied from that pattern but its inputs were never populated.

Map marker label

The one client-side naval display that is live: updatetownmarkers.sqf:71-73 prefixes the carrier's town name onto its marker text for any wfbe_is_naval_hvt town, so the LHDs show up named on the map. (This is unrelated to the dead wfbe_naval_marker recolour.)

The Naval CAP (defending air patrol)

Each carrier gets its own proximity-gated GUER combat air patrol, defined inline in the orchestrator (Init_NavalHVT.sqf:615-859) — one spawned thread per logic. This is the patrol the prompt asks to verify against GUER Air Defense Loop: they are separate loops in separate files and do not share code. The GUER Air Defense Loop (Server/Server_GuerAirDef.sqf:1-2) keeps Ka-137s/Mi-24s over active GUER-held towns; the naval CAP keeps its own patrol over each carrier. Cross-link them as related GUER air, not as one loop.

By default this is a twin-L39_TK_EP1 circuit patrol, not the legacy Hind/An2 orbit; WFBE_C_NAVAL_CAP_L39 defaults to 1 and supersedes both WFBE_C_NAVAL_CAP_THREE_HINDS and the base Hind+An2 path when >0 (Init_NavalHVT.sqf:630, Common/Init/Init_CommonConstants.sqf:2182).

Property Value Source
Loop cadence sleep 10 per cycle Init_NavalHVT.sqf:654
Arming radius any player within 1800 m of the asset Init_NavalHVT.sqf:662
Arm condition only while sideID == WFBE_C_GUER_ID (stops arming once captured) Init_NavalHVT.sqf:672
nil-guard _jet1/_jet2/_jetPilot1/_jetPilot2 pre-set to objNull before the arming branch, fixing a live-RPT bug where orbit/despawn ticks read them undefined Init_NavalHVT.sqf:626
Jets (default path) 2x L39_TK_EP1, setVelocity 90 m/s at spawn (avoids the zero-velocity stall-dive), flyInHeight 550/600 Init_NavalHVT.sqf:685-702
Pilot class WFBE_GUER_PILOT_CLASS (default GUE_Soldier) Init_NavalHVT.sqf:690-691
EASA randomisation if WFBE_C_NAVAL_EASA_RANDOM > 0 (default 1), both jets get a random EASA loadout stamped for client pickup Init_NavalHVT.sqf:710-719
GC protection wfbe_naval_cap=true tagged on group + both jets Init_NavalHVT.sqf:722-724
Circuit route 3-point circuit over the 2 outer carriers + the middle carrier, altitude 550, built once at arm time Init_NavalHVT.sqf:632-645
Airfield leg every 3rd lap, one leg to an inland airfield (alternating NEAF/NWAF), altitude 550 Init_NavalHVT.sqf:646-651,798-802
Route advance jet1 pilot advances to the next leg when within 500m, or after a 120s timeout (anti-stall) Init_NavalHVT.sqf:806-812
Formation jet2 pilot follows the same leg offset by +300/+300 m Init_NavalHVT.sqf:814
Legacy fallback (flag=0) 3x Mi24_P (WFBE_C_NAVAL_CAP_THREE_HINDS) or Mi24_P + An2_1_TK_CIV_EP1, fixed-radius orbit around the carrier Init_NavalHVT.sqf:727-828
Despawn inactivity timer hits >= 120s with no player in radius → delete crew + aircraft + group Init_NavalHVT.sqf:835-855

Because the arm gate checks GUER ownership (Init_NavalHVT.sqf:672), a captured carrier stops generating new CAP — but already-airborne CAP is not force-despawned on capture, only on the inactivity timeout.

SCUD Launcher (dynamic middle carrier)

The SCUD payoff is no longer hardcoded to Khe Sanh Charlie. Init_NavalHVT.sqf:166-199 computes which of the 3 carriers is geometrically the MIDDLE one (the pair with the largest separation is the "outer" pair; the remaining carrier is the middle) and stores it as WFBE_NAVAL_MIDDLE_LOGIC/WFBE_NAVAL_MIDDLE_ANCHOR. In the current mission.sqm layout this still resolves to Khe Sanh Charlie (Init_NavalHVT.sqf:280-283), but the mapping is derived, not fixed.

  • A HeliHCivil pad is created at the middle carrier's deck (_scudDeckZ, default 15.9), tagged wfbe_is_scud_pad, and linked back to the logic as wfbe_scud_pad_ref (Init_NavalHVT.sqf:294-299).
  • WFBE_NAVAL_HVT_PLATFORMS is published as [_scudLogic] (Init_NavalHVT.sqf:300) — the SCUD validation in Support_ScudStrike.sqf:36-39 iterates exactly this list.
  • The addAction is gated server-side (owning-side team leader within 50m of the visual launcher, not the pad) and then dispatched to the client — the actual addAction call lives in Client/PVFunctions/HandleSpecial.sqf:91-117 (case "scud-action-add"), not in Init_NavalHVT.sqf (Init_NavalHVT.sqf:302-336).
  • The visual MAZ_543_SCUD_TK_EP1 is spawned in deck-part model space (_scudDeckPart modelToWorld [8, -14, 0]), raised via the scudLaunch action, then attachTo'd to the deck hull part at deckZ + WFBE_C_NAVAL_SCUD_CLEARANCE (default 1.6) so it cannot slide off (Init_NavalHVT.sqf:351-393). It sits ON the deck, not inside the hull and not at a hardcoded z=16.

The four SCUD strings (STR_WF_SCUD_ACTION, STR_WF_SCUD_NO_FUNDS, STR_WF_SCUD_SELECT_TARGET, STR_WF_SCUD_LAUNCHED) exist in stringtable.xml as before.

Capturable Camp Bunkers (NAVALHVT-CAMP)

Each carrier carries 2 capturable camp bunkers of its own, built at runtime by Init_NavalHVT.sqf:861-1038, guarded by WFBE_C_NAVAL_CAMPS_DECK (default 1, always-on correctness fix — Common/Init/Init_CommonConstants.sqf:2223).

Property Value Source
Camps per carrier 2 (6 total across the 3 carriers) Init_NavalHVT.sqf:961
Bunker model WFBE_C_CAMP = Land_Fort_Watchtower (same class land-town camps use) Common/Config/Core_Models/CombinedOps_W.sqf:5
Flag model WFBE_C_CAMP_FLAG = FlagCarrierGUE Common/Config/Core_Models/CombinedOps_W.sqf:6
Damage coefficient WFBE_C_CAMP_HEALTH_COEF = 30 Common/Config/Core_Models/CombinedOps_W.sqf:8
Placement deck-part model-space offsets [-10,18,0] and [-10,-18,0] (port side, clear of the SCUD at [8,-14]) Init_NavalHVT.sqf:961
Capture logic HeliHEmpty stand-in logic per camp, tagged wfbe_camp_bunker; side/supply copied from the town; starts Server/FSM/server_town_camp.sqf Init_NavalHVT.sqf:940-964
Depot WFBE_C_DEPOT = Land_fortified_nest_big_EP1, reseated to the carrier anchor at deck height via a bounded nearestObjects search Init_NavalHVT.sqf:965-974,1024-1035

Why runtime-built and not mission.sqm-synced: carrier towns never receive LocationLogicCamp entities from Init_Town.sqf, so a wait for a synced camps variable always times out empty — every carrier previously shipped with zero capturable camps. The code comment documents the live-RPT symptom directly (Init_NavalHVT.sqf:920-927). A dormant re-seat path for synced camps still exists (Init_NavalHVT.sqf:977-1022) but never fires for these towns.

Risk Register

Status Finding Evidence
Now live Carrier hangar / aircraft-sell respawn block is wired: wfbe_is_carrier_hvt is set on every naval logic. Init_NavalHVT.sqf:603; server_town.sqf:411-435.
Correctness fix Alpha/Bravo heli pads and SCUD/camp props previously sat at sea level inside the hull (z=0); now set to the engine-verified deck height 15.9m. Init_NavalHVT.sqf:213,220,295.
By design Default naval CAP is a 2x L39_TK_EP1 circuit patrol, not Mi24_P+An2; the legacy pair is only used when WFBE_C_NAVAL_CAP_L39=0. Init_NavalHVT.sqf:630,676-726; Common/Init/Init_CommonConstants.sqf:2182.
Doc note SCUD carrier is derived at runtime (largest-separation-pair geometry), not hardcoded to Charlie, though it currently resolves to Charlie. Init_NavalHVT.sqf:166-199,280-283.
Dead code Naval HVT marker recolour on capture never fires. server_town.sqf:293-296; wfbe_naval_marker unset.
Doc drift Orchestrator header says "2 naval logics" but the code handles 3 (towns[] lookup, parts, CAP loops, WFBE_NAVAL_HVT_LOGICS). Init_NavalHVT.sqf:103 vs :106-118,376,282.
Needs in-engine review LHD part offsets, deck-Z, and anchor coordinates are best-guess; flagged by the author. Init_NavalHVT.sqf:18-23,57-59; NAVALHVT-WARN water check at :131-135.
Behavior note Already-airborne CAP is not force-despawned when its carrier is captured; only the 120s inactivity timer or game-over removes it. Re-arming correctly stops after capture. Init_NavalHVT.sqf:300-373 (:319 arm gate, :363 despawn).
Typo (noted, unfixed) WFBE_GUERAIRPORTUNITS vs WFBE_GUEAIRPORTUNITS air-sell typo called out by the author but left for the air-sell integration. Init_NavalHVT.sqf:22.

Smoke Checklist

Change type Minimum smoke
Master gate Boot with WFBE_C_NAVAL_HVT=0: no LHDs, no CAP, no SCUD action; RPT shows the skip line (Init_NavalHVT.sqf:27).
Placement Boot on; confirm three named carriers over water (no NAVALHVT-WARN in RPT), hulls indestructible, decks at ~z16.
CAP Approach within 1800m of a GUER carrier → 2x L39 arm and fly the 3-carrier circuit (watch for the periodic airfield leg); leave for 120s → both despawn; capture the carrier, confirm CAP stops re-arming.
Camps On a GUER-held carrier, confirm 2 capturable camp bunkers exist on the deck and can be captured like a land camp.
SCUD deck Confirm the erect SCUD model sits flush on the deck of the middle carrier (not floating/sunk), and does not slide when the carrier logic reseats.
Capture Flip a carrier; confirm sideID changes and the naval-hvt-captured log/announce fires with a `MATCH
Respawn As GUER, with a friendly carrier, respawn and confirm you land on the deck (deckZ+2), not in the sea.
SCUD pad On the GUER-held middle carrier (currently Khe Sanh Charlie), as team leader within 50m, confirm the SCUD action appears; full strike behavior is smoked on the SCUD page.

Continue Reading

Sidebar

Clone this wiki locally