Campaign loading and asset resolution
For measured menu/loading resource residency and reclamation priorities, see WC3 memory.
Loading-screen ownership
CL_BeginLoadingMap publishes the resolved destination in the session-only map cvar before
SCR_BeginLoadingPlaque freezes a frame. This covers console launches, menu selections, game menu actions,
and incoming CS_WORLD. The client owns loading state; only CL_PrepRefresh promotes it to ca_active.
The WC3 UI reads the current destination and caches metadata per path, not per UI lifetime.
UI_UpdateLoadingMapInfo reads the nested map MPQ's war3map.w3i and war3map.wts through
UI_ReadMapInfo. Custom loading models take precedence; otherwise the campaign background number indexes
UI/WorldEditData.txt's LoadingScreens section (model plus sequence). Maps without an authored background
use the existing LoadingMeleeBackground skin entry. Geometry and text fields come from native
UI/FrameDef/Glue/Loading.fdf and its generated binding.
June 28 regression
Commit b6349c392 removed cl.loading_map/GetLoadingMap but left CL_BeginLoadingMap ignoring its
mapName argument. UI lookup could only see a startup +map cvar, explaining why direct map launches
worked while campaign buttons produced a black background plus LOADING. Runtime diagnostics for Human01
showed a valid requested destination and an empty UI map cvar. In addition, the UI looked up its own
cached path, preventing invalidation on subsequent maps. Both paths now use the published destination.
TFT has an additional independent schema difference: ROC LoadingScreens rows are
label,sequence,model, while TFT rows are expansion-category,label,sequence,model, including ROC campaigns
under TFT archives. Fixed ROC indices interpreted HumanX01's sequence 6 as a filename. UI_ParseLoadingRow
consumes the optional numeric category and validates the sequence/model fields; malformed rows log their key.
Preserve the loading-state draw check before game_mode dispatch: menu commands are queued asynchronously.
Asset names are data
| Source | Meaning / resolution |
|---|---|
Units/DestructableData.slk, texFile |
_ (or empty/absent) means no replacement image. Preserve an authored extension; do not append .blp in the spawn code. Human01 LT05 uses ReplaceableTextures\Cliff\Cliff0.tga; crates/gates use _. |
Texture references ending in .tga |
The exact file wins. If absent, R_ReadTextureFile tries the same stem with .blp, then normal renderer diagnostics/placeholders apply. This handles converted source names without overriding real custom TGA files. |
ReplaceableTextures\CameraMasks\White_mask.tga |
Human01's cinematic script requests this; the local ROC archive contains White_mask.blp (1422 bytes), not TGA. The cliff BLP is 90592 bytes. |
Native StandardTemplates.fdf |
Some unused templates reference art absent from ROC archives (HeavyBorder*, LightBorder*, ButtonBackGround, ButtonCorners, GlueScreen-PlayerButton-BorderRight, GlueScreen-ROC-EditionButton-*). Parsing records texture keys/indices; UI_GetTexture loads only on consumption. Do not replace missing art with invented paths or suppress renderer warnings for consumed resources. |
UI_GetTexture caches both real and placeholder renderer handles. Decorated names are re-evaluated on theme
changes; an unchanged theme does not reload. Parsing or inheriting a template alone must not fetch its art.
Cliff-transition classification
Terrain vertices are ordered NE, NW, SE, SW by GetTileVertices; model configuration letters use
SW, NW, NE, SE. A transition requires exactly two adjacent ramp corners one cliff level apart.
Two same-height flagged corners belong to an adjoining ordinary cliff, not a sloped transition.
Human01 cell (64,31) yielded model-order levels [1,0,1,1] and ramp flags [1,0,0,1].
The former GetTileRamps(tile) > 1 test built nonexistent CliffTransHABH0.mdx and omitted its geometry.
Correct classification selects the ordinary CliffsBABB0.mdx. The native transition directory contains
L/H and H/X edge pairs, not an HH or LX edge. Do not turn file-not-found into a guessed terrain fallback.
The Warsmash terrain loader
is a useful secondary reference for separating transition edges from regular cliff cells; local archive
contents and logged vertex metadata establish this case.
Diagnostics and verification
build/bin/mpqtool -mpq 'data/Warcraft III/War3.mpq' cat Units/DestructableData.slk
build/bin/mpqtool -mpq 'data/Warcraft III/War3.mpq' ls ReplaceableTextures/CameraMasks
build/bin/mpqtool -mpq 'data/Warcraft III/War3.mpq' ls Doodads/Terrain/CliffTrans
build/bin/mpqtool -mpq 'data/Warcraft III/War3.mpq' cat UI/FrameDef/Glue/StandardTemplates.fdf
build/bin/openwarcraft3 -data 'data/Warcraft III' +map 'Maps/Campaign/Human01.w3m' +com_frame_limit 100
build/bin/openwarcraft3 -data 'data/Warcraft III' -tft +map 'Maps/FrozenThrone/Campaign/HumanX01.w3x' +com_frame_limit 100
make test-renderer-model test-ui
make test
For the menu regression, launch without +map, then select Single Player → Campaign → Human. The console
registers menu_single_player_campaign, but menu_single_player_campaign_human is a UI-handler command,
not a console command. A diagnostic replay can temporarily invoke that handler after showing the campaign
screen; remove the hook afterward. Queue screenshot 1 before the handler to capture the frozen loading plaque.
Use +com_frame_limit 100 for bounded runs; engine screenshots appear under screenshots/.
Regression tests cover texture extension lookup and exact-file precedence, SLK replacement sentinels, ROC/TFT loading-row schemas, rotated/equal-height/diagonal cliff edges, unused FDF art, lazy texture cache hits/misses and theme changes, and loading destination/cache invalidation including UI reinitialization. The loading-cache unit test uses existing metadata-less map fixtures to exercise the melee/default path; campaign artwork needs ROC/TFT runtime verification against real archives.
See also UI authoring, scene workflow, and filesystem loading.