diff --git a/main.lua b/main.lua index c55bdea..083f2c0 100644 --- a/main.lua +++ b/main.lua @@ -488,6 +488,51 @@ local function is_joker(card) return card.config and card.config.center and card.config.center.set == 'Joker' end +-- Consumable advice ------------------------------------------------------------ + +-- A shop consumable or booster pack is fuel for the tag-driven jokers the +-- player already owns: a Planet card feeds Constellation, an Arcana Pack +-- feeds Fortune Teller, a Standard Pack permanently adds playing cards, +-- which is what card_gen wanters grow on. Booster centers carry their +-- family in `kind` (game.lua: p_celestial_* has kind = 'Celestial'). +local CONSUMABLE_TAG = { + Planet = 'planet', Tarot = 'tarot_gen', Spectral = 'spectral_gen', + Celestial = 'planet', Arcana = 'tarot_gen', Standard = 'card_gen', +} + +function JCA.consumable_tag(center) + if not center then return nil end + if center.set == 'Booster' then return CONSUMABLE_TAG[center.kind] end + return CONSUMABLE_TAG[center.set] +end + +-- Returns the owned jokers a consumable/pack feeds ({key, name} each, may be +-- empty) plus the tag that linked them, or nil when the card is not advice +-- material at all. Unknown (modded) jokers on the board are skipped, never +-- an error. +function JCA.consumable_partners(card) + local tag = JCA.consumable_tag(card.config and card.config.center) + if not tag then return nil end + local fed = {} + for _, j in ipairs((G.jokers and G.jokers.cards) or {}) do + local key = j.config and j.config.center and j.config.center.key + local entry = key and JCA.db[key] + if entry and entry.wants[tag] then + fed[#fed + 1] = {key = key, name = name_of(key)} + end + end + return fed, tag +end + +local function owns(key) + for _, j in ipairs((G.jokers and G.jokers.cards) or {}) do + if j.config and j.config.center and j.config.center.key == key then + return true + end + end + return false +end + -- Hover tooltip --------------------------------------------------------------- -- Wrap partner names into short tooltip lines. @@ -865,11 +910,45 @@ local function tooltip_rows(card) return rows end +-- The consumable counterpart of tooltip_rows: names the owned jokers a +-- Planet/Tarot/Spectral card or its pack feeds. Quiet unless an owned joker +-- actually cares, so the tooltip adds nothing for everyone else. +local function consumable_rows(card) + local S = JCA.config.touch_mode and 1.4 or 1 + local fed, tag = JCA.consumable_partners(card) + if not tag then return nil end + local rows = {} + local function text_row(str, colour) + rows[#rows + 1] = {{n = G.UIT.T, config = { + text = str, colour = colour or G.C.UI.TEXT_DARK, scale = 0.32 * S, + }}} + end + if #fed > 0 then + for i, l in ipairs(wrap_names(fed, 34, 2)) do + text_row((i == 1 and 'Feeds: ' or ' ') .. l) + end + end + -- A Standard Pack permanently adds playing cards, and Erosion is paid per + -- card MISSING from the deck (card.lua:4318) -- the same verified mechanism + -- as its clashes with DNA/Marble/Certificate, from a pack instead. + if tag == 'card_gen' and owns('j_erosion') then + text_row("Caution: shrinks Erosion's Mult", G.C.RED) + end + if #rows == 0 then return nil end + rows.name = 'Combo Advisor' + return rows +end + local orig_gen_aut = Card.generate_UIBox_ability_table function Card:generate_UIBox_ability_table(vars_only) -- vars_only returns multiple values; pass that path through untouched if vars_only then return orig_gen_aut(self, vars_only) end local aut = orig_gen_aut(self) + if aut and aut.info and not is_joker(self) + and (in_buy_area(self) or (G.shop_booster and self.area == G.shop_booster)) then + local ok, rows = pcall(consumable_rows, self) + if ok and rows then aut.info[#aut.info + 1] = rows end + end if aut and aut.info and is_joker(self) then dbg('hover joker', self.config.center.key, 'in_buy_area=', in_buy_area(self), 'owned=', self.area == G.jokers) diff --git a/test.lua b/test.lua index 2941e61..7756828 100644 --- a/test.lua +++ b/test.lua @@ -623,6 +623,41 @@ field('j_jolly') looking = JCA.build_gaps() eq(table.concat(looking, ','), 'pair', 'a lone cluster member still wants its cluster') +-------------------------------------------------------------------------------- +section('Engine: consumable advice names the fed jokers') +-------------------------------------------------------------------------------- + +local function consumable(set, kind) + return {config = {center = {set = set, kind = kind, key = 'c_test'}}} +end + +field('j_constellation', 'j_fortune_teller', 'j_mod_unknown') + +local fed, tag = JCA.consumable_partners(consumable('Planet')) +eq(tag, 'planet', 'a Planet card maps to the planet tag') +eq(#fed, 1, 'exactly one owned joker is fed by a Planet card') +eq(fed[1].key, 'j_constellation', 'and it is Constellation') + +fed, tag = JCA.consumable_partners(consumable('Booster', 'Celestial')) +eq(tag, 'planet', 'a Celestial Pack counts as Planet supply') +eq(fed[1].key, 'j_constellation', 'the pack feeds Constellation too') + +fed = JCA.consumable_partners(consumable('Tarot')) +eq(fed[1].key, 'j_fortune_teller', 'a Tarot card feeds Fortune Teller') + +-- Advice material with nobody home: tag resolves, list stays empty. +fed, tag = JCA.consumable_partners(consumable('Spectral')) +eq(tag, 'spectral_gen', 'a Spectral card still resolves its tag') +eq(#fed, 0, 'but feeds nobody on this board') + +-- A Standard Pack is card supply; a Buffoon Pack is not advice material. +fed, tag = JCA.consumable_partners(consumable('Booster', 'Standard')) +eq(tag, 'card_gen', 'a Standard Pack maps to card_gen') +eq(JCA.consumable_partners(consumable('Booster', 'Buffoon')), nil, + 'a Buffoon Pack yields no consumable advice') +eq(JCA.consumable_partners({config = {center = {set = 'Voucher'}}}), nil, + 'a Voucher yields no consumable advice') + -------------------------------------------------------------------------------- section('Data: themes are reachable') --------------------------------------------------------------------------------