Add new joker, add unit tests, fix long-standing bugs

This commit is contained in:
Emik 2026-01-27 04:30:02 +01:00
parent 6ace22f122
commit 13b9289bbf
Signed by: emik
GPG key ID: 6B0CD72A5E503BDF
16 changed files with 579 additions and 20 deletions

BIN
assets/1x/martingale.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

BIN
assets/2x/martingale.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -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 = { Spectral = {
c_Roland_afterimage = { c_Roland_afterimage = {
@ -65,9 +78,11 @@ return {
misc = { misc = {
challenge_names = { challenge_names = {
c_Roland_Jokerful = "Jokerful", c_Roland_Jokerful = "Jokerful",
c_Roland_Pastries = "Sweet Pastries",
}, },
v_text = { v_text = {
ch_c_Roland_Jokerful = {"Only the {C:common}default Joker{} can appear in shops"}, 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"},
}, },
}, },
} }

View file

@ -6,11 +6,11 @@
"author": [ "author": [
"Emik" "Emik"
], ],
"version": "1.4.7", "version": "1.5.0",
"badge_colour": "8BE9FD", "badge_colour": "8BE9FD",
"main_file": "src/main.lua", "main_file": "src/main.lua",
"badge_text_colour": "44475A", "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.", "description": "Adds several disconnected funny ideas I had in my head that I couldn't resist implementing in the game.",
"provides": [], "provides": [],
"conflicts": [], "conflicts": [],

1
refs/Balatest Symbolic link
View file

@ -0,0 +1 @@
../../Balatest/src/

View file

@ -1,4 +1,24 @@
local jokerful = {banned_cards = {}} 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 { SMODS.Challenge {
key = "Jokerful", key = "Jokerful",
@ -7,17 +27,20 @@ SMODS.Challenge {
pronouns = "he_him", pronouns = "he_him",
} }
SMODS.Challenge {
key = "Pastries",
rules = {custom = {{id = "Roland_Pastries"}}},
restrictions = pastries,
pronouns = "she_them",
}
G.E_MANAGER:add_event(Event { G.E_MANAGER:add_event(Event {
trigger = "immediate", trigger = "immediate",
func = function() func = function()
F.foreach( F.foreach(F.filter(G.P_CENTERS, is_joker), adder(jokerful.banned_cards))
F.filter( F.foreach(F.filter(G.P_TAGS, is_banned_from_pastry), adder(pastries.banned_tags))
G.P_CENTERS, F.foreach(F.filter(G.P_BLINDS, is_banned_from_pastry), adder(pastries.banned_other))
function(v) return v.set == "Joker" end F.foreach(F.filter(G.P_CENTERS, is_center_banned_from_pastry), adder(pastries.banned_cards))
),
function(v) table.insert(jokerful.banned_cards, {id = v.key}) end
)
return true return true
end, end,
}) })

View file

@ -23,6 +23,10 @@ local function destructible(card)
return not card.highlighted and not (card.ability or {}).eternal return not card.highlighted and not (card.ability or {}).eternal
end end
local function is_carbon(card)
return card.edition and card.edition.key == "e_Bakery_Carbon"
end
local function is_mergeable_with(it) local function is_mergeable_with(it)
return function(card) return function(card)
return it.rank ~= card.rank and return it.rank ~= card.rank and
@ -38,6 +42,13 @@ SMODS.Atlas {
path = "escapey.png", path = "escapey.png",
} }
SMODS.Atlas {
px = 71,
py = 95,
key = "martingale",
path = "martingale.png",
}
SMODS.Joker { SMODS.Joker {
key = "escapey", key = "escapey",
atlas = "escapey", atlas = "escapey",
@ -59,7 +70,7 @@ SMODS.Joker {
local quotes = loc_self.quotes local quotes = loc_self.quotes
local merge = G.jokers 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 {} and loc_self.merge or {}
local normal = (merge[1] or sinister) and {} or local normal = (merge[1] or sinister) and {} or
@ -102,7 +113,7 @@ SMODS.Joker {
return "DEBUFFED" return "DEBUFFED"
end 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" F.any(F.filter(G.jokers.cards, is_mergeable_with(card))) and "FUSE" or "ESCAPE"
end, end,
---@param card Card ---@param card Card
@ -112,22 +123,27 @@ SMODS.Joker {
end end
local consumables = F.filter(G.consumeables.cards, destructible) local consumables = F.filter(G.consumeables.cards, destructible)
local consumable_count = F.count(consumables) local consumable_count = #consumables
local object_count = consumable_count + #G.GAME.tags 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 level_sum, sell_sum = 0, 0
local any_carbon = is_carbon(card)
F.foreach( F.foreach(
F.filter(G.jokers.cards, is_mergeable_with(card)), F.filter(G.jokers.cards, is_mergeable_with(card)),
function(v) 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) 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) sell_sum = sell_sum + v.sell_cost * (v.getEvalQty and v:getEvalQty() or 1)
v:start_dissolve({HEX("57ecab")}, nil, 1.6) v:start_dissolve({HEX("57ecab")}, nil, 1.6)
end 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 card.sell_cost = card.sell_cost + sell_sum
return return
end end
@ -179,6 +195,8 @@ SMODS.Joker {
) )
end end
local destroyed = 0
if consumable_count == 0 then if consumable_count == 0 then
local trigger = #G.GAME.tags >= 30 and "immediate" or "before" local trigger = #G.GAME.tags >= 30 and "immediate" or "before"
local delay = #G.GAME.tags >= 30 and 0 or 1 / #G.GAME.tags local delay = #G.GAME.tags >= 30 and 0 or 1 / #G.GAME.tags
@ -186,19 +204,27 @@ SMODS.Joker {
F.foreach( F.foreach(
G.GAME.tags, G.GAME.tags,
function(v) 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 end
) )
else else
F.foreach( F.foreach(
consumables, consumables,
function(v) function(v)
destroyed = destroyed + 1
v:start_dissolve({HEX("57ecab")}, nil, 1.6) v:start_dissolve({HEX("57ecab")}, nil, 1.6)
end end
) )
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( update_hand_text(
{sound = "button", volume = 0.7, pitch = 1.1, delay = 0}, {sound = "button", volume = 0.7, pitch = 1.1, delay = 0},
@ -206,3 +232,46 @@ SMODS.Joker {
) )
end, 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,
}

View file

@ -4,11 +4,17 @@ assert(SMODS.load_file("src/spectral.lua"))()
assert(SMODS.load_file("src/blind.lua"))() assert(SMODS.load_file("src/blind.lua"))()
assert(SMODS.load_file("src/joker.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 { SMODS.Atlas {
px = 256, px = 256,
py = 256, py = 256,
key = "modicon", key = "modicon",
path = "icon.png", path = "icon.png",
} }
SMODS.Joker:take_ownership("joker", {cost = 1}, true)

60
src/tests/blind.tests.lua Normal file
View file

@ -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,
}

352
src/tests/joker.tests.lua Normal file
View file

@ -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,
}

View file

@ -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,
}