From 3e8bbb402a402369ddf808e70bc488d0739cd57e Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sat, 15 Aug 2026 00:33:00 +0300 Subject: [PATCH 01/27] uncomment jokerdisplay --- items/joker_display.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 4947da4f3..db7740c05 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -140,8 +140,6 @@ --Adroit Joker --Penetrating Joker --Treacherous Joker - ---[[ if JokerDisplay then --Side note: I Don't think retrigger type exp gives a correct value with Emult jokers, but ehhhhh ig I can live with that (It's good enough) @@ -2044,6 +2042,5 @@ if JokerDisplay then --end of Jokerdisplays end -]] --- + return { name = "JokerDisplay" } From be8e8bb101b5ea5144d11e70d1d3643af940af42 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sat, 15 Aug 2026 01:27:21 +0300 Subject: [PATCH 02/27] update joker status --- items/joker_display.lua | 404 ++++++++++++++++++++++++++-------------- 1 file changed, 262 insertions(+), 142 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index db7740c05..06d621d50 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -1,145 +1,265 @@ ---=============== Page 1 ===============-- ---SuperCell ---Dropshot ---Kidnapping ---Iterum ---Happy House ---Bubble M ---Fast Food M ---M Stack ---Exponentia ---Neon M ---Virgo ---Notebook ---Pot Of Jokes ---Bonk ---Loopy ---=============== Page 2 ===============-- ---Old Membership Card ---Redeo ---Scrabble Tile ---Sacrifice ---Googol Play Card ---Weebonacci ---Reverse card ---Tiny ---Tenebris ---Huge ---Tredecim ---The WHIP ---Lucky Joker ---Canvas ---Megg ---=============== Page 3 ===============-- ---Jolly Joker? ---Cursor ---Pickle ---ERROR ---Cube ---Triplet Rhythm ---Chili Pepper ---Compound Interest ---Crustulum ---Big Cube ---m ---Boredom ---Eternal Flame ---Nice ---Chad ---=============== Page 4 ===============-- ---Jimball ---Fidget Spinner ---Number Blocks ---Luigi ---Waluigi ---Mario ---Nostalgic candy ---Wario ---Krusty the Clown ---Primus ---Garden of Forking Paths ---Light Up the Night ---No sound, No Memory ---...Like Antennas To heavem ---Caramel ---=============== Page 5 ===============-- ---Sob ---Consume-able ---2D ---Red Bloon ---AP Joker ---Fridge Magnet ---Stella Mortis ---Unjust Dagger ---Monkey Dagger ---Bonus Joker ---Pirate Dagger ---Mondrian ---Sapling ---Celestial Globe ---:D ---=============== Page 6 ===============-- ---Meteor Shower ---Exoplanet ---Stardust ---Mult Joker ---Gold Joker ---Nostalgic Googol play Card ---Circulus Pistoris ---The Duos ---The Home ---The Nuts ---The Quintet ---The Unity ---The Swarm ---The Filler ---Crypto Coin ---=============== Page 7 ===============-- ---Wheel Of Hope ---Old Blueprint ---Night ---Bus Driver ---Morse Code ---Membership Card ---M Chain ---Copy/Paste ---Cut ---Python ---Monster ---Non-Verisimile ---Gemini ---Nostalgic Invisible Joker ---Facile ---=============== Page 8 ===============-- ---Giggly Joker ---Nutty Joker ---Manic Joker ---Silly Joker ---Delirious Joker ---Wacky Joker ---Kooky Joker ---Dubious Joker ---Shrewd Joker ---Tricksy Joker ---Foxy Joker ---Savvy Joker ---Subtle Joker ---Discreet Joker ---Fractal ---=============== Page 9 ===============-- ---Ace Aequilibrium ---Duplicare ---Queen's Gambit ---Formidiulosus ---The Stronghold ---The Fuck!? ---The Clash ---Bonkers Joker ---Fucked Up Joker ---Foolhardy Joker ---Adroit Joker ---Penetrating Joker ---Treacherous Joker +--=============== Page 11 ===============-- +-- ------- Implemented ------- +-- m +-- Dropshot +-- Canvas +-- Cursor +-- Queen's Gambit +-- Jimball +-- Compound Interest +-- Triplet Rhythm +-- Cube +-- Number Blocks +-- Googol Play Card +-- The WHIP +-- ------ Unimplemented ------ +-- Double Scale +-- Maximized +-- ---------- Bugged --------- +-- Happy House: crashes game on hover +--=============== Page 12 ===============-- +-- ------- Implemented ------- +-- Giggly Joker +-- Nutty Joker +-- Manic Joker +-- Silly Joker +-- Delirious Joker +-- Wacky Joker +-- Kooky Joker +-- Dubious Joker +-- Shrewd Joker +-- Tricksy Joker +-- Foxy Joker +-- Savvy Joker +-- Subtle Joker +-- Discreet Joker +-- ---------- Bugged --------- +-- Kidnapping: crashes game on hover +--=============== Page 13 ===============-- +-- ------- Implemented ------- +-- Krusty the Clown +-- Boredom +-- Membership Card +-- Lucky Joker +-- AP Joker +-- Meteor Shower +-- Exoplanet +-- Stardust +-- Night +-- Sapling +-- Nostalgic Candy +-- Mondrian +-- Pickle +-- ------ Unimplemented ------ +-- Circus +-- Booster Joker +--=============== Page 14 ===============-- +-- ------- Implemented ------- +-- Bus Driver +-- Chili Pepper +-- Monkey Dagger +-- Old Membership Card +-- Crypto Coin +-- Morse Code +-- Nostalgic Googol Play Card +-- ------ Unimplemented ------ +-- Panopticon +-- Blurred Joker +-- Translucent Joker +-- Sync Catalyst +-- Kaleidoscope +-- One for All +-- RNJoker +-- Labyrinth +--=============== Page 15 ===============-- +-- ------- Implemented ------- +-- 2D +-- :D +-- M Chain +-- Garden of Forking Paths +-- Light Up the Night +-- No Sound, No Memory +-- ...Like Antennas to Heaven +-- Chad +-- ERROR +-- Celestial Globe +-- Wheel of Hope +-- Bonus Joker +-- ------ Unimplemented ------ +-- Jimbo-tron 9000 +-- Negative Joker +-- ---------- Bugged --------- +-- Supercell: incorrect display for modest(shows +chips and +mult when shouldn't) +--=============== Page 16 ===============-- +-- ------- Implemented ------- +-- Fractal Fingers +-- Fidget Spinner +-- Nostalgic Invisible Joker +-- Consume-able +-- Gold Joker +-- Sob +-- Old Blueprint +-- Nice +-- Waluigi +-- Wario +-- The Filler +-- The Duos +-- The Home +-- The Nuts +-- ------ Unimplemented ------ +-- SUS +--=============== Page 17 ===============-- +-- ------- Implemented ------- +-- The Quintet +-- The Unity +-- The Swarm +-- Fridge Magnet +-- Red Bloon +-- Weebonacci +-- Mult Joker +-- Eternal Flame +-- Unjust Dagger +-- Pirate Dagger +-- Pot of Jokes +-- Big Cube +-- Caramel +-- Bonkers Joker +-- ------ Unimplemented ------ +-- Seal the Deal +--=============== Page 18 ===============-- +-- ------- Implemented ------- +-- Fucked-Up Joker +-- Foolhardy Joker +-- Adroit Joker +-- Penetrating Joker +-- Treacherous Joker +-- The Stronghold +-- The Fuck!? +-- The Clash +-- ------ Unimplemented ------ +-- Undefined Joker +-- Words Can't Even Begin to Describe This Joker +-- Nebulous Joker +-- Many Have Lost Their Minds Comprehending This Joker +-- Universe +-- The +-- The Complete and Utter Annihilation of Everything That Makes Balatro Sacred +--=============== Page 19 ===============-- +-- ------ Unimplemented ------ +-- Astral in a Bottle +-- Exposed +-- Mask +-- Tropical Smoothie +-- Necromancer +-- Oil Lamp +-- Tax Fraud +-- Pity Prize +-- Digital Hallucinations +-- Cotton Candy +-- Arsonist +-- Wrapped Candy +-- Zooble +-- Chocolate Die +-- Spectrogram +--=============== Page 20 ===============-- +-- ------ Unimplemented ------ +-- Kitty Printer +-- Clicked Cookie +-- LeBaron James +-- Hunting Season +-- Trick-or-Treat +-- Clockwork Joker +-- Candy Basket +-- Blacklist +-- Rotten Egg +-- Familiar Currency +-- High Five +-- Sock and Sock +-- Candy Dagger +-- Broken Home +-- Candy Cane +--=============== Page 21 ===============-- +-- ------ Unimplemented ------ +-- Yarn Ball +-- Candy Buttons +-- Pizza +-- Pizza Slice +-- Jawbreaker +-- Paved Joker +-- Mellowcreme +-- Fading Joker +-- Brittle Candy +-- Poor Joker +-- Monopoly Money +-- Broken Sync Catalyst +-- Thalia and Melpomeme +-- Key Change +-- Candy Sticks +--=============== Page 22 ===============-- +-- ------- Implemented ------- +-- Bubble M +-- Fast Food M +-- M Stack +-- Neon M +-- Notebook +-- Bonk +-- Loopy +-- Scrabble Tile +-- Sacrifice +-- Reverse Card +-- ------ Unimplemented ------ +-- Emergency Chips +-- Flesh Panopticon +-- Wonka Bar +-- Buttercup +-- M +--=============== Page 23 ===============-- +-- ------- Implemented ------- +-- Monster +-- Megg +-- Tiny +-- Virgo +-- Jolly Joker? +-- Huge +-- Copy/Paste +-- Cut +-- ------ Unimplemented ------ +-- Macabre Joker +-- Doodle M +-- Demicolon +-- Starfruit +-- Project Sundial +-- Code Joker +-- Blender +--=============== Page 24 ===============-- +-- ------- Implemented ------- +-- Python +-- Iterum +-- Stella Mortis +-- Exponentia +-- Redeo +-- Tenebris +-- Crustulum +-- Circulus Pistoris +-- Primus +-- Ace Aequilibrium +-- Facile +-- ------ Unimplemented ------ +-- Scalae +-- Universum +-- Speculo +-- Effarcire +--=============== Page 25 ===============-- +-- ------- Implemented ------- +-- Gemini +-- Non Verisimile +-- Duplicare +-- Formidiulosus +-- Tredecim +-- ------ Unimplemented ------ +-- Energia +-- Caeruleum + if JokerDisplay then --Side note: I Don't think retrigger type exp gives a correct value with Emult jokers, but ehhhhh ig I can live with that (It's good enough) From f020d2a482b0ddb630d38662dc3d3dd5b1871527 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sat, 15 Aug 2026 18:14:01 +0300 Subject: [PATCH 03/27] update comments --- items/joker_display.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 06d621d50..97c61619c 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -2,9 +2,9 @@ -- ------- Implemented ------- -- m -- Dropshot --- Canvas +-- Canvas: needs rework (add "retriggers" below counter) -- Cursor --- Queen's Gambit +-- Queen's Gambit: needs rework (show counter like with Seance) -- Jimball -- Compound Interest -- Triplet Rhythm @@ -13,8 +13,8 @@ -- Googol Play Card -- The WHIP -- ------ Unimplemented ------ --- Double Scale --- Maximized +-- Double Scale(unnecessary) +-- Maximized(unnecessary) -- ---------- Bugged --------- -- Happy House: crashes game on hover --=============== Page 12 ===============-- From be8843aa9ceda583dd86cce02c8bce07f7746d55 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sat, 15 Aug 2026 21:55:31 +0300 Subject: [PATCH 04/27] Update comments --- items/joker_display.lua | 108 ++++++++++++++++++++++++---------------- 1 file changed, 65 insertions(+), 43 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 97c61619c..0c62bbfae 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -2,24 +2,27 @@ -- ------- Implemented ------- -- m -- Dropshot --- Canvas: needs rework (add "retriggers" below counter) -- Cursor --- Queen's Gambit: needs rework (show counter like with Seance) --- Jimball -- Compound Interest -- Triplet Rhythm -- Cube -- Number Blocks -- Googol Play Card -- The WHIP --- ------ Unimplemented ------ --- Double Scale(unnecessary) --- Maximized(unnecessary) +-- Canvas +-- ------ Need Rework -------- +-- Queen's Gambit: show counter like with Seance +-- ------ Unnecessary ------ +-- Double Scale +-- Maximized -- ---------- Bugged --------- -- Happy House: crashes game on hover +-- Jimball: weird crash when selecting cards??? --=============== Page 12 ===============-- --- ------- Implemented ------- --- Giggly Joker +-- ---------- Bugged --------- +-- Kidnapping: crashes game on hover +-- # All below: incorrect display (show +0 ERROR at all times) # +-- Absurd Joker -- Nutty Joker -- Manic Joker -- Silly Joker @@ -33,8 +36,6 @@ -- Savvy Joker -- Subtle Joker -- Discreet Joker --- ---------- Bugged --------- --- Kidnapping: crashes game on hover --=============== Page 13 ===============-- -- ------- Implemented ------- -- Krusty the Clown @@ -42,77 +43,81 @@ -- Membership Card -- Lucky Joker -- AP Joker --- Meteor Shower --- Exoplanet --- Stardust -- Night -- Sapling -- Nostalgic Candy -- Mondrian -- Pickle +-- Meteor Shower +-- Stardust +-- Exoplanet -- ------ Unimplemented ------ -- Circus -- Booster Joker --=============== Page 14 ===============-- -- ------- Implemented ------- --- Bus Driver -- Chili Pepper -- Monkey Dagger --- Old Membership Card --- Crypto Coin -- Morse Code -- Nostalgic Googol Play Card +-- Old Membership Card +-- ----- Need Rework --------- +-- Bus Driver: show chances for each outcome +-- Crypto Coin: add "sold Joker" or something like that below values -- ------ Unimplemented ------ --- Panopticon -- Blurred Joker -- Translucent Joker -- Sync Catalyst --- Kaleidoscope -- One for All -- RNJoker +-- ------ Unnecessary -------- +-- Panopticon -- Labyrinth +-- Kaleidoscope --=============== Page 15 ===============-- -- ------- Implemented ------- --- 2D --- :D --- M Chain -- Garden of Forking Paths -- Light Up the Night --- No Sound, No Memory --- ...Like Antennas to Heaven --- Chad -- ERROR -- Celestial Globe -- Wheel of Hope --- Bonus Joker +-- Chad +-- 2D +-- No Sound, No Memory +-- ----- Need Rework --------- +-- :D: Need to add "+Joker" above "Round" +-- M Chain: rework description -- ------ Unimplemented ------ -- Jimbo-tron 9000 +-- ----- Unnecessary --------- -- Negative Joker -- ---------- Bugged --------- -- Supercell: incorrect display for modest(shows +chips and +mult when shouldn't) +-- ...Like Antennas to Heaven: stuck at X1, not updating +-- Bonus Joker: crashes game (on spawning?) --=============== Page 16 ===============-- -- ------- Implemented ------- -- Fractal Fingers -- Fidget Spinner -- Nostalgic Invisible Joker --- Consume-able -- Gold Joker -- Sob --- Old Blueprint -- Nice -- Waluigi -- Wario -- The Filler +-- ------ Need Rework -------- +-- Consume-able: add "Consumable" text +-- ------- Bugged ------------ +-- Old Blueprint: loses probability text when copying a joker +-- # All below: incorrect display (show x1 ERROR at all times) # -- The Duos -- The Home -- The Nuts --- ------ Unimplemented ------ +-- ------ Unnecessary -------- -- SUS --=============== Page 17 ===============-- -- ------- Implemented ------- --- The Quintet --- The Unity --- The Swarm -- Fridge Magnet -- Red Bloon -- Weebonacci @@ -123,11 +128,17 @@ -- Pot of Jokes -- Big Cube -- Caramel --- Bonkers Joker -- ------ Unimplemented ------ -- Seal the Deal +-- ------ Bugged ------------- +-- # All below: incorrect display (show +0/x1 ERROR at all times) # +-- The Quintet +-- The Unity +-- The Swarm +-- Bonkers Joker --=============== Page 18 ===============-- --- ------- Implemented ------- +-- ------- Bugged ------------- +-- # All below: incorrect display # -- Fucked-Up Joker -- Foolhardy Joker -- Adroit Joker @@ -146,21 +157,22 @@ -- The Complete and Utter Annihilation of Everything That Makes Balatro Sacred --=============== Page 19 ===============-- -- ------ Unimplemented ------ --- Astral in a Bottle -- Exposed -- Mask -- Tropical Smoothie --- Necromancer -- Oil Lamp -- Tax Fraud -- Pity Prize -- Digital Hallucinations --- Cotton Candy -- Arsonist -- Wrapped Candy -- Zooble -- Chocolate Die -- Spectrogram +-- ---- Unnecessary --------- +-- Astral in a Bottle +-- Necromancer +-- Cotton Candy --=============== Page 20 ===============-- -- ------ Unimplemented ------ -- Kitty Printer @@ -194,29 +206,32 @@ -- Broken Sync Catalyst -- Thalia and Melpomeme -- Key Change +-- ---- Unnecessary --------- -- Candy Sticks --=============== Page 22 ===============-- -- ------- Implemented ------- --- Bubble M -- Fast Food M -- M Stack -- Neon M --- Notebook -- Bonk -- Loopy -- Scrabble Tile -- Sacrifice -- Reverse Card +-- ------ Need Rework -------- +-- Bubble M: add "+Jolly" text -- ------ Unimplemented ------ -- Emergency Chips -- Flesh Panopticon -- Wonka Bar +-- ---- Unnecessary --------- -- Buttercup -- M +-- ------ Bugged ------------- +-- Notebook: shows "ERROR" and doesn't correctly update status --=============== Page 23 ===============-- -- ------- Implemented ------- -- Monster --- Megg -- Tiny -- Virgo -- Jolly Joker? @@ -229,8 +244,11 @@ -- Demicolon -- Starfruit -- Project Sundial +-- ---- Unnecessary ---------- -- Code Joker -- Blender +-- ------ Bugged ------------- +-- Megg: no info shown --=============== Page 24 ===============-- -- ------- Implemented ------- -- Python @@ -240,25 +258,29 @@ -- Redeo -- Tenebris -- Crustulum --- Circulus Pistoris -- Primus -- Ace Aequilibrium -- Facile --- ------ Unimplemented ------ +-- ----- Need Rework -------- +-- Circulus Pistoris: incorrect echips/emult visual display and needs to add active/inactive text +-- ------ Unimplemented ----- -- Scalae -- Universum +-- ---- Unnecessary --------- -- Speculo -- Effarcire --=============== Page 25 ===============-- -- ------- Implemented ------- --- Gemini -- Non Verisimile -- Duplicare -- Formidiulosus --- Tredecim +-- ------ Need Rework -------- +-- Gemini: show what Joker it's doubling -- ------ Unimplemented ------ -- Energia -- Caeruleum +-- ----- Bugged ------------ +-- Tredecim: only shows emult for jolly jokers and not m jokers if JokerDisplay then --Side note: I Don't think retrigger type exp gives a correct value with Emult jokers, but ehhhhh ig I can live with that (It's good enough) From 9b2ae85d2293a0eb4b64af5474b43ff29617835f Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sat, 15 Aug 2026 23:52:06 +0300 Subject: [PATCH 05/27] fix and implement all hand-type dependent scoring jokers --- items/joker_display.lua | 192 +++++++++++++++++++++++++--------------- 1 file changed, 120 insertions(+), 72 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 0c62bbfae..6513029c9 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -19,9 +19,7 @@ -- Happy House: crashes game on hover -- Jimball: weird crash when selecting cards??? --=============== Page 12 ===============-- --- ---------- Bugged --------- --- Kidnapping: crashes game on hover --- # All below: incorrect display (show +0 ERROR at all times) # +-- ------- Implemented ------- -- Absurd Joker -- Nutty Joker -- Manic Joker @@ -36,6 +34,8 @@ -- Savvy Joker -- Subtle Joker -- Discreet Joker +-- ---------- Bugged --------- +-- Kidnapping: crashes game on hover --=============== Page 13 ===============-- -- ------- Implemented ------- -- Krusty the Clown @@ -106,14 +106,13 @@ -- Waluigi -- Wario -- The Filler +-- The Duos +-- The Home +-- The Nuts -- ------ Need Rework -------- -- Consume-able: add "Consumable" text -- ------- Bugged ------------ -- Old Blueprint: loses probability text when copying a joker --- # All below: incorrect display (show x1 ERROR at all times) # --- The Duos --- The Home --- The Nuts -- ------ Unnecessary -------- -- SUS --=============== Page 17 ===============-- @@ -128,33 +127,30 @@ -- Pot of Jokes -- Big Cube -- Caramel --- ------ Unimplemented ------ --- Seal the Deal --- ------ Bugged ------------- --- # All below: incorrect display (show +0/x1 ERROR at all times) # -- The Quintet -- The Unity -- The Swarm -- Bonkers Joker +-- ------ Unimplemented ------ +-- Seal the Deal --=============== Page 18 ===============-- --- ------- Bugged ------------- --- # All below: incorrect display # +-- ------- Implemented ------- -- Fucked-Up Joker -- Foolhardy Joker +-- Undefined Joker +-- Words Can't Even Begin to Describe This Joker -- Adroit Joker -- Penetrating Joker -- Treacherous Joker +-- Nebulous Joker +-- Many Have Lost Their Minds Comprehending This Joker -- The Stronghold -- The Fuck!? -- The Clash --- ------ Unimplemented ------ --- Undefined Joker --- Words Can't Even Begin to Describe This Joker --- Nebulous Joker --- Many Have Lost Their Minds Comprehending This Joker --- Universe -- The -- The Complete and Utter Annihilation of Everything That Makes Balatro Sacred +-- ------ Unimplemented ------ +-- Universe --=============== Page 19 ===============-- -- ------ Unimplemented ------ -- Exposed @@ -1782,13 +1778,108 @@ if JokerDisplay then { text = ")" }, }, calc_function = function(card) + local hand_type = (card.ability.extra and card.ability.extra.type) or card.ability.type + local xmult_val = (card.ability.extra and (card.ability.extra.Xmult or card.ability.extra.x_mult or card.ability.extra.xmult)) or card.ability.Xmult or card.ability.x_mult or card.ability.xmult or 1 local x_mult = 1 local text, poker_hands, _ = JokerDisplay.evaluate_hand() - if text ~= "Unknown" and poker_hands[card.ability.type] and next(poker_hands[card.ability.type]) then - x_mult = card.ability.x_mult + if text ~= "Unknown" and hand_type then + local matches = (poker_hands[hand_type] and next(poker_hands[hand_type])) or text == hand_type + if card.config.center.key == "j_cry_duos" then + matches = matches or (poker_hands["Full House"] and next(poker_hands["Full House"])) or text == "Full House" + end + if matches then + x_mult = xmult_val + end end card.joker_display_values.x_mult = x_mult - card.joker_display_values.localized_text = localize(card.ability.type, "poker_hands") + card.joker_display_values.localized_text = hand_type and localize(hand_type, "poker_hands") or "-" + end, + } + local hand_tmult_jd = { + text = { + { text = "+", colour = G.C.MULT }, + { + ref_table = "card.joker_display_values", + ref_value = "t_mult", + colour = G.C.MULT, + retrigger_type = "mult", + }, + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = G.C.ORANGE }, + { text = ")" }, + }, + calc_function = function(card) + local hand_type = (card.ability.extra and card.ability.extra.type) or card.ability.type + local mult_val = (card.ability.extra and (card.ability.extra.t_mult or card.ability.extra.mult)) or card.ability.t_mult or card.ability.mult or 0 + local t_mult = 0 + local text, poker_hands, _ = JokerDisplay.evaluate_hand() + if text ~= "Unknown" and hand_type then + if (poker_hands[hand_type] and next(poker_hands[hand_type])) or text == hand_type then + t_mult = mult_val + end + end + card.joker_display_values.t_mult = t_mult + card.joker_display_values.localized_text = hand_type and localize(hand_type, "poker_hands") or "-" + end, + } + local hand_tchips_jd = { + text = { + { text = "+", colour = G.C.CHIPS }, + { + ref_table = "card.joker_display_values", + ref_value = "t_chips", + colour = G.C.CHIPS, + retrigger_type = "mult", + }, + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = G.C.ORANGE }, + { text = ")" }, + }, + calc_function = function(card) + local hand_type = (card.ability.extra and card.ability.extra.type) or card.ability.type + local chip_val = (card.ability.extra and (card.ability.extra.t_chips or card.ability.extra.chips)) or card.ability.t_chips or card.ability.chips or 0 + local t_chips = 0 + local text, poker_hands, _ = JokerDisplay.evaluate_hand() + if text ~= "Unknown" and hand_type then + if (poker_hands[hand_type] and next(poker_hands[hand_type])) or text == hand_type then + t_chips = chip_val + end + end + card.joker_display_values.t_chips = t_chips + card.joker_display_values.localized_text = hand_type and localize(hand_type, "poker_hands") or "-" + end, + } + local hand_emult_jd = { + text = { + { + border_nodes = { + { text = "^" }, + { ref_table = "card.joker_display_values", ref_value = "e_mult", retrigger_type = "exp" }, + }, + border_colour = G.C.DARK_EDITION, + }, + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = G.C.ORANGE }, + { text = ")" }, + }, + calc_function = function(card) + local hand_type = (card.ability.extra and card.ability.extra.type) or card.ability.type + local emult_val = (card.ability.extra and (card.ability.extra.Emult or card.ability.extra.emult or card.ability.extra.e_mult)) or card.ability.Emult or card.ability.emult or card.ability.e_mult or 1 + local e_mult = 1 + local text, poker_hands, _ = JokerDisplay.evaluate_hand() + if text ~= "Unknown" and hand_type then + if (poker_hands[hand_type] and next(poker_hands[hand_type])) or text == hand_type then + e_mult = emult_val + end + end + card.joker_display_values.e_mult = e_mult + card.joker_display_values.localized_text = hand_type and localize(hand_type, "poker_hands") or "-" end, } JokerDisplay.Definitions["j_cry_duos"] = hand_xmult_jd @@ -2029,56 +2120,7 @@ if JokerDisplay then --This is here so it shows up on the github symbol panel (easy to scroll to) local page8 = {} - local hand_tmult_jd = { - text = { - { text = "+", colour = G.C.MULT }, - { - ref_table = "card.joker_display_values", - ref_value = "t_mult", - colour = G.C.MULT, - retrigger_type = "mult", - }, - }, - reminder_text = { - { text = "(" }, - { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = G.C.ORANGE }, - { text = ")" }, - }, - calc_function = function(card) - local t_mult = 0 - local text, poker_hands, _ = JokerDisplay.evaluate_hand() - if text ~= "Unknown" and poker_hands[card.ability.type] and next(poker_hands[card.ability.type]) then - t_mult = card.ability.t_mult - end - card.joker_display_values.t_mult = t_mult - card.joker_display_values.localized_text = localize(card.ability.type, "poker_hands") - end, - } - local hand_tchips_jd = { - text = { - { text = "+", colour = G.C.CHIPS }, - { - ref_table = "card.joker_display_values", - ref_value = "t_chips", - colour = G.C.CHIPS, - retrigger_type = "mult", - }, - }, - reminder_text = { - { text = "(" }, - { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = G.C.ORANGE }, - { text = ")" }, - }, - calc_function = function(card) - local t_chips = 0 - local text, poker_hands, _ = JokerDisplay.evaluate_hand() - if text ~= "Unknown" and poker_hands[card.ability.type] and next(poker_hands[card.ability.type]) then - t_chips = card.ability.t_chips - end - card.joker_display_values.t_chips = t_chips - card.joker_display_values.localized_text = localize(card.ability.type, "poker_hands") - end, - } + JokerDisplay.Definitions["j_cry_giggly"] = hand_tmult_jd JokerDisplay.Definitions["j_cry_nutty"] = hand_tmult_jd JokerDisplay.Definitions["j_cry_manic"] = hand_tmult_jd @@ -2175,12 +2217,18 @@ if JokerDisplay then JokerDisplay.Definitions["j_cry_stronghold"] = hand_xmult_jd JokerDisplay.Definitions["j_cry_wtf"] = hand_xmult_jd JokerDisplay.Definitions["j_cry_clash"] = hand_xmult_jd + JokerDisplay.Definitions["j_cry_the"] = hand_xmult_jd + JokerDisplay.Definitions["j_cry_words_cant_even"] = hand_xmult_jd JokerDisplay.Definitions["j_cry_bonkers"] = hand_tmult_jd JokerDisplay.Definitions["j_cry_fuckedup"] = hand_tmult_jd JokerDisplay.Definitions["j_cry_foolhardy"] = hand_tmult_jd + JokerDisplay.Definitions["j_cry_undefined"] = hand_tmult_jd JokerDisplay.Definitions["j_cry_adroit"] = hand_tchips_jd JokerDisplay.Definitions["j_cry_penetrating"] = hand_tchips_jd JokerDisplay.Definitions["j_cry_treacherous"] = hand_tchips_jd + JokerDisplay.Definitions["j_cry_nebulous"] = hand_tchips_jd + JokerDisplay.Definitions["j_cry_many_lost_minds"] = hand_tchips_jd + JokerDisplay.Definitions["j_cry_annihalation"] = hand_emult_jd --end of Jokerdisplays end From ed1b4b2ef03b84fd22bbbed2121f102f3087e2b0 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sun, 16 Aug 2026 15:34:52 +0300 Subject: [PATCH 06/27] add critical bug section --- items/joker_display.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 6513029c9..2cb1d1387 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -15,7 +15,7 @@ -- ------ Unnecessary ------ -- Double Scale -- Maximized --- ---------- Bugged --------- +-- -- Critically Bugged ------ -- Happy House: crashes game on hover -- Jimball: weird crash when selecting cards??? --=============== Page 12 ===============-- @@ -34,7 +34,7 @@ -- Savvy Joker -- Subtle Joker -- Discreet Joker --- ---------- Bugged --------- +-- -- Critically Bugged ------ -- Kidnapping: crashes game on hover --=============== Page 13 ===============-- -- ------- Implemented ------- @@ -94,6 +94,7 @@ -- ---------- Bugged --------- -- Supercell: incorrect display for modest(shows +chips and +mult when shouldn't) -- ...Like Antennas to Heaven: stuck at X1, not updating +-- -- Critically Bugged ------ -- Bonus Joker: crashes game (on spawning?) --=============== Page 16 ===============-- -- ------- Implemented ------- From 497e971cd71594c6cc2a59a356156090e410a430 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sun, 16 Aug 2026 17:04:25 +0300 Subject: [PATCH 07/27] fix all game-crashing jokers --- items/joker_display.lua | 77 ++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 2cb1d1387..e0a978988 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -10,14 +10,13 @@ -- Googol Play Card -- The WHIP -- Canvas +-- Happy House +-- Jimball -- ------ Need Rework -------- -- Queen's Gambit: show counter like with Seance -- ------ Unnecessary ------ -- Double Scale -- Maximized --- -- Critically Bugged ------ --- Happy House: crashes game on hover --- Jimball: weird crash when selecting cards??? --=============== Page 12 ===============-- -- ------- Implemented ------- -- Absurd Joker @@ -34,8 +33,7 @@ -- Savvy Joker -- Subtle Joker -- Discreet Joker --- -- Critically Bugged ------ --- Kidnapping: crashes game on hover +-- Kidnapping --=============== Page 13 ===============-- -- ------- Implemented ------- -- Krusty the Clown @@ -84,6 +82,7 @@ -- Chad -- 2D -- No Sound, No Memory +-- Bonus Joker -- ----- Need Rework --------- -- :D: Need to add "+Joker" above "Round" -- M Chain: rework description @@ -94,8 +93,6 @@ -- ---------- Bugged --------- -- Supercell: incorrect display for modest(shows +chips and +mult when shouldn't) -- ...Like Antennas to Heaven: stuck at X1, not updating --- -- Critically Bugged ------ --- Bonus Joker: crashes game (on spawning?) --=============== Page 16 ===============-- -- ------- Implemented ------- -- Fractal Fingers @@ -361,14 +358,14 @@ if JokerDisplay then JokerDisplay.Definitions["j_cry_kidnap"] = { text = { { text = "+$" }, - { ref_table = "card.joker_display_values", ref_value = "extra" }, + { ref_table = "card.joker_display_values", ref_value = "dollars" }, }, text_config = { colour = G.C.GOLD }, reminder_text = { { ref_table = "card.joker_display_values", ref_value = "localized_text" }, }, calc_function = function(card) - local abc = 0 + local count = 0 if G.GAME and G.GAME.jokers_sold then for _, v in ipairs(G.GAME.jokers_sold) do local center = G.P_CENTERS[v] @@ -386,11 +383,12 @@ if JokerDisplay then or center.name == "Crafty Joker" ) then - abc = abc + 1 + count = count + 1 end end end - card.joker_display_values.extra = card.ability.extra * abc + local money_per = (card.ability and card.ability.extra and type(card.ability.extra) == "table" and card.ability.extra.money) or (type(card.ability.extra) == "number" and card.ability.extra) or 4 + card.joker_display_values.dollars = money_per * count card.joker_display_values.localized_text = "(" .. localize("k_round") .. ")" end, } @@ -429,13 +427,7 @@ if JokerDisplay then { ref_table = "card.joker_display_values", ref_value = "e_mult", - retrigger_type = function(number, triggers) - local num = number - for i = 1, triggers - 1 do - num = num ^ number - end - return num - end, + retrigger_type = "exp", }, }, border_colour = G.C.DARK_EDITION, @@ -443,11 +435,19 @@ if JokerDisplay then }, reminder_text = { { text = "(" }, - { ref_table = "card.ability.extra", ref_value = "check" }, - { text = "/114)" }, + { ref_table = "card.joker_display_values", ref_value = "check" }, + { text = "/" }, + { ref_table = "card.joker_display_values", ref_value = "trigger" }, + { text = ")" }, }, calc_function = function(card) - card.joker_display_values.e_mult = card.ability.extra.check >= 114 and card.ability.extra.mult or 1 + local immutable = (card.ability and card.ability.immutable) or {} + local check = immutable.check or 0 + local trigger = immutable.trigger or 114 + local mult = immutable.mult or 4 + card.joker_display_values.e_mult = check >= trigger and mult or 1 + card.joker_display_values.check = check + card.joker_display_values.trigger = trigger end, } JokerDisplay.Definitions["j_cry_bubblem"] = { @@ -1088,22 +1088,23 @@ if JokerDisplay then }, }, calc_function = function(card) - local hand = G.hand.highlighted + local cur_xmult = (card.ability and card.ability.extra and card.ability.extra.x_mult) or 1 + local mod = (card.ability and card.ability.extra and card.ability.extra.x_mult_mod) or 0.15 + local hand = G.hand and G.hand.highlighted local text, _, _ = JokerDisplay.evaluate_hand(hand) - local play_more_than = 0 - local hand_exists = text ~= "Unknown" and G.GAME and G.GAME.hands and G.GAME.hands[text] - if hand_exists then + if text ~= "Unknown" and G.GAME and G.GAME.hands and G.GAME.hands[text] then + local play_more_than = G.GAME.hands[text].played or 0 + local will_reset = false for k, v in pairs(G.GAME.hands) do if text ~= k and v.played and v.played >= play_more_than and v.visible then - play_more_than = v.played + will_reset = true + break end end + card.joker_display_values.x_mult = will_reset and 1 or (cur_xmult + mod) + else + card.joker_display_values.x_mult = cur_xmult end - card.joker_display_values.x_mult = ( - hand_exists - and (G.GAME.hands[text].played < play_more_than and 1 or card.ability.x_mult + card.ability.extra) - or card.ability.x_mult - ) end, } JokerDisplay.Definitions["j_cry_fspinner"] = { @@ -1468,24 +1469,28 @@ if JokerDisplay then { text = "(" }, { ref_table = "card.joker_display_values", ref_value = "odds" }, { text = " in " }, - { ref_table = "card.ability.extra", ref_value = "odds" }, + { ref_table = "card.joker_display_values", ref_value = "max_odds" }, { text = ")" }, }, }, extra_config = { colour = G.C.GREEN, scale = 0.3 }, calc_function = function(card) local count = 0 - local hand = next(G.play.cards) and G.play.cards or G.hand.highlighted + local hand = (G.play and next(G.play.cards)) and G.play.cards or (G.hand and G.hand.highlighted) local text, _, scoring_hand = JokerDisplay.evaluate_hand(hand) - if text ~= "Unknown" then + if text ~= "Unknown" and scoring_hand then for _, scoring_card in pairs(scoring_hand) do - if scoring_card.ability.effect and scoring_card.ability.effect == "Bonus Card" then + if SMODS and SMODS.has_enhancement and SMODS.has_enhancement(scoring_card, "m_bonus") then + count = count + JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) + elseif scoring_card.ability and scoring_card.ability.effect == "Bonus Card" then count = count + JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) end end end - card.joker_display_values.count = math.min(count, 2 - card.ability.extra.check) + local check = (card.ability and card.ability.immutable and card.ability.immutable.check) or 0 + card.joker_display_values.count = math.min(count, math.max(0, 2 - check)) card.joker_display_values.odds = G.GAME and G.GAME.probabilities.normal or 1 + card.joker_display_values.max_odds = (card.ability and card.ability.extra and card.ability.extra.odds) or 8 end, } JokerDisplay.Definitions["j_cry_pirate_dagger"] = { From def4eddc6ca454211b357b36a3861bace61123f2 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sun, 16 Aug 2026 18:10:41 +0300 Subject: [PATCH 08/27] fix all bugged jokers --- items/joker_display.lua | 122 ++++++++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 31 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index e0a978988..897289bfd 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -83,6 +83,8 @@ -- 2D -- No Sound, No Memory -- Bonus Joker +-- Supercell +-- ...Like Antennas to Heaven -- ----- Need Rework --------- -- :D: Need to add "+Joker" above "Round" -- M Chain: rework description @@ -90,9 +92,6 @@ -- Jimbo-tron 9000 -- ----- Unnecessary --------- -- Negative Joker --- ---------- Bugged --------- --- Supercell: incorrect display for modest(shows +chips and +mult when shouldn't) --- ...Like Antennas to Heaven: stuck at X1, not updating --=============== Page 16 ===============-- -- ------- Implemented ------- -- Fractal Fingers @@ -107,10 +106,9 @@ -- The Duos -- The Home -- The Nuts +-- Old Blueprint -- ------ Need Rework -------- -- Consume-able: add "Consumable" text --- ------- Bugged ------------ --- Old Blueprint: loses probability text when copying a joker -- ------ Unnecessary -------- -- SUS --=============== Page 17 ===============-- @@ -212,6 +210,7 @@ -- Scrabble Tile -- Sacrifice -- Reverse Card +-- Notebook -- ------ Need Rework -------- -- Bubble M: add "+Jolly" text -- ------ Unimplemented ------ @@ -220,9 +219,7 @@ -- Wonka Bar -- ---- Unnecessary --------- -- Buttercup --- M --- ------ Bugged ------------- --- Notebook: shows "ERROR" and doesn't correctly update status +-- M --=============== Page 23 ===============-- -- ------- Implemented ------- -- Monster @@ -232,6 +229,7 @@ -- Huge -- Copy/Paste -- Cut +-- Megg -- ------ Unimplemented ------ -- Macabre Joker -- Doodle M @@ -241,8 +239,6 @@ -- ---- Unnecessary ---------- -- Code Joker -- Blender --- ------ Bugged ------------- --- Megg: no info shown --=============== Page 24 ===============-- -- ------- Implemented ------- -- Python @@ -268,13 +264,12 @@ -- Non Verisimile -- Duplicare -- Formidiulosus +-- Tredecim -- ------ Need Rework -------- -- Gemini: show what Joker it's doubling -- ------ Unimplemented ------ -- Energia -- Caeruleum --- ----- Bugged ------------ --- Tredecim: only shows emult for jolly jokers and not m jokers if JokerDisplay then --Side note: I Don't think retrigger type exp gives a correct value with Emult jokers, but ehhhhh ig I can live with that (It's good enough) @@ -284,10 +279,10 @@ if JokerDisplay then JokerDisplay.Definitions["j_cry_supercell"] = { text = { - { text = "+", colour = G.C.CHIPS }, - { ref_table = "card.ability.extra", ref_value = "stat1", colour = G.C.CHIPS, retrigger_type = "mult" }, - { text = " +", colour = G.C.MULT }, - { ref_table = "card.ability.extra", ref_value = "stat1", colour = G.C.MULT, retrigger_type = "mult" }, + { ref_table = "card.joker_display_values", ref_value = "plus_chips", colour = G.C.CHIPS }, + { ref_table = "card.joker_display_values", ref_value = "stat1_chips", colour = G.C.CHIPS, retrigger_type = "mult" }, + { ref_table = "card.joker_display_values", ref_value = "plus_mult", colour = G.C.MULT }, + { ref_table = "card.joker_display_values", ref_value = "stat1_mult", colour = G.C.MULT, retrigger_type = "mult" }, }, extra = { { @@ -318,6 +313,12 @@ if JokerDisplay then }, }, calc_function = function(card) + local is_modest = Card.get_gameset and Card.get_gameset(card) == "modest" + local stat1 = (card.ability and card.ability.extra and card.ability.extra.stat1) or 15 + card.joker_display_values.plus_chips = not is_modest and "+" or "" + card.joker_display_values.stat1_chips = not is_modest and stat1 or "" + card.joker_display_values.plus_mult = not is_modest and " +" or "" + card.joker_display_values.stat1_mult = not is_modest and stat1 or "" card.joker_display_values.localized_text = "(" .. localize("k_round") .. ")" end, } @@ -547,27 +548,34 @@ if JokerDisplay then end, } JokerDisplay.Definitions["j_cry_notebook"] = { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "slots" }, + }, + text_config = { colour = G.C.DARK_EDITION }, reminder_text = { { text = "(" }, - { ref_table = "card.ability.extra", ref_value = "slot" }, - { text = ") " }, - { ref_table = "card.joker_display_values", ref_value = "localized_text" }, + { ref_table = "card.joker_display_values", ref_value = "active_text", colour = G.C.ORANGE }, + { text = ")" }, }, extra = { { { text = "(" }, { ref_table = "card.joker_display_values", ref_value = "odds" }, { text = " in " }, - { ref_table = "card.ability.extra", ref_value = "odds" }, + { ref_table = "card.joker_display_values", ref_value = "max_odds" }, { text = ")" }, }, }, extra_config = { colour = G.C.GREEN, scale = 0.3 }, calc_function = function(card) - card.joker_display_values.localized_text = "(" - .. (card.ability.extra.check and localize("k_active_ex") or "Inactive") - .. ")" + local immutable = (card.ability and card.ability.immutable) or {} + local extra = (card.ability and card.ability.extra) or {} + card.joker_display_values.slots = immutable.slots or 0 + local is_active = extra.check ~= false + card.joker_display_values.active_text = is_active and localize("cry_active") or localize("cry_inactive") card.joker_display_values.odds = G.GAME and G.GAME.probabilities.normal or 1 + card.joker_display_values.max_odds = extra.odds or 7 end, } JokerDisplay.Definitions["j_cry_pot_of_jokes"] = { @@ -735,17 +743,31 @@ if JokerDisplay then } JokerDisplay.Definitions["j_cry_mprime"] = { mod_function = function(card, mod_joker) + local is_m_or_jolly = (card.is_jolly and card:is_jolly()) + or card.ability.name == "Jolly Joker" + or (card.edition and card.edition.key == "e_cry_m") + or (card.config and card.config.center and Cryptid.safe_get(card.config.center, "pools", "M")) return { - e_mult = ( - card.ability.name == "Jolly Joker" - or card.edition and card.edition.key == "e_cry_m" - or Cryptid.safe_get(card, "pools", "M") - ) + e_mult = (card ~= mod_joker and is_m_or_jolly) and mod_joker.ability.extra.mult * JokerDisplay.calculate_joker_triggers(mod_joker) or nil, } end, } + JokerDisplay.Definitions["j_cry_megg"] = { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "amount" }, + }, + text_config = { colour = G.C.DARK_EDITION }, + reminder_text = { + { text = "(Sell)" }, + }, + calc_function = function(card) + local amount = (card.ability and card.ability.extra and card.ability.extra.amount) or 0 + card.joker_display_values.amount = math.floor(amount) + end, + } JokerDisplay.Definitions["j_cry_whip"] = { text = { { @@ -1291,7 +1313,7 @@ if JokerDisplay then { border_nodes = { { text = "X" }, - { ref_table = "card.ability.extra", ref_value = "x_chips", retrigger_type = "exp" }, + { ref_table = "card.joker_display_values", ref_value = "x_chips", retrigger_type = "exp" }, }, border_colour = G.C.CHIPS, }, @@ -1299,6 +1321,25 @@ if JokerDisplay then reminder_text = { { text = "(7,4)" }, }, + calc_function = function(card) + local count = 0 + local playing_hand = G.play and next(G.play.cards) + if not playing_hand then + local hand = G.hand and G.hand.highlighted + local text, _, scoring_hand = JokerDisplay.evaluate_hand(hand) + if text ~= "Unknown" and scoring_hand then + for _, scoring_card in pairs(scoring_hand) do + local rank = scoring_card:get_id() + if rank == 4 or rank == 7 then + count = count + JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) + end + end + end + end + local cur_xchips = (card.ability and card.ability.extra and card.ability.extra.x_chips) or 1 + local bonus = (card.ability and card.ability.extra and card.ability.extra.bonus) or 0.1 + card.joker_display_values.x_chips = cur_xchips + count * bonus + end, } JokerDisplay.Definitions["j_cry_caramel"] = { text = { @@ -1930,9 +1971,9 @@ if JokerDisplay then extra = { { { text = "(" }, - { ref_table = "G.GAME.probabilities", ref_value = "normal" }, --the usual thing doesn't work for some reason + { ref_table = "card.joker_display_values", ref_value = "odds" }, { text = " in " }, - { ref_table = "card.ability.extra", ref_value = "odds" }, + { ref_table = "card.joker_display_values", ref_value = "max_odds" }, { text = ")" }, }, }, @@ -1940,7 +1981,26 @@ if JokerDisplay then calc_function = function(card) local copied_joker, copied_debuff = JokerDisplay.calculate_blueprint_copy(card) card.joker_display_values.blueprint_compat = localize("k_incompatible") + local prev_loaded = card.joker_display_values.blueprint_ability_joker JokerDisplay.copy_display(card, copied_joker, copied_debuff) + if copied_joker and card.children.joker_display and not card.joker_display_values.blueprint_debuff then + if not card.joker_display_values.oldblueprint_extra_added or prev_loaded ~= copied_joker then + card.children.joker_display:add_extra({ + { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "odds" }, + { text = " in " }, + { ref_table = "card.ability.extra", ref_value = "odds" }, + { text = ")" }, + }, + }, { colour = G.C.GREEN, scale = 0.3 }, card) + card.joker_display_values.oldblueprint_extra_added = true + end + else + card.joker_display_values.oldblueprint_extra_added = false + end + card.joker_display_values.odds = G.GAME and G.GAME.probabilities.normal or 1 + card.joker_display_values.max_odds = (card.ability and card.ability.extra and card.ability.extra.odds) or 4 end, get_blueprint_joker = function(card) for i = 1, #G.jokers.cards do From 216e948f196eb4d7e5bf3dfe04d695225cbbc8d9 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sun, 16 Aug 2026 19:00:37 +0300 Subject: [PATCH 09/27] rework some displays --- items/joker_display.lua | 211 ++++++++++++++++++++++++++++++---------- 1 file changed, 160 insertions(+), 51 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 897289bfd..4ab95542d 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -12,11 +12,11 @@ -- Canvas -- Happy House -- Jimball --- ------ Need Rework -------- --- Queen's Gambit: show counter like with Seance --- ------ Unnecessary ------ +-- Queen's Gambit +-- -------- Unnecessary ------ -- Double Scale -- Maximized + --=============== Page 12 ===============-- -- ------- Implemented ------- -- Absurd Joker @@ -34,6 +34,7 @@ -- Subtle Joker -- Discreet Joker -- Kidnapping + --=============== Page 13 ===============-- -- ------- Implemented ------- -- Krusty the Clown @@ -52,6 +53,7 @@ -- ------ Unimplemented ------ -- Circus -- Booster Joker + --=============== Page 14 ===============-- -- ------- Implemented ------- -- Chili Pepper @@ -59,19 +61,19 @@ -- Morse Code -- Nostalgic Googol Play Card -- Old Membership Card --- ----- Need Rework --------- --- Bus Driver: show chances for each outcome --- Crypto Coin: add "sold Joker" or something like that below values +-- Bus Driver +-- Crypto Coin -- ------ Unimplemented ------ -- Blurred Joker -- Translucent Joker -- Sync Catalyst -- One for All -- RNJoker --- ------ Unnecessary -------- +-- -------- Unnecessary ------ -- Panopticon -- Labyrinth -- Kaleidoscope + --=============== Page 15 ===============-- -- ------- Implemented ------- -- Garden of Forking Paths @@ -85,13 +87,13 @@ -- Bonus Joker -- Supercell -- ...Like Antennas to Heaven --- ----- Need Rework --------- --- :D: Need to add "+Joker" above "Round" --- M Chain: rework description +-- :D +-- M Chain -- ------ Unimplemented ------ -- Jimbo-tron 9000 --- ----- Unnecessary --------- +-- -------- Unnecessary ------ -- Negative Joker + --=============== Page 16 ===============-- -- ------- Implemented ------- -- Fractal Fingers @@ -107,10 +109,10 @@ -- The Home -- The Nuts -- Old Blueprint --- ------ Need Rework -------- --- Consume-able: add "Consumable" text --- ------ Unnecessary -------- +-- Consume-able +-- -------- Unnecessary ------ -- SUS + --=============== Page 17 ===============-- -- ------- Implemented ------- -- Fridge Magnet @@ -129,6 +131,7 @@ -- Bonkers Joker -- ------ Unimplemented ------ -- Seal the Deal + --=============== Page 18 ===============-- -- ------- Implemented ------- -- Fucked-Up Joker @@ -147,6 +150,7 @@ -- The Complete and Utter Annihilation of Everything That Makes Balatro Sacred -- ------ Unimplemented ------ -- Universe + --=============== Page 19 ===============-- -- ------ Unimplemented ------ -- Exposed @@ -161,10 +165,11 @@ -- Zooble -- Chocolate Die -- Spectrogram --- ---- Unnecessary --------- +-- -------- Unnecessary ------ -- Astral in a Bottle -- Necromancer -- Cotton Candy + --=============== Page 20 ===============-- -- ------ Unimplemented ------ -- Kitty Printer @@ -182,6 +187,7 @@ -- Candy Dagger -- Broken Home -- Candy Cane + --=============== Page 21 ===============-- -- ------ Unimplemented ------ -- Yarn Ball @@ -198,8 +204,9 @@ -- Broken Sync Catalyst -- Thalia and Melpomeme -- Key Change --- ---- Unnecessary --------- +-- -------- Unnecessary ------ -- Candy Sticks + --=============== Page 22 ===============-- -- ------- Implemented ------- -- Fast Food M @@ -211,15 +218,15 @@ -- Sacrifice -- Reverse Card -- Notebook --- ------ Need Rework -------- --- Bubble M: add "+Jolly" text +-- Bubble M -- ------ Unimplemented ------ -- Emergency Chips -- Flesh Panopticon -- Wonka Bar --- ---- Unnecessary --------- +-- -------- Unnecessary ------ -- Buttercup --- M +-- M + --=============== Page 23 ===============-- -- ------- Implemented ------- -- Monster @@ -236,9 +243,10 @@ -- Demicolon -- Starfruit -- Project Sundial --- ---- Unnecessary ---------- +-- -------- Unnecessary ------ -- Code Joker -- Blender + --=============== Page 24 ===============-- -- ------- Implemented ------- -- Python @@ -251,22 +259,21 @@ -- Primus -- Ace Aequilibrium -- Facile --- ----- Need Rework -------- --- Circulus Pistoris: incorrect echips/emult visual display and needs to add active/inactive text --- ------ Unimplemented ----- +-- Circulus Pistoris +-- ------ Unimplemented ------ -- Scalae -- Universum --- ---- Unnecessary --------- +-- -------- Unnecessary ------ -- Speculo -- Effarcire + --=============== Page 25 ===============-- -- ------- Implemented ------- -- Non Verisimile -- Duplicare -- Formidiulosus -- Tredecim --- ------ Need Rework -------- --- Gemini: show what Joker it's doubling +-- Gemini -- ------ Unimplemented ------ -- Energia -- Caeruleum @@ -452,6 +459,10 @@ if JokerDisplay then end, } JokerDisplay.Definitions["j_cry_bubblem"] = { + text = { + { text = "+1 Jolly" }, + }, + text_config = { colour = G.C.DARK_EDITION }, reminder_text = { { text = "(" }, { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = G.C.ORANGE }, @@ -459,7 +470,8 @@ if JokerDisplay then }, reminder_text_config = { scale = 0.35 }, calc_function = function(card) - card.joker_display_values.localized_text = localize(card.ability.extra.type, "poker_hands") + local p_type = (card.ability and card.ability.extra and card.ability.extra.type) or "Three of a Kind" + card.joker_display_values.localized_text = localize(p_type, "poker_hands") end, } JokerDisplay.Definitions["j_cry_foodm"] = { @@ -1391,6 +1403,9 @@ if JokerDisplay then { ref_table = "card.ability.extra", ref_value = "money" }, }, text_config = { colour = G.C.GOLD }, + reminder_text = { + { text = "(Consumable)" }, + }, } JokerDisplay.Definitions["j_cry_weegaming"] = { retrigger_function = function(playing_card, scoring_hand, held_in_hand, joker_card) @@ -1586,6 +1601,10 @@ if JokerDisplay then end, } JokerDisplay.Definitions["j_cry_happy"] = { + text = { + { text = "+1 Joker" }, + }, + text_config = { colour = G.C.BLUE }, reminder_text = { { ref_table = "card.joker_display_values", ref_value = "localized_text" }, }, @@ -1792,22 +1811,44 @@ if JokerDisplay then } JokerDisplay.Definitions["j_cry_circulus_pistoris"] = { text = { - { text = "^", colour = G.C.CHIPS }, - { ref_table = "card.ability.extra", ref_value = "Echips", colour = G.C.CHIPS }, - { text = "^", colour = G.C.MULT }, - { ref_table = "card.ability.extra", ref_value = "Emult", colour = G.C.MULT }, - }, - extra = { - { - ref_table = "card.joker_display_values", - ref_value = "localized_text", - colour = G.C.UI.TEXT_INACTIVE, - scale = 0.3, + border_nodes = { + { text = "^" }, + { ref_table = "card.joker_display_values", ref_value = "e_chips", retrigger_type = "exp" }, + }, + border_colour = G.C.CHIPS, }, + { text = " " }, + { + border_nodes = { + { text = "^" }, + { ref_table = "card.joker_display_values", ref_value = "e_mult", retrigger_type = "exp" }, + }, + border_colour = G.C.DARK_EDITION, + }, + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "hands_req" }, + { text = " " }, + { ref_table = "card.joker_display_values", ref_value = "hands_text" }, + { text = ")" }, }, calc_function = function(card) - card.joker_display_values.localized_text = "(" .. localize("k_round") .. ")" + local hands_req = (card.ability and card.ability.extra and card.ability.extra.hands_remaining) or 3 + local hands_left = G.GAME and G.GAME.current_round and G.GAME.current_round.hands_left or 0 + local playing_hand = G.play and next(G.play.cards) + local is_active = (not playing_hand and hands_left == hands_req + 1) or (playing_hand and hands_left == hands_req) + local pi = math.pi + local is_oversat = (card.edition and (card.edition.cry_oversat or card.edition.key == "e_cry_oversat" or card.edition.type == "cry_oversat")) + or (Cryptid and Cryptid.safe_get and Cryptid.safe_get(card, "edition", "cry_oversat")) + if is_oversat then + pi = 2 * pi + end + card.joker_display_values.e_chips = is_active and pi or 1 + card.joker_display_values.e_mult = is_active and pi or 1 + card.joker_display_values.hands_req = hands_req + card.joker_display_values.hands_text = hands_req == 1 and localize("k_hand") or localize("k_hud_hands") end, } local hand_xmult_jd = { @@ -1940,12 +1981,18 @@ if JokerDisplay then text = { { text = "+$" }, { ref_table = "card.ability.extra", ref_value = "money" }, - { text = "-" }, - { ref_table = "card.joker_display_values", ref_value = "money" }, + { text = "-$" }, + { ref_table = "card.joker_display_values", ref_value = "max_money" }, }, text_config = { colour = G.C.GOLD }, + reminder_text = { + { text = "(sold Joker)" }, + }, calc_function = function(card) - card.joker_display_values.money = (card.ability.extra.money * 10) + local is_modest = Card.get_gameset and Card.get_gameset(card) == "modest" + local money_mod = is_modest and 4 or ((card.ability and card.ability.immutable and card.ability.immutable.money_mod) or 10) + local money = (card.ability and card.ability.extra and card.ability.extra.money) or 1 + card.joker_display_values.max_money = money * money_mod end, } @@ -2045,11 +2092,32 @@ if JokerDisplay then } JokerDisplay.Definitions["j_cry_busdriver"] = { text = { + { text = "(", colour = G.C.GREEN }, + { ref_table = "card.joker_display_values", ref_value = "odds_gain", colour = G.C.GREEN }, + { text = " in ", colour = G.C.GREEN }, + { ref_table = "card.joker_display_values", ref_value = "max_odds", colour = G.C.GREEN }, + { text = ") ", colour = G.C.GREEN }, { text = "+", colour = G.C.MULT }, - { ref_table = "card.ability.extra", ref_value = "mult", colour = G.C.MULT }, - { text = " or -", colour = G.C.MULT }, - { ref_table = "card.ability.extra", ref_value = "mult", colour = G.C.MULT }, + { ref_table = "card.ability.extra", ref_value = "mult", colour = G.C.MULT, retrigger_type = "mult" }, }, + extra = { + { + { text = "(", colour = G.C.GREEN }, + { ref_table = "card.joker_display_values", ref_value = "odds_loss", colour = G.C.GREEN }, + { text = " in ", colour = G.C.GREEN }, + { ref_table = "card.joker_display_values", ref_value = "max_odds", colour = G.C.GREEN }, + { text = ") ", colour = G.C.GREEN }, + { text = "-", colour = G.C.MULT }, + { ref_table = "card.ability.extra", ref_value = "mult", colour = G.C.MULT, retrigger_type = "mult" }, + }, + }, + calc_function = function(card) + local prob = G.GAME and G.GAME.probabilities.normal or 1 + local odds = (card.ability and card.ability.extra and card.ability.extra.odds) or 4 + card.joker_display_values.odds_gain = math.max(0, odds * prob - 1) + card.joker_display_values.odds_loss = 1 + card.joker_display_values.max_odds = odds * prob + end, } JokerDisplay.Definitions["j_cry_morse"] = { text = { @@ -2079,10 +2147,13 @@ if JokerDisplay then } JokerDisplay.Definitions["j_cry_cryptidmoment"] = { text = { - { text = "+" }, + { text = "+$" }, { ref_table = "card.ability.extra", ref_value = "money" }, }, - text_config = { colour = G.C.ORANGE }, + text_config = { colour = G.C.GOLD }, + reminder_text = { + { text = "(Sell Value)" }, + }, } JokerDisplay.Definitions["j_cry_copypaste"] = { extra = { @@ -2147,10 +2218,19 @@ if JokerDisplay then }, text_config = { colour = G.C.GREEN }, reminder_text = { - { ref_table = "card.joker_display_values", ref_value = "localized_text" }, + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "target_name", colour = G.C.ORANGE }, + { text = ")" }, }, calc_function = function(card) - card.joker_display_values.localized_text = "(" .. localize("k_round") .. ")" + local target = G.jokers and G.jokers.cards and G.jokers.cards[1] + if target and target ~= card and not (Card.no and Card.no(target, "immutable", true)) and not (target.config and target.config.center and target.config.center.immutable) then + local target_key = target.config and target.config.center and target.config.center.key + local target_name = target_key and localize({ type = "name_text", set = "Joker", key = target_key }) + card.joker_display_values.target_name = (target_name and target_name ~= "ERROR" and target_name) or (target.ability and target.ability.name) or "Joker" + else + card.joker_display_values.target_name = localize("k_incompatible") + end end, } JokerDisplay.Definitions["j_cry_oldinvisible"] = { @@ -2239,13 +2319,42 @@ if JokerDisplay then end, } JokerDisplay.Definitions["j_cry_queens_gambit"] = { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "count", retrigger_type = "mult" }, + }, + text_config = { colour = G.C.DARK_EDITION }, reminder_text = { { text = "(" }, { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = G.C.ORANGE }, { text = ")" }, }, - reminder_text_config = { scale = 0.35 }, calc_function = function(card) + local count = 0 + local hand = (G.play and next(G.play.cards)) and G.play.cards or (G.hand and G.hand.highlighted) + local text, poker_hands, scoring_hand = JokerDisplay.evaluate_hand(hand) + if text ~= "Unknown" and scoring_hand and #scoring_hand >= 5 then + local is_straight_flush = (text == "Straight Flush") or (poker_hands and poker_hands["Straight Flush"] and next(poker_hands["Straight Flush"])) + if is_straight_flush then + local min_rank = 10 + local has_queen = false + for _, scoring_card in pairs(scoring_hand) do + local id = scoring_card:get_id() + if id then + if id < min_rank then + min_rank = id + end + if id == 12 then + has_queen = true + end + end + end + if min_rank >= 10 and has_queen then + count = 1 + end + end + end + card.joker_display_values.count = count card.joker_display_values.localized_text = localize("Royal Flush", "poker_hands") end, } From 5e323afc025de2a6b31943367455ce606a208e20 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sun, 16 Aug 2026 19:18:40 +0300 Subject: [PATCH 10/27] update emult/echips visual --- items/joker_display.lua | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 4ab95542d..f8038daac 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -438,7 +438,7 @@ if JokerDisplay then retrigger_type = "exp", }, }, - border_colour = G.C.DARK_EDITION, + border_colour = G.C.emult or G.C.DARK_EDITION, }, }, reminder_text = { @@ -528,7 +528,7 @@ if JokerDisplay then end, }, }, - border_colour = G.C.DARK_EDITION, + border_colour = G.C.emult or G.C.DARK_EDITION, }, }, } @@ -1244,7 +1244,7 @@ if JokerDisplay then end, }, }, - border_colour = G.C.DARK_EDITION, + border_colour = G.C.emult or G.C.DARK_EDITION, }, }, reminder_text = { @@ -1493,7 +1493,7 @@ if JokerDisplay then end, }, }, - border_colour = G.C.DARK_EDITION, + border_colour = G.C.emult or G.C.DARK_EDITION, }, }, } @@ -1816,7 +1816,7 @@ if JokerDisplay then { text = "^" }, { ref_table = "card.joker_display_values", ref_value = "e_chips", retrigger_type = "exp" }, }, - border_colour = G.C.CHIPS, + border_colour = G.C.echips or G.C.CHIPS, }, { text = " " }, { @@ -1824,7 +1824,7 @@ if JokerDisplay then { text = "^" }, { ref_table = "card.joker_display_values", ref_value = "e_mult", retrigger_type = "exp" }, }, - border_colour = G.C.DARK_EDITION, + border_colour = G.C.emult or G.C.DARK_EDITION, }, }, reminder_text = { @@ -1948,7 +1948,7 @@ if JokerDisplay then { text = "^" }, { ref_table = "card.joker_display_values", ref_value = "e_mult", retrigger_type = "exp" }, }, - border_colour = G.C.DARK_EDITION, + border_colour = G.C.emult or G.C.DARK_EDITION, }, }, reminder_text = { @@ -2075,7 +2075,7 @@ if JokerDisplay then end, }, }, - border_colour = G.C.DARK_EDITION, + border_colour = G.C.emult or G.C.DARK_EDITION, }, }, reminder_text = { @@ -2247,7 +2247,7 @@ if JokerDisplay then { text = "^" }, { ref_table = "card.joker_display_values", ref_value = "Emult", retrigger_type = "exp" }, }, - border_colour = G.C.DARK_EDITION, + border_colour = G.C.emult or G.C.DARK_EDITION, }, }, calc_function = function(card) @@ -2385,7 +2385,7 @@ if JokerDisplay then end, }, }, - border_colour = G.C.DARK_EDITION, + border_colour = G.C.emult or G.C.DARK_EDITION, }, }, } From c681758089c411a4c1a53399c0594b4e57eee43f Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sun, 16 Aug 2026 19:47:00 +0300 Subject: [PATCH 11/27] implement jokers on page 13 --- items/joker_display.lua | 55 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index f8038daac..5ee997a9b 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -50,7 +50,6 @@ -- Meteor Shower -- Stardust -- Exoplanet --- ------ Unimplemented ------ -- Circus -- Booster Joker @@ -1227,6 +1226,60 @@ if JokerDisplay then }, }, } + JokerDisplay.Definitions["j_cry_circus"] = { + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "count", colour = G.C.ORANGE }, + { text = " Jokers)" }, + }, + calc_function = function(card) + local count = 0 + if G.jokers then + for _, joker_card in ipairs(G.jokers.cards) do + if joker_card ~= card and joker_card.config and joker_card.config.center then + local rarity = joker_card.config.center.rarity + local rarity_map = (card.ability and card.ability.immutable and card.ability.immutable.rarity_map) + or { [3] = "3_mult_mod", ["cry_epic"] = "cry_epic_mult_mod", [4] = "4_mult_mod", ["cry_exotic"] = "cry_exotic_mult_mod" } + local mod_key = rarity_map[rarity] + if mod_key and card.ability and card.ability.extra and card.ability.extra[mod_key] and to_big(card.ability.extra[mod_key]) > to_big(1) then + count = count + 1 + end + end + end + end + card.joker_display_values.count = count + end, + mod_function = function(card, mod_joker) + if card ~= mod_joker and card.config and card.config.center then + local rarity = card.config.center.rarity + local rarity_map = (mod_joker.ability and mod_joker.ability.immutable and mod_joker.ability.immutable.rarity_map) + or { [3] = "3_mult_mod", ["cry_epic"] = "cry_epic_mult_mod", [4] = "4_mult_mod", ["cry_exotic"] = "cry_exotic_mult_mod" } + local mod_key = rarity_map[rarity] + if mod_key and mod_joker.ability and mod_joker.ability.extra and mod_joker.ability.extra[mod_key] then + local xmult = mod_joker.ability.extra[mod_key] + if to_big(xmult) > to_big(1) then + return { x_mult = xmult ^ JokerDisplay.calculate_joker_triggers(mod_joker) } + end + end + end + return {} + end, + } + JokerDisplay.Definitions["j_cry_booster"] = { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "slots" }, + }, + text_config = { colour = G.C.DARK_EDITION }, + reminder_text = { + { text = "(Slots)" }, + }, + calc_function = function(card) + local max_slots = (card.ability and card.ability.immutable and card.ability.immutable.max_slots) or 25 + local slots = (card.ability and card.ability.extra and card.ability.extra.booster_slots) or 1 + card.joker_display_values.slots = math.min(max_slots, slots) + end, + } JokerDisplay.Definitions["j_cry_primus"] = { text = { { From d3d4228eea9d36ab78e4a18e638b1bd21e1d624b Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sun, 16 Aug 2026 20:17:00 +0300 Subject: [PATCH 12/27] implement jokers on page 14 and 15 --- items/joker_display.lua | 166 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 164 insertions(+), 2 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 5ee997a9b..4e784122a 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -62,13 +62,13 @@ -- Old Membership Card -- Bus Driver -- Crypto Coin --- ------ Unimplemented ------ -- Blurred Joker --- Translucent Joker -- Sync Catalyst -- One for All +-- ------ Unimplemented ------ -- RNJoker -- -------- Unnecessary ------ +-- Translucent Joker -- Panopticon -- Labyrinth -- Kaleidoscope @@ -1280,6 +1280,168 @@ if JokerDisplay then card.joker_display_values.slots = math.min(max_slots, slots) end, } + JokerDisplay.Definitions["j_cry_blurred"] = { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "extra_hands" }, + }, + text_config = { colour = G.C.BLUE }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = G.C.ORANGE }, + { text = ")" }, + }, + calc_function = function(card) + local max_hands = (card.ability and card.ability.immutable and card.ability.immutable.max_hand_size_mod) or 1000 + local extra = (card.ability and card.ability.extra and card.ability.extra.extra_hands) or 1 + card.joker_display_values.extra_hands = math.min(max_hands, extra) + card.joker_display_values.localized_text = localize("k_round") + end, + } + JokerDisplay.Definitions["j_cry_sync_catalyst"] = { + text = { + { text = "Balance", colour = G.C.DARK_EDITION }, + }, + } + JokerDisplay.Definitions["j_cry_soccer"] = { + text = { + { text = "+" }, + { ref_table = "card.ability.extra", ref_value = "holygrail" }, + }, + text_config = { colour = G.C.DARK_EDITION }, + reminder_text = { + { text = "(All Slots)" }, + }, + } + JokerDisplay.Definitions["j_cry_jtron"] = { + text = { + { + border_nodes = { + { text = "^" }, + { + ref_table = "card.ability.immutable", + ref_value = "current", + retrigger_type = function(number, triggers) + local num = number + for i = 1, triggers - 1 do + num = num ^ number + end + return num + end, + }, + }, + border_colour = G.C.emult or G.C.DARK_EDITION, + }, + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = G.C.ORANGE }, + { text = ")" }, + }, + calc_function = function(card) + local bonus = (card.ability and card.ability.extra and card.ability.extra.bonus) or 1 + local jokers = (G.jokers and SMODS.find_card and #SMODS.find_card("j_joker")) or 0 + if card.ability and card.ability.immutable then + card.ability.immutable.current = 1 + bonus * jokers + end + card.joker_display_values.localized_text = localize({ type = "name_text", set = "Joker", key = "j_joker" }) + end, + } + --[[ + JokerDisplay.Definitions["j_cry_rnjoker"] = { + text = { + { + border_nodes = { + { ref_table = "card.joker_display_values", ref_value = "prefix" }, + { ref_table = "card.joker_display_values", ref_value = "value" }, + }, + border_colour = G.C.DARK_EDITION, + }, + }, + reminder_text = { + { ref_table = "card.joker_display_values", ref_value = "reminder_text" }, + }, + calc_function = function(card) + local ability = card.ability and card.ability.abilities and card.ability.abilities[1] + if not ability then + card.joker_display_values.prefix = "" + card.joker_display_values.value = "" + card.joker_display_values.reminder_text = "" + return + end + + local val = card.ability.extra and card.ability.extra.value or ability.value or 0 + if ability.stat == "plus_mult" then + card.joker_display_values.prefix = "+" + card.joker_display_values.value = val + card.joker_display_values.reminder_text = "(Mult)" + elseif ability.stat == "plus_chips" then + card.joker_display_values.prefix = "+" + card.joker_display_values.value = val + card.joker_display_values.reminder_text = "(Chips)" + elseif ability.stat == "x_mult" then + card.joker_display_values.prefix = "X" + card.joker_display_values.value = val + card.joker_display_values.reminder_text = "(Mult)" + elseif ability.stat == "x_chips" then + card.joker_display_values.prefix = "X" + card.joker_display_values.value = val + card.joker_display_values.reminder_text = "(Chips)" + elseif ability.stat == "h_size" then + card.joker_display_values.prefix = "+" + card.joker_display_values.value = val + card.joker_display_values.reminder_text = "(Hand Size)" + elseif ability.stat == "money" then + card.joker_display_values.prefix = "+$" + card.joker_display_values.value = val + card.joker_display_values.reminder_text = "(Money)" + elseif ability.act then + if ability.act == "make_joker" then + card.joker_display_values.prefix = "+" + card.joker_display_values.value = 1 + card.joker_display_values.reminder_text = "(Joker)" + elseif ability.act == "make_tarot" then + card.joker_display_values.prefix = "+" + card.joker_display_values.value = val > 0 and val or 1 + card.joker_display_values.reminder_text = "(Tarot)" + elseif ability.act == "make_planet" then + card.joker_display_values.prefix = "+" + card.joker_display_values.value = val > 0 and val or 1 + card.joker_display_values.reminder_text = "(Planet)" + elseif ability.act == "make_spectral" then + card.joker_display_values.prefix = "+" + card.joker_display_values.value = 1 + card.joker_display_values.reminder_text = "(Spectral)" + elseif ability.act == "add_dollars" then + card.joker_display_values.prefix = "+$" + card.joker_display_values.value = val + card.joker_display_values.reminder_text = "(Dollars)" + end + else + card.joker_display_values.prefix = "" + card.joker_display_values.value = val + card.joker_display_values.reminder_text = "" + end + end, + mod_function = function(card, mod_joker) + local ability = mod_joker.ability and mod_joker.ability.abilities and mod_joker.ability.abilities[1] + if ability and ability.context == "other_joker" and card ~= mod_joker then + local val = mod_joker.ability.extra and mod_joker.ability.extra.value or ability.value or 0 + local triggers = JokerDisplay.calculate_joker_triggers(mod_joker) + if ability.stat == "plus_mult" then + return { mult = val * triggers } + elseif ability.stat == "plus_chips" then + return { chips = val * triggers } + elseif ability.stat == "x_mult" then + return { x_mult = val ^ triggers } + elseif ability.stat == "x_chips" then + return { x_chips = val ^ triggers } + end + end + return {} + end, + } + --]] JokerDisplay.Definitions["j_cry_primus"] = { text = { { From aef0b837c0561089ad3765dd9d5457fa2fbd07e1 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sun, 16 Aug 2026 20:41:29 +0300 Subject: [PATCH 13/27] Implement panopticon, labyrinth and seal the deal --- items/joker_display.lua | 59 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 4e784122a..567ea9d46 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -65,12 +65,12 @@ -- Blurred Joker -- Sync Catalyst -- One for All +-- Panopticon +-- Labyrinth -- ------ Unimplemented ------ -- RNJoker -- -------- Unnecessary ------ -- Translucent Joker --- Panopticon --- Labyrinth -- Kaleidoscope --=============== Page 15 ===============-- @@ -88,7 +88,6 @@ -- ...Like Antennas to Heaven -- :D -- M Chain --- ------ Unimplemented ------ -- Jimbo-tron 9000 -- -------- Unnecessary ------ -- Negative Joker @@ -128,7 +127,6 @@ -- The Unity -- The Swarm -- Bonkers Joker --- ------ Unimplemented ------ -- Seal the Deal --=============== Page 18 ===============-- @@ -280,6 +278,40 @@ if JokerDisplay then --Side note: I Don't think retrigger type exp gives a correct value with Emult jokers, but ehhhhh ig I can live with that (It's good enough) + -- Panopticon & Labyrinth calculation hooks + local orig_card_calc_jd = Card.calculate_joker_display + function Card:calculate_joker_display(...) + local temp_hands_played = G.GAME and G.GAME.current_round and G.GAME.current_round.hands_played + local temp_discards_used = G.GAME and G.GAME.current_round and G.GAME.current_round.discards_used + local temp_hands_left = G.GAME and G.GAME.current_round and G.GAME.current_round.hands_left + + local has_maze = G.jokers and SMODS.find_card and next(SMODS.find_card("j_cry_maze")) + local has_panopticon = G.jokers and SMODS.find_card and next(SMODS.find_card("j_cry_panopticon")) + + if G.GAME and G.GAME.current_round then + if has_maze then + G.GAME.current_round.hands_played = 0 + G.GAME.current_round.discards_used = 0 + end + if has_panopticon then + G.GAME.current_round.hands_left = (G.play and G.play.cards and next(G.play.cards)) and 0 or 1 + end + end + + local res = orig_card_calc_jd(self, ...) + + if G.GAME and G.GAME.current_round then + if temp_hands_played ~= nil then G.GAME.current_round.hands_played = temp_hands_played end + if temp_discards_used ~= nil then G.GAME.current_round.discards_used = temp_discards_used end + if temp_hands_left ~= nil then G.GAME.current_round.hands_left = temp_hands_left end + end + + return res + end + + JokerDisplay.Definitions["j_cry_panopticon"] = {} + JokerDisplay.Definitions["j_cry_maze"] = {} + --This is here so it shows up on the github symbol panel (easy to scroll to) local page1 = {} @@ -1442,6 +1474,25 @@ if JokerDisplay then end, } --]] + JokerDisplay.Definitions["j_cry_seal_the_deal"] = { + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "active_text" }, + { text = ")" }, + }, + calc_function = function(card) + local hands_left = G.GAME and G.GAME.current_round and G.GAME.current_round.hands_left or 0 + card.joker_display_values.is_active = (hands_left == 1 and not next(G.play.cards)) + or (hands_left == 0 and next(G.play.cards)) + or hands_left <= 0 + card.joker_display_values.active_text = localize("jdis_" .. (card.joker_display_values.is_active and "active" or "inactive")) + end, + style_function = function(card, text, reminder_text, extra) + if reminder_text and reminder_text.children and reminder_text.children[2] then + reminder_text.children[2].config.colour = card.joker_display_values.is_active and G.C.GREEN or G.C.UI.TEXT_INACTIVE + end + end, + } JokerDisplay.Definitions["j_cry_primus"] = { text = { { From b495c2bd1e5ea2eeb13aff1fda231aa4c0d97682 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sun, 16 Aug 2026 21:18:28 +0300 Subject: [PATCH 14/27] Implement mosaic, astral edition and Universe --- items/joker_display.lua | 71 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 567ea9d46..88934ec4b 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -145,7 +145,6 @@ -- The Clash -- The -- The Complete and Utter Annihilation of Everything That Makes Balatro Sacred --- ------ Unimplemented ------ -- Universe --=============== Page 19 ===============-- @@ -312,6 +311,25 @@ if JokerDisplay then JokerDisplay.Definitions["j_cry_panopticon"] = {} JokerDisplay.Definitions["j_cry_maze"] = {} + -- Cryptid Edition Definitions + JokerDisplay.Edition_Definitions = JokerDisplay.Edition_Definitions or {} + JokerDisplay.Edition_Definitions["e_cry_astral"] = { + condition_function = function(card) + return not card.debuff and card.edition and (card.edition.cry_astral or card.edition.key == "e_cry_astral" or card.edition.key == "astral") + end, + mod_function = function(card) + return { e_mult = (card.edition and card.edition.e_mult) or 1.1 } + end, + } + JokerDisplay.Edition_Definitions["e_cry_mosaic"] = { + condition_function = function(card) + return not card.debuff and card.edition and (card.edition.cry_mosaic or card.edition.key == "e_cry_mosaic" or card.edition.key == "mosaic") + end, + mod_function = function(card) + return { x_chips = (card.edition and card.edition.x_chips) or 2.5 } + end, + } + --This is here so it shows up on the github symbol panel (easy to scroll to) local page1 = {} @@ -2013,6 +2031,57 @@ if JokerDisplay then } end, } + JokerDisplay.Definitions["j_cry_universe"] = { + text = { + { + border_nodes = { + { text = "^" }, + { ref_table = "card.joker_display_values", ref_value = "emult", retrigger_type = "exp" }, + }, + border_colour = G.C.emult or G.C.DARK_EDITION, + }, + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = G.C.DARK_EDITION }, + { text = ")" }, + }, + calc_function = function(card) + local count = 0 + local playing_hand = next(G.play.cards) + local hand = next(G.play.cards) and G.play.cards or G.hand.highlighted + local text, _, scoring_hand = JokerDisplay.evaluate_hand(hand) + if text ~= "Unknown" then + for _, scoring_card in pairs(scoring_hand) do --Astral cards scored + if scoring_card.edition and scoring_card.edition.cry_astral == true then + count = count + JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) + end + end + end + for _, playing_card in ipairs(G.hand.cards) do --Astral cards held in hand + if playing_hand or not playing_card.highlighted then + if + not (playing_card.facing == "back") + and not playing_card.debuff + and playing_card.edition + and playing_card.edition.cry_astral == true + then + count = count + JokerDisplay.calculate_card_triggers(playing_card, nil, true) + end + end + end + card.joker_display_values.emult = (card.ability.extra.emult or 1.2) ^ count + card.joker_display_values.localized_text = + localize({ type = "name_text", set = "Edition", key = "e_cry_astral" }) + end, + mod_function = function(card, mod_joker) --Astral Jokers + return { + e_mult = (card ~= mod_joker and card.edition and card.edition.cry_astral == true) + and (mod_joker.ability.extra.emult ^ JokerDisplay.calculate_joker_triggers(mod_joker)) + or nil, + } + end, + } JokerDisplay.Definitions["j_cry_multjoker"] = { text = { { text = "+" }, From 81c6712e7505346fdb9458021363ceaeae212e19 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Mon, 17 Aug 2026 00:38:16 +0300 Subject: [PATCH 15/27] Implement Page 19 jokers in JokerDisplay --- items/joker_display.lua | 264 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 263 insertions(+), 1 deletion(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 88934ec4b..1d27edc65 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -148,7 +148,7 @@ -- Universe --=============== Page 19 ===============-- --- ------ Unimplemented ------ +-- ------- Implemented ------- -- Exposed -- Mask -- Tropical Smoothie @@ -2082,6 +2082,268 @@ if JokerDisplay then } end, } + JokerDisplay.Definitions["j_cry_exposed"] = { + retrigger_function = function(playing_card, scoring_hand, held_in_hand, joker_card) + if held_in_hand or (playing_card:is_face()) then + return 0 + end + return math.min(joker_card.ability.immutable.max_retriggers or 40, (joker_card.ability.extra and joker_card.ability.extra.retriggers) or 2) + * JokerDisplay.calculate_joker_triggers(joker_card) + end, + } + JokerDisplay.Definitions["j_cry_mask"] = { + retrigger_function = function(playing_card, scoring_hand, held_in_hand, joker_card) + if held_in_hand or (not playing_card:is_face()) then + return 0 + end + return math.min(joker_card.ability.immutable.max_retriggers or 40, (joker_card.ability.extra and joker_card.ability.extra.retriggers) or 3) + * JokerDisplay.calculate_joker_triggers(joker_card) + end, + } + JokerDisplay.Definitions["j_cry_tropical_smoothie"] = { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.ability", ref_value = "extra", retrigger_type = "exp" }, + }, + border_colour = G.C.DARK_EDITION, + }, + }, + reminder_text = { + { text = "(On Sell)" }, + }, + } + JokerDisplay.Definitions["j_cry_oil_lamp"] = { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.ability.extra", ref_value = "increase", retrigger_type = "exp" }, + }, + border_colour = G.C.DARK_EDITION, + }, + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "localized_text" }, + { text = ")" }, + }, + calc_function = function(card) + local other_joker = nil + if card.area and card.area.cards then + for i = 1, #card.area.cards do + if card.area.cards[i] == card then + other_joker = card.area.cards[i + 1] + break + end + end + end + local compatible = other_joker and other_joker ~= card and not other_joker.config.center.immutable + card.joker_display_values.compatible = compatible + local other_key = compatible and other_joker.config and other_joker.config.center and other_joker.config.center.key + card.joker_display_values.localized_text = other_key and localize({ type = "name_text", key = other_key, set = "Joker" }) or localize("k_incompatible") + end, + style_function = function(card, text, reminder_text, extra) + if reminder_text and reminder_text.children and reminder_text.children[2] then + reminder_text.children[2].config.colour = card.joker_display_values.compatible and G.C.GREEN or G.C.UI.TEXT_INACTIVE + end + end, + } + JokerDisplay.Definitions["j_cry_tax_fraud"] = { + text = { + { text = "+$" }, + { ref_table = "card.joker_display_values", ref_value = "dollars" }, + }, + text_config = { colour = G.C.GOLD }, + reminder_text = { + { ref_table = "card.joker_display_values", ref_value = "localized_text" }, + }, + calc_function = function(card) + local rentals = 0 + if Cryptid and Cryptid.advanced_find_joker then + rentals = #Cryptid.advanced_find_joker(nil, nil, nil, { "rental" }, true) + elseif G.jokers and G.jokers.cards then + for _, j in ipairs(G.jokers.cards) do + if j.ability and j.ability.rental then + rentals = rentals + 1 + end + end + end + card.joker_display_values.dollars = (card.ability.extra and card.ability.extra.money or 6) * rentals + card.joker_display_values.localized_text = "(" .. localize("k_round") .. ")" + end, + } + JokerDisplay.Definitions["j_cry_pity_prize"] = { + text = { + { text = "+1", colour = G.C.DARK_EDITION }, + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "active_text" }, + { text = ")" }, + }, + calc_function = function(card) + local is_in_booster = (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.PLANET_PACK + or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.STANDARD_PACK + or G.STATE == G.STATES.BUFFOON_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED + or (G.booster_pack and not G.booster_pack.REMOVED)) + card.joker_display_values.is_active = is_in_booster + card.joker_display_values.active_text = localize("jdis_" .. (card.joker_display_values.is_active and "active" or "inactive")) + end, + style_function = function(card, text, reminder_text, extra) + if reminder_text and reminder_text.children and reminder_text.children[2] then + reminder_text.children[2].config.colour = card.joker_display_values.is_active and G.C.GREEN or G.C.UI.TEXT_INACTIVE + end + end, + } + JokerDisplay.Definitions["j_cry_digitalhallucinations"] = { + extra = { + { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "odds" }, + { text = ")" }, + }, + }, + extra_config = { colour = G.C.GREEN, scale = 0.3 }, + calc_function = function(card) + local numerator, denominator = (G.GAME.probabilities.normal or 1), (card.ability and card.ability.odds or 2) + if SMODS then + numerator, denominator = SMODS.get_probability_vars(card, 1, denominator, "Digital Hallucinations") + end + card.joker_display_values.odds = localize({ type = "variable", key = "jdis_odds", vars = { numerator, denominator } }) + end, + } + JokerDisplay.Definitions["j_cry_arsonist"] = { + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "active_text" }, + { text = ")" }, + }, + calc_function = function(card) + local hand = next(G.play.cards) and G.play.cards or G.hand.highlighted + local text, _, _ = JokerDisplay.evaluate_hand(hand) + local is_full_house = text == "Full House" or text == "Flush House" + card.joker_display_values.is_active = is_full_house + card.joker_display_values.active_text = localize("jdis_" .. (card.joker_display_values.is_active and "active" or "inactive")) + end, + style_function = function(card, text, reminder_text, extra) + if reminder_text and reminder_text.children and reminder_text.children[2] then + reminder_text.children[2].config.colour = card.joker_display_values.is_active and G.C.GREEN or G.C.UI.TEXT_INACTIVE + end + end, + } + JokerDisplay.Definitions["j_cry_wrapped"] = { + text = { + { text = "+1", colour = G.C.FILTER }, + }, + reminder_text = { + { ref_table = "card.joker_display_values", ref_value = "rounds_remaining" }, + }, + calc_function = function(card) + local rounds_left = (card.ability and card.ability.extra and card.ability.extra.rounds) or 2 + local rounds_passed = math.max(0, 2 - rounds_left) + card.joker_display_values.rounds_remaining = "(" .. rounds_passed .. "/2)" + end, + } + JokerDisplay.Definitions["j_cry_zooble"] = { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "mult", retrigger_type = "mult" }, + }, + text_config = { colour = G.C.MULT }, + reminder_text = { + { text = "(No Straight)" }, + }, + calc_function = function(card) + local mult = (card.ability and card.ability.extra and card.ability.extra.mult) or 0 + local hand = next(G.play.cards) and G.play.cards or G.hand.highlighted + local text, _, scoring_hand = JokerDisplay.evaluate_hand(hand) + if text ~= "Unknown" and hand and #hand > 0 and not (next(G.play.cards)) then + local eval = evaluate_poker_hand(hand) + if not (eval and eval["Straight"] and next(eval["Straight"])) then + local unique_ranks = {} + for _, v in ipairs(scoring_hand) do + if not (SMODS.has_no_rank(v) and not v.vampired) then + local id = v:get_id() + if id then + unique_ranks[id] = true + end + end + end + local count = 0 + for _ in pairs(unique_ranks) do + count = count + 1 + end + if count >= 1 then + mult = mult + count * ((card.ability and card.ability.extra and card.ability.extra.a_mult) or 1) + end + end + end + card.joker_display_values.mult = mult + end, + } + JokerDisplay.Definitions["j_cry_chocolate_dice"] = { + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "event_text" }, + { text = ")" }, + }, + calc_function = function(card) + local roll = card.ability and card.ability.extra and card.ability.extra.roll or 0 + if roll == 0 then + card.joker_display_values.event_text = localize("k_none") + else + local ev_key = "ev_cry_choco" .. roll + local name = (G.localization and G.localization.descriptions and G.localization.descriptions.Other and G.localization.descriptions.Other[ev_key] and G.localization.descriptions.Other[ev_key].name) + or localize({ type = "name_text", set = "Other", key = ev_key }) + if name and name ~= "ERROR" then + local parsed = name:match(":%s*(.+)$") or name + card.joker_display_values.event_text = parsed + else + card.joker_display_values.event_text = "Event " .. roll + end + end + end, + } + JokerDisplay.Definitions["j_cry_spectrogram"] = { + text = { + { text = "x" }, + { ref_table = "card.joker_display_values", ref_value = "num_retriggers" }, + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "target_name" }, + { text = ")" }, + }, + calc_function = function(card) + local count = 0 + local hand = next(G.play.cards) and G.play.cards or G.hand.highlighted + local text, _, scoring_hand = JokerDisplay.evaluate_hand(hand) + if text ~= "Unknown" then + for _, scoring_card in pairs(scoring_hand) do + if scoring_card.config and scoring_card.config.center_key == "m_cry_echo" and not scoring_card.debuff then + count = count + 1 + end + end + end + local target = G.jokers and G.jokers.cards and G.jokers.cards[#G.jokers.cards] + local valid_target = target and target ~= card + local target_key = valid_target and target.config and target.config.center and target.config.center.key + card.joker_display_values.num_retriggers = count + card.joker_display_values.valid_target = valid_target + card.joker_display_values.target_name = target_key and localize({ type = "name_text", key = target_key, set = "Joker" }) or localize("k_none") + end, + style_function = function(card, text, reminder_text, extra) + if reminder_text and reminder_text.children and reminder_text.children[2] then + reminder_text.children[2].config.colour = card.joker_display_values.valid_target and G.C.DARK_EDITION or G.C.UI.TEXT_INACTIVE + end + end, + retrigger_joker_function = function(card, retrigger_joker) + local is_rightmost = G.jokers and G.jokers.cards and card == G.jokers.cards[#G.jokers.cards] and card ~= retrigger_joker + return is_rightmost and (retrigger_joker.joker_display_values.num_retriggers or 0) or 0 + end, + } JokerDisplay.Definitions["j_cry_multjoker"] = { text = { { text = "+" }, From 0e7d488d9be8731e7980a3017455f5747153223e Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Mon, 17 Aug 2026 18:44:37 +0300 Subject: [PATCH 16/27] change to orange color --- items/joker_display.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 1d27edc65..183f4f83b 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -1320,7 +1320,7 @@ if JokerDisplay then { text = "+" }, { ref_table = "card.joker_display_values", ref_value = "slots" }, }, - text_config = { colour = G.C.DARK_EDITION }, + text_config = { colour = G.C.ORANGE }, reminder_text = { { text = "(Slots)" }, }, @@ -2176,7 +2176,7 @@ if JokerDisplay then } JokerDisplay.Definitions["j_cry_pity_prize"] = { text = { - { text = "+1", colour = G.C.DARK_EDITION }, + { text = "+1", colour = G.C.ORANGE }, }, reminder_text = { { text = "(" }, From 6d6be4a1ea45546aeb26b48381118ab3ace0346b Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Mon, 17 Aug 2026 19:24:43 +0300 Subject: [PATCH 17/27] Implement Page 20 jokers in JokerDisplay --- items/joker_display.lua | 308 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 307 insertions(+), 1 deletion(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 183f4f83b..699b52594 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -167,7 +167,7 @@ -- Cotton Candy --=============== Page 20 ===============-- --- ------ Unimplemented ------ +-- ------- Implemented ------- -- Kitty Printer -- Clicked Cookie -- LeBaron James @@ -2344,6 +2344,312 @@ if JokerDisplay then return is_rightmost and (retrigger_joker.joker_display_values.num_retriggers or 0) or 0 end, } + JokerDisplay.Definitions["j_cry_kittyprinter"] = { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.ability.extra", ref_value = "Xmult", retrigger_type = "exp" }, + }, + }, + }, + } + JokerDisplay.Definitions["j_cry_clicked_cookie"] = { + text = { + { text = "+" }, + { ref_table = "card.ability.extra", ref_value = "chips", retrigger_type = "mult" }, + }, + text_config = { colour = G.C.CHIPS }, + } + JokerDisplay.Definitions["j_cry_lebaron_james"] = { + text = { + { text = "+" }, + { ref_table = "card.ability.immutable", ref_value = "added_h" }, + }, + text_config = { colour = G.C.ORANGE }, + reminder_text = { + { text = "(Kings)" }, + }, + } + JokerDisplay.Definitions["j_cry_huntingseason"] = { + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "active_text" }, + { text = ")" }, + }, + calc_function = function(card) + local hand = next(G.play.cards) and G.play.cards or G.hand.highlighted + card.joker_display_values.is_active = (hand and #hand == 3) + card.joker_display_values.active_text = localize("jdis_" .. (card.joker_display_values.is_active and "active" or "inactive")) + end, + style_function = function(card, text, reminder_text, extra) + if reminder_text and reminder_text.children and reminder_text.children[2] then + reminder_text.children[2].config.colour = card.joker_display_values.is_active and G.C.GREEN or G.C.UI.TEXT_INACTIVE + end + end, + } + JokerDisplay.Definitions["j_cry_trick_or_treat"] = { + text = { + { text = "+" }, + { ref_table = "card.ability.extra", ref_value = "num_candies" }, + }, + text_config = { colour = G.C.ORANGE }, + reminder_text = { + { text = "(On Sell)" }, + }, + extra = { + { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "odds" }, + { text = ")" }, + }, + }, + extra_config = { colour = G.C.GREEN, scale = 0.3 }, + calc_function = function(card) + local numerator, denominator = 3 * (G.GAME.probabilities.normal or 1), (card.ability and card.ability.extra and card.ability.extra.odds or 4) + if SMODS then + numerator, denominator = SMODS.get_probability_vars(card, 3, denominator, "Trick-or-Treat") + end + card.joker_display_values.odds = localize({ type = "variable", key = "jdis_odds", vars = { numerator, denominator } }) + end, + } + JokerDisplay.Definitions["j_cry_clockwork"] = { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.ability.extra", ref_value = "xmult", retrigger_type = "exp" }, + }, + }, + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "active_text" }, + { text = ")" }, + }, + calc_function = function(card) + local is_active = false + if card.config and card.config.center and card.config.center.loc_vars then + local res = card.config.center:loc_vars({}, card) + if res and res.vars then + for i = 1, 4 do + if res.vars[i] == localize("k_active_ex") then + is_active = true + break + end + end + end + end + card.joker_display_values.is_active = is_active + card.joker_display_values.active_text = localize("jdis_" .. (card.joker_display_values.is_active and "active" or "inactive")) + end, + style_function = function(card, text, reminder_text, extra) + if reminder_text and reminder_text.children and reminder_text.children[2] then + reminder_text.children[2].config.colour = card.joker_display_values.is_active and G.C.GREEN or G.C.UI.TEXT_INACTIVE + end + end, + } + JokerDisplay.Definitions["j_cry_candy_basket"] = { + text = { + { text = "+" }, + { ref_table = "card.ability.extra", ref_value = "candies" }, + }, + text_config = { colour = G.C.ORANGE }, + reminder_text = { + { text = "(On Sell)" }, + }, + } + JokerDisplay.Definitions["j_cry_blacklist"] = { + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "active_text" }, + { text = ")" }, + }, + calc_function = function(card) + local blacklist = false + local target_id = (card.ability and card.ability.extra and card.ability.extra.blacklist) or 14 + if G.play and G.play.cards then + for _, c in ipairs(G.play.cards) do + if c:get_id() == target_id then + blacklist = true + break + end + end + end + if not blacklist and G.hand and G.hand.cards then + for _, c in ipairs(G.hand.cards) do + if c:get_id() == target_id then + blacklist = true + break + end + end + end + card.joker_display_values.is_active = blacklist + card.joker_display_values.active_text = localize("jdis_" .. (card.joker_display_values.is_active and "active" or "inactive")) + end, + style_function = function(card, text, reminder_text, extra) + if reminder_text and reminder_text.children and reminder_text.children[2] then + reminder_text.children[2].config.colour = card.joker_display_values.is_active and G.C.RED or G.C.UI.TEXT_INACTIVE + end + end, + } + JokerDisplay.Definitions["j_cry_rotten_egg"] = { + text = { + { text = "-$" }, + { ref_table = "card.ability.extra", ref_value = "lose_money" }, + }, + text_config = { colour = G.C.GOLD }, + reminder_text = { + { ref_table = "card.joker_display_values", ref_value = "localized_text" }, + { ref_table = "card.joker_display_values", ref_value = "progress_text" }, + }, + calc_function = function(card) + card.joker_display_values.localized_text = "(" .. localize("k_round") .. ") " + local left = (card.ability and card.ability.extra and card.ability.extra.left_money) or 10 + local needed = (card.ability and card.ability.extra and card.ability.extra.needed_money) or 10 + card.joker_display_values.progress_text = "(" .. math.max(0, needed - left) .. "/$" .. needed .. ")" + end, + } + JokerDisplay.Definitions["j_cry_familiar_currency"] = { + text = { + { text = "+1", colour = G.C.ORANGE }, + { text = " (-$" }, + { ref_table = "card.ability", ref_value = "extra" }, + { text = ")" }, + }, + text_config = { colour = G.C.GOLD }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "localized_text" }, + { text = ")" }, + }, + calc_function = function(card) + card.joker_display_values.localized_text = localize("k_round") + end, + } + JokerDisplay.Definitions["j_cry_highfive"] = { + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "active_text" }, + { text = ")" }, + }, + calc_function = function(card) + local hand = next(G.play.cards) and G.play.cards or G.hand.highlighted + local text, _, scoring_hand = JokerDisplay.evaluate_hand(hand) + local active = false + if text ~= "Unknown" and scoring_hand and #scoring_hand > 0 then + local maximum = -1 + local fives = 0 + for _, v in ipairs(scoring_hand) do + if not (SMODS and SMODS.has_no_rank and SMODS.has_no_rank(v)) then + local id = v:get_id() + local rank_val = id == 14 and 1 or id + if rank_val == 5 then fives = fives + 1 end + if rank_val > maximum then maximum = rank_val end + end + end + if maximum == 5 and fives ~= #scoring_hand then + active = true + end + end + card.joker_display_values.is_active = active + card.joker_display_values.active_text = localize("jdis_" .. (card.joker_display_values.is_active and "active" or "inactive")) + end, + style_function = function(card, text, reminder_text, extra) + if reminder_text and reminder_text.children and reminder_text.children[2] then + reminder_text.children[2].config.colour = card.joker_display_values.is_active and G.C.GREEN or G.C.UI.TEXT_INACTIVE + end + end, + } + JokerDisplay.Definitions["j_cry_sock_and_sock"] = { + retrigger_function = function(playing_card, scoring_hand, held_in_hand, joker_card) + if held_in_hand or not (SMODS and SMODS.has_enhancement and SMODS.has_enhancement(playing_card, "m_cry_abstract")) then + return 0 + end + return math.min((joker_card.ability and joker_card.ability.immutable and joker_card.ability.immutable.max_retriggers) or 40, (joker_card.ability and joker_card.ability.extra and joker_card.ability.extra.retriggers) or 1) + * JokerDisplay.calculate_joker_triggers(joker_card) + end, + } + JokerDisplay.Definitions["j_cry_candy_dagger"] = { + text = { + { text = "+1", colour = G.C.ORANGE }, + }, + reminder_text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "target_name" }, + { text = ")" }, + }, + calc_function = function(card) + local other_joker = nil + if card.area and card.area.cards then + for i = 1, #card.area.cards do + if card.area.cards[i] == card then + other_joker = card.area.cards[i + 1] + break + end + end + end + local compatible = other_joker and other_joker ~= card and not (SMODS and SMODS.is_eternal and SMODS.is_eternal(other_joker)) + card.joker_display_values.compatible = compatible + local other_key = compatible and other_joker.config and other_joker.config.center and other_joker.config.center.key + card.joker_display_values.target_name = other_key and localize({ type = "name_text", key = other_key, set = "Joker" }) or localize("k_incompatible") + end, + style_function = function(card, text, reminder_text, extra) + if reminder_text and reminder_text.children and reminder_text.children[2] then + reminder_text.children[2].config.colour = card.joker_display_values.compatible and G.C.GREEN or G.C.UI.TEXT_INACTIVE + end + end, + } + JokerDisplay.Definitions["j_cry_brokenhome"] = { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.ability.extra", ref_value = "Xmult", retrigger_type = "exp" }, + }, + }, + }, + extra = { + { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "odds" }, + { text = ")" }, + }, + }, + extra_config = { colour = G.C.GREEN, scale = 0.3 }, + calc_function = function(card) + local numerator, denominator = (G.GAME.probabilities.normal or 1), (card.ability and card.ability.extra and card.ability.extra.odds or 4) + if SMODS then + numerator, denominator = SMODS.get_probability_vars(card, 1, denominator, "Broken Home") + end + card.joker_display_values.odds = localize({ type = "variable", key = "jdis_odds", vars = { numerator, denominator } }) + end, + } + JokerDisplay.Definitions["j_cry_candy_cane"] = { + text = { + { text = "+$" }, + { ref_table = "card.joker_display_values", ref_value = "dollars" }, + }, + text_config = { colour = G.C.GOLD }, + reminder_text = { + { ref_table = "card.joker_display_values", ref_value = "rounds_remaining" }, + }, + calc_function = function(card) + local hand = next(G.play.cards) and G.play.cards or G.hand.highlighted + local text, _, scoring_hand = JokerDisplay.evaluate_hand(hand) + local total_retriggers = 0 + if text ~= "Unknown" and scoring_hand then + for _, scoring_card in ipairs(scoring_hand) do + local triggers = JokerDisplay.calculate_card_triggers(scoring_card, scoring_hand) + total_retriggers = total_retriggers + math.max(0, triggers - 1) + end + end + local dollars_per = (card.ability and card.ability.extra and card.ability.extra.dollars) or 4 + card.joker_display_values.dollars = total_retriggers * dollars_per * JokerDisplay.calculate_joker_triggers(card) + local rounds_left = (card.ability and card.ability.extra and card.ability.extra.rounds) or 11 + card.joker_display_values.rounds_remaining = "(" .. rounds_left .. "/11)" + end, + } JokerDisplay.Definitions["j_cry_multjoker"] = { text = { { text = "+" }, From 56dff22c3a0cdffe4d1ef421449869d2bfe19654 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Mon, 17 Aug 2026 19:58:20 +0300 Subject: [PATCH 18/27] Implement Page 21 jokers in JokerDisplay --- items/joker_display.lua | 230 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 229 insertions(+), 1 deletion(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 699b52594..bebb0862b 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -185,7 +185,7 @@ -- Candy Cane --=============== Page 21 ===============-- --- ------ Unimplemented ------ +-- ------- Implemented ------- -- Yarn Ball -- Candy Buttons -- Pizza @@ -2650,6 +2650,234 @@ if JokerDisplay then card.joker_display_values.rounds_remaining = "(" .. rounds_left .. "/11)" end, } + JokerDisplay.Definitions["j_cry_yarnball"] = { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "odds" }, + }, + text_config = { colour = G.C.GREEN }, + reminder_text = { + { text = "(Cat Tags)" }, + }, + calc_function = function(card) + local highest_cat_lvl = 0 + if G.GAME and G.GAME.tags then + for _, tag in pairs(G.GAME.tags) do + local lvl = tag.ability and tag.ability.level + if highest_cat_lvl < 1 and tag.key == "tag_cry_cat" then + highest_cat_lvl = 1 + end + if lvl and lvl > highest_cat_lvl then + highest_cat_lvl = lvl + end + end + end + card.joker_display_values.odds = highest_cat_lvl + end, + } + JokerDisplay.Definitions["j_cry_candy_buttons"] = { + reminder_text = { + { ref_table = "card.joker_display_values", ref_value = "rounds_remaining" }, + }, + calc_function = function(card) + local rerolls_left = (card.ability and card.ability.extra and card.ability.extra.rerolls) or 15 + card.joker_display_values.rounds_remaining = "(" .. rerolls_left .. "/15)" + end, + } + JokerDisplay.Definitions["j_cry_pizza"] = { + text = { + { text = "+" }, + { ref_table = "card.ability.extra", ref_value = "slices" }, + }, + text_config = { colour = G.C.ORANGE }, + reminder_text = { + { text = "(On Sell) " }, + { ref_table = "card.joker_display_values", ref_value = "rounds_remaining" }, + }, + calc_function = function(card) + local rounds_left = (card.ability and card.ability.extra and card.ability.extra.rounds_left) or 3 + local rounds_needed = (card.ability and card.ability.extra and card.ability.extra.rounds_needed) or 3 + card.joker_display_values.rounds_remaining = "(" .. math.max(0, rounds_needed - rounds_left) .. "/" .. rounds_needed .. ")" + end, + } + JokerDisplay.Definitions["j_cry_pizza_slice"] = { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.ability.extra", ref_value = "xmult", retrigger_type = "exp" }, + }, + }, + }, + } + JokerDisplay.Definitions["j_cry_jawbreaker"] = { + text = { + { + border_nodes = { + { text = "X2" }, + }, + border_colour = G.C.DARK_EDITION, + }, + }, + reminder_text = { + { text = "(Adjacent) " }, + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "active_text" }, + { text = ")" }, + }, + calc_function = function(card) + local is_boss = G.GAME and G.GAME.blind and Cryptid.is_boss_blind(G.GAME.blind) + card.joker_display_values.is_active = is_boss + card.joker_display_values.active_text = localize("jdis_" .. (card.joker_display_values.is_active and "active" or "inactive")) + end, + style_function = function(card, text, reminder_text, extra) + if reminder_text and reminder_text.children and reminder_text.children[3] then + reminder_text.children[3].config.colour = card.joker_display_values.is_active and G.C.GREEN or G.C.UI.TEXT_INACTIVE + end + end, + } + JokerDisplay.Definitions["j_cry_paved_joker"] = { + text = { + { text = "+" }, + { ref_table = "card.ability", ref_value = "extra" }, + }, + text_config = { colour = G.C.ORANGE }, + reminder_text = { + { text = "(Stone Fills)" }, + }, + } + JokerDisplay.Definitions["j_cry_mellowcreme"] = { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.ability.extra", ref_value = "sell_mult", retrigger_type = "exp" }, + }, + border_colour = G.C.DARK_EDITION, + }, + }, + reminder_text = { + { text = "(On Sell)" }, + }, + } + JokerDisplay.Definitions["j_cry_fading_joker"] = { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.ability.extra", ref_value = "xmult", retrigger_type = "exp" }, + }, + }, + }, + } + JokerDisplay.Definitions["j_cry_brittle"] = { + text = { + { text = "Enhance", colour = G.C.FILTER }, + }, + reminder_text = { + { ref_table = "card.joker_display_values", ref_value = "rounds_remaining" }, + }, + calc_function = function(card) + local rounds_left = (card.ability and card.ability.extra and card.ability.extra.rounds) or 9 + card.joker_display_values.rounds_remaining = "(" .. rounds_left .. "/9)" + end, + } + JokerDisplay.Definitions["j_cry_poor_joker"] = { + text = { + { text = "+" }, + { ref_table = "card.ability.extra", ref_value = "mult", retrigger_type = "mult" }, + }, + text_config = { colour = G.C.MULT }, + } + JokerDisplay.Definitions["j_cry_monopoly_money"] = { + extra = { + { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "odds" }, + { text = ")" }, + }, + }, + extra_config = { colour = G.C.GREEN, scale = 0.3 }, + calc_function = function(card) + local numerator, denominator = (G.GAME.probabilities.normal or 1), (card.ability and card.ability.extra and card.ability.extra.odds or 4) + if SMODS then + numerator, denominator = SMODS.get_probability_vars(card, 1, denominator, "Monopoly Money") + end + card.joker_display_values.odds = localize({ type = "variable", key = "jdis_odds", vars = { numerator, denominator } }) + end, + } + JokerDisplay.Definitions["j_cry_broken_sync_catalyst"] = { + text = { + { ref_table = "card.joker_display_values", ref_value = "chips_percent", colour = G.C.CHIPS }, + { text = " / " }, + { ref_table = "card.joker_display_values", ref_value = "mult_percent", colour = G.C.MULT }, + }, + reminder_text = { + { text = "(Swap)" }, + }, + calc_function = function(card) + local portion_chips = (card.ability and card.ability.extra and (card.ability.extra.chips_portion or card.ability.extra.portion)) or 0.1 + local portion_mult = (card.ability and card.ability.extra and (card.ability.extra.mult_portion or card.ability.extra.portion)) or 0.1 + local chips_pct = math.floor(Cryptid.clamp(portion_chips * 100, 0, 100) + 0.5) + local mult_pct = math.floor(Cryptid.clamp(portion_mult * 100, 0, 100) + 0.5) + card.joker_display_values.chips_percent = chips_pct .. "%" + card.joker_display_values.mult_percent = mult_pct .. "%" + end, + } + JokerDisplay.Definitions["j_cry_thalia"] = { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.joker_display_values", ref_value = "x_mult", retrigger_type = "exp" }, + }, + }, + }, + calc_function = function(card) + local x_mult = 1 + if card.config and card.config.center and card.config.center.calc_xmult then + x_mult = card.config.center:calc_xmult(card) + else + local seen = {} + local n = 0 + if G.jokers and G.jokers.cards then + for _, c in ipairs(G.jokers.cards) do + local r = c.config and c.config.center and c.config.center.rarity + if r and not seen[r] then + seen[r] = true + n = n + 1 + end + end + end + local bonus = (n * (n - 1)) / 2 + x_mult = bonus >= 1 and (bonus * ((card.ability and card.ability.extra and card.ability.extra.xmgain) or 1)) or 1 + end + card.joker_display_values.x_mult = x_mult + end, + } + JokerDisplay.Definitions["j_cry_keychange"] = { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.joker_display_values", ref_value = "x_mult", retrigger_type = "exp" }, + }, + }, + }, + reminder_text = { + { text = "(First Hand)" }, + }, + calc_function = function(card) + local hand = next(G.play.cards) and G.play.cards or G.hand.highlighted + local text, _, _ = JokerDisplay.evaluate_hand(hand) + local xm = (card.ability and card.ability.extra and card.ability.extra.xm) or 1 + if text ~= "Unknown" and G.GAME and G.GAME.hands and G.GAME.hands[text] and G.GAME.hands[text].played_this_round < 1 then + xm = xm + ((card.ability and card.ability.extra and card.ability.extra.xmgain) or 0.25) + end + card.joker_display_values.x_mult = xm + end, + } + JokerDisplay.Definitions["j_cry_candy_sticks"] = {} JokerDisplay.Definitions["j_cry_multjoker"] = { text = { { text = "+" }, From fa8142deb02859a74d317ac784530ae47a8f3637 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Mon, 17 Aug 2026 20:21:39 +0300 Subject: [PATCH 19/27] Implement Page 22 remaining jokers in JokerDisplay --- items/joker_display.lua | 47 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index bebb0862b..bc1d5d2b5 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -215,7 +215,6 @@ -- Reverse Card -- Notebook -- Bubble M --- ------ Unimplemented ------ -- Emergency Chips -- Flesh Panopticon -- Wonka Bar @@ -2878,6 +2877,52 @@ if JokerDisplay then end, } JokerDisplay.Definitions["j_cry_candy_sticks"] = {} + JokerDisplay.Definitions["j_cry_emergencychips"] = { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "percent" }, + }, + text_config = { colour = G.C.CHIPS }, + reminder_text = { + { text = "(On Sell)" }, + }, + calc_function = function(card) + local mult = (card.ability and card.ability.immutable and card.ability.immutable.blind_mult) or 0.2 + card.joker_display_values.percent = math.floor(mult * 100 + 0.5) .. "%" + end, + } + JokerDisplay.Definitions["j_cry_fleshpanopticon"] = { + text = { + { text = "+1 Gateway" }, + }, + text_config = { colour = G.C.SECONDARY_SET.Spectral }, + reminder_text = { + { text = "(On Boss Blind defeat)" }, + }, + extra = { + { + { text = "X", colour = G.C.RED }, + { ref_table = "card.joker_display_values", ref_value = "blind_size", colour = G.C.RED }, + { text = " Blind" }, + }, + }, + calc_function = function(card) + local is_boss = G.GAME and G.GAME.blind and Cryptid.is_boss_blind(G.GAME.blind) + local boss_size = (card.ability and card.ability.extra and card.ability.extra.boss_size) or 20 + card.joker_display_values.blind_size = is_boss and boss_size or 1 + end, + } + JokerDisplay.Definitions["j_cry_wonka_bar"] = { + text = { + { text = "+" }, + { ref_table = "card.ability", ref_value = "extra" }, + { text = " Limit" }, + }, + text_config = { colour = G.C.ORANGE }, + reminder_text = { + { text = "(On Sell)" }, + }, + } JokerDisplay.Definitions["j_cry_multjoker"] = { text = { { text = "+" }, From 8dc40f166aa87974127fa84951b784b1c3da6405 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Mon, 17 Aug 2026 20:46:00 +0300 Subject: [PATCH 20/27] Implement Page 23 remaining jokers in JokerDisplay --- items/joker_display.lua | 116 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index bc1d5d2b5..b0719e4d1 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -232,7 +232,6 @@ -- Copy/Paste -- Cut -- Megg --- ------ Unimplemented ------ -- Macabre Joker -- Doodle M -- Demicolon @@ -2923,6 +2922,121 @@ if JokerDisplay then { text = "(On Sell)" }, }, } + JokerDisplay.Definitions["j_cry_macabre"] = { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "count", colour = G.C.ORANGE }, + { text = " Jolly", colour = G.C.BLUE }, + }, + reminder_text = { + { text = "(Setting Blind)" }, + }, + calc_function = function(card) + local count = 0 + if G.jokers and G.jokers.cards then + for _, v in ipairs(G.jokers.cards) do + if + v ~= card + and not (v.is_jolly and v:is_jolly()) + and v.config and v.config.center and v.config.center.key ~= "j_cry_mprime" + and not ( + (SMODS and SMODS.is_eternal and SMODS.is_eternal(v)) + or v.getting_sliced + or (Cryptid and Cryptid.safe_get and Cryptid.safe_get(v.config.center, "pools", "M")) + ) + then + count = count + 1 + end + end + end + local add = (card.ability and card.ability.extra and card.ability.extra.add) or 1 + local max_spawn = (card.ability and card.ability.immutable and card.ability.immutable.max_spawn) or 15 + card.joker_display_values.count = math.min(max_spawn, count * add) + end, + } + JokerDisplay.Definitions["j_cry_doodlem"] = { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "count", colour = G.C.ORANGE }, + { text = " Consumables" }, + }, + reminder_text = { + { text = "(Setting Blind)" }, + }, + calc_function = function(card) + local init = (card.ability and card.ability.extra and card.ability.extra.init) or 2 + local add = (card.ability and card.ability.extra and card.ability.extra.add) or 1 + local max_jollies = (card.ability and card.ability.immutable and card.ability.immutable.max_jollies) or 25 + local jollycount = init + if G.jokers and G.jokers.cards then + for _, v in ipairs(G.jokers.cards) do + if v.is_jolly and v:is_jolly() then + jollycount = jollycount + add + end + end + end + card.joker_display_values.count = math.min(max_jollies, jollycount) + end, + } + JokerDisplay.Definitions["j_cry_demicolon"] = { + text = { + { text = "(" }, + { ref_table = "card.joker_display_values", ref_value = "target_name" }, + { text = ")" }, + }, + reminder_text = { + { text = "(Force-trigger)" }, + }, + calc_function = function(card) + local other_joker = nil + if card.area and card.area.cards then + for i = 1, #card.area.cards do + if card.area.cards[i] == card then + other_joker = card.area.cards[i + 1] + break + end + end + end + local compatible = false + if other_joker and other_joker ~= card then + if Cryptid and Cryptid.demicolonGetTriggerable then + local m = Cryptid.demicolonGetTriggerable(other_joker) + compatible = m[1] and not m[2] + else + compatible = other_joker.config and other_joker.config.center and (other_joker.config.center.demicoloncompat == true or other_joker.config.center.demicoloncompat == nil) + end + end + card.joker_display_values.compatible = compatible + local other_key = other_joker and other_joker.config and other_joker.config.center and other_joker.config.center.key + card.joker_display_values.target_name = (compatible and other_key and localize({ type = "name_text", key = other_key, set = "Joker" })) or localize("k_incompatible") + end, + style_function = function(card, text, reminder_text, extra) + if text and text.children and text.children[2] then + text.children[2].config.colour = card.joker_display_values.compatible and G.C.GREEN or G.C.UI.TEXT_INACTIVE + end + end, + } + JokerDisplay.Definitions["j_cry_starfruit"] = { + text = { + { + border_nodes = { + { text = "^" }, + { ref_table = "card.ability", ref_value = "emult", retrigger_type = "exp" }, + }, + border_colour = G.C.emult or G.C.DARK_EDITION, + }, + }, + reminder_text = { + { text = "(-0.2/Reroll)" }, + }, + } + JokerDisplay.Definitions["j_cry_sundial"] = { + reminder_text = { + { text = "(On Sell) (" }, + { ref_table = "card.ability.extra", ref_value = "handleft" }, + { text = "/12)" }, + }, + } JokerDisplay.Definitions["j_cry_multjoker"] = { text = { { text = "+" }, From 0efdf1f48f5bf2a01092bc18c99e4da29f127420 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Mon, 17 Aug 2026 21:30:13 +0300 Subject: [PATCH 21/27] Implement Page 24 and Page 25 Jokers (Scalae, Universum, Energia, Caeruleum) --- items/joker_display.lua | 176 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 174 insertions(+), 2 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index b0719e4d1..7623aa8b4 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -254,7 +254,6 @@ -- Ace Aequilibrium -- Facile -- Circulus Pistoris --- ------ Unimplemented ------ -- Scalae -- Universum -- -------- Unnecessary ------ @@ -268,7 +267,6 @@ -- Formidiulosus -- Tredecim -- Gemini --- ------ Unimplemented ------ -- Energia -- Caeruleum @@ -3695,6 +3693,180 @@ if JokerDisplay then JokerDisplay.Definitions["j_cry_many_lost_minds"] = hand_tchips_jd JokerDisplay.Definitions["j_cry_annihalation"] = hand_emult_jd + JokerDisplay.Definitions["j_cry_Scalae"] = { + text = { + { text = "Degree-" }, + { ref_table = "card.ability.extra", ref_value = "scale", colour = G.C.ORANGE }, + }, + reminder_text = { + { text = "(Scaling)" }, + }, + } + JokerDisplay.Definitions["j_cry_scalae"] = JokerDisplay.Definitions["j_cry_Scalae"] + JokerDisplay.Definitions["j_cry_universum"] = { + text = { + { + border_nodes = { + { text = "X" }, + { ref_table = "card.ability", ref_value = "extra" }, + { text = " Levels" }, + }, + border_colour = G.C.DARK_EDITION, + }, + }, + } + JokerDisplay.Definitions["j_cry_energia"] = { + text = { + { text = "+" }, + { ref_table = "card.joker_display_values", ref_value = "tags", colour = G.C.ORANGE }, + { text = " Tags" }, + }, + reminder_text = { + { text = "(Tag Added)" }, + }, + calc_function = function(card) + local max_tags = (card.ability and card.ability.immutable and card.ability.immutable.max_tags) or 40 + local tags = (card.ability and card.ability.extra and card.ability.extra.tags) or 1 + card.joker_display_values.tags = math.min(max_tags, tags) + end, + } + JokerDisplay.Definitions["j_cry_caeruleum"] = {} + + -- Caeruleum JokerDisplay Hooks: + -- Caeruleum has no text box of its own, but dynamically promotes adjacent Chips Jokers in real-time + -- (+Chips -> XChips border badge, XChips -> ^Chips E-Chips border badge). + + -- Checks if a given card is directly adjacent to Caeruleum in G.jokers + local function check_caeruleum_adjacent(card) + if not G.jokers or not G.jokers.cards then return false end + for i = 1, #G.jokers.cards do + if G.jokers.cards[i] == card then + local left = G.jokers.cards[i - 1] + local right = G.jokers.cards[i + 1] + if (left and left.config and left.config.center and left.config.center.key == "j_cry_caeruleum") + or (right and right.config and right.config.center and right.config.center.key == "j_cry_caeruleum") then + return true + end + break + end + end + return false + end + + -- Transforms flat/bordered chip definition nodes into their next hyperoperation tier + local function promote_chips_text(orig_text) + if not orig_text then return nil end + local new_text = copy_table(orig_text) + + -- Check if orig_text contains border_nodes with X (promoting Xchips -> ^chips) + local has_border_x = false + for _, node in ipairs(new_text) do + if node.border_nodes then + for _, bn in ipairs(node.border_nodes) do + if bn.text == "X" then + has_border_x = true + bn.text = "^" + end + end + if has_border_x then + node.border_colour = G.C.echips or G.C.CHIPS + end + end + end + + if has_border_x then + return new_text + end + + -- Otherwise, promote flat +chips (or flat X) into a bordered badge + local val_nodes = {} + local is_plus = false + for _, node in ipairs(new_text) do + if node.text == "+" then + is_plus = true + elseif node.text == "X" then + is_plus = false + else + local n = copy_table(node) + n.retrigger_type = "exp" + val_nodes[#val_nodes + 1] = n + end + end + + local border_col = is_plus and G.C.CHIPS or (G.C.echips or G.C.CHIPS) + local border_char = is_plus and "X" or "^" + local bordered = { + { + border_nodes = { + { text = border_char }, + }, + border_colour = border_col, + } + } + for _, vn in ipairs(val_nodes) do + table.insert(bordered[1].border_nodes, vn) + end + return bordered + end + + -- Intercepts Card:initialize_joker_display to apply promoted chips text/badges when adjacent to Caeruleum + local card_init_jd_ref = Card.initialize_joker_display + function Card:initialize_joker_display(custom_parent, stop_calc) + local is_adj = check_caeruleum_adjacent(self) + local orig_def = self.config and self.config.center and JokerDisplay.Definitions[self.config.center.key] + local modified = false + local saved_text = nil + local saved_text_config = nil + + if is_adj and orig_def and orig_def.text then + local is_chips = (orig_def.text_config and orig_def.text_config.colour == G.C.CHIPS) + if not is_chips then + for _, node in ipairs(orig_def.text) do + if node.colour == G.C.CHIPS or node.border_colour == G.C.CHIPS then + is_chips = true + break + end + if node.border_nodes then + for _, bn in ipairs(node.border_nodes) do + if bn.colour == G.C.CHIPS or bn.border_colour == G.C.CHIPS then + is_chips = true + break + end + end + end + end + end + + if is_chips then + saved_text = orig_def.text + saved_text_config = orig_def.text_config + orig_def.text = promote_chips_text(orig_def.text) + orig_def.text_config = nil + modified = true + end + end + + card_init_jd_ref(self, custom_parent, stop_calc) + + if modified and saved_text then + orig_def.text = saved_text + orig_def.text_config = saved_text_config + end + end + + -- Intercepts Card:update to detect position changes next to Caeruleum and trigger reload + local card_update_ref = Card.update + function Card:update(dt) + card_update_ref(self, dt) + if self.ability and self.children and (self.children.joker_display or self.children.joker_display_small) then + local is_adj = check_caeruleum_adjacent(self) + if is_adj ~= self._cry_caer_adj then + self._cry_caer_adj = is_adj + self:update_joker_display(false, true, "Caeruleum") + end + end + end + --end of Jokerdisplays end From 12f8ec192a2fe44af92f5aa03fc0395806a957d7 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Mon, 17 Aug 2026 21:33:59 +0300 Subject: [PATCH 22/27] Clean up the page comments --- items/joker_display.lua | 72 +++++++++-------------------------------- 1 file changed, 15 insertions(+), 57 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 7623aa8b4..12d9a3ad9 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -1,5 +1,4 @@ ---=============== Page 11 ===============-- --- ------- Implemented ------- +--=============== Page 1 ===============-- -- m -- Dropshot -- Cursor @@ -13,12 +12,8 @@ -- Happy House -- Jimball -- Queen's Gambit --- -------- Unnecessary ------ --- Double Scale --- Maximized ---=============== Page 12 ===============-- --- ------- Implemented ------- +--=============== Page 2 ===============-- -- Absurd Joker -- Nutty Joker -- Manic Joker @@ -35,8 +30,7 @@ -- Discreet Joker -- Kidnapping ---=============== Page 13 ===============-- --- ------- Implemented ------- +--=============== Page 3 ===============-- -- Krusty the Clown -- Boredom -- Membership Card @@ -53,8 +47,7 @@ -- Circus -- Booster Joker ---=============== Page 14 ===============-- --- ------- Implemented ------- +--=============== Page 4 ===============-- -- Chili Pepper -- Monkey Dagger -- Morse Code @@ -67,14 +60,8 @@ -- One for All -- Panopticon -- Labyrinth --- ------ Unimplemented ------ --- RNJoker --- -------- Unnecessary ------ --- Translucent Joker --- Kaleidoscope ---=============== Page 15 ===============-- --- ------- Implemented ------- +--=============== Page 5 ===============-- -- Garden of Forking Paths -- Light Up the Night -- ERROR @@ -89,11 +76,8 @@ -- :D -- M Chain -- Jimbo-tron 9000 --- -------- Unnecessary ------ --- Negative Joker ---=============== Page 16 ===============-- --- ------- Implemented ------- +--=============== Page 6 ===============-- -- Fractal Fingers -- Fidget Spinner -- Nostalgic Invisible Joker @@ -108,11 +92,8 @@ -- The Nuts -- Old Blueprint -- Consume-able --- -------- Unnecessary ------ --- SUS ---=============== Page 17 ===============-- --- ------- Implemented ------- +--=============== Page 7 ===============-- -- Fridge Magnet -- Red Bloon -- Weebonacci @@ -129,8 +110,7 @@ -- Bonkers Joker -- Seal the Deal ---=============== Page 18 ===============-- --- ------- Implemented ------- +--=============== Page 8 ===============-- -- Fucked-Up Joker -- Foolhardy Joker -- Undefined Joker @@ -147,8 +127,7 @@ -- The Complete and Utter Annihilation of Everything That Makes Balatro Sacred -- Universe ---=============== Page 19 ===============-- --- ------- Implemented ------- +--=============== Page 9 ===============-- -- Exposed -- Mask -- Tropical Smoothie @@ -161,13 +140,8 @@ -- Zooble -- Chocolate Die -- Spectrogram --- -------- Unnecessary ------ --- Astral in a Bottle --- Necromancer --- Cotton Candy ---=============== Page 20 ===============-- --- ------- Implemented ------- +--=============== Page 10 ===============-- -- Kitty Printer -- Clicked Cookie -- LeBaron James @@ -184,8 +158,7 @@ -- Broken Home -- Candy Cane ---=============== Page 21 ===============-- --- ------- Implemented ------- +--=============== Page 11 ===============-- -- Yarn Ball -- Candy Buttons -- Pizza @@ -200,11 +173,8 @@ -- Broken Sync Catalyst -- Thalia and Melpomeme -- Key Change --- -------- Unnecessary ------ --- Candy Sticks ---=============== Page 22 ===============-- --- ------- Implemented ------- +--=============== Page 12 ===============-- -- Fast Food M -- M Stack -- Neon M @@ -218,12 +188,8 @@ -- Emergency Chips -- Flesh Panopticon -- Wonka Bar --- -------- Unnecessary ------ --- Buttercup --- M ---=============== Page 23 ===============-- --- ------- Implemented ------- +--=============== Page 13 ===============-- -- Monster -- Tiny -- Virgo @@ -237,12 +203,8 @@ -- Demicolon -- Starfruit -- Project Sundial --- -------- Unnecessary ------ --- Code Joker --- Blender ---=============== Page 24 ===============-- --- ------- Implemented ------- +--=============== Page 14 ===============-- -- Python -- Iterum -- Stella Mortis @@ -256,12 +218,8 @@ -- Circulus Pistoris -- Scalae -- Universum --- -------- Unnecessary ------ --- Speculo --- Effarcire ---=============== Page 25 ===============-- --- ------- Implemented ------- +--=============== Page 15 ===============-- -- Non Verisimile -- Duplicare -- Formidiulosus From 165588947c7408d8dbfe14c412341bb7b3e1a5bf Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Mon, 17 Aug 2026 21:45:28 +0300 Subject: [PATCH 23/27] add config/menu option for JD --- Cryptid.lua | 8 ++++++++ config.lua | 1 + items/joker_display.lua | 9 ++++++++- localization/en-us.lua | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Cryptid.lua b/Cryptid.lua index 3036c563d..c502fd2e1 100644 --- a/Cryptid.lua +++ b/Cryptid.lua @@ -421,6 +421,14 @@ local cryptidConfigTab = function() ref_table = Cryptid_config, ref_value = "menu", }) + if (SMODS.Mods and SMODS.Mods["JokerDisplay"] and not SMODS.Mods["JokerDisplay"].disabled) or JokerDisplay ~= nil then + cry_nodes[#cry_nodes + 1] = create_toggle({ + label = localize("cry_feat_jokerdisplay"), + active_colour = HEX("2e7cd6"), + ref_table = Cryptid_config, + ref_value = "joker_display", + }) + end cry_nodes[#cry_nodes + 1] = UIBox_button({ colour = G.C.CRY_ALTGREENGRADIENT, button = "reset_gameset_config", diff --git a/config.lua b/config.lua index af48d1bed..693958a83 100644 --- a/config.lua +++ b/config.lua @@ -11,4 +11,5 @@ return { ["force_tooltips"] = true, -- acivates lovely patch to always show the desc of jokers and stuff ["HTTPS"] = true, -- your internet connection ["menu"] = true, -- Restart game and the main menu is now blue + ["joker_display"] = true, -- enable/disable JokerDisplay integration } diff --git a/items/joker_display.lua b/items/joker_display.lua index 12d9a3ad9..121f0fe2f 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -228,12 +228,15 @@ -- Energia -- Caeruleum -if JokerDisplay then +if JokerDisplay and (Cryptid_config.joker_display == nil or Cryptid_config.joker_display) then --Side note: I Don't think retrigger type exp gives a correct value with Emult jokers, but ehhhhh ig I can live with that (It's good enough) -- Panopticon & Labyrinth calculation hooks local orig_card_calc_jd = Card.calculate_joker_display function Card:calculate_joker_display(...) + if Cryptid_config and Cryptid_config.joker_display == false then + return orig_card_calc_jd(self, ...) + end local temp_hands_played = G.GAME and G.GAME.current_round and G.GAME.current_round.hands_played local temp_discards_used = G.GAME and G.GAME.current_round and G.GAME.current_round.discards_used local temp_hands_left = G.GAME and G.GAME.current_round and G.GAME.current_round.hands_left @@ -3770,6 +3773,9 @@ if JokerDisplay then -- Intercepts Card:initialize_joker_display to apply promoted chips text/badges when adjacent to Caeruleum local card_init_jd_ref = Card.initialize_joker_display function Card:initialize_joker_display(custom_parent, stop_calc) + if Cryptid_config and Cryptid_config.joker_display == false then + return card_init_jd_ref(self, custom_parent, stop_calc) + end local is_adj = check_caeruleum_adjacent(self) local orig_def = self.config and self.config.center and JokerDisplay.Definitions[self.config.center.key] local modified = false @@ -3816,6 +3822,7 @@ if JokerDisplay then local card_update_ref = Card.update function Card:update(dt) card_update_ref(self, dt) + if Cryptid_config and Cryptid_config.joker_display == false then return end if self.ability and self.children and (self.children.joker_display or self.children.joker_display_small) then local is_adj = check_caeruleum_adjacent(self) if is_adj ~= self._cry_caer_adj then diff --git a/localization/en-us.lua b/localization/en-us.lua index 71c7ffe7a..1e20dcc92 100644 --- a/localization/en-us.lua +++ b/localization/en-us.lua @@ -5215,7 +5215,7 @@ return { ["cry_feat_misc."] = "Misc.", ["cry_feat_misc. jokers"] = "Misc. Jokers", cry_feat_planets = "Planets", - cry_feat_jokerdisplay = "JokerDisplay (Does Nothing)", + cry_feat_jokerdisplay = "JokerDisplay Integration (Needs restart)", cry_feat_tags = "Tags", cry_feat_sleeves = "Sleeves", cry_feat_spectrals = "Spectrals", From 21683c94c49948e1bf49fcd64e1b6c2416e1fed9 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Tue, 18 Aug 2026 16:55:49 +0300 Subject: [PATCH 24/27] update old membership card code --- items/joker_display.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 121f0fe2f..caa973609 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -636,7 +636,10 @@ if JokerDisplay and (Cryptid_config.joker_display == nil or Cryptid_config.joker }, text_config = { colour = G.C.CHIPS }, calc_function = function(card) - card.joker_display_values.stat = card.ability.extra.chips * Cryptid.member_count + local chips_mod = (card.ability and card.ability.immutable and card.ability.immutable.chips_mod) or 1 + local member_count = Cryptid.member_count or 0 + local chips = (card.ability and card.ability.extra and card.ability.extra.chips) or 1 + card.joker_display_values.stat = chips * math.floor(member_count / chips_mod) end, } JokerDisplay.Definitions["j_cry_redeo"] = { From 357b51695441b5b2a063060cf45c7746e80cb980 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Fri, 21 Aug 2026 01:14:50 +0300 Subject: [PATCH 25/27] update canvas jd code --- items/joker_display.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index caa973609..2ec915927 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -836,17 +836,25 @@ if JokerDisplay and (Cryptid_config.joker_display == nil or Cryptid_config.joker { ref_table = "card.joker_display_values", ref_value = "num_retriggers" }, }, calc_function = function(card) + local is_modest = Card.get_gameset and Card.get_gameset(card) == "modest" local num_retriggers = 0 if G.jokers then for i = 1, #G.jokers.cards do + local other = G.jokers.cards[i] + local is_common = (other.is_rarity and other:is_rarity(1)) or (other.config and other.config.center and other.config.center.rarity == 1) + local is_candy = (other.is_rarity and other:is_rarity("cry_candy")) or (other.config and other.config.center and other.config.center.rarity == "cry_candy") if - card.T.x + card.T.w / 2 < G.jokers.cards[i].T.x + G.jokers.cards[i].T.w / 2 - and G.jokers.cards[i].config.center.rarity ~= 1 + card.T.x + card.T.w / 2 < other.T.x + other.T.w / 2 + and not is_common + and (not is_modest or not is_candy) then num_retriggers = num_retriggers + 1 end end end + if is_modest then + num_retriggers = math.min(2, num_retriggers) + end card.joker_display_values.num_retriggers = num_retriggers end, retrigger_joker_function = function(card, retrigger_joker) From cfec111f3e31b78cbe6caa622468b3f7fe8de69e Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Mon, 24 Aug 2026 23:04:40 +0300 Subject: [PATCH 26/27] Update locs for other languages --- localization/de.lua | 2 +- localization/es_419.lua | 2 +- localization/es_ES.lua | 2 +- localization/fr.lua | 2 +- localization/id.lua | 2 +- localization/ja.lua | 2 +- localization/ko.lua | 2 +- localization/nl.lua | 2 +- localization/pl.lua | 2 +- localization/pt_BR.lua | 2 +- localization/ru.lua | 2 +- localization/vi.lua | 2 +- localization/zh_CN.lua | 2 +- localization/zh_TW.lua | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/localization/de.lua b/localization/de.lua index 8968f7e2a..9de65e8b5 100644 --- a/localization/de.lua +++ b/localization/de.lua @@ -4998,7 +4998,7 @@ return { ["cry_feat_misc."] = "Verschiedenes", ["cry_feat_misc. jokers"] = "Verschiedene Joker", cry_feat_planets = "Planeten", - cry_feat_jokerdisplay = "JokerDisplay (Macht nichts)", + cry_feat_jokerdisplay = "JokerDisplay-Integration (Neustart erforderlich)", cry_feat_tags = "Tags", cry_feat_sleeves = "Hüllen", cry_feat_spectrals = "Geister-Karten", diff --git a/localization/es_419.lua b/localization/es_419.lua index e240e58dd..d17f21349 100644 --- a/localization/es_419.lua +++ b/localization/es_419.lua @@ -3543,7 +3543,7 @@ return { ["cry_feat_misc."] = "Misc.", ["cry_feat_misc. jokers"] = "Comodines misceláneos", cry_feat_planets = "Planetas", - cry_feat_jokerdisplay = "JokerDisplay (no hace nada)", + cry_feat_jokerdisplay = "Integración con JokerDisplay (Requiere reinicio)", cry_feat_tags = "Etiquetas", cry_feat_sleeves = "Mangas", cry_feat_spectrals = "Espectrales", diff --git a/localization/es_ES.lua b/localization/es_ES.lua index f5d7106d1..b266a93b7 100644 --- a/localization/es_ES.lua +++ b/localization/es_ES.lua @@ -4530,7 +4530,7 @@ return { ["cry_feat_misc."] = "Misceláneo", ["cry_feat_misc. jokers"] = "Comodines misceláneos", cry_feat_planets = "Planetas", - cry_feat_jokerdisplay = "JokerDisplay (no hace nada)", + cry_feat_jokerdisplay = "Integración con JokerDisplay (Requiere reinicio)", cry_feat_tags = "Etiquetas", cry_feat_sleeves = "Fundas", cry_feat_spectrals = "Espectrales", diff --git a/localization/fr.lua b/localization/fr.lua index df3eaebbc..493c29dc2 100644 --- a/localization/fr.lua +++ b/localization/fr.lua @@ -5063,7 +5063,7 @@ return { ["cry_feat_misc."] = "Divers", ["cry_feat_misc. jokers"] = "Jokers divers", cry_feat_planets = "Planètes", - cry_feat_jokerdisplay = "JokerDisplay (Fait rien)", + cry_feat_jokerdisplay = "Intégration JokerDisplay (Redémarrage requis)", cry_feat_tags = "Badges", cry_feat_sleeves = "Pochettes", cry_feat_spectrals = "Cartes spectrales", diff --git a/localization/id.lua b/localization/id.lua index 1ea171d8b..65ea7349a 100644 --- a/localization/id.lua +++ b/localization/id.lua @@ -3026,7 +3026,7 @@ return { ["cry_feat_misc."] = "Misc.", ["cry_feat_misc. jokers"] = "Misc. Jokers", cry_feat_planets = "Planets", - cry_feat_jokerdisplay = "JokerDisplay (Does Nothing)", + cry_feat_jokerdisplay = "Integrasi JokerDisplay (Perlu restart)", cry_feat_tags = "Tags", cry_feat_sleeves = "Sleeves", cry_feat_spectrals = "Spectrals", diff --git a/localization/ja.lua b/localization/ja.lua index 102635331..282b4421a 100644 --- a/localization/ja.lua +++ b/localization/ja.lua @@ -5183,7 +5183,7 @@ return { ["cry_feat_misc."] = "その他", ["cry_feat_misc. jokers"] = "その他のジョーカー", cry_feat_planets = "惑星", - cry_feat_jokerdisplay = "JokerDisplay (Does Nothing)", + cry_feat_jokerdisplay = "JokerDisplay 連携 (要再起動)", cry_feat_tags = "タグ", cry_feat_sleeves = "スリーブ", cry_feat_spectrals = "スペクトル", diff --git a/localization/ko.lua b/localization/ko.lua index d650f2201..556b7eb0d 100644 --- a/localization/ko.lua +++ b/localization/ko.lua @@ -5043,7 +5043,7 @@ return { ["cry_feat_misc."] = "기타", ["cry_feat_misc. jokers"] = "기타 조커", cry_feat_planets = "행성", - cry_feat_jokerdisplay = "조커 디스플레이 (아무 효과 없음)", + cry_feat_jokerdisplay = "조커 디스플레이 연동 (재시작 필요)", cry_feat_tags = "태그", cry_feat_sleeves = "슬리브", cry_feat_spectrals = "유령", diff --git a/localization/nl.lua b/localization/nl.lua index fbc905167..0bb54a094 100644 --- a/localization/nl.lua +++ b/localization/nl.lua @@ -3032,7 +3032,7 @@ return { ["cry_feat_misc."] = "Misc.", ["cry_feat_misc. jokers"] = "Misc. Jokers", cry_feat_planets = "Planets", - cry_feat_jokerdisplay = "JokerDisplay (Does Nothing)", + cry_feat_jokerdisplay = "JokerDisplay-integratie (Herstart vereist)", cry_feat_tags = "Tags", cry_feat_sleeves = "Sleeves", cry_feat_spectrals = "Spectrals", diff --git a/localization/pl.lua b/localization/pl.lua index e5f5da231..52274460d 100644 --- a/localization/pl.lua +++ b/localization/pl.lua @@ -3632,7 +3632,7 @@ return { ["cry_feat_misc."] = "Różnorodne Jokery", ["cry_feat_misc. jokers"] = "Inne Jokery", cry_feat_planets = "Karty Planet", - cry_feat_jokerdisplay = "JokerDisplay (Nie robi nic)", + cry_feat_jokerdisplay = "Integracja JokerDisplay (Wymaga restartu)", cry_feat_tags = "Znaczniki", cry_feat_sleeves = "Pokrowce", cry_feat_spectrals = "Karty Ducha", diff --git a/localization/pt_BR.lua b/localization/pt_BR.lua index fe4d9f882..5c07e4ed0 100644 --- a/localization/pt_BR.lua +++ b/localization/pt_BR.lua @@ -4456,7 +4456,7 @@ return { ["cry_feat_misc."] = "Misc.", ["cry_feat_misc. jokers"] = "Misc. Jokers", cry_feat_planets = "Planets", - cry_feat_jokerdisplay = "JokerDisplay (Does Nothing)", + cry_feat_jokerdisplay = "Integração com JokerDisplay (Requer reinício)", cry_feat_tags = "Tags", cry_feat_sleeves = "Sleeves", cry_feat_spectrals = "Spectrals", diff --git a/localization/ru.lua b/localization/ru.lua index ca01d0e09..49c629a8a 100644 --- a/localization/ru.lua +++ b/localization/ru.lua @@ -4024,7 +4024,7 @@ return { ["cry_feat_misc."] = "Проч.", ["cry_feat_misc. jokers"] = "Проч. Джокеры", cry_feat_planets = "Планеты", - cry_feat_jokerdisplay = "ПоказДжокера (Ничего не делает)", + cry_feat_jokerdisplay = "Интеграция JokerDisplay (нужен перезапуск)", cry_feat_tags = "Теги", cry_feat_sleeves = "Рукава", cry_feat_spectrals = "Спектры", diff --git a/localization/vi.lua b/localization/vi.lua index ef5196b20..f30810e8c 100644 --- a/localization/vi.lua +++ b/localization/vi.lua @@ -4247,7 +4247,7 @@ return { ["cry_feat_misc."] = "Khác", ["cry_feat_misc. jokers"] = "Joker Khác", cry_feat_planets = "Hành Tinh", - cry_feat_jokerdisplay = "JokerDisplay (Vô Dụng)", + cry_feat_jokerdisplay = "Tích hợp JokerDisplay (Cần khởi động lại)", cry_feat_tags = "Nhãn", cry_feat_sleeves = "Bọc Bài", cry_feat_spectrals = "Siêu Linh", diff --git a/localization/zh_CN.lua b/localization/zh_CN.lua index e0649a668..05a51aa29 100644 --- a/localization/zh_CN.lua +++ b/localization/zh_CN.lua @@ -5040,7 +5040,7 @@ return { ["cry_feat_misc."] = "杂项", ["cry_feat_misc. jokers"] = "杂项小丑", cry_feat_planets = "星球牌", - cry_feat_jokerdisplay = "JokerDisplay 兼容 (没啥用)", + cry_feat_jokerdisplay = "JokerDisplay 兼容 (需要重启)", cry_feat_tags = "标签", cry_feat_sleeves = "牌套", cry_feat_spectrals = "幻灵牌", diff --git a/localization/zh_TW.lua b/localization/zh_TW.lua index eaf94afbb..64dfe7766 100644 --- a/localization/zh_TW.lua +++ b/localization/zh_TW.lua @@ -3025,7 +3025,7 @@ return { ["cry_feat_misc."] = "Misc.", ["cry_feat_misc. jokers"] = "Misc. Jokers", cry_feat_planets = "Planets", - cry_feat_jokerdisplay = "JokerDisplay (Does Nothing)", + cry_feat_jokerdisplay = "JokerDisplay 兼容 (需要重啟)", cry_feat_tags = "Tags", cry_feat_sleeves = "Sleeves", cry_feat_spectrals = "Spectrals", From 3f47ad4aec61fa43a255a9e9f232360e76c3f010 Mon Sep 17 00:00:00 2001 From: Nanuzer0 Date: Sun, 30 Aug 2026 00:10:43 +0300 Subject: [PATCH 27/27] update caeruleum display code --- items/joker_display.lua | 213 ++++++++++++++++++++++++++-------------- 1 file changed, 138 insertions(+), 75 deletions(-) diff --git a/items/joker_display.lua b/items/joker_display.lua index 2ec915927..3a3dbde20 100644 --- a/items/joker_display.lua +++ b/items/joker_display.lua @@ -3707,78 +3707,135 @@ if JokerDisplay and (Cryptid_config.joker_display == nil or Cryptid_config.joker -- Caeruleum JokerDisplay Hooks: -- Caeruleum has no text box of its own, but dynamically promotes adjacent Chips Jokers in real-time -- (+Chips -> XChips border badge, XChips -> ^Chips E-Chips border badge). + -- Supports stacking (e.g. 2 adjacent Caeruleums give 2 operator rises: +Chips -> ^Chips). - -- Checks if a given card is directly adjacent to Caeruleum in G.jokers - local function check_caeruleum_adjacent(card) - if not G.jokers or not G.jokers.cards then return false end + -- Counts how many active Caeruleums are directly adjacent to a given card in G.jokers + local function count_caeruleum_adjacent(card) + if not G.jokers or not G.jokers.cards then return 0 end + if card.config and card.config.center and card.config.center.key == "j_cry_caeruleum" then + return 0 + end + local count = 0 for i = 1, #G.jokers.cards do if G.jokers.cards[i] == card then local left = G.jokers.cards[i - 1] local right = G.jokers.cards[i + 1] - if (left and left.config and left.config.center and left.config.center.key == "j_cry_caeruleum") - or (right and right.config and right.config.center and right.config.center.key == "j_cry_caeruleum") then - return true + if left and left.config and left.config.center and left.config.center.key == "j_cry_caeruleum" and not left.debuff then + count = count + 1 + end + if right and right.config and right.config.center and right.config.center.key == "j_cry_caeruleum" and not right.debuff then + count = count + 1 end break end end - return false + return count end - -- Transforms flat/bordered chip definition nodes into their next hyperoperation tier - local function promote_chips_text(orig_text) - if not orig_text then return nil end - local new_text = copy_table(orig_text) + local function is_chips_ref(ref) + if not ref or type(ref) ~= "string" then return false end + return ref == "chips" or ref == "x_chips" or ref == "e_chips" or ref == "chip_mod" or ref:find("chips") ~= nil + end - -- Check if orig_text contains border_nodes with X (promoting Xchips -> ^chips) - local has_border_x = false - for _, node in ipairs(new_text) do - if node.border_nodes then - for _, bn in ipairs(node.border_nodes) do - if bn.text == "X" then - has_border_x = true - bn.text = "^" - end - end - if has_border_x then - node.border_colour = G.C.echips or G.C.CHIPS + local function is_chip_node(node, default_colour) + if not node then return false end + if node.colour == G.C.CHIPS or node.border_colour == G.C.CHIPS then return true end + if node.border_nodes then + if node.border_colour == G.C.CHIPS or (not node.border_colour and default_colour == G.C.CHIPS) then + return true + end + for _, bn in ipairs(node.border_nodes) do + if bn.colour == G.C.CHIPS or bn.border_colour == G.C.CHIPS or is_chips_ref(bn.ref_value) then + return true end end end + if is_chips_ref(node.ref_value) then return true end + if not node.colour and default_colour == G.C.CHIPS then return true end + return false + end - if has_border_x then - return new_text + local function has_chips(nodes, config) + if not nodes then return false end + local def_col = config and config.colour + if def_col == G.C.CHIPS then return true end + for _, node in ipairs(nodes) do + if is_chip_node(node, def_col) then return true end end + return false + end - -- Otherwise, promote flat +chips (or flat X) into a bordered badge - local val_nodes = {} + -- Transforms chip definition nodes into their next hyperoperation tier for 1 step + local function promote_chips_step(nodes, default_colour) + if not nodes then return nil end + local result = {} + local flat_chip_nodes = {} local is_plus = false - for _, node in ipairs(new_text) do - if node.text == "+" then - is_plus = true - elseif node.text == "X" then + + local function flush_flat_chips() + if #flat_chip_nodes > 0 then + local bordered = { + border_nodes = { + { text = is_plus and "X" or "^" }, + }, + border_colour = is_plus and G.C.CHIPS or (G.C.echips or G.C.CHIPS), + } + for _, vn in ipairs(flat_chip_nodes) do + table.insert(bordered.border_nodes, vn) + end + table.insert(result, bordered) + flat_chip_nodes = {} is_plus = false + end + end + + for _, node in ipairs(nodes) do + if node.border_nodes then + flush_flat_chips() + local new_node = copy_table(node) + if is_chip_node(node, default_colour) then + local promoted = false + for _, bn in ipairs(new_node.border_nodes) do + if bn.text == "X" then + bn.text = "^" + promoted = true + end + end + if promoted or (new_node.border_nodes[1] and new_node.border_nodes[1].text == "^") then + new_node.border_colour = G.C.echips or G.C.CHIPS + end + end + table.insert(result, new_node) + elseif is_chip_node(node, default_colour) then + if node.text == "+" or node.ref_value == "plus_chips" then + is_plus = true + elseif node.text == "X" then + is_plus = false + else + local n = copy_table(node) + n.retrigger_type = "exp" + n.colour = nil + table.insert(flat_chip_nodes, n) + end else - local n = copy_table(node) - n.retrigger_type = "exp" - val_nodes[#val_nodes + 1] = n + flush_flat_chips() + table.insert(result, copy_table(node)) end end + flush_flat_chips() + return result + end - local border_col = is_plus and G.C.CHIPS or (G.C.echips or G.C.CHIPS) - local border_char = is_plus and "X" or "^" - local bordered = { - { - border_nodes = { - { text = border_char }, - }, - border_colour = border_col, - } - } - for _, vn in ipairs(val_nodes) do - table.insert(bordered[1].border_nodes, vn) + -- Applies `count` operator promotions to chip nodes + local function promote_chips_text(orig_text, text_config, count) + if not orig_text or not count or count <= 0 then return orig_text end + local cur = copy_table(orig_text) + local def_col = text_config and text_config.colour + for i = 1, count do + cur = promote_chips_step(cur, def_col) + def_col = nil end - return bordered + return cur end -- Intercepts Card:initialize_joker_display to apply promoted chips text/badges when adjacent to Caeruleum @@ -3787,45 +3844,51 @@ if JokerDisplay and (Cryptid_config.joker_display == nil or Cryptid_config.joker if Cryptid_config and Cryptid_config.joker_display == false then return card_init_jd_ref(self, custom_parent, stop_calc) end - local is_adj = check_caeruleum_adjacent(self) + local caer_count = count_caeruleum_adjacent(self) local orig_def = self.config and self.config.center and JokerDisplay.Definitions[self.config.center.key] local modified = false local saved_text = nil local saved_text_config = nil + local saved_extra = nil - if is_adj and orig_def and orig_def.text then - local is_chips = (orig_def.text_config and orig_def.text_config.colour == G.C.CHIPS) - if not is_chips then - for _, node in ipairs(orig_def.text) do - if node.colour == G.C.CHIPS or node.border_colour == G.C.CHIPS then - is_chips = true - break - end - if node.border_nodes then - for _, bn in ipairs(node.border_nodes) do - if bn.colour == G.C.CHIPS or bn.border_colour == G.C.CHIPS then - is_chips = true - break - end - end - end - end - end - - if is_chips then + if caer_count > 0 and orig_def then + if orig_def.text and has_chips(orig_def.text, orig_def.text_config) then saved_text = orig_def.text saved_text_config = orig_def.text_config - orig_def.text = promote_chips_text(orig_def.text) + orig_def.text = promote_chips_text(orig_def.text, orig_def.text_config, caer_count) orig_def.text_config = nil modified = true end + if orig_def.extra then + local extra_has_chips = false + for _, line in ipairs(orig_def.extra) do + if has_chips(line, orig_def.extra_config) then + extra_has_chips = true + break + end + end + if extra_has_chips then + saved_extra = orig_def.extra + local new_extra = {} + for _, line in ipairs(orig_def.extra) do + table.insert(new_extra, promote_chips_text(line, orig_def.extra_config, caer_count)) + end + orig_def.extra = new_extra + modified = true + end + end end card_init_jd_ref(self, custom_parent, stop_calc) - if modified and saved_text then - orig_def.text = saved_text - orig_def.text_config = saved_text_config + if modified then + if saved_text ~= nil then + orig_def.text = saved_text + orig_def.text_config = saved_text_config + end + if saved_extra ~= nil then + orig_def.extra = saved_extra + end end end @@ -3835,9 +3898,9 @@ if JokerDisplay and (Cryptid_config.joker_display == nil or Cryptid_config.joker card_update_ref(self, dt) if Cryptid_config and Cryptid_config.joker_display == false then return end if self.ability and self.children and (self.children.joker_display or self.children.joker_display_small) then - local is_adj = check_caeruleum_adjacent(self) - if is_adj ~= self._cry_caer_adj then - self._cry_caer_adj = is_adj + local count = count_caeruleum_adjacent(self) + if count ~= self._cry_caer_count then + self._cry_caer_count = count self:update_joker_display(false, true, "Caeruleum") end end