Context
The in-game HUD (ConsoleUI) is currently server-authored in g_ui_stubs.c — 1405 lines of hardcoded pixel coordinates generating UIFRAME structs sent via svc_layout. This duplicates layout data that Blizzard already ships in FDF files inside the MPQ archives.
Meanwhile, every menu screen in ui/screens/ follows a clean pattern: FDF for layout + generated binding header + screen controller for dynamic data.
Goal
Replace the server-authored svc_layout HUD with client-side FDF-driven screen controllers, matching the established ui/ pattern. Delete g_ui_stubs.c and the UIFRAME render path.
Blizzard's FDF files
All of these already exist in War3.mpq at UI/FrameDef/UI/:
ConsoleUI.fdf — Top/bottom decorative art bars
ResourceBar.fdf — Gold/lumber/supply/upkeep with named icons and text frames
UpperButtonBar.fdf — Quests/Menu/Allies/Chat buttons with full template inheritance
InfoPanelUnitDetail.fdf — Unit selection: name, armor, damage, speed, range, hero attributes
InfoPanelBuildingDetail.fdf — Building selection: name, armor, supply, build queue
InfoPanelItemDetail.fdf — Item selection: name, description
SimpleInfoPanel.fdf — Simplified variants (non-hero, cargo, ally resources)
CinematicPanel.fdf — Cinematic dialogue UI
InfoPanelTemplates.fdf — Shared text/label/value templates
Frozen Throne ConsoleUI.fdf extends the base with wider layout (ConsoleTexture05/ConsoleTexture06).
Architecture
stb_fdf.h — shared FDF library
Extract the FDF parser + frame API from ui_fdf.c into a single-header stb_fdf.h:
FRAMEDEF struct and types (frame point, frame type enum)
- FDF parser (
UI_ParseFDF, UI_EnsureFDF, template inheritance)
- Programmatic frame API (
UI_InitFrame, UI_SetPoint, UI_SetText, UI_Spawn, UI_FindFrame, etc.)
BZ_FDF_BIND_* macros and convenience macros
Both ui/ and game/ include this header. Write functions (UI_WriteFrame, UI_WriteLayout) are declared as extern stubs — each module provides its own implementation:
ui/ gets no-op stubs (client doesn't write svc_layout)
game/ keeps real implementations for any remaining server-authored layouts
ConsoleUI screen controller — client-side
One .c file per panel in ui/screens/:
| Screen Controller |
Binding Header |
FDF |
console_ui.c |
generated/console_ui.h |
ConsoleUI.fdf |
resource_bar.c |
generated/resource_bar.h (exists) |
ResourceBar.fdf |
upper_button_bar.c |
generated/upper_button_bar.h |
UpperButtonBar.fdf |
info_panel.c |
generated/info_panel_unit_detail.h |
InfoPanelUnitDetail.fdf |
info_panel_building.c |
generated/info_panel_building_detail.h |
InfoPanelBuildingDetail.fdf |
info_panel_item.c |
generated/info_panel_item_detail.h |
InfoPanelItemDetail.fdf |
cinematic_panel.c |
generated/cinematic_panel.h (exists) |
CinematicPanel.fdf |
Data flow
- Server sends raw game data via existing
svc_unit_ui messages (uiCommandButton_t[], uiInventoryItem_t[], uiQueueItem_t[])
- Server sends player resources in
playerState_t stats fields (PLAYERSTATE_RESOURCE_GOLD, etc.)
- Client
console_ui.c loads FDF, binds frames, populates dynamic content (gold text, unit name, command buttons, inventory slots)
- Client renders through
ui_render.c — no separate UIFRAME render path
Procedural panels
Command card, inventory, portrait, minimap, build queue, tooltips — spawned programmatically but anchored to FDF-defined container parents (same pattern as ui_dialog.c).
What gets deleted
g_ui_stubs.c — entire file
UIFRAME struct and related types
cl_layout.c / cl_unit_layout.c — UIFRAME render path (keep for transient messages only)
- The hardcoded pixel-coordinate macros (
INFO_PANEL_X, COMMAND_BUTTON_CENTER_X, etc.)
Implementation steps
- Create
stb_fdf.h — extract from ui_fdf.c, keeping the parser + frame API. Update ui_local.h to include it.
- Generate binding headers — run
fdfbindgen on ConsoleUI FDF files.
- Write screen controllers —
console_ui.c and per-panel controllers following the ui/screens/ pattern.
- Wire data flow — connect
ui.UpdateUnitUI() and playerState_t stats to the screen controllers.
- Delete
g_ui_stubs.c and remove UIFRAME render path from cl_layout.c / cl_unit_layout.c.
- Update AGENTS.md — document
stb_fdf.h, the per-panel pattern, and the ConsoleUI workflow.
Related
- See
doc/games/warcraft-3/docs/ui.md for the Phase 8 migration plan
console_ui.c is listed as a recognized gap in the UI migration docs
generated/resource_bar.h and generated/cinematic_panel.h already exist as stubs for this exact architecture
Context
The in-game HUD (ConsoleUI) is currently server-authored in
g_ui_stubs.c— 1405 lines of hardcoded pixel coordinates generatingUIFRAMEstructs sent viasvc_layout. This duplicates layout data that Blizzard already ships in FDF files inside the MPQ archives.Meanwhile, every menu screen in
ui/screens/follows a clean pattern: FDF for layout + generated binding header + screen controller for dynamic data.Goal
Replace the server-authored
svc_layoutHUD with client-side FDF-driven screen controllers, matching the establishedui/pattern. Deleteg_ui_stubs.cand theUIFRAMErender path.Blizzard's FDF files
All of these already exist in
War3.mpqatUI/FrameDef/UI/:ConsoleUI.fdf— Top/bottom decorative art barsResourceBar.fdf— Gold/lumber/supply/upkeep with named icons and text framesUpperButtonBar.fdf— Quests/Menu/Allies/Chat buttons with full template inheritanceInfoPanelUnitDetail.fdf— Unit selection: name, armor, damage, speed, range, hero attributesInfoPanelBuildingDetail.fdf— Building selection: name, armor, supply, build queueInfoPanelItemDetail.fdf— Item selection: name, descriptionSimpleInfoPanel.fdf— Simplified variants (non-hero, cargo, ally resources)CinematicPanel.fdf— Cinematic dialogue UIInfoPanelTemplates.fdf— Shared text/label/value templatesFrozen Throne
ConsoleUI.fdfextends the base with wider layout (ConsoleTexture05/ConsoleTexture06).Architecture
stb_fdf.h — shared FDF library
Extract the FDF parser + frame API from
ui_fdf.cinto a single-headerstb_fdf.h:FRAMEDEFstruct and types (frame point, frame type enum)UI_ParseFDF,UI_EnsureFDF, template inheritance)UI_InitFrame,UI_SetPoint,UI_SetText,UI_Spawn,UI_FindFrame, etc.)BZ_FDF_BIND_*macros and convenience macrosBoth
ui/andgame/include this header. Write functions (UI_WriteFrame,UI_WriteLayout) are declared as extern stubs — each module provides its own implementation:ui/gets no-op stubs (client doesn't writesvc_layout)game/keeps real implementations for any remaining server-authored layoutsConsoleUI screen controller — client-side
One
.cfile per panel inui/screens/:console_ui.cgenerated/console_ui.hConsoleUI.fdfresource_bar.cgenerated/resource_bar.h(exists)ResourceBar.fdfupper_button_bar.cgenerated/upper_button_bar.hUpperButtonBar.fdfinfo_panel.cgenerated/info_panel_unit_detail.hInfoPanelUnitDetail.fdfinfo_panel_building.cgenerated/info_panel_building_detail.hInfoPanelBuildingDetail.fdfinfo_panel_item.cgenerated/info_panel_item_detail.hInfoPanelItemDetail.fdfcinematic_panel.cgenerated/cinematic_panel.h(exists)CinematicPanel.fdfData flow
svc_unit_uimessages (uiCommandButton_t[],uiInventoryItem_t[],uiQueueItem_t[])playerState_tstats fields (PLAYERSTATE_RESOURCE_GOLD, etc.)console_ui.cloads FDF, binds frames, populates dynamic content (gold text, unit name, command buttons, inventory slots)ui_render.c— no separateUIFRAMErender pathProcedural panels
Command card, inventory, portrait, minimap, build queue, tooltips — spawned programmatically but anchored to FDF-defined container parents (same pattern as
ui_dialog.c).What gets deleted
g_ui_stubs.c— entire fileUIFRAMEstruct and related typescl_layout.c/cl_unit_layout.c—UIFRAMErender path (keep for transient messages only)INFO_PANEL_X,COMMAND_BUTTON_CENTER_X, etc.)Implementation steps
stb_fdf.h— extract fromui_fdf.c, keeping the parser + frame API. Updateui_local.hto include it.fdfbindgenon ConsoleUI FDF files.console_ui.cand per-panel controllers following theui/screens/pattern.ui.UpdateUnitUI()andplayerState_tstats to the screen controllers.g_ui_stubs.cand removeUIFRAMErender path fromcl_layout.c/cl_unit_layout.c.stb_fdf.h, the per-panel pattern, and the ConsoleUI workflow.Related
doc/games/warcraft-3/docs/ui.mdfor the Phase 8 migration planconsole_ui.cis listed as a recognized gap in the UI migration docsgenerated/resource_bar.handgenerated/cinematic_panel.halready exist as stubs for this exact architecture