Mission Debug Panel Moves to JavaScript
One more piece of hardcoded C++ found its way into script territory. The "Mission Info" panel in the
developer debug overlay — which shows live mission state during playtesting — is now rendered entirely
from mission_debug.js rather than C++. It's a small change in terms of lines, but part of
a broader effort to make the engine's internals more accessible without recompiling.
What the Panel Shows
When you open the debug overlay during a mission, the Mission Info section displays a handful of fields that are useful during development:
- scenario_id — which scenario file is currently loaded
- campaign_id — the campaign this scenario belongs to
- mission_rank — position in the campaign sequence
- starting_kingdom — kingdom rating the player starts with
- personal_savings — deben carried over from previous missions
- scenario_mode — campaign vs. custom mission
- is_custom — whether it's a user-made map
Previously all of this was drawn directly in C++. Now the script does it, calling into ImGui through a thin binding layer.
How the Event Bridge Works
The tricky part was getting C++ and JavaScript to talk to each other at the right moment. The solution follows the same pattern used elsewhere in the engine: C++ fires an event, JavaScript catches it.
On the C++ side, a new ANK_REGISTER_PROPS_ITERATOR registers
draw_debug_properties_handler as one of the functions that runs each frame when the debug
overlay is open. When it's time to draw, it emits event_draw_debug_properties into the
MuJS VM. On the JavaScript side, mission_debug.js listens for exactly that event:
[es=event_draw_debug_properties]
function mission_debug_draw_properties_mission_info(ev) {
if (!imgui.tree_node_ex("Mission Info")) { return }
imgui.begin_table("MissionInfo", 2, imgui.table_flags_debug_props())
imgui.property_input("scenario_id", scenario.campaign_scenario_id)
imgui.property_input("campaign_id", __game_campaign_id_for_scenario(...))
imgui.property_input("mission_rank", scenario.campaign_mission_rank)
imgui.property_input("personal_savings", city.kingdome.personal_savings)
// ...
imgui.end_table()
imgui.tree_pop()
}
The ImGui calls themselves — tree_node_ex, begin_table,
property_input, etc. — are now part of the imgui object defined in
ui_common.js, each one backed by a C++ function registered in imgui_js.cpp.
What Stayed in C++
Not everything migrated. The Victory conditions panel and the Migration panel in the same overlay are still drawn in C++. They involve more complex state that would need additional bindings to expose safely, so they're staying put for now.
Why Bother?
Moving debug tooling to script might seem like a low priority, but it has a practical benefit: you can
edit mission_debug.js and reload it with --mixed without restarting the game.
If you want to add a new field to the debug panel — say, the current prosperity tick or a walker count —
it's a one-line addition in a text file, not a recompile. For anyone actively developing or modding
missions, that feedback loop matters.