Add new art, modernize, nerf invisible tag

This commit is contained in:
Emik 2026-06-02 17:42:40 +02:00
parent 554fdf250a
commit 54e35d3d36
Signed by: emik
GPG key ID: 6B0CD72A5E503BDF
18 changed files with 122 additions and 51 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 845 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View file

@ -403,7 +403,12 @@ return {
},
tag_Roland_invisible = {
name = "Invisible Tag",
text = {"{C:attention}Duplicate {}a random Joker", "{C:inactive}(Must have room)"},
text = {
"{C:attention}Duplicate {}a random",
"Joker after {C:attention}#1#{} rounds",
"{C:inactive}(Must have room)",
"{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)",
},
},
},
Tarot = {

View file

@ -3,20 +3,20 @@
"id": "Roland",
"name": "Roland",
"prefix": "Roland",
"author": [
"Emik"
],
"version": "2.7.5",
"version": "2.8.0",
"badge_colour": "8BE9FD",
"display_name": "Roland",
"main_file": "src/main.lua",
"badge_text_colour": "44475A",
"display_name": "Roland",
"description": "Adds mechanics that are meant to have interesting interactions with the base game. Not meant to be balanced, but not entirely broken either.",
"provides": [],
"conflicts": [],
"author": [
"Emik"
],
"dependencies": [
"Steamodded (>=1.0~*)",
"Steamodded (>=1.0.0~BETA-1606b)",
"Lovely (>=0.6)",
"Bakery (>=0.1.26~*)"
"Bakery (>=3.2.0~*)"
]
}

View file

@ -22,6 +22,7 @@ local back = (function()
return (calculate and G.GAME.selected_sleeve ~= "sleeve_Roland_" .. key) and calculate(self, ...) or nil
end
tbl.artist = tbl.artist and "Roland_" .. tbl.artist or nil
tbl.pos = {x = x, y = 0}
tbl.atlas = "back"
@ -91,7 +92,7 @@ local _ = _G["CardSleeves"] and SMODS.Atlas {
back {
key = "blossom",
pronouns = "any_all",
artist = "Roland_bakersdozenbagels",
artist = "bakersdozenbagels",
config = {extra = {alt_times = 4, times = 2}},
attributes = {"boss_blind"},
loc_vars = function(self, _, _)
@ -133,7 +134,7 @@ back {
back {
key = "swapper",
pronouns = "he_him",
artist = "Roland_bakersdozenbagels",
artist = "bakersdozenbagels",
attributes = {"spectral", "tarot"},
apply = function(self)
local modifiers = G.GAME.modifiers

View file

@ -347,6 +347,11 @@ function SMODS.current_mod:calculate(context)
local _ = type(G.calc) == "function" and G.calc(f(context):keys():string())
local improbable, orig = G.GAME.modifiers.Roland_improbable, G.GAME.probabilities
local _ = context.end_of_round and
context.main_eval and
not context.blueprint and
G.P_TAGS.tag_Roland_invisible.increment()
-- Normally unreachable since we set it to nil ourselves,
-- but other mods may want to use this modifier.
if improbable == false then

View file

@ -95,6 +95,7 @@ SMODS.Challenge {
key = "Eternally_Amber",
rules = {custom = {{id = "Roland_Eternally_Amber"}, {id = "Roland_Showdown_Amber"}}},
restrictions = amber,
pronouns = "they_them",
calculate = function(_, context)
local function slide(pitch)
q(function()
@ -132,6 +133,7 @@ SMODS.Challenge {
key = "Eternally_Cerulean",
rules = {custom = {{id = "Roland_Eternally_Cerulean"}, {id = "Roland_Showdown_Cerulean"}}},
restrictions = cerulean,
pronouns = "she_her",
calculate = function(_, context)
if not context.hand_drawn then
return
@ -157,6 +159,7 @@ SMODS.Challenge {
key = "Eternally_Crimson",
rules = {custom = {{id = "Roland_Eternally_Crimson"}, {id = "Roland_Showdown_Crimson"}}},
restrictions = crimson,
pronouns = "she_her",
calculate = function(_, context)
local _ = context.blind_defeated and f(G.jokers.cards):each(function(v)
v.ability.Roland_crimson_heart_chosen = nil
@ -216,6 +219,7 @@ SMODS.Challenge {
key = "Eternally_Verdant",
rules = {custom = {{id = "Roland_Eternally_Verdant"}, {id = "Roland_Showdown_Verdant"}}},
restrictions = verdant,
pronouns = "she_her",
calculate = function(_, context)
if context.setting_blind then
G.GAME.modifiers.Roland_Eternally_Verdant = true
@ -237,6 +241,7 @@ SMODS.Challenge {
key = "Eternally_Violet",
rules = {custom = {{id = "Roland_Eternally_Violet"}, {id = "Roland_Showdown_Violet"}}},
restrictions = violet,
pronouns = "she_they",
calculate = function(_, context)
if context.setting_blind then
G.GAME.blind.chips = G.GAME.blind.chips * 6

View file

@ -53,7 +53,7 @@ charm {
G.STATE = G.STATES.SHOP
G.GAME.shop_free = nil
G.GAME.shop_d6ed = nil
G.STATE_COMPLETE = false
-- G.STATE_COMPLETE = false
play_sound("whoosh1", 1.33333, 0.8)
play_sound("whoosh1", 0.66666, 0.8)
end)

View file

@ -87,6 +87,7 @@ SMODS.Edition {
shader = "frozen",
sound = {sound = "Roland_frozen", per = 1, vol = 0.8},
attributes = {"passive", "scaling", "mod_chance"},
pronouns = "any_all",
weight = 8,
extra_cost = 4,
in_shop = true,

View file

@ -69,6 +69,21 @@ local function localize_card(card, fallback)
}
end
---@param card Card
---@return boolean
local function has_rank_and_suit(card)
return not SMODS.has_no_rank(card) and not SMODS.has_no_suit(card)
end
---@param value table
---@return fun(other: table): boolean
local function ranksuitnq(value)
return function(other)
local v, o = value.base or value, other.base or other
return value == other or v.suit ~= o.suit or v.value ~= o.value
end
end
SMODS.Atlas {
key = "joker",
path = "joker.png",
@ -157,7 +172,7 @@ joker {
joker {
key = "sunny",
pronouns = "they_them",
pronouns = "it_its",
artist = "char",
attributes = {"food", "on_sell"},
cost = 2,
@ -192,7 +207,7 @@ joker {
joker {
key = "hardboiled",
pronouns = "they_them",
pronouns = "it_its",
attributes = {"food", "editions", "modify_card", "on_sell"},
cost = 5,
rarity = 2,
@ -386,7 +401,7 @@ joker {
joker {
key = "snowsquall",
pronouns = "they_them",
pronouns = "he_they",
config = {extra = {mult_gain = 1, mult = 0}},
attributes = {"mult", "scaling", "hand_type"},
cost = 6,
@ -420,7 +435,7 @@ joker {
joker {
key = "arctic",
pronouns = "it_its",
pronouns = "they_them",
cost = 10,
rarity = 3,
config = {extra = {frozen = 2, non_frozen = 1}},
@ -529,7 +544,7 @@ joker {
joker {
key = "bulldozer",
pronouns = "it_its",
pronouns = "she_her",
attributes = {"xmult"},
cost = 6,
rarity = 2,
@ -592,7 +607,7 @@ joker {
key = "nilly",
pronouns = "any_all",
config = {extra = {flipped = false}},
attributes = {"xmult"},
attributes = {"xmult", "bakery_double_sided"},
cost = 0,
rarity = 2,
eternal_compat = true,
@ -602,10 +617,6 @@ joker {
local key = card.ability.extra.flipped and "b_Roland_enabled" or "b_Roland_disabled"
return {vars = {localize {type = "variable", key = key}}}
end,
inject = function(...)
SMODS.Joker.inject(...)
Bakery_API.double_sided_jokers.j_Roland_nilly = true
end,
calculate = function(_, card, context)
if (not context.joker_main or not card.ability.extra.flipped) and not context.forcetrigger then
return
@ -628,7 +639,7 @@ joker {
joker {
key = "amber",
pronouns = "he_they",
pronouns = "they_them",
config = {extra = {xmult = 3}},
pixel_size = {w = 68, h = 68},
attributes = {"xmult"},
@ -709,7 +720,7 @@ joker {
joker {
key = "idle",
pronouns = "they_them",
pronouns = "any_all",
rarity = 2,
Roland_idle_capacity = 6,
cost = G.P_CENTERS.j_idol.cost,
@ -749,28 +760,39 @@ joker {
end):any(f().eq(context.other_card)) and {xmult = card.ability.extra.xmult} or nil
end,
Bakery_can_use = function(self, card)
local key = self:Roland_idle_status(card)
local new_cards = G.hand.highlighted
local extra = card.ability.extra
if extra.last_text ~= key then
extra.last_text = key
Bakery_API.rehighlight(card)
end
local function all_cards()
return f(new_cards):concat(extra.cards or {})
end
return not card.debuff and
next(G.hand.highlighted) and
self.Roland_idle_capacity - #card.ability.extra.cards - #G.hand.highlighted >= 0 and
f(G.hand.highlighted):all(function(v)
return not SMODS.has_no_rank(v) and
not SMODS.has_no_suit(v) and
f(card.ability.extra.cards or {}):all(function(o)
return v.base.suit ~= o.suit or v.base.value ~= o.value
end)
next(new_cards) and
self.Roland_idle_capacity - #extra.cards - #new_cards >= 0 and
f(new_cards):all(has_rank_and_suit) and
all_cards():all(function(v)
return all_cards():all(ranksuitnq(v))
end)
end,
Bakery_use_button_text = function(self, card)
local key = card.debuff and "b_Roland_debuffed" or
(self.Roland_idle_capacity - #card.ability.extra.cards > 0 and "b_Roland_add" or "b_Roland_full")
return localize {type = "variable", key = key}
return localize {type = "variable", key = self:Roland_idle_status(card)}
end,
Bakery_use_joker = function(_, card)
f(G.hand.highlighted):each(function(v)
table.insert(card.ability.extra.cards, {suit = v.base.suit, value = v.base.value})
end)
end,
Roland_idle_status = function(self, card)
return card.debuff and "b_Roland_debuffed" or
(self.Roland_idle_capacity - #card.ability.extra.cards > 0 and "b_Roland_add" or "b_Roland_full")
end,
}
joker {
@ -827,7 +849,7 @@ end
joker {
key = "artemis",
pronouns = "she_they",
pronouns = "any_all",
cost = 6,
rarity = 2,
config = {extra = {
@ -837,13 +859,10 @@ joker {
flipped = false,
sequence = {"c_earth", "c_mars", "c_earth"},
}},
attributes = {"economy", "scaling", "planet", "space", "bakery_double_sided"},
calc_dollar_bonus = function(_, card)
return card.ability.extra.dollars
end,
inject = function(...)
SMODS.Joker.inject(...)
Bakery_API.double_sided_jokers.j_Roland_artemis = true
end,
loc_vars = function(_, info_queue, card)
local extra = card.ability.extra
@ -895,7 +914,7 @@ joker {
cost = 7,
rarity = 3,
config = {extra = {probability = 1, probability_mult = 2, reset = 1}},
attributes = {"hands", "mod_chance", "scaling"},
attributes = {"hands", "mod_chance", "scaling", "reset"},
eternal_compat = true,
blueprint_compat = false,
perishable_compat = true,

View file

@ -107,7 +107,7 @@ end
---@nodiscard
function f.index(v)
return function(x)
return x[v]
return x and x[v]
end
end
@ -512,7 +512,7 @@ end
---@generic K, V
---@param self F|{ [K]: V }
---@param func F|fun(v: V, k: K): boolean
---@param func F|fun(v: V, k: K): any
---@return boolean|V
---@nodiscard
---@overload fun(self: F|{ [K]: V }, func: string?): boolean|V
@ -530,7 +530,7 @@ end
---@generic K, V
---@param self F|{ [K]: V }
---@param func F|fun(v: V, k: K): boolean
---@param func F|fun(v: V, k: K): any
---@return boolean|V
---@nodiscard
---@overload fun(self: F|{ [K]: V }, func: string?): boolean|V
@ -548,7 +548,7 @@ end
---@generic K, V
---@param self F|{ [K]: V }
---@param func F|fun(v: V, k: K): boolean
---@param func F|fun(v: V, k: K): any
---@return integer
---@nodiscard
---@overload fun(self: F|{ [K]: V }, func: string): integer

View file

@ -23,7 +23,7 @@ local function protect_ev(fun)
return fun
end
---@alias Attributes "mult"|"chips"|"xmult"|"xchips"|"score"|"xscore"|"blindsize"|"xblindsize"|"balance"|"swap"|"retrigger"|"scaling"|"reset"|"suit"|"diamonds"|"hearts"|"spades"|"clubs"|"hand_type"|"rank"|"ace"|"two"|"three"|"four"|"five"|"six"|"seven"|"eight"|"nine"|"ten"|"jack"|"queen"|"king"|"face"|"economy"|"generation"|"destroy_card"|"hands"|"discard"|"hand_size"|"chance"|"joker_slot"|"mod_chance"|"copying"|"full_deck"|"passive"|"joker"|"tarot"|"planet"|"spectral"|"enhancements"|"seals"|"editions"|"tag"|"skip"|"modify_card"|"perma_bonus"|"prevents_death"|"boss_blind"|"reroll"|"on_sell"|"sell_value"|"food"|"space"
---@alias Attributes "mult"|"chips"|"xmult"|"xchips"|"score"|"xscore"|"blindsize"|"xblindsize"|"balance"|"swap"|"retrigger"|"scaling"|"reset"|"suit"|"diamonds"|"hearts"|"spades"|"clubs"|"hand_type"|"rank"|"ace"|"two"|"three"|"four"|"five"|"six"|"seven"|"eight"|"nine"|"ten"|"jack"|"queen"|"king"|"face"|"economy"|"generation"|"destroy_card"|"hands"|"discard"|"hand_size"|"chance"|"joker_slot"|"mod_chance"|"copying"|"full_deck"|"passive"|"joker"|"tarot"|"planet"|"spectral"|"enhancements"|"seals"|"editions"|"tag"|"skip"|"modify_card"|"perma_bonus"|"prevents_death"|"boss_blind"|"reroll"|"on_sell"|"sell_value"|"food"|"space"|"bakery_double_sided"
if false then
-- This allows for better type inference.
SMODS.Mods.Roland.config = require "config"

View file

@ -52,8 +52,11 @@ end
SMODS.Atlas {
px = 256,
py = 256,
fps = 12,
frames = 12,
key = "modicon",
path = "icon.png",
atlas_table = "ANIMATION_ATLAS",
}
SMODS.current_mod.qol = qol

View file

@ -13,7 +13,7 @@ SMODS.Seal {
pos = {x = 0, y = 0},
attributes = {"destroy_card", "tag"},
badge_colour = HEX "a6a6a6ff",
pronouns = "he_him",
pronouns = "they_them",
calculate = function(_, card, context)
local function eq(v)
return v == card

View file

@ -36,7 +36,7 @@ SMODS.Sound {
spectral {
key = "afterimage",
pronouns = "he_they",
pronouns = "she_they",
artist = "aster",
config = {extra = {amount = 2}},
attributes = {"seal", "modify_card", "spectral"},
@ -69,6 +69,7 @@ spectral {
spectral {
key = "primal",
pronouns = "he_him",
artist = "aster",
attributes = {"enhancements", "modify_card", "spectral"},
loc_vars = function(_, info_queue)
table.insert(info_queue, G.P_CENTERS.m_stone)
@ -128,7 +129,7 @@ spectral {
spectral {
key = "refract",
pronouns = "he_him",
pronouns = "it_its",
artist = "aster",
config = {extra = {amount = 2}},
attributes = {"seal", "modify_card", "spectral"},

View file

@ -55,6 +55,7 @@ end
SMODS.Tag {
key = "freeze",
atlas = "tag",
pronouns = "any_all",
min_ante = 1,
pos = {x = 0, y = 0},
config = {amount = 5},
@ -73,6 +74,7 @@ SMODS.Tag {
if tag.triggered or
(tag.ability.amount or self.config.amount) <= 0 or
(context.card.edition and context.card.edition.Roland_frozen) or
context.type ~= "Bakery_score_card" then
return
end
@ -85,13 +87,42 @@ SMODS.Tag {
SMODS.Tag {
key = "invisible",
atlas = "tag",
pronouns = "any_all",
min_ante = 2,
pos = {x = 1, y = 0},
apply = function(_, tag)
config = {invis_rounds = 0, total_rounds = 2},
loc_vars = function(self, _, tag)
tag.ability = tag.ability or f(self.config):table()
local main_end = {}
local _ = f((G.jokers or {}).cards or {}):map "edition":any "negative" and
localize {type = "other", key = "remove_negative", nodes = main_end, vars = {}}
return {
vars = {
tag.ability.total_rounds or self.config.total_rounds,
tag.ability.invis_rounds or self.config.invis_rounds,
},
main_end = main_end[1],
}
end,
increment = function(self)
f(G.GAME.tags):where("key", "tag_Roland_invisible"):each(function(v)
v.ability = v.ability or {}
v.ability.invis_rounds = (v.ability.invis_rounds or self.config.invis_rounds) + 1
v:juice_up()
end)
end,
apply = function(self, tag)
local modifiers = G.GAME.modifiers
tag.ability = tag.ability or {}
local ab = tag.ability
ab.invis_rounds = ab.invis_rounds or self.config.invis_rounds
ab.total_rounds = ab.total_rounds or self.config.total_rounds
if tag.triggered or
not next(G.jokers.cards) or
ab.invis_rounds < ab.total_rounds or
#G.jokers.cards + (modifiers.Roland_invisible or 0) >= G.jokers.config.card_limit then
return
end
@ -101,7 +132,7 @@ SMODS.Tag {
tag:yep("!", G.C.GREY, function()
local copied = pseudorandom_element(G.jokers.cards, pseudoseed "Roland_invisible")
local copy = copy_card(copied)
local copy = copy_card(copied, nil, nil, nil, copied.edition and copied.edition.negative)
G.jokers:emplace(copy)
copy:add_to_deck()
modifiers.Roland_invisible = (modifiers.Roland_invisible or 0) - 1