Move the synergy catalog from the run HUD to the pause menu

The purple Combos button lived in the run HUD button_area; move it to a
"Combos" row in the pause menu (Escape > under Settings, before
restart_button) so the play screen stays clear. Same overlay, same tabs;
Mods > Combo Advisor is unchanged.

restart_button is an id vanilla only builds during a run, so the row never
reaches the main menu. Because the pause menu builds its node list as a table
constructor with conditional entries (an unseeded run leaves a hole at the
seed row's index), find_trail/insert_node walk and shift by explicit numeric
key rather than ipairs/table.insert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
funman300
2026-07-27 12:44:37 -07:00
parent 124e8da8ed
commit a66faadc21
5 changed files with 356 additions and 240 deletions
+14 -3
View File
@@ -169,9 +169,10 @@ Three-layer split; `JCA` is the single global namespace:
in with no animation on tab open and page switch. Only the first card of a
page build plays the sound (vanilla's `i>1 or j>1` silence flag); tab defs
call `begin_page()` so the counter spans the page, not one row. The same
tabs open in-run via a "Combos" HUD button (wrapped `create_UIBox_HUD`,
injected into the `button_area` node under Run Info/Options); the pagers
work there because vanilla `create_tabs` also names its body
tabs open in-run via a "Combos" row in the pause menu (wrapped
`create_UIBox_options`, inserted before `restart_button` — an id vanilla
only builds during a run, so the row never reaches the main menu); the
pagers work there because vanilla `create_tabs` also names its body
`tab_contents`.
- Discovery: `CardArea:emplace` hook calls `JCA.check_discoveries` when a
joker lands in `G.jokers`; famous pairs fielded together persist in
@@ -262,6 +263,16 @@ Three-layer split; `JCA` is the single global namespace:
"fix" them: `j_gluttenous_joker`, `j_selzer`, `j_ticket` (Golden Ticket),
`j_trousers` (Spare Trousers), `j_ring_master` (Showman), `j_caino` (Canio),
`j_delayed_grat`, `j_todo_list`.
- **Never walk a vanilla node tree with `ipairs`** (or resize one with
`table.insert`/`#`). Vanilla builds node lists as table constructors with
conditional entries — the pause menu's seed row is
`G.GAME.seeded and current_seed or nil` (`UI_definitions.lua:2469`) — so an
unseeded run leaves a **hole** at index 2 with real nodes above it. The game
never notices because it iterates with `pairs` (`engine/ui.lua:273`); `ipairs`
stops dead at the hole. `find_trail`/`insert_node` in `main.lua` walk and
shift by explicit index, bounded by the highest numeric key, and any test or
smoke assertion that reads a menu back must do the same or it will report a
menu no player ever sees.
- Unknown joker keys (from other mods) must keep scoring 0 — never index
`JCA.db[key]` without a nil guard.
- Display names go through `localize{type='name_text', set='Joker', ...}` with a