diff --git a/assets/1x/icon.png b/assets/1x/icon.png index 3b52142..b129e83 100644 Binary files a/assets/1x/icon.png and b/assets/1x/icon.png differ diff --git a/assets/1x/spectral.png b/assets/1x/spectral.png index 9542615..a05c3b2 100644 Binary files a/assets/1x/spectral.png and b/assets/1x/spectral.png differ diff --git a/assets/2x/icon.png b/assets/2x/icon.png index 9da1c61..ee10a32 100644 Binary files a/assets/2x/icon.png and b/assets/2x/icon.png differ diff --git a/assets/2x/spectral.png b/assets/2x/spectral.png index 5fcb181..ba537b9 100644 Binary files a/assets/2x/spectral.png and b/assets/2x/spectral.png differ diff --git a/localization/en-us.lua b/localization/en-us.lua index 6a52171..fc5451e 100644 --- a/localization/en-us.lua +++ b/localization/en-us.lua @@ -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 = { diff --git a/manifest.json b/manifest.json index 48bc988..00f1473 100644 --- a/manifest.json +++ b/manifest.json @@ -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~*)" ] } \ No newline at end of file diff --git a/src/back.lua b/src/back.lua index f4830c7..7418cef 100644 --- a/src/back.lua +++ b/src/back.lua @@ -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 diff --git a/src/blind.lua b/src/blind.lua index d286ba9..6961d3a 100644 --- a/src/blind.lua +++ b/src/blind.lua @@ -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 diff --git a/src/challenge.lua b/src/challenge.lua index b6b2c85..f67f124 100644 --- a/src/challenge.lua +++ b/src/challenge.lua @@ -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 diff --git a/src/charm.lua b/src/charm.lua index 08c6ac4..7c411da 100644 --- a/src/charm.lua +++ b/src/charm.lua @@ -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) diff --git a/src/edition.lua b/src/edition.lua index ddc6c67..759b3ac 100644 --- a/src/edition.lua +++ b/src/edition.lua @@ -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, diff --git a/src/joker.lua b/src/joker.lua index 52224c3..02cd210 100644 --- a/src/joker.lua +++ b/src/joker.lua @@ -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, diff --git a/src/lib/funky.lua b/src/lib/funky.lua index c6f8baf..6b5e326 100644 --- a/src/lib/funky.lua +++ b/src/lib/funky.lua @@ -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 diff --git a/src/lib/shared.lua b/src/lib/shared.lua index 11169ae..a54fabe 100644 --- a/src/lib/shared.lua +++ b/src/lib/shared.lua @@ -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" diff --git a/src/main.lua b/src/main.lua index f055824..6387270 100644 --- a/src/main.lua +++ b/src/main.lua @@ -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 diff --git a/src/seal.lua b/src/seal.lua index 4461da2..8968f51 100644 --- a/src/seal.lua +++ b/src/seal.lua @@ -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 diff --git a/src/spectral.lua b/src/spectral.lua index 0439315..8cdc3f6 100644 --- a/src/spectral.lua +++ b/src/spectral.lua @@ -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"}, diff --git a/src/tag.lua b/src/tag.lua index 6b219e5..c5d2c06 100644 --- a/src/tag.lua +++ b/src/tag.lua @@ -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