Add theme-level discovery

A synergy theme counts as explored the first time two different
fielded jokers connect it (one gives the tag, one wants it; cluster
members carry both sides, so any two qualify). Explored themes
persist in config.themes_found, badge their catalog page with
"explored!", and feed a per-tab progress line. One toast per
emplacement, with famous pairs outranking themes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-07-09 21:58:47 -07:00
parent 608e23ed14
commit 35e54e6976
4 changed files with 89 additions and 4 deletions
+6
View File
@@ -86,6 +86,12 @@ Three-layer split; `JCA` is the single global namespace:
`config.discovered` (saved immediately via `SMODS.save_mod_config`) and
per-run in `G.GAME.jca_run_combos`. Undiscovered pairs render face-down
with a `???` caption in the Combos tab; blurb replaces it once fielded.
Themes (every `theme_info` tag) persist in `config.themes_found` once
two DIFFERENT jokers connect the tag (giver + wanter; a joker carrying
both sides needs a second joker). One toast per emplacement, famous
pair outranking theme. Badge/progress render in `theme_tab_def`; toast
names come from `JCA.theme_names` (filled after THEME_TABS, used only
at gameplay time).
- Post-run recap: wraps `create_UIBox_game_over`/`create_UIBox_win` and
inserts a "Combos fielded this run" row (from `G.GAME.jca_run_combos`)
relative to vanilla button ids (`from_game_over`; `from_game_won` or
+4
View File
@@ -16,6 +16,10 @@ recommends joker combos while you play:
"New combo!" toast fires and the pair is permanently inked into the
catalog — until then its cards sit face-down with a "???" caption, so
filling in the Combos tab becomes its own collection hunt.
- **Theme discovery**: assembling any synergy theme for the first time —
one joker that provides it plus another that wants it — fires a
"Theme explored!" toast, badges that theme's catalog page, and counts
toward a per-tab progress line ("3 of 10 themes explored").
- **Hover a joker you own** to see its active combos with the rest of your
lineup.
- **Browse the synergy catalog** any time: a purple **Combos** button in the
+1
View File
@@ -6,4 +6,5 @@ return {
threshold = 4, -- total synergy score needed to recommend a card
learning_mode = false, -- hide verdicts (pulse, "Strong pick!"), keep reasons
discovered = {}, -- famous pairs the player has fielded (pair keys)
themes_found = {}, -- synergy themes the player has assembled (tags)
}
+77 -3
View File
@@ -18,8 +18,10 @@ JCA.db = data.jokers
-- Fallback defaults keep the engine usable outside the game (tests).
JCA.mod = SMODS.current_mod
JCA.config = SMODS.current_mod and SMODS.current_mod.config
or { pulse = true, owned_tooltip = true, threshold = 4, discovered = {} }
or { pulse = true, owned_tooltip = true, threshold = 4,
discovered = {}, themes_found = {} }
JCA.config.discovered = JCA.config.discovered or {}
JCA.config.themes_found = JCA.config.themes_found or {}
-- Explicit famous pairs, stored under a canonical "a|b" key (a < b).
JCA.pair_list = data.pairs
@@ -315,8 +317,43 @@ function JCA.check_discoveries()
end
end
end
-- Theme discovery: a theme is explored once two DIFFERENT fielded jokers
-- connect it — one gives the tag, another wants it (cluster members do
-- both, so any two of them qualify).
local new_theme
for tag in pairs(data.theme_info or {}) do
if not JCA.config.themes_found[tag] then
local giver, wanter
for idx, k in ipairs(keys) do
local e = JCA.db[k]
if e then
if e.gives[tag] and not giver then giver = idx end
if e.wants[tag] and not wanter then wanter = idx end
end
end
if giver and wanter and giver == wanter then
wanter = nil -- same joker on both sides: find a second one
for idx, k in ipairs(keys) do
local e = JCA.db[k]
if e and idx ~= giver and (e.gives[tag] or e.wants[tag]) then
wanter = idx
break
end
end
end
if giver and wanter then
JCA.config.themes_found[tag] = true
new_theme = new_theme or tag
end
end
end
if (new_pair or new_theme) and JCA.mod and SMODS.save_mod_config then
SMODS.save_mod_config(JCA.mod)
end
-- One toast per emplacement; a famous pair outranks a theme (both stay
-- recorded either way).
if new_pair then
if JCA.mod and SMODS.save_mod_config then SMODS.save_mod_config(JCA.mod) end
pcall(function()
attention_text({
text = 'New combo: ' .. new_pair .. '!',
@@ -326,6 +363,18 @@ function JCA.check_discoveries()
})
play_sound('card1', 1.1, 0.6)
end)
elseif new_theme then
pcall(function()
attention_text({
text = 'Theme explored: '
.. ((JCA.theme_names and JCA.theme_names[new_theme]) or new_theme)
.. '!',
scale = 0.7, hold = 4, major = G.play, align = 'cm',
offset = {x = 0, y = -3.5}, silent = true,
backdrop_colour = G.C.SECONDARY_SET.Planet,
})
play_sound('card1', 1.1, 0.6)
end)
end
end
@@ -463,6 +512,13 @@ local THEME_TABS = {
}},
}
-- Display names for theme tags (used by the discovery toast, which runs
-- before this point in the file but only ever fires during gameplay).
JCA.theme_names = {}
for _, group in ipairs(THEME_TABS) do
for _, t in ipairs(group.themes) do JCA.theme_names[t.tag] = t.name end
end
-- Joker keys for a tag, split into pure sources (give only), pure payoffs
-- (want only), and cluster members (both). Sorted by display name.
local function theme_members(tag)
@@ -625,10 +681,18 @@ local function theme_tab_def(group, page_no)
if #both > 0 then groups[#groups + 1] = both end
if #sources > 0 then groups[#groups + 1] = sources; captions = captions + 1 end
if #payoffs > 0 then groups[#groups + 1] = payoffs; captions = captions + 1 end
local layout = pick_layout(groups, 1 + #blurb_lines + captions)
-- +2 text rows: the title and the group progress line above the pager
local layout = pick_layout(groups, 2 + #blurb_lines + captions)
local nodes = {}
if JCA.config.themes_found[theme.tag] then
nodes[#nodes + 1] = {n = G.UIT.R, config = {align = 'cm', padding = 0.02}, nodes = {
{n = G.UIT.T, config = {text = theme.name, colour = G.C.GOLD, scale = 0.3}},
{n = G.UIT.T, config = {text = ' explored!', colour = G.C.GREEN, scale = 0.3}},
}}
else
add_caption(nodes, theme.name)
end
add_info_rows(nodes, data.theme_info[theme.tag], 70, 0.26)
if #both > 0 then
add_card_rows(nodes, both, layout.scale, layout.per_row)
@@ -641,6 +705,16 @@ local function theme_tab_def(group, page_no)
add_caption(nodes, 'Payoffs - these want it')
add_card_rows(nodes, payoffs, layout.scale, layout.per_row)
end
local explored = 0
for _, t in ipairs(group.themes) do
if JCA.config.themes_found[t.tag] then explored = explored + 1 end
end
nodes[#nodes + 1] = {n = G.UIT.R, config = {align = 'cm', padding = 0.02}, nodes = {
{n = G.UIT.T, config = {
text = ('%d of %d themes explored - field a source and a payoff together')
:format(explored, #group.themes),
colour = G.C.UI.TEXT_LIGHT, scale = 0.24}},
}}
local options = {}
for i, t in ipairs(group.themes) do options[i] = t.name end
nodes[#nodes + 1] = pager_row(options, page_no, 'jca_page_' .. group.label)