Compare commits

..

No commits in common. "main" and "2.9.17" have entirely different histories.
main ... 2.9.17

17 changed files with 403 additions and 178 deletions

View file

@ -500,14 +500,14 @@ return {
name = "Ceres", name = "Ceres",
text = { text = {
"Level up {C:attention}Flush House", "Level up {C:attention}Flush House",
"by {C:attention}#1# {}when it is played", "when it is played",
}, },
}, },
v_Roland_neptune = { v_Roland_neptune = {
name = "Neptune", name = "Neptune",
text = { text = {
"Level up {C:attention}Straight Flush", "Level up {C:attention}Straight Flush",
"by {C:attention}#1# {}when it is played", "when it is played",
}, },
}, },
}, },

View file

@ -3,7 +3,7 @@
"id": "Roland", "id": "Roland",
"name": "Roland", "name": "Roland",
"prefix": "Roland", "prefix": "Roland",
"version": "2.9.28", "version": "2.9.17",
"badge_colour": "8BE9FD", "badge_colour": "8BE9FD",
"display_name": "Roland", "display_name": "Roland",
"main_file": "src/main.lua", "main_file": "src/main.lua",

View file

@ -52,7 +52,7 @@ end
local function has_enhancement(card) local function has_enhancement(card)
local e = SMODS.get_enhancements(card) local e = SMODS.get_enhancements(card)
return e and next(e) return not not (e and next(e))
end end
local function set_freeze(state) local function set_freeze(state)
@ -354,11 +354,13 @@ function SMODS.current_mod:calculate(context)
f {"v_Roland_ceres", "v_Roland_neptune"} f {"v_Roland_ceres", "v_Roland_neptune"}
:where(f.index_into(G.GAME.used_vouchers)) :where(f.index_into(G.GAME.used_vouchers))
:map(f.index_into(G.P_CENTERS)) :map(f.index_into(G.P_CENTERS))
:where("config.extra.hand_type", context.scoring_name) :where("config.hand_type", context.scoring_name)
:pun "SMODS.Voucher" :any() and
:each(function(v, _) SMODS.calculate_effect {
SMODS.smart_level_up_hand(nil, v.config.extra.hand_type, nil, v.config.extra.amount) level_up = true,
end) message = localize "k_level_up_ex",
card = G.play.cards[math.ceil(#G.play.cards / 2)] or G.deck.cards[#G.deck.cards] or {},
}
local improbable, orig = G.GAME.modifiers.Roland_improbable, G.GAME.probabilities local improbable, orig = G.GAME.modifiers.Roland_improbable, G.GAME.probabilities

View file

@ -188,7 +188,7 @@ SMODS.Challenge {
end) end)
local mod = G.GAME.modifiers local mod = G.GAME.modifiers
mod.Roland_Eternally_Crimson = context.setting_blind and true or mod.Roland_Eternally_Crimson mod.Roland_Eternally_Crimson = not context.setting_blind and mod.Roland_Eternally_Crimson or nil
local debuff = context.debuff_card local debuff = context.debuff_card
local cards = G.jokers.cards local cards = G.jokers.cards
@ -262,7 +262,7 @@ SMODS.Challenge {
SMODS.Challenge { SMODS.Challenge {
key = "Eternally_Violet", key = "Eternally_Violet",
rules = {custom = {{id = "Roland_Eternally_Violet"}, {id = "Roland_Showdown_Violet"}}}, rules = {custom = {{id = "Roland_Eternally_Violet"}, {id = "Roland_Showdown_Violet"}}},
jokers = {{id = "j_joker"}, {id = "j_Roland_violet"}}, jokers = {{id = "j_Roland_violet"}},
restrictions = violet, restrictions = violet,
pronouns = "she_they", pronouns = "she_they",
calculate = function(_, context) calculate = function(_, context)

View file

@ -261,7 +261,7 @@ local orig_apply_to_run = Tag.apply_to_run
function Tag:apply_to_run(...) function Tag:apply_to_run(...)
if G.GAME.Bakery_charm == "BakeryCharm_Roland_wii" and if G.GAME.Bakery_charm == "BakeryCharm_Roland_wii" and
G.Bakery_charm_area.cards[1].ability.extra.active then G.Bakery_charm_area.cards[1].config.center.ability.extra.active then
return return
end end

View file

@ -13,7 +13,7 @@ end
frozen_sound "_click" frozen_sound "_click"
local frozen_blocklist = {CardSleeve = true} local frozen_blocklist = {CardSleeve = true}
local frozen_sounds = f(4):map(frozen_sound):map "key":table() local frozen_sounds = f(4):map(frozen_sound):map("key"):table()
local needs_chip_mult_override = { local needs_chip_mult_override = {
Bull = true, Bull = true,
@ -144,7 +144,7 @@ local function hook_proxy()
local orig_calculate = proxy.calculate local orig_calculate = proxy.calculate
function proxy:calculate(card, context, ...) function proxy:calculate(card, context, ...)
if not (card or {}).Roland_frozen or not (card.edition or {}).Roland_frozen then if not card or not card.edition or not card.edition.Roland_frozen then
return orig_calculate(self, card, context, ...) return orig_calculate(self, card, context, ...)
else else
return SMODS.blueprint_effect(card, get_proxied_joker(card), context) return SMODS.blueprint_effect(card, get_proxied_joker(card), context)
@ -154,7 +154,7 @@ local function hook_proxy()
local orig_loc_vars = proxy.loc_vars local orig_loc_vars = proxy.loc_vars
function proxy:loc_vars(info_queue, card, ...) function proxy:loc_vars(info_queue, card, ...)
if not (card or {}).Roland_frozen or not (card.edition or {}).Roland_frozen then if not card or not card.edition or not card.edition.Roland_frozen then
return orig_loc_vars(self, info_queue, card, ...) return orig_loc_vars(self, info_queue, card, ...)
end end

View file

@ -488,9 +488,11 @@ joker {
end end
end end
return SMODS.merge_effects( local key = card.config.center.key
local merged = SMODS.merge_effects(
f(G.jokers.cards):where(is_frozen):where(function(v) f(G.jokers.cards):where(is_frozen):where(function(v)
return v.config.center.key ~= card.config.center.key return v.config.center.key ~= key
end):map(function(v) end):map(function(v)
return SMODS.blueprint_effect(card, v, context) return SMODS.blueprint_effect(card, v, context)
end):where(type, "table"):map(function(v) end):where(type, "table"):map(function(v)
@ -498,6 +500,8 @@ joker {
return v return v
end):values():table() end):values():table()
) )
return merged
end, end,
} }
@ -648,7 +652,7 @@ joker {
local _ = card.area == G.jokers and self:cerulean(false) local _ = card.area == G.jokers and self:cerulean(false)
end, end,
cerulean = function(_, value) cerulean = function(_, value)
local _ = G.jokers and f(G.jokers.cards):each(function(v) f(G.jokers.cards):each(function(v)
f {"click", "drag", "focus", "hover"}:map(f.index_into(v.states)):each(function(s) f {"click", "drag", "focus", "hover"}:map(f.index_into(v.states)):each(function(s)
s.can = value or v.config.center.key == "j_Roland_cerulean" s.can = value or v.config.center.key == "j_Roland_cerulean"
end) end)
@ -675,7 +679,7 @@ joker {
{card = card, xmult = card.ability.extra.xmult} or nil {card = card, xmult = card.ability.extra.xmult} or nil
end, end,
crimson = function() crimson = function()
local _ = G.jokers and f(G.jokers.cards, ipairs_reversed):where(is_frozen, false):each(function(v) f(G.jokers.cards, ipairs_reversed):where(is_frozen, false):each(function(v)
local right = G.jokers.cards[v.rank + 1] local right = G.jokers.cards[v.rank + 1]
local debuffed_by_crimson = right and local debuffed_by_crimson = right and
@ -684,13 +688,11 @@ joker {
right.config.center.key == "j_Roland_crimson" right.config.center.key == "j_Roland_crimson"
if debuffed_by_crimson and v.ability.Roland_crimson == nil then if debuffed_by_crimson and v.ability.Roland_crimson == nil then
local debuff = not not v.debuff v.ability.Roland_crimson = not not v.debuff
v:set_debuff(true) v:set_debuff(true)
v.ability.Roland_crimson = debuff
elseif not debuffed_by_crimson and v.ability.Roland_crimson ~= nil then elseif not debuffed_by_crimson and v.ability.Roland_crimson ~= nil then
local debuff = v.ability.Roland_crimson v:set_debuff(v.ability.Roland_crimson)
v.ability.Roland_crimson = nil v.ability.Roland_crimson = nil
v:set_debuff(debuff)
end end
end) end)
end, end,
@ -757,7 +759,7 @@ joker {
key = "violet", key = "violet",
pronouns = "she_they", pronouns = "she_they",
idea = "hamester", idea = "hamester",
config = {extra = {before = 0.1, xmult = 6}}, config = {extra = {before = 0.1, xmult = 9}},
pixel_size = {w = 68, h = 68}, pixel_size = {w = 68, h = 68},
attributes = {"xmult"}, attributes = {"xmult"},
cost = 6, cost = 6,
@ -1258,7 +1260,7 @@ joker {
return {card = card, numerator = extra.probability} return {card = card, numerator = extra.probability}
end end
if context.end_of_round and not context.repetition and extra.probability ~= extra.reset then if context.end_of_round and extra.probability ~= extra.reset then
extra.probability = extra.reset extra.probability = extra.reset
return {message = localize "k_reset", colour = G.C.RED, message_card = card, repetitions = 0} return {message = localize "k_reset", colour = G.C.RED, message_card = card, repetitions = 0}
end end

View file

@ -128,6 +128,13 @@ local function autopairs(tbl, fpairs)
return (fpairs or (tbl[#tbl] and ipairs or pairs))(tbl) return (fpairs or (tbl[#tbl] and ipairs or pairs))(tbl)
end end
---@param any any
---@return boolean
---@nodiscard
local function is_f(any)
return type(any) == "table" and any.from == f.from and any.new == f.new
end
--- Always returns nil. --- Always returns nil.
---@return nil ---@return nil
---@nodiscard ---@nodiscard
@ -195,15 +202,6 @@ function f.const(v)
end end
end end
---@param i integer
---@return fun(...: any): any
---@nodiscard
function f.arg(i)
return function(...)
return ({...})[i]
end
end
---@generic K, V ---@generic K, V
---@param v K ---@param v K
---@return fun(x: { [K]: V }): V ---@return fun(x: { [K]: V }): V
@ -242,32 +240,21 @@ function f.indices(v)
end end
end end
---@param any any
---@return boolean
---@nodiscard
function f.isf(any)
return type(any) == "table" and any.from == f.from and any.new == f.new
end
f[true and "chain"] = function(...) f[true and "chain"] = function(...)
local ret for _, v in ipairs(...) do
for _, v in ipairs {...} do
if type(v) == "table" then if type(v) == "table" then
for _, vv in ipairs(v) do for _, vv in ipairs(v) do
local copy = ret
vv = autofunc(vv) vv = autofunc(vv)
ret = ret and function(...) ret = ret and function(...)
return vv(copy(...)) return vv(ret(...))
end or vv end or vv
end end
else else
local copy = ret
v = autofunc(v) v = autofunc(v)
ret = ret and function(...) ret = ret and function(...)
return v(copy(...)) return v(ret(...))
end or v end or v
end end
end end
@ -284,7 +271,6 @@ function f.new(fnext)
return { return {
all = f.all, all = f.all,
any = f.any, any = f.any,
arg = f.arg,
chain = f.chain, chain = f.chain,
concat = f.concat, concat = f.concat,
const = f.const, const = f.const,
@ -299,7 +285,6 @@ function f.new(fnext)
index = f.index, index = f.index,
index_into = f.index_into, index_into = f.index_into,
indices = f.indices, indices = f.indices,
isf = f.isf,
keys = f.keys, keys = f.keys,
map = f.map, map = f.map,
new = f.new, new = f.new,
@ -386,7 +371,7 @@ function f:concat(...)
local sum, last = 0, 0 local sum, last = 0, 0
for i = 1, #fs do for i = 1, #fs do
fs[i] = f.isf(fs[i]) and fs[i] or f.from(fs[i]) fs[i] = is_f(fs[i]) and fs[i] or f.from(fs[i])
end end
return f.new(function() return f.new(function()

View file

@ -19,21 +19,15 @@ Balatest = Balatest
--- @type { constants?: { TEN: table }, new: (fun(self: self, arr?: number[], sign?: number, noNormalize?: boolean): table), pow: (fun(x: number, y: number): number) } --- @type { constants?: { TEN: table }, new: (fun(self: self, arr?: number[], sign?: number, noNormalize?: boolean): table), pow: (fun(x: number, y: number): number) }
Big = Big Big = Big
--- @type table? --- @type table
CardSleeves = CardSleeves CardSleeves = CardSleeves
--- @type table|fun(obj: SMODS.Back): SMODS.Back --- @type fun(obj: SMODS.Back): SMODS.Back
CardSleeves.Sleeve = CardSleeves.Sleeve CardSleeves.Sleeve = CardSleeves.Sleeve
--- @type {aliases: { [string]: [string] }}
Cryptid = Cryptid
--- @type fun(area: CardArea, ...: ...): Card --- @type fun(area: CardArea, ...: ...): Card
create_card_for_shop = create_card_for_shop create_card_for_shop = create_card_for_shop
--- @type boolean|table
G.Bakery_charm_area.cards[1].ability.extra = G.Bakery_charm_area.cards[1].ability.extra
SMODS.Mods.Roland.config = require "config" SMODS.Mods.Roland.config = require "config"
---@type userdata|{getWidth: fun(self: self): number} ---@type userdata|{getWidth: fun(self: self): number}

View file

@ -1,59 +1,5 @@
local f = assert(SMODS.load_file "src/lib/funky.lua")() or require "lib.funky" local f = assert(SMODS.load_file "src/lib/funky.lua")() or require "lib.funky"
---@param v string
---@return Card|Tag
local function add(v)
if not G.P_TAGS[v] then
return SMODS.add_card {no_edition = true, key = v}
end
local tag = Tag(v)
if tag.name == "Orbital Tag" then
local hands = f(G.GAME.hands):where "visible":keys():table()
tag.ability.orbital_hand = pseudorandom_element(hands, pseudoseed "Roland_c_orbital_tag")
end
add_tag(tag)
return tag
end
local function simplify(x)
return type(x) == "string" and x:lower():gsub("%s", ""):gsub("_", ""):gsub("^the", "") or x
end
local function flatten(v)
return type(v) ~= "table" and {v} or (f.isf(v) and v:table() or v)
end
---@param it string
local function find(it)
if (G.P_CENTERS[it] or {}).config then
return it
end
local match = simplify(it)
local pool = f(G.P_CENTER_POOLS):any(f.chain(f.arg(2), simplify, f.eq(match)))
if type(pool) == "table" and next(pool) then
return pseudorandom_element(pool, pseudoseed "Roland_c").key
end
if Cryptid and Cryptid.aliases and Cryptid.aliases[it] then
return Cryptid.aliases[it]
end
return f(G.localization.descriptions)
:flatmap(flatten)
:where(type, "table")
:where(f.chain(f.arg(2), f.index_into(G.P_CENTERS), "config"))
:where(function(v, k)
return match == simplify(k) or match == simplify(v.name)
end)
:keys()
:any()
end
local function protect(fun) local function protect(fun)
return function() return function()
local res, ret = pcall(fun) local res, ret = pcall(fun)
@ -110,35 +56,4 @@ local function u()
G.STATE ~= G.STATES.PLAY_TAROT) G.STATE ~= G.STATES.PLAY_TAROT)
end end
--- Creates one or more cards. return {f, q, u}
---@param ... any
---@return Card|Tag|(Card|Tag[])
local function c(...)
local cards = f {...}
:flatmap(flatten)
:where(type, "string")
:map(string.lower)
:map(find)
:where(f.id)
:map(add)
:values()
:table()
return #cards > 1 and cards or cards[1]
end
return {f, q, u, setmetatable({}, {
__call = function(_, ...)
return c(...)
end,
__index = function(_, k)
return c(k)
end,
__newindex = function(_, k, v)
local n = tonumber(v)
for _ = 1, type(n) == "number" and n or 1 do
c(k)
end
end,
})}

View file

@ -52,11 +52,9 @@ q {
-- G.ARGS.LOC_COLOURS["Bakery_credit_bg_Roland_" .. k] = v.bg -- G.ARGS.LOC_COLOURS["Bakery_credit_bg_Roland_" .. k] = v.bg
end) end)
if not SMODS.Mods.DebugPlus or not SMODS.Mods.Roland.config.import_funky then if SMODS.Mods.DebugPlus and SMODS.Mods.Roland.config.import_funky then
return _G.f, _G.q, _G.u = unpack(qol)
end end
_G.f, _G.q, _G.u, _G.c = unpack(qol)
end, end,
} }

View file

@ -69,15 +69,15 @@ spectral {
table.insert(info_queue, G.P_CENTERS.m_stone) table.insert(info_queue, G.P_CENTERS.m_stone)
end, end,
can_use = function() can_use = function()
return next(G.hand.cards) and u() return u() and not not next(G.hand.cards)
end, end,
use = function(_, card) use = function(_, card)
q { q {
trigger = "after", trigger = "after",
delay = 0.4, delay = 0.4,
func = function() func = function()
card:juice_up(0.3, 0.5)
play_sound("tarot1") play_sound("tarot1")
card:juice_up(0.3, 0.5)
end, end,
} }
@ -89,8 +89,8 @@ spectral {
delay = 0.15, delay = 0.15,
func = function() func = function()
v:flip() v:flip()
v:juice_up(0.3, 0.3)
play_sound("card1", percent) play_sound("card1", percent)
v:juice_up(0.3, 0.3)
return true return true
end, end,
} }
@ -110,8 +110,8 @@ spectral {
delay = 0.15, delay = 0.15,
func = function() func = function()
v:flip() v:flip()
v:juice_up(0.3, 0.3)
play_sound("tarot2", percent, 0.6) play_sound("tarot2", percent, 0.6)
v:juice_up(0.3, 0.3)
return true return true
end, end,
} }
@ -155,7 +155,7 @@ spectral {
return {vars = {card.ability.extra.amount}} return {vars = {card.ability.extra.amount}}
end, end,
can_use = function() can_use = function()
return next(G.playing_cards) and u() return #G.playing_cards > 1 and not not u()
end, end,
use = function(_, card) use = function(_, card)
local function destructible(v) local function destructible(v)

View file

@ -192,9 +192,9 @@ Balatest.TestPlay {
} }
Balatest.TestPlay { Balatest.TestPlay {
category = {"blind", "mitotic"}, category = {"blind", "xerox"},
name = "mitotic", name = "xerox",
blind = "bl_Roland_mitotic", blind = "bl_Roland_xerox",
execute = function() execute = function()
Balatest.discard {"2S"} Balatest.discard {"2S"}
end, end,
@ -204,9 +204,9 @@ Balatest.TestPlay {
} }
Balatest.TestPlay { Balatest.TestPlay {
category = {"blind", "mitotic"}, category = {"blind", "xerox"},
name = "mitotic_disabled", name = "xerox_disabled",
blind = "bl_Roland_mitotic", blind = "bl_Roland_xerox",
jokers = {"j_chicot"}, jokers = {"j_chicot"},
execute = function() execute = function()
Balatest.discard {"2S"} Balatest.discard {"2S"}

View file

@ -2,6 +2,330 @@ if not Balatest then
return return
end 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.levels, 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.levels, 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.levels, 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.levels, 1)
end,
}
Balatest.TestPlay { Balatest.TestPlay {
category = {"joker", "martingale"}, category = {"joker", "martingale"},
name = "martingale_oops", name = "martingale_oops",
@ -10,7 +334,7 @@ Balatest.TestPlay {
Balatest.play_hand {"2S"} Balatest.play_hand {"2S"}
end, end,
assert = function() assert = function()
Balatest.assert_chips(7) Balatest.assert_chips(7 * 2)
end, end,
} }
@ -23,6 +347,6 @@ Balatest.TestPlay {
Balatest.play_hand {"2S"} Balatest.play_hand {"2S"}
end, end,
assert = function() assert = function()
Balatest.assert_chips(1 / 0) Balatest.assert_chips(7 * math.pow(2, 32))
end, end,
} }

View file

@ -2,6 +2,22 @@ if not Balatest then
return return
end 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 { Balatest.TestPlay {
category = {"spectral", "void"}, category = {"spectral", "void"},
name = "spectral", name = "spectral",

View file

@ -2,16 +2,11 @@ local f, q = (... or require "lib.shared")[1], (... or require "lib.shared")[2]
SMODS.Joker:take_ownership("joker", {cost = 1}, true) SMODS.Joker:take_ownership("joker", {cost = 1}, true)
local orig_set_debuff = Card.set_debuff local orig_set_debuff = Card.set_debuff
function Card:set_debuff(should_debuff, ...) function Card:set_debuff(...)
if self.ability.Roland_crimson ~= nil then
self.ability.Roland_crimson = not not should_debuff
return
end
if SMODS.get_enhancements(self).m_wild and SMODS.Mods.Roland.config.no_wild_debuff then if SMODS.get_enhancements(self).m_wild and SMODS.Mods.Roland.config.no_wild_debuff then
self.debuff = false self.debuff = false
else else
orig_set_debuff(self, should_debuff, ...) orig_set_debuff(self, ...)
end end
end end

View file

@ -22,13 +22,10 @@ SMODS.Atlas {
voucher { voucher {
key = "ceres", key = "ceres",
pronouns = "it_its", pronouns = "it_its",
config = {extra = {amount = 1, hand_type = "Flush House"}}, config = {hand_type = "Flush House"},
attributes = {"planet", "passive", "hand_type", "space"}, attributes = {"planet", "passive", "hand_type", "space"},
loc_vars = function(_, _, card)
return {vars = {card.ability.extra.amount}}
end,
in_pool = function(self) in_pool = function(self)
return G.GAME.hands[self.config.extra.hand_type].visible return G.GAME.hands[self.config.hand_type].visible
end, end,
} }
@ -36,9 +33,6 @@ voucher {
key = "neptune", key = "neptune",
pronouns = "it_its", pronouns = "it_its",
requires = {"v_Roland_ceres"}, requires = {"v_Roland_ceres"},
config = {extra = {amount = 2, hand_type = "Straight Flush"}}, config = {hand_type = "Straight Flush"},
attributes = {"planet", "passive", "hand_type", "space"}, attributes = {"planet", "passive", "hand_type", "space"},
loc_vars = function(_, _, card)
return {vars = {card.ability.extra.amount}}
end,
} }