Answer the fuse button: advise on fusions when Fusion Jokers is installed

Hovering a joker that is a fusion component now names the fusion it feeds,
its cost with discounts applied, and what is still missing. In the shop the
card is counted as if already bought, so it answers the buy-side question
("Buy to fuse into Diamond Bard ($12 to fuse)") instead of restating what
you already own.

The line worth having is the last one. Fusing CONSUMES its components --
fuse_card calls ingredient:remove() -- so every combo those jokers held with
the rest of the board dies with them, and the FUSE button cannot tell you
that. "Fusing drops combos with: Smeared" is computed from the surviving
board, and a component being spent is not counted as a loss.

Three things about their code shaped this:

  * Card:get_card_fusion() would have answered most of it, but it drives its
    price flicker with math.randomseed(love.timer.getTime() * 8). An advisor
    reseeding Lua's RNG on every hover has no business doing that, so this
    reads FusionJokers.fusions directly and mirrors their discount arithmetic
    (flat then percentage, per-result and universal, floored, min $1).
  * Recipes take repeated components -- their own debug fusion needs 3x Joker
    -- so components are counted by quantity, not presence.
  * Affordability is judged only on plain numbers: Fusion Jokers uses to_big,
    and Talisman turns G.GAME.dollars into an object. Guessing wrong about
    someone's money is worse than staying quiet, so the money line just
    does not appear.

Ownership is board membership, not card.area, matching copy_source and
dagger_victim -- the area pointer answers differently for the same card
depending on who built it.

Verified against the shipped recipe table: all 15 resolve at the right cost,
and all 30 components are jokers the database already knows. Not installed
means silence, like every other integration.

918 tests pass on 5.4 and LuaJIT (31 new), and 18/18 in the real game.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
funman300
2026-07-22 15:16:14 -07:00
parent c479f7854d
commit 319f79bc5d
6 changed files with 426 additions and 1 deletions
+41
View File
@@ -793,6 +793,47 @@ local function tooltip_rows(card)
end
end
-- Fusion Jokers (see integrations.lua). The FUSE button consumes the
-- components, so the advice is the recipe, the price, and -- the part only
-- this advisor can answer -- which of your current combos die with them.
-- Two plans max: a joker can be a component of several recipes. These are
-- mechanical facts, not verdicts, so learning mode keeps them.
if JCA.fusion_plans then
local ok, plans = pcall(JCA.fusion_plans, card)
for i = 1, (ok and math.min(2, #plans) or 0) do
local p = plans[i]
local rname = name_of(p.result)
local price = p.cost and (' ($' .. p.cost .. ')') or ''
if not p.ready then
local want = {}
for _, m in ipairs(p.missing) do
want[#want + 1] = (m.n > 1 and (m.n .. 'x ') or '') .. name_of(m.key)
end
text_row(('Fuses into %s%s - still needs %s')
:format(rname, price, table.concat(want, ', ')))
elseif in_buy_area(card) then
-- Deliberately no affordability check here: the player would be
-- paying for the card AND the fusion, and guessing at that sum
-- would be advice about money we have not actually done.
text_row(('Buy to fuse into %s%s'):format(rname,
p.cost and (' ($' .. p.cost .. ' to fuse)') or ''), G.C.GREEN)
elseif p.affordable == false then
text_row(('Fuses into %s - $%d, you have $%d')
:format(rname, p.cost, p.dollars or 0), G.C.RED)
else
text_row(('Fusion ready: %s%s'):format(rname, price), G.C.GREEN)
end
if #p.loses > 0 then
local names = {}
for _, k in ipairs(p.loses) do names[#names + 1] = {name = name_of(k)} end
for li, l in ipairs(wrap_names(names, 30, 2)) do
text_row((li == 1 and 'Fusing drops combos with: ' or ' ') .. l,
G.C.RED)
end
end
end
end
-- Run context: this deck, these hand levels. Facts that frame the tags,
-- never part of the score; capped at two lines so multi-suit jokers do
-- not flood the tooltip. Fixed iteration order keeps hovers stable.