Read the perishable timer instead of assuming it, and fix a pcall idiom
test / test (push) Successful in 14s

Two fixes from a review pass, plus the first tests to reach the post-run
recap at all.

The perishable caution said "gains die in 5 rounds" as a literal, but the
count is a game variable (G.GAME.perishable_rounds, game.lua:1961) and
vanilla's own sticker tooltip reads it (common_events.lua:3339). A challenge
or another mod moving it made the advisor state a wrong number, in the one
place this mod promises mechanical facts. It now reads perish_tally when the
sticker is already ticking, falls back to the game value, then to 5, and
says "1 round" rather than "1 rounds". The new tests fail against the old
literal, so this one was real.

The win screen's recap fallback tested only the second pcall return:

    local _, inserted = pcall(insert_recap, ui, 'from_game_won', 2, 1)
    if not inserted then ... win_cta ... end

The first return is the ok flag, so on a throw `inserted` holds the error
MESSAGE -- a truthy string -- and a failure reads as a success. That is a
trap worth removing, but being honest about its blast radius: it is NOT
currently reachable. Every way the first call can throw (recap_row, or
find_trail on a malformed tree) throws identically for win_cta, and the
table.insert cannot go out of bounds because spot.index indexes the very
list being inserted into. The whole suite passes with the old idiom. This
is a latent correctness fix, not a live bug -- it stops the trap biting if
insert_recap ever grows an anchor-specific failure.

The recap machinery (recap_row, find_trail, insert_recap) had no coverage.
It does now, including the win_cta fallback and the empty-run case.

925 tests pass on 5.4 and LuaJIT, 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:22:47 -07:00
parent 319f79bc5d
commit b4e4f8e23e
2 changed files with 83 additions and 3 deletions
+15 -3
View File
@@ -342,7 +342,14 @@ function JCA.sticker_cautions(card)
local key = card.config and card.config.center and card.config.center.key
local a = card.ability or {}
if a.perishable and key and JCA.scalers[key] then
out[#out + 1] = 'perishable: gains die in 5 rounds'
-- Read the round count, never hardcode it: perishable_rounds is a game
-- variable (game.lua:1961 defaults it to 5, and vanilla's own sticker
-- tooltip reads it at common_events.lua:3339), so a challenge or
-- another mod can move it. perish_tally is what this card has left
-- (card.lua:680) and is the honest number when it is already ticking.
local n = a.perish_tally or (G.GAME and G.GAME.perishable_rounds) or 5
out[#out + 1] = ('perishable: gains die in %d round%s')
:format(n, n == 1 and '' or 's')
end
if a.rental and key and JCA.db[key] and JCA.db[key].gives.money then
out[#out + 1] = 'rental: rent may eat its payout'
@@ -1282,12 +1289,17 @@ end
-- Win: the buttons live inside the right-hand stats column; two levels up
-- places the recap below the whole two-column stats row. 'win_cta' replaces
-- 'from_game_won' when the CTA variant of the screen is shown.
--
-- Keep BOTH pcall returns. The first is the ok flag; on a throw the second is
-- the error MESSAGE, which is a truthy string -- so testing it alone reads a
-- failure as a success and skips the win_cta fallback, which exists precisely
-- because the two win screens anchor at different ids.
if create_UIBox_win then
local orig_win = create_UIBox_win
function create_UIBox_win(...)
local ui = orig_win(...)
local _, inserted = pcall(insert_recap, ui, 'from_game_won', 2, 1)
if not inserted then pcall(insert_recap, ui, 'win_cta', 2, 1) end
local ok, inserted = pcall(insert_recap, ui, 'from_game_won', 2, 1)
if not (ok and inserted) then pcall(insert_recap, ui, 'win_cta', 2, 1) end
return ui
end
end