From 13b9289bbf8951aff2ef177e0f3c3aea8a68deb7 Mon Sep 17 00:00:00 2001 From: Emik Date: Tue, 27 Jan 2026 04:30:02 +0100 Subject: [PATCH] Add new joker, add unit tests, fix long-standing bugs --- assets/1x/martingale.png | Bin 0 -> 346 bytes assets/2x/afterimage.png | Bin 3337 -> 3337 bytes assets/2x/blind.png | Bin 2653 -> 2653 bytes assets/2x/escapey.png | Bin 1592 -> 1592 bytes assets/2x/icon.png | Bin 80997 -> 80997 bytes assets/2x/martingale.png | Bin 0 -> 398 bytes assets/2x/void.png | Bin 13455 -> 13455 bytes localization/en-us.lua | 15 ++ manifest.json | 4 +- refs/Balatest | 1 + src/challenge.lua | 39 +++- src/joker.lua | 85 ++++++++- src/main.lua | 10 +- src/tests/blind.tests.lua | 60 ++++++ src/tests/joker.tests.lua | 352 +++++++++++++++++++++++++++++++++++ src/tests/spectral.tests.lua | 33 ++++ 16 files changed, 579 insertions(+), 20 deletions(-) create mode 100644 assets/1x/martingale.png create mode 100644 assets/2x/martingale.png create mode 120000 refs/Balatest create mode 100644 src/tests/blind.tests.lua create mode 100644 src/tests/joker.tests.lua create mode 100644 src/tests/spectral.tests.lua diff --git a/assets/1x/martingale.png b/assets/1x/martingale.png new file mode 100644 index 0000000000000000000000000000000000000000..601c006b9509c4531bdc496448e045682c57f87b GIT binary patch literal 346 zcmeAS@N?(olHy`uVBq!ia0y~yU~p$(V2I~nV_;y|WqRu+0|TR?r;B4q#hkZyH~Jnm z5OKK3k}4I!U^PR=DuUq}qw1uG+Dhe&^Dn#jUHWlq-TiF^nb!L&YXARcy2$eSZAcX!Z8~^^Yx;?%u7NV|nJ?p8v|{>ax=Kjo-)~)4e68*C~92^ASs7lZE3P z1wR4xjzPwKD3QB?zfpo&F>QPKk8+J;ZyL}2jz4cd!}N1{?2a$YSCUn7V!p}$Vqjok N@O1TaS?83{1OSScgx&xE literal 0 HcmV?d00001 diff --git a/assets/2x/afterimage.png b/assets/2x/afterimage.png index 7dade4ba5ff0042779ac825b90c4062ea89e67ed..7fdce1987de877d4982e6c8a5fb7bff4f767cf20 100644 GIT binary patch delta 62 zcmeB_>Xh1Wor&ueqZF?ZGi%6;%iF>$Gx=^7a78kvO{8e5qfSQ!{=8yHv_7-R@M S=Vf4EVDNPHb6Mw<&;$SXh1Wor&uun*Bx diff --git a/assets/2x/blind.png b/assets/2x/blind.png index 4d9e630dc3241236c827dbb4202286b5191ade82..c06474814bd2c4a325b7ff7064b3cedb36ff4a17 100644 GIT binary patch delta 60 zcmcaBa#v)+Zmw61QoKgYta-DhZ#-JWsb;2YV5nKls%EBZV5nUW=(Hw-`dW&!&=Qu*T7KM$SlOr*vizv%D`CLz`)AD VAVc6eF9QPugQu&X%Q~loCIIet6Y~H7 delta 65 zcmaF*gXQTDmI<|7FWDq`_!U)W&OhJSzO|ikhqaoiu7R1Zkx7W5k(HsTm9eq5fq|8Q V!A$w4qYMlT44$rjF6*2Ung9=;6%POa diff --git a/assets/2x/martingale.png b/assets/2x/martingale.png new file mode 100644 index 0000000000000000000000000000000000000000..1ce9b94125d1adcf56e64b9e29ccd7c190895cbe GIT binary patch literal 398 zcmeAS@N?(olHy`uVBq!ia0y~yVCZ9DVA#jR%)r1f@8x|n1_lO&WRDFdh=icyN!h?zBS)^r92hCojj$B>A_ zZ*MLXJ)j`K>ge<9aKa_|XRCbJ3m&cB6KN~^M&jVLoj2W9pL=`L^*w8-xUG4xbdv%H zDtghb@jbeUU*r4IpxXLJ#ubApigX delta 60 zcmeCr?9ZH#!S#|&f`?ye&xCWO8;iahtC{K=nCTjsgcurG8Jb!dn`j#tSQ!|^?AYVY Qz`(%Z>FVdQ&MBb@0Bj5rz5oCK diff --git a/localization/en-us.lua b/localization/en-us.lua index 955f8cd..9ec3197 100644 --- a/localization/en-us.lua +++ b/localization/en-us.lua @@ -42,6 +42,19 @@ return { }, }, }, + j_Roland_martingale = { + name = "Martingale", + text = { + "{C:green}#1# in #2#{} chance to give {X:mult,C:white}X#2#{} Mult", + "{s:0.9}Otherwise {C:green,s:0.9}#1# in #2#{s:0.9} chance to give {X:mult,C:white,s:0.9}X#3#{s:0.9} Mult", + "{s:0.81}Otherwise {C:green,s:0.81}#1# in #2#{s:0.81} chance to give {X:mult,C:white,s:0.81}X#4#{s:0.81} Mult", + "{s:0.6561}Otherwise {C:green,s:0.6561}#1# in #2#{s:0.6561} chance to give {X:mult,C:white,s:0.6561}X#5#{s:0.6561} Mult", + "{s:0.43046721}Otherwise {C:green,s:0.43046721}#1# in #2#{s:0.43046721} chance to give {X:mult,C:white,s:0.43046721}X#6#{s:0.43046721} Mult", + "{s:0.1853020188851841}Otherwise {C:green,s:0.1853020188851841}#1# in #2#{s:0.1853020188851841} chance to give {X:mult,C:white,s:0.1853020188851841}X#7#{s:0.1853020188851841} Mult", + "{s:0.0343368382029250877861747139}Otherwise {C:green,s:0.0343368382029250877861747139}#1# in #2#{s:0.0343368382029250877861747139} chance to give {X:mult,C:white,s:0.0343368382029250877861747139}X#8#{s:0.0343368382029250877861747139} Mult", + "{s:0}Otherwise {C:green,s:0}#1# in #2#{s:0} chance to give {X:mult,C:white,s:0}X#9#{s:0} Mult", + }, + }, }, Spectral = { c_Roland_afterimage = { @@ -65,9 +78,11 @@ return { misc = { challenge_names = { c_Roland_Jokerful = "Jokerful", + c_Roland_Pastries = "Sweet Pastries", }, v_text = { ch_c_Roland_Jokerful = {"Only the {C:common}default Joker{} can appear in shops"}, + ch_c_Roland_Pastries = {"All blinds, cards, and tags are of {C:gold}Bakery{} or {C:blue}Roland"}, }, }, } diff --git a/manifest.json b/manifest.json index e5a5045..3a2fb30 100644 --- a/manifest.json +++ b/manifest.json @@ -6,11 +6,11 @@ "author": [ "Emik" ], - "version": "1.4.7", + "version": "1.5.0", "badge_colour": "8BE9FD", "main_file": "src/main.lua", "badge_text_colour": "44475A", - "display_name": "Roland (Emik)", + "display_name": "Roland", "description": "Adds several disconnected funny ideas I had in my head that I couldn't resist implementing in the game.", "provides": [], "conflicts": [], diff --git a/refs/Balatest b/refs/Balatest new file mode 120000 index 0000000..c89a2b4 --- /dev/null +++ b/refs/Balatest @@ -0,0 +1 @@ +../../Balatest/src/ \ No newline at end of file diff --git a/src/challenge.lua b/src/challenge.lua index 7abf50e..cf47676 100644 --- a/src/challenge.lua +++ b/src/challenge.lua @@ -1,4 +1,24 @@ local jokerful = {banned_cards = {}} +local pastries = {banned_cards = {}, banned_tags = {}, banned_other = {}} + +local function adder(tbl) + return function(v) + table.insert(tbl, {id = v.key}) + end +end + +local function is_banned_from_pastry(_, k) + return not k:find("_Bakery_") and not k:find("_Roland_") +end + +local function is_center_banned_from_pastry(v, k) + local pastries_targets = {Enhanced = true, Joker = true, Tarot = true, Spectral = true} + return pastries_targets[v.set] and is_banned_from_pastry(v, k) +end + +local function is_joker(v) + return v.set == "Joker" +end SMODS.Challenge { key = "Jokerful", @@ -7,17 +27,20 @@ SMODS.Challenge { pronouns = "he_him", } +SMODS.Challenge { + key = "Pastries", + rules = {custom = {{id = "Roland_Pastries"}}}, + restrictions = pastries, + pronouns = "she_them", +} + G.E_MANAGER:add_event(Event { trigger = "immediate", func = function() - F.foreach( - F.filter( - G.P_CENTERS, - function(v) return v.set == "Joker" end - ), - function(v) table.insert(jokerful.banned_cards, {id = v.key}) end - ) - + F.foreach(F.filter(G.P_CENTERS, is_joker), adder(jokerful.banned_cards)) + F.foreach(F.filter(G.P_TAGS, is_banned_from_pastry), adder(pastries.banned_tags)) + F.foreach(F.filter(G.P_BLINDS, is_banned_from_pastry), adder(pastries.banned_other)) + F.foreach(F.filter(G.P_CENTERS, is_center_banned_from_pastry), adder(pastries.banned_cards)) return true end, }) diff --git a/src/joker.lua b/src/joker.lua index fdec2fe..2fb7e3c 100644 --- a/src/joker.lua +++ b/src/joker.lua @@ -23,6 +23,10 @@ local function destructible(card) return not card.highlighted and not (card.ability or {}).eternal end +local function is_carbon(card) + return card.edition and card.edition.key == "e_Bakery_Carbon" +end + local function is_mergeable_with(it) return function(card) return it.rank ~= card.rank and @@ -38,6 +42,13 @@ SMODS.Atlas { path = "escapey.png", } +SMODS.Atlas { + px = 71, + py = 95, + key = "martingale", + path = "martingale.png", +} + SMODS.Joker { key = "escapey", atlas = "escapey", @@ -59,7 +70,7 @@ SMODS.Joker { local quotes = loc_self.quotes local merge = G.jokers - and F.count(F.filter(G.jokers.cards, is_mergeable_with(card))) > 0 + and #F.filter(G.jokers.cards, is_mergeable_with(card)) > 0 and loc_self.merge or {} local normal = (merge[1] or sinister) and {} or @@ -102,7 +113,7 @@ SMODS.Joker { return "DEBUFFED" end - return #G.GAME.tags == 0 and F.count(G.consumeables.cards, destructible) == 0 and + return #G.GAME.tags == 0 and #F.filter(G.consumeables.cards, destructible) == 0 and F.any(F.filter(G.jokers.cards, is_mergeable_with(card))) and "FUSE" or "ESCAPE" end, ---@param card Card @@ -112,22 +123,27 @@ SMODS.Joker { end local consumables = F.filter(G.consumeables.cards, destructible) - local consumable_count = F.count(consumables) - local object_count = consumable_count + #G.GAME.tags + local consumable_count = #consumables + local tag_count = #G.GAME.tags - if object_count == 0 then + if consumable_count == 0 and tag_count == 0 then local level_sum, sell_sum = 0, 0 + local any_carbon = is_carbon(card) F.foreach( F.filter(G.jokers.cards, is_mergeable_with(card)), function(v) + any_carbon = any_carbon or is_carbon(v) level_sum = level_sum + v.ability.extra.level_up_by * (v.getEvalQty and v:getEvalQty() or 1) sell_sum = sell_sum + v.sell_cost * (v.getEvalQty and v:getEvalQty() or 1) v:start_dissolve({HEX("57ecab")}, nil, 1.6) end ) - card.ability.extra.level_up_by = card.ability.extra.level_up_by + level_sum + if not any_carbon then + card.ability.extra.level_up_by = card.ability.extra.level_up_by + level_sum + end + card.sell_cost = card.sell_cost + sell_sum return end @@ -179,6 +195,8 @@ SMODS.Joker { ) end + local destroyed = 0 + if consumable_count == 0 then local trigger = #G.GAME.tags >= 30 and "immediate" or "before" local delay = #G.GAME.tags >= 30 and 0 or 1 / #G.GAME.tags @@ -186,19 +204,27 @@ SMODS.Joker { F.foreach( G.GAME.tags, function(v) - G.E_MANAGER:add_event(Event {trigger = trigger, blocking = #G.GAME.tags < 30, delay = delay, func = fast_delete(v)}) + destroyed = destroyed + 1 + + G.E_MANAGER:add_event(Event { + trigger = trigger, + blocking = #G.GAME.tags < 30, + delay = delay, + func = fast_delete(v), + }) end ) else F.foreach( consumables, function(v) + destroyed = destroyed + 1 v:start_dissolve({HEX("57ecab")}, nil, 1.6) end ) end - level_up_hand(card, hand, nil, object_count * card.ability.extra.level_up_by) + level_up_hand(card, hand, nil, destroyed * card.ability.extra.level_up_by) update_hand_text( {sound = "button", volume = 0.7, pitch = 1.1, delay = 0}, @@ -206,3 +232,46 @@ SMODS.Joker { ) end, } + +SMODS.Joker { + key = "martingale", + atlas = "martingale", + pronouns = "he_him", + pos = {x = 0, y = 0}, + config = {extra = {odds = 2, times = 0, martingale = true}}, + cost = 7, + rarity = 3, + eternal_compat = true, + blueprint_compat = true, + perishable_compat = true, + loc_vars = function(_, _, card) + local normal = G.GAME.probabilities.normal + local odds = card.ability.extra.odds + local vars = {normal} + + for i = #vars, 9 do + vars[i + 1] = math.pow(odds, i) + end + + return {vars = vars} + end, + calculate = function(_, card, context) + if not context.joker_main then + return + end + + local extra = card.ability.extra + local xmult = extra.odds + + for _ = 1, 31 do + if SMODS.pseudorandom_probability(card, "j_Roland_martingale", 1, extra.odds, "Martingale") then + break + end + + SMODS.calculate_effect({card = card, repetitions = 1, message = "1/" .. number_format(xmult)}, card) + xmult = xmult * extra.odds + end + + SMODS.calculate_effect({card = card, xmult = xmult}, card) + end, +} diff --git a/src/main.lua b/src/main.lua index 6a733a3..7eda99a 100644 --- a/src/main.lua +++ b/src/main.lua @@ -4,11 +4,17 @@ assert(SMODS.load_file("src/spectral.lua"))() assert(SMODS.load_file("src/blind.lua"))() assert(SMODS.load_file("src/joker.lua"))() +if Balatest then + assert(SMODS.load_file("src/tests/joker.tests.lua"))() + assert(SMODS.load_file("src/tests/blind.tests.lua"))() + assert(SMODS.load_file("src/tests/spectral.tests.lua"))() +end + +SMODS.Joker:take_ownership("joker", {cost = 1}, true) + SMODS.Atlas { px = 256, py = 256, key = "modicon", path = "icon.png", } - -SMODS.Joker:take_ownership("joker", {cost = 1}, true) diff --git a/src/tests/blind.tests.lua b/src/tests/blind.tests.lua new file mode 100644 index 0000000..b4e1275 --- /dev/null +++ b/src/tests/blind.tests.lua @@ -0,0 +1,60 @@ +if not Balatest then + return +end + +Balatest.TestPlay { + category = {"blind", "improbable"}, + name = "improbable", + blind = "bl_Roland_improbable", + jokers = {"j_oops", "j_oops", "j_oops"}, + deck = {cards = {{s = "S", r = "2", e = "m_lucky"}, {s = "S", r = "3"}}}, + execute = function() + Balatest.play_hand {"2S"} + end, + assert = function() + Balatest.assert_chips(7) + end, +} + +Balatest.TestPlay { + category = {"blind", "improbable"}, + name = "improbable_not_leaky", + blind = "bl_Roland_improbable", + jokers = {"j_oops", "j_oops", "j_oops"}, + deck = {cards = {{s = "S", r = "2", e = "m_lucky"}, {s = "S", r = "3"}}}, + execute = function() + Balatest.play_hand {"2S"} + Balatest.next_round("bl_small") + Balatest.play_hand {"2S"} + end, + assert = function() + Balatest.assert_chips(7 * 21) + end, +} + +Balatest.TestPlay { + category = {"blind", "nimble"}, + name = "nimble", + blind = "bl_Roland_nimble", + deck = {cards = { + {s = "S", r = "2"}, + {s = "S", r = "2"}, + {s = "S", r = "2"}, + {s = "S", r = "2"}, + {s = "S", r = "2"}, + }}, + no_auto_start = true, + execute = function() + Balatest.q(function() + G.FUNCS.select_blind { + config = {ref_table = G.P_BLINDS[Balatest.current_test_object.blind]}, + UIBox = {get_UIE_by_ID = function() end}, + } + end) + + Balatest.wait_for_input() + end, + assert = function() + Balatest.assert_chips(2720) + end, +} diff --git a/src/tests/joker.tests.lua b/src/tests/joker.tests.lua new file mode 100644 index 0000000..b9dd613 --- /dev/null +++ b/src/tests/joker.tests.lua @@ -0,0 +1,352 @@ +if not Balatest then + return +end + +Balatest.TestPlay { + category = {"joker", "martingale"}, + name = "martingale_oops", + jokers = {"j_Roland_martingale", "j_oops"}, + execute = function() + Balatest.play_hand {"2S"} + end, + assert = function() + Balatest.assert_chips(7 * 2) + end, +} + +Balatest.TestPlay { + category = {"joker", "martingale"}, + name = "martingale_improbable", + blind = "bl_Roland_improbable", + jokers = {"j_Roland_martingale"}, + execute = function() + Balatest.play_hand {"2S"} + end, + assert = function() + Balatest.assert_chips(7 * math.pow(2, 32)) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "escape"}, + name = "escapey_none", + jokers = {"j_Roland_escapey"}, + execute = function() end, + assert = function() + Balatest.assert(not G.jokers.cards[1].config.center:Bakery_can_use(G.jokers.cards[1])) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "escape"}, + name = "escapey_one_consumable", + jokers = {"j_Roland_escapey"}, + consumeables = {"c_strength"}, + execute = function() + Balatest.q(function() + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}} + end) + + Balatest.wait() + end, + assert = function() + Balatest.assert_eq(G.GAME.hands["High Card"].level, 2) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "escape"}, + name = "escapey_two_consumables", + jokers = {"j_Roland_escapey"}, + consumeables = {"c_strength", "c_strength"}, + execute = function() + Balatest.q(function() + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}} + end) + + Balatest.wait() + end, + assert = function() + Balatest.assert_eq(G.GAME.hands["High Card"].level, 3) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "escape"}, + name = "escapey_one_tag", + jokers = {"j_Roland_escapey"}, + no_auto_start = true, + execute = function() + Balatest.skip_blind("tag_investment") + + Balatest.q(function() + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}} + end) + + Balatest.wait() + end, + assert = function() + Balatest.assert_eq(G.GAME.hands["High Card"].level, 2) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "escape"}, + name = "escapey_two_tags", + jokers = {"j_Roland_escapey"}, + no_auto_start = true, + execute = function() + Balatest.skip_blind("tag_investment") + Balatest.skip_blind("tag_investment") + + Balatest.q(function() + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}} + end) + + Balatest.wait() + end, + assert = function() + Balatest.assert_eq(G.GAME.hands["High Card"].level, 3) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "escape"}, + name = "escapey_consumables_and_tags", + jokers = {"j_Roland_escapey"}, + consumeables = {"c_strength"}, + no_auto_start = true, + execute = function() + Balatest.skip_blind("tag_investment") + Balatest.skip_blind("tag_investment") + + Balatest.q(function() + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}} + end) + + Balatest.wait() + end, + assert = function() + Balatest.assert_eq(G.GAME.hands["High Card"].level, 2) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "escape"}, + name = "escapey_partial_selected_consumables_and_tags", + jokers = {"j_Roland_escapey"}, + consumeables = {"c_strength", "c_strength"}, + no_auto_start = true, + execute = function() + Balatest.skip_blind("tag_investment") + Balatest.skip_blind("tag_investment") + + Balatest.q(function() + G.consumeables:add_to_highlighted(G.consumeables.cards[1]) + end) + + Balatest.wait() + + Balatest.q(function() + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}} + end) + + Balatest.wait() + end, + assert = function() + Balatest.assert_eq(G.GAME.hands["High Card"].level, 2) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "escape"}, + name = "escapey_full_selected_consumables_and_tags", + jokers = {"j_Roland_escapey"}, + consumeables = {"c_strength"}, + no_auto_start = true, + execute = function() + Balatest.skip_blind("tag_investment") + Balatest.skip_blind("tag_investment") + + Balatest.q(function() + G.consumeables:add_to_highlighted(G.consumeables.cards[1]) + end) + + Balatest.wait() + + Balatest.q(function() + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}} + end) + + Balatest.wait() + end, + assert = function() + Balatest.assert_eq(G.GAME.hands["High Card"].level, 3) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "fuse"}, + name = "escapey_fusion", + jokers = {"j_Roland_escapey", "j_Roland_escapey"}, + execute = function() + Balatest.q(function() + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}} + end) + + Balatest.wait() + end, + assert = function() + Balatest.assert_eq(#G.jokers.cards, 1) + Balatest.assert_eq(G.jokers.cards[1].sell_cost, 8) + Balatest.assert_eq(G.jokers.cards[1].ability.extra.level_up_by, 2) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "fuse"}, + name = "escapey_consumable_takes_precedence", + jokers = {"j_Roland_escapey", "j_Roland_escapey"}, + consumeables = {"c_strength"}, + execute = function() + Balatest.q(function() + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}} + end) + + Balatest.wait() + end, + assert = function() + Balatest.assert_eq(#G.jokers.cards, 2) + Balatest.assert_eq(G.GAME.hands["High Card"].level, 2) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "fuse"}, + name = "escapey_tag_takes_precedence", + jokers = {"j_Roland_escapey", "j_Roland_escapey"}, + no_auto_start = true, + execute = function() + Balatest.skip_blind("tag_investment") + + Balatest.q(function() + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}} + end) + + Balatest.wait() + end, + assert = function() + Balatest.assert_eq(#G.jokers.cards, 2) + Balatest.assert_eq(G.GAME.hands["High Card"].level, 2) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "fuse"}, + name = "escapey_fusion_takes_precedence", + jokers = {"j_Roland_escapey", "j_Roland_escapey"}, + consumeables = {"c_strength"}, + execute = function() + Balatest.q(function() + G.consumeables:add_to_highlighted(G.consumeables.cards[1]) + end) + + Balatest.wait() + + Balatest.q(function() + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}} + end) + + Balatest.wait() + end, + assert = function() + Balatest.assert_eq(#G.jokers.cards, 1) + Balatest.assert_eq(G.jokers.cards[1].sell_cost, 8) + Balatest.assert_eq(G.jokers.cards[1].ability.extra.level_up_by, 2) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "fuse"}, + name = "escapey_scribe_fusion", + jokers = {"j_Roland_escapey"}, + execute = function() + if not G.P_CENTERS.c_Bakery_Scribe then + sendWarnMessage("escapey_scribe_fusion cannot run without c_Bakery_Scribe, skipping test.") + return + end + + Balatest.q(function() + local scribe = create_card(nil, G.consumeables, nil, nil, nil, nil, "c_Bakery_Scribe", "balatest") + scribe:add_to_deck() + G.consumeables:emplace(scribe) + end) + + Balatest.wait() + + Balatest.q(function() + G.jokers:add_to_highlighted(G.jokers.cards[1]) + end) + + Balatest.wait() + Balatest.use(function() return G.consumeables.cards[1] end) + + Balatest.q(function() + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}} + end) + + Balatest.wait() + end, + assert = function() + if not G.P_CENTERS.c_Bakery_Scribe then + return + end + + Balatest.assert_eq(#G.jokers.cards, 1) + Balatest.assert_eq(G.jokers.cards[1].sell_cost, 8) + Balatest.assert_eq(G.jokers.cards[1].ability.extra.level_up_by, 1) + end, +} + +Balatest.TestPlay { + category = {"joker", "escapey", "fuse"}, + name = "escapey_scribe_fusion_alt", + jokers = {"j_Roland_escapey"}, + execute = function() + if not G.P_CENTERS.c_Bakery_Scribe then + sendWarnMessage("escapey_scribe_fusion_alt cannot run without c_Bakery_Scribe, skipping test.") + return + end + + Balatest.q(function() + local scribe = create_card(nil, G.consumeables, nil, nil, nil, nil, "c_Bakery_Scribe", "balatest") + scribe:add_to_deck() + G.consumeables:emplace(scribe) + end) + + Balatest.wait() + + Balatest.q(function() + G.jokers:add_to_highlighted(G.jokers.cards[1]) + end) + + Balatest.wait() + Balatest.use(function() return G.consumeables.cards[1] end) + + Balatest.q(function() + G.jokers:add_to_highlighted(G.jokers.cards[2]) + G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[2]}} + end) + + Balatest.wait() + end, + assert = function() + if not G.P_CENTERS.c_Bakery_Scribe then + return + end + + Balatest.assert_eq(#G.jokers.cards, 1) + Balatest.assert_eq(G.jokers.cards[1].sell_cost, 8) + Balatest.assert_eq(G.jokers.cards[1].ability.extra.level_up_by, 1) + end, +} diff --git a/src/tests/spectral.tests.lua b/src/tests/spectral.tests.lua new file mode 100644 index 0000000..3cce18c --- /dev/null +++ b/src/tests/spectral.tests.lua @@ -0,0 +1,33 @@ +if not Balatest then + return +end + +Balatest.TestPlay { + category = {"spectral", "afterimage"}, + name = "afterimage", + consumeables = {"c_Roland_afterimage"}, + deck = {cards = {{s = "S", r = "2"}}}, + execute = function() + Balatest.highlight({"2S"}) + Balatest.use(G.consumeables.cards[1]) + Balatest.end_round() + end, + assert = function() + Balatest.assert_eq(G.hand.config.card_limit, 51) + Balatest.assert(G.deck.cards[1].edition.negative) + end, +} + +Balatest.TestPlay { + category = {"spectral", "void"}, + name = "spectral", + consumeables = {"c_Roland_void"}, + execute = function() + Balatest.end_round() + Balatest.use(G.consumeables.cards[1]) + end, + assert = function() + Balatest.assert_eq(#G.deck.cards, 0) + Balatest.assert_eq(#G.consumeables.cards, 2) + end, +}