As of 2026-11-15 (night update: nested config, join in progress, carrier-down notice, replay trackers, HUD overlay, new document site prefab, GitHub README). Written for whoever picks this up next, human or Claude session. Read this first,
then docs/test-routine.md (what to check in play) and Endgame 1989 implementation plan.md (the
original plan; parts are superseded, see "Decisions that changed the plan").
Legend: played = seen working in a Workbench or dedicated run. written = code exists and compiles, never seen working. open = known problem or missing piece.
Two sides (BLUFOR/US, OPFOR/USSR, 1989) on a COALITION Lobby game mode, Eden terrain. FIA militia
(AI) holds every site and fights both sides. Phase 1: clear your FOB. Phase 2: copy documents at
3 sites. Phase 3: find the cipher and transmit at a radio site for 12 minutes. The briefing for
players is docs/briefing.md.
| Path | What |
|---|---|
Scripts/Game/GRAD_Endgame/GameMode/ |
Phase state machine (GRAD_Endgame_GameModeComponent), admin RPCs, EPhase |
.../Respawn/ |
Per-side wave respawn on top of COALITION's respawn manager (modded COA_RespawnManager), wave rules + self-test |
.../Objectives/ |
FOB, document site + copy action, radio site + transmit action, cipher + cipher sites, vehicle spots, site selection, TableScan (finds tables for the documents), ArsenalFree (arsenals cost no supplies) |
.../AI/ |
GRAD_Endgame_GarrisonComponent: spawns FIA groups once, tiers LIGHT/MEDIUM/HEAVY, defend waypoint per group |
.../Info/ |
GRAD_Endgame_TaskService (objectives as vanilla SCR_Tasks), InfoService (server), InfoClient (client, owner RPCs) |
.../UI/ |
FieldLogDisplay (HUD info display), MapStatusLine, Typewriter sounds, AdminMenu, MapJournalGuard |
.../Replay/ |
Copy of BreakingContact's replay (GRAD_BC_* renamed GRAD_Endgame_*) + ReplayStubs |
.../Config/, .../Log/ |
GRAD_Endgame_Config (all tunables, now NESTED: one m_GRAD_Endgame object with groups m_Respawn, m_Factions, m_Fob, m_Documents, m_Fia, m_Radio, m_Hud, m_Match, m_Debug; getters unchanged), match log ($profile:GRAD_Endgame/match_*.log) |
.../GameMode/GRAD_Endgame_LateJoin.c |
Join in progress: Shift+O opens COALITION's slotting menu for a slotless late joiner (phases 1 and 2); server gate in a modded COA_SlottingManager.UpdateSlotPlayerID |
.../Objectives/GRAD_Endgame_NoPickup.c |
Modded SCR_InventoryAction: refuses every inventory action on a document site (the site prefab inherits a vanilla inventory item) |
.../Replay/GRAD_Endgame_*Tracker.c, ExplosiveCatalog, DetonationWatcher |
Shots, grenades, smoke, rockets for the replay (ported from BreakingContact). Hooked in by minimal overrides in Prefabs/Characters/Core/Character_Base.et, Prefabs/Weapons/Core/{Ammo_Rocket,FragGrenade,SmokeGrenade}_Base.et and a component on the lobby entity |
Missions/Endgame89.conf + Scripts/.../Config/GRAD_Endgame_Config.c |
The options. GRAD_Endgame_Config is a SCR_MissionHeader subclass: all values live in the mission file (currently a TEST config, see "Before a real match"); a server overrides any of them under game.gameProperties.missionHeader (server_config.sample.json lists all 70). There is no separate config file |
Configs/System/chimeraInputCommon.conf |
Input actions: Shift+J/K/T/U, plus V/C on the replay map |
Configs/Map/MapFullscreen.conf |
Adds the replay map layer to the fullscreen map (same GUID as vanilla, partial override like BreakingContact) |
Configs/Gearscripts/ |
US 80s and USSR 80s gearscripts (copied from BreakingContact) |
Prefabs/ |
FOB (per side), document site (Items/Misc/IntelligenceFolder_E_01/EG_IntelligenceFolder_E_01, inherits the vanilla intel folder, made in Workbench; placed on a RANDOM free table by script; hidden when the site is not chosen; pickup blocked; the old table-based prefab and DocumentSite_Auto were deleted), radio site, cipher item, cipher site, vehicle spots, ammo arsenal boxes, test garrison |
Prefabs/!Systems/!Characters/Core/COA_PlayerController.et |
Override of COALITION's controller: adds our HUD display (made in Workbench) |
Missions/Endgame89.conf |
The scenario ({3C7A91E05B2D48F6}Missions/Endgame89.conf) |
worlds/endgame.ent + endgame_Layers/default.layer |
Test world: sub-scene of Eden; lobby, 2 FOBs, 9 document sites, 3 radio sites, 2 cipher sites, vehicle spots |
UI/layouts/, UI/Textures/Icons/, UI/Textures/LoadingScreen/ |
HUD layouts (Roboto Mono font), replay map icons (copied from BreakingContact, same GUIDs), the loading screen image (m_sLoadingScreen, m_sPreviewImage, m_sIcon of the mission file) |
README.md (root) |
The GitHub README: pitch, phases, admin config, credits |
Sounds/ |
Typewriter audio projects (key1..5, return, bing) |
docs/ |
briefing.md, test-routine.md, garrison-orders-research.md, this file |
Dependencies (addon.gproj): the base game, COALITION Lobby, Coalition VON.
- COALITION reaches GAME. Match log opens, document and radio sites are chosen (balanced between the FOBs), phase stays WAITING.
- Phase 1 (FOB) starts when COALITION's freeze time (safestart) ends (
WaitForFreezeEnd, log linefreeze_over). Garrisons and vehicles spawn, each side gets a task for its own FOB. - First FOB cleared: phase 2 for both sides. Each side only sees and may copy documents once its own FOB is cleared. Spawns move to the cleared FOB, waiting dead are released.
- A side with the threshold (default 3) of copies: phase 3 for both. Cipher spawns (0.5 m above its
site), the leading side's leaders get its position as a task. Players dead at that moment are released at once;
any death after it is final (permadeath switches on after a grace period for the released ones). Anyone carrying the cipher may transmit
(
m_eTransmissionRole 1). When the cipher carrier goes down (dead or unconscious) BOTH sides get a task and a HUD notice with the last known position, blurred tom_fCipherLastKnownRadius(25 m). It is cleared when a living player carries the cipher again; the other side's stale "Recover the cipher" task is removed at the first pickup. Join in progress: a player who connects after the match went live has no slot and (COALITION only offers slotting during safestart) sees no lobby. A HUD hint and Shift+O open the slotting menu until the phasem_eLateJoinClosesAt(default RADIO = phases 1 and 2) begins. - Win: transmission finished, or a side eliminated (only if both sides had players at phase 3 start), or time (COALITION limit 60 min = draw). Then the replay plays, then COALITION's AAR.
| Area | Status | Notes |
|---|---|---|
| Phase machine, FOB capture, first-FOB rule, document/radio/cipher flow | played (listen server and dedicated) | Match logs show every transition |
| Site selection balance | played | Self-test 20/20 fair; real layout is unbalanced (see open) |
| Garrison spawn, clearing | played | 14 groups / ~69 agents on a 2-core server |
| Garrison waypoints | played | Defend waypoint added 2 s after spawn. Navmesh fixed by the mapper; garrisons move (confirmed 2026-11-14) |
| FIA vehicle patrols | played | 2 UAZ PKM FIA, crewed by a fire team, loop over the chosen document sites (GRAD_Endgame_FiaPatrol.c, config m_iFiaPatrol*). Confirmed driving (2026-11-14) |
| Wave respawn | played | Death to release exactly 27 s at debug scale 10 (270 s real) |
| Permadeath wave bug (wave kept running after permadeath) | written | Fixed in EndgameTick, not run |
| Freeze-time phase start | written | Not run |
Tasks (native SCR_Task) |
played | Click-through crash guarded by MapJournalGuard (workaround) |
| HUD field log, map status line | written / partly played | Display registered via the controller override; keys Shift+J/K/T/U new and untested; status line not registered in a map config yet |
| Copy action vs widget sync | written | Reworked: widget follows the action's real Duration (prefab, 10 s). Untested |
| Typewriter sounds | written | Wired to Sounds/*.acp; untested in a match |
| Replay | written / partly played | Recording and playback start ran (69 frames). Fixed after that run, not rerun: spectator parked at y=100000 is no longer recorded, living players open the vanilla map menu (pan/zoom, no HUD), FIA garrison soldiers are recorded (neutral icon). After-action hand-off not yet seen |
| Document placement on tables | written / partly played | TableScan found a table within 100 m of all 9 sites. Auto placement worked for 4 of 5 chosen sites (doc_placed log). Drill benches now accepted, same-floor limit 2.5 m, 5 cm drop onto the surface. Untested after the last prefab change |
| Document site action ("Copy documents") | open | The Auto prefab is a vanilla paper prop with no RplComponent: added back (with the GM editable component). Whether the prop has a collider the action can aim at is unconfirmed |
| Game Master debug | written | Document sites and the cipher item are GM editables (the cipher site is NOT: the editable component put it at 0 0 0, so it has an orange marker instead); a green/grey sphere and line mark the planned document spot (only while the GM view is open); a GM move of a site is sent on to clients (doc_moved) |
| Admin RPCs (advance phase, end match, threshold) | written | No UI; need a console or a menu |
| Gearscripts | works, 6 check errors | Inherited from BreakingContact; radios are shared default items (see below) |
Nested config (m_GRAD_Endgame groups) |
open, broken | Server JSON overrides in the nested layout work, but the nested values in Missions/Endgame89.conf are NOT applied (local Workbench play: self-tests and m_fDebugTimeScale 10 ignored; earlier server: empty garrison lists). The code defaults therefore carry the prefab paths and arrays. UIWidgets.Object on the nested attributes did not help (checked 2026-11-15) |
| Join in progress (Shift+O) | written | Untested: hint shows for a spectator?, key reaches the spectator screen?, slot pick spawns him, refusal after the window (late_join_refused) |
| Cipher carrier-down notice and task | written | Played once: cipher_last line, notice and task appeared in the match log; the radius, clearing and both sides' notice are untested with two sides |
| Replay: shots, smoke, HE, rockets | written | Trackers ported. First test: one of two HE showed, smoke did not. Likely cause fixed (grenade poll gave up after 180 s in an inventory), not retested. Debug prints are off because the .conf debug flag is ignored |
| Replay: FIA colour, FIA-crewed vehicles | written | FIA = neutral icons tinted green; a vehicle with no faction of its own takes its occupant's faction (was recorded Empty = yellow). Untested |
| HUD overlay (cards above spectator menu and replay) | played | A second copy of the HUD layout in its own top layer (OVERLAY_ZORDER 1000); the HUD copy is hidden. Confirmed working above the map and the replay (2026-11-15). Only one live display instance (old ones retire: they doubled the typewriter sound): not yet tested through a spectator/respawn cycle |
| Hidden inactive document sites | played | Visible flag off for sites not chosen; confirmed in play (2026-11-15). Collision stays |
| FOB capture diagnostics | written | garrison_left lines (positions of the last 3 soldiers) when a FOB will not fall. A FOB is taken only when EVERY agent of its garrison is gone |
| Dedicated server / Workshop publish | played | Server loads the mission and the addon. Two crashes in Physics simulation on 2026-11-14 (server 20:47 UTC, one client 22:07), cause unknown; see open problems |
- Objectives are native Reforger tasks (no custom marker layer); the local-marker code in
InfoClient(ShowOnMap) is now unused and can go once tasks are confirmed. - No terrain-snap script: placement is exactly what the editor says.
- Phase 2 starts at the FIRST cleared FOB; the other side sees no documents until its own FOB is
cleared (and cannot copy: "Take your FOB first"). FOB taken-state is mirrored on the game-mode
component because the FOB prefab has no
RplComponent. - Transmission is open to every role; the radio operator slot exists but is optional.
- Phase 1 waits for COALITION's freeze time.
- Copy time = the action's
Durationin the document site prefab.m_fCopySecondsis unused. - Replay = BreakingContact's own code, copied (fast track, no extra dependency). Our first lean replay was deleted.
- Documents go on tables that are already in the world: the server scans around each placed site
(
m_fPlaceRadius100 m), picks a RANDOM free suitable table on the same floor (not the nearest: that was the same table every match) and sends the position to clients.m_bAutoPlaceoff keeps the documents where a mapper put them (manual). - The cipher item is an inventory item: its parent is now
Campaign_CacheNote_FIA.et(a different look from the document folder). The cipher also lies on a free table near its site (m_bAutoPlaceon the cipher site). - The document site is no longer a paper prop with our own
RplComponent/ActionsManagerComponent: it inherits the vanilla folder prefab, so those components are inherited. Adding them again givescannot be combined with component ...and no site. The Copy action was added in Workbench to the inherited actions manager (default context). Disable the inheritedInventoryItemComponentin the prefab (done by hand); a server-sideRequestUserLockcall was removed (it logged oneunregistred itemRPC error per site). - Late join is open in phases 1 and 2 (decided 2026-11-14); phase 3 locks every open slot as before. Players dead when phase 3 starts respawn at once; a later death is final, even inside the grace period.
- Radio/leadership gear flags are off in the lobby (
m_bEnableLeadershipRadios 0,m_bEnableRTORadios 0); everyone carries the shared radio and binoculars.
A. Nested .conf values are ignored (see the status table). Until fixed, the .conf test values (debug scale 10, self-tests, debug log) do nothing, and so does any other value the .conf sets above the code default. Idea: in GRAD_Endgame_ConfigLoader read the container (BaseContainer.GetObject("m_GRAD_Endgame") and each group) and copy it into the instance with BaseContainerTools.WriteToInstance; for a real header the same repair would have to run without overwriting server JSON overrides. Not built.
B. Physics crash, server and a client, both in Physics simulation with no script stack. The server log had nine Attempting to send an RPC through unregistred item errors from the (removed) RequestUserLock. Next A/B: disable the RigidBody on EG_IntelligenceFolder_E_01 (the script places the folders anyway), or put the document site back on the old paper prop.
C. A FOB that will not fall (documents never appear): read garrison_left in the match log; consider "most of the garrison dead" or a radius rule.
D. Late join key and hint need a test with a second client; if Shift+O does nothing on the spectator screen, find the input context COALITION's spectator menu activates and add the action to it.
- Document site (EG folder prefab). Check on the next run: no
cannot be combinederror, the folder sits on its table, "Copy documents" appears, no pickup prompt, inactive sites are hidden. If the action does not appear, check the Copy action's context in the inherited actions manager. Also the site at 5507,10551 only has a drill bench in reach. 0b. Cipher visual: giveGRAD_Endgame_CipherItema real inventory item with a model (briefcase, folder, codebook) as parent; no beam (it would reveal the position). Navmeshfixed by the mapper; garrisons and patrols confirmed moving (2026-11-14).- Map exception in the spectator menu in phase 3 (not seen in the last run, only two
COA_SpectatorMenu.OnMenuCloseNULL pointers at exit, in COALITION's own code) (earlier:SCR_MapEntity.UpdateViewPort, NULL pointer every frame). Unknown whether ourConfigs/Map/MapFullscreen.confcauses it. A/B test: remove that file, reload, die in phase 3. Arsenal ammo greyed outdone: ammunition supply works (confirmed 2026-11-14, with theArsenalFreeoverride).- Layout: OPFOR start spawn is 54 m from a document site (garrison next to spawn); document sites are skewed towards the BLUFOR FOB; the first radio site is 444 m from a FOB; cipher site 2 is 3.3 km from the OPFOR FOB. A minimum distance from start spawns for site selection (and a validator warning) is proposed, not built.
- Replay end to end: check recording starts, playback, the after-action hand-off, and that the
normal map still works. The trackers for shots, grenades, smoke and rockets are now ported (2026-11-14:
GRAD_Endgame_WeaponFireTracker,GrenadeTracker,RocketTracker,DetonationWatcher,ExplosionTracker,ExplosiveCataloginScripts/.../Replay/; hooked in by minimal overrides ofCharacter_Base,Ammo_Rocket_Base,FragGrenade_Base,SmokeGrenade_Base, and the tracker on the lobby entity). Not run yet. - Task visibility may be a client-side filter only. If the task system replicates every task to every client, exact positions (cipher) leak to a modified client. Check the wiki; fall back to owner RPCs for the cipher if needed.
- Re-pick the FIA group prefabs in the config UI to remove the
Wrong GUID {0000...}log spam (the config holds plain paths). - HUD finish: register
GRAD_Endgame_MapStatusLinein the in-game map config; typewriter font / paper texture polish; confirm the key bindings (Shift+J/K/T/U) are free. - Mission thumbnails: the mission uses vanilla
GM_Edenimages; the publisher logsFailed to load metafile of image. Use own images. - Gear check errors (6): radios per role are not configured for COALITION's own radio system. Harmless for now (shared default radios).
- Admin UI: the admin calls have no button except the threshold box (needs a layout override).
COALITION runs fixed-timer respawn (lobby m_iTimeToRespawn 60, waves off); the client counts
down and asks the server for the respawn, the server does not check the time. Our override
supplies the countdown (GetWaveSecondsRemaining) and gates RespawnPlayer. The "30 s" wait was
ours: 27.4 s (270 s / debug scale 10), not COALITION's. Open: the pre-timestamp seed is 60 s
(set m_iTimeToRespawn to 3-5 in the layer, or return a positive value instead of -1), and the
permadeath wave fix was not running in the last test (the script was saved after Workbench had
started). Use SetRespawnEnabled(false) for permadeath (already done).
The live config is a test config. Set in Missions/Endgame89.conf (or in the server config's missionHeader; server_config.sample.json already has release values):
m_fDebugTimeScale 1 (it is 10: waves 27 s, transmission 72 s), m_bDebugLog 0,
m_bRunSelfTests 0. Local Workbench play runs transmissions ten times shorter (#ifdef WORKBENCH in GetTransmissionSeconds); a published server is not affected. Mind that the nested .conf values are currently ignored (open problem A). Check the document site prefab Duration (copy time). Remove or re-place
test objects (GRAD_Endgame_Garrison on the first document site).
- Never override a prefab by hand-writing a file at its path. An override without the parent
and root
IDreplaces the prefab (it dropped COALITION's controller and left an ocean camera). Create overrides in Workbench ("override/inherit"). - Replicated state needs an
RplComponenton the entity. Prop prefabs inherited from vanilla tables have one; our bareGenericEntityprefabs (FOB, spots, cipher site) do not. State that clients need goes on the game-mode component. - Do not overload methods of vanilla base classes (
Showon anSCR_InfoDisplayExtendedbroke vanilla callbacks with 4 errors inSCR_VoiceoverSystem). GetCopySeconds()and other timers are divided bym_fDebugTimeScale; a value compared against an engine-side time (prefabDuration) will disagree under a test scale.- Layer files are rewritten by Workbench. Close the world without saving before editing it on disk.
- Workbench keeps script statics between play sessions. The client info (order, notices)
survived a restart and showed an old "Decoded order" at the start;
Clear()now resets it and runs at every match start. SetActive(true)on a site that is already active changes nothing: put logic that must run at selection time before that early return.- Vanilla prop prefabs may lack an
RplComponentand the editable component; the replication guard logs it at startup. - The replay recorder had parked spectators at (40, 100000, 0) in its frames.
- The replay assets share GUIDs with BreakingContact. Do not load both addons on one server.
- COALITION shows no lobby and no slotting prompt to a player who joins after safestart: the "open slotting" prompt of its spectator menu exists only while safestart is on.
m_bLockUnusedSlots(hidden attribute) locks empty slots at go-live and is a different thing. - The HUD manager creates a new display every time the controlled entity changes (spectator, slot, character, respawn). Old
SCR_InfoDisplayExtendedinstances keep updating unless retired: several typewriters, doubled sounds, stacked key listeners. - A layout that ships with all cards visible (sample text) needs them hidden by script; moving the script to a second copy of the layout leaves the first copy's sample cards on screen unless it is hidden too.
- Do not call
InventoryItemComponent.RequestUserLockinOnPostInit(RPC through an unregistered item). - Inheriting a vanilla prefab and adding
ActionsManagerComponentorRplComponentwith new IDs givescannot be combined. Use Workbench's inherit and edit the inherited component. - The Workbench MCP tools see nothing useful while Workbench is in game mode; terrain height queries return 0. The vanilla packed prefabs cannot be read from disk.
- Server logs:
GRAD_Endgame/match_*.login the server profile plusconsole.logof the run;garrison_left,doc_placed("one of N free tables"),cipher_last,late_join_refused,radio_start_deadare the new lines.
docs/test-routine.md has the numbered checks (1 to 51). Next run should also cover: self-test PASS lines (is the .conf applied?), doc_placed randomness over several matches, hidden inactive sites, the HUD overlay over the spectator menu and the replay (no doubled sound, no cards at start), Shift+O for a late joiner, cipher_last with two sides, a smoke and two HE thrown late in the replay, and the physics crash A/B. The older list: doc_placed lines and the document action, the replay map (pan/zoom, FIA and your marker visible), the order widget not showing at start, the arsenal ammo, freeze-time phase
start (freeze_over before phase;;;;WAITING -> FOB), permadeath deaths (no wave lines after
permadeath), copy bar vs engine bar, any-role transmit, Shift key bindings, replay and
after-action, the has waypoint log lines once the navmesh is fixed.