From e5bd52a1a3d5a188d770b32f8569f0508f5a75b1 Mon Sep 17 00:00:00 2001 From: Emik Date: Sun, 1 Feb 2026 04:29:41 +0100 Subject: [PATCH] Add many new jokers --- lovely.toml | 21 +++++ src/back.lua | 25 ++--- src/blind.lua | 26 +++--- src/challenge.lua | 2 +- src/functional.lua | 4 +- src/joker.lua | 226 +++++++++++++++++++++++++++++++++++++++++++-- src/main.lua | 4 +- src/seal.lua | 31 +++++-- src/spectral.lua | 60 ++++++++++-- 9 files changed, 342 insertions(+), 57 deletions(-) diff --git a/lovely.toml b/lovely.toml index c6e8827..f79db91 100644 --- a/lovely.toml +++ b/lovely.toml @@ -64,3 +64,24 @@ pattern = "elseif G.GAME.round_resets.blind == G.P_BLINDS.bl_big then" position = "at" payload = "elseif G.GAME.blind_on_deck == 'Big' then" match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if self.seal == 'Purple' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then" +position = "at" +payload = """if self.seal == 'Purple' and + (next(SMODS.find_card "j_Roland_negative") or + #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit) then""" +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "local card = create_card('Tarot',G.consumeables, nil, nil, nil, nil, nil, '8ba')" +position = "after" +times = 1 +payload = """if next(SMODS.find_card "j_Roland_negative") then + card:set_edition "e_negative" +end""" +match_indent = true diff --git a/src/back.lua b/src/back.lua index c3f8ffc..326e54c 100644 --- a/src/back.lua +++ b/src/back.lua @@ -20,15 +20,6 @@ SMODS.Back { save_run() end, calculate = function(self, _, context) - local function disable() - for _ = 1, self.config.extra.times do - G.GAME.blind:disable() - end - - play_sound("timpani") - return true - end - if not context.setting_blind then return end @@ -36,7 +27,14 @@ SMODS.Back { local blinds = G.GAME.round_resets.blind_states if blinds.Small == "Current" or blinds.Big == "Current" then - q(disable) + q(function() + for _ = 1, self.config.extra.times do + G.GAME.blind:disable() + end + + play_sound "timpani" + return true + end) end end, } @@ -47,16 +45,13 @@ SMODS.Back { atlas = "void", pos = {x = 0, y = 0}, apply = function(_, _) - local function add_credit_card() + q(function() local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_credit_card", "Roland_go") card:add_to_deck() card:start_materialize() G.jokers:emplace(card) save_run() - return true - end - - q(add_credit_card) + end) end, calculate = function(_, _, context) if context.starting_shop then diff --git a/src/blind.lua b/src/blind.lua index 3a3631a..5a0fb7c 100644 --- a/src/blind.lua +++ b/src/blind.lua @@ -93,7 +93,7 @@ end SMODS.Blind { key = "improbable", boss = {min = 2, max = 10}, - boss_colour = HEX("009966"), + boss_colour = HEX "009966", atlas = "blind", pos = {x = 0, y = 0}, pronouns = "it_its", @@ -109,7 +109,7 @@ SMODS.Blind { SMODS.Blind { key = "nimble", boss = {min = 1, max = 10}, - boss_colour = HEX("0291fb"), + boss_colour = HEX "0291fb", atlas = "blind", pos = {x = 0, y = 1}, pronouns = "she_her", @@ -148,14 +148,14 @@ SMODS.Blind { SMODS.Blind { key = "divide", boss = {min = 4, max = 10}, - boss_colour = HEX("0291fb"), + boss_colour = HEX "0291fb", atlas = "blind", pos = {x = 0, y = 1}, pronouns = "they_them", mult = 2, dollars = 5, disable = function() - local function disable() + q(function() local count = #G.discard.cards f(G.discard.cards):take(count):foreach(function(v, i) @@ -165,12 +165,11 @@ SMODS.Blind { f(G.discard.cards):take(count):foreach(function(v, i) draw_card(G.hand, G.deck, i / count * 100, "up", false, v) end) - end - - q(disable) + end) end, set_blind = function() - local function force_hand() + -- Allows the background to ease in first before drawing cards. + q(function() local length = (#G.deck.cards - 2) / 2 for i = 0, length do @@ -182,17 +181,14 @@ SMODS.Blind { local card = G.deck.cards[#G.deck.cards - i] draw_card(G.hand, G.discard, i / length * 100, "down", false, card, nil, nil, true) end - end - - -- Allows the background to ease in first before drawing cards. - q(force_hand) + end) end, } SMODS.Blind { key = "tranquilizer", boss = {min = 4, max = 10}, - boss_colour = HEX("0291fb"), + boss_colour = HEX "0291fb", atlas = "blind", pos = {x = 0, y = 1}, pronouns = "they_them", @@ -249,7 +245,7 @@ SMODS.Blind { SMODS.Blind { key = "xerox", boss = {min = 2, max = 10}, - boss_colour = HEX("0291fb"), + boss_colour = HEX "0291fb", atlas = "blind", pos = {x = 0, y = 1}, pronouns = "they_them", @@ -267,7 +263,7 @@ SMODS.Blind { local count = #G.hand.highlighted f(G.hand.highlighted, ipairs):take(count):foreach(function(v, i) - local copy = copy_card(G.hand.highlighted[i]) + local copy = copy_card(v) copy:add_to_deck() table.insert(G.hand, copy) table.insert(cards_added, copy) diff --git a/src/challenge.lua b/src/challenge.lua index fce9721..4f4c434 100644 --- a/src/challenge.lua +++ b/src/challenge.lua @@ -9,7 +9,7 @@ local function adder(tbl) end local function is_banned_from_pastry(_, k) - return not k:find("_Bakery_") and not k:find("_Roland_") + return not k:find "_Bakery_" and not k:find "_Roland_" end local function is_center_banned_from_pastry(v, k) diff --git a/src/functional.lua b/src/functional.lua index 5b8e46c..9080bc6 100644 --- a/src/functional.lua +++ b/src/functional.lua @@ -23,7 +23,7 @@ local function protect_ev(fun) return fun end -local luaf = assert(SMODS.load_file("src/LuaFunctional/functional.lua"))() or require "src.LuaFunctional.functional" +local luaf = assert(SMODS.load_file "src/LuaFunctional/functional.lua")() or require "src.LuaFunctional.functional" if false then ---Returns the elements from the given `list`. This function is equivalent to @@ -52,7 +52,7 @@ if false then ---@return T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 ---@nodiscard function unpack(list, i, j) - error({list, i, j}) + error {list, i, j} end end diff --git a/src/joker.lua b/src/joker.lua index 51bfeeb..4db1107 100644 --- a/src/joker.lua +++ b/src/joker.lua @@ -65,10 +65,10 @@ SMODS.Joker { and loc_self.merge or {} local normal = (merge[1] or sinister) and {} or - pseudorandom_element(quotes.normal, pseudoseed("EscapeyQuotes")) or {} + pseudorandom_element(quotes.normal, pseudoseed "EscapeyQuotes") or {} local scared = (merge[1] or not sinister) and {} or - pseudorandom_element(quotes.scared, pseudoseed("EscapeyQuotes")) or {} + pseudorandom_element(quotes.scared, pseudoseed "EscapeyQuotes") or {} return { vars = { @@ -127,7 +127,7 @@ SMODS.Joker { 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) + v:start_dissolve({HEX "57ecab"}, nil, 1.6) end) if not any_carbon then @@ -155,7 +155,7 @@ SMODS.Joker { local function fast_delete(v) return function() - attention_text({ + attention_text { scale = 0.7, align = "cm", text = "ESC", @@ -163,7 +163,7 @@ SMODS.Joker { colour = G.C.WHITE, cover_colour = G.C.BLACK, hold = 0.3 / G.SETTINGS.GAMESPEED, - }) + } play_sound("cancel", 1.66, 0.5) v.HUD_tag.states.visible = false @@ -174,7 +174,7 @@ SMODS.Joker { local hand = common_hand() if hand == "all" or hand == "allhands" or hand == "all_hands" then - update(localize("k_all_hands"), "...", "...", "") + update(localize "k_all_hands", "...", "...", "") elseif G.GAME.hands[hand or "NO_HAND_SPECIFIED"] then update( localize(hand, "poker_hands"), @@ -202,7 +202,7 @@ SMODS.Joker { end) else f(consumables):foreach(function(v) - v:start_dissolve({HEX("57ecab")}, nil, 1.6) + v:start_dissolve({HEX "57ecab"}, nil, 1.6) destroyed = destroyed + 1 end) end @@ -216,6 +216,218 @@ SMODS.Joker { end, } +SMODS.Joker { + key = "temp", + atlas = "void", + pronouns = "they_them", + pos = {x = 0, y = 0}, + cost = 1, + rarity = 1, + config = {extra = {chips = 30}}, + loc_vars = function(_, _, card) + return {vars = {card.ability.extra.chips}} + end, + calculate = function(_, card, context) + return context.joker_main and {card = card, chips = card.ability.extra.chips} or nil + end, +} + +SMODS.Joker { + key = "temp2", + atlas = "void", + pronouns = "they_them", + pos = {x = 0, y = 0}, + cost = 6, + rarity = 2, + loc_vars = function(self, _, _) + return {vars = {self.xmult()}} + end, + calculate = function(self, card, context) + return context.joker_main and {card = card, xmult = self.xmult()} or nil + end, + xmult = function() + return ((G.GAME or {}).blind or {}).mult or 1 + end, +} + +SMODS.Joker { + key = "temp3", + atlas = "void", + pronouns = "they_them", + pos = {x = 0, y = 0}, + cost = 8, + rarity = 3, + config = {extra = {probability = 1}}, + loc_vars = function(_, _, card) + return {vars = {card.ability.extra.probability}} + end, + calculate = function(_, card, context) + if context.mod_probability then + return {numerator = card.ability.extra.probability} + elseif context.after and not context.blueprint then + card.ability.extra.probability = card.ability.extra.probability + 1 + end + end, +} + +SMODS.Joker { + key = "temp4", + atlas = "void", + pronouns = "they_them", + pos = {x = 0, y = 0}, + cost = 8, + rarity = 3, + calculate = function(_, _, context) + return context.joker_main and {mult = hand_chips} or nil + end, +} + +SMODS.Joker { + key = "temp5", + atlas = "void", + pronouns = "they_them", + pos = {x = 0, y = 0}, + cost = 2, + rarity = 1, + calculate = function(_, _, context) + local _ = context.selling_self and + draw_card(G.deck, G.hand, 100, "up", false, G.deck.cards[#G.deck.cards]) + end, +} + +SMODS.Joker { + key = "temp6", + atlas = "void", + pronouns = "they_them", + pos = {x = 0, y = 0}, + config = {extra = {money = 2}}, + cost = 6, + rarity = 2, + loc_vars = function(_, _, card) + return {vars = {card.ability.extra.money}} + end, + calculate = function(_, card, context) + return context.remove_playing_cards and + {dollars = card.ability.extra.money * #context.removed, card = card} or nil + end, +} + +SMODS.Joker { + key = "temp7", + atlas = "void", + pronouns = "they_them", + pos = {x = 0, y = 0}, + cost = 3, + rarity = 1, + calculate = function(_, _, context) + return context.repetition and + context.cardarea == G.play and + context.scoring_name == "Four of a Kind" and {repetitions = 1} or nil + end, +} + +SMODS.Joker { + key = "temp8", + atlas = "void", + pronouns = "they_them", + pos = {x = 0, y = 0}, + config = {extra = {mult = 0}}, + cost = 8, + rarity = 2, + calculate = function(_, card, context) + if context.joker_main then + return {mult = card.ability.extra.mult} + end + + if context.individual and + context.cardarea == "unscored" and + context.scoring_name == "Four of a Kind" then + card.ability.extra.mult = card.ability.extra.mult + context.other_card.base.nominal + end + end, +} + +SMODS.Joker { + key = "temp9", + atlas = "void", + pronouns = "they_them", + pos = {x = 0, y = 0}, + config = {extra = {mult = 0}}, + cost = 8, + rarity = 3, + calculate = function(_, _, context) + if not context.individual or + context.cardarea ~= "unscored" or + context.scoring_name ~= "Four of a Kind" then + return + end + + q(function() + playing_card_joker_effects(f(G.play):take(#G.play):map(function(v) + G.playing_card = (G.playing_card and G.playing_card + 1) or 1 + G.deck.config.card_limit = G.deck.config.card_limit + 1 + local copy = copy_card(v, nil, nil, G.playing_card) + copy:add_to_deck() + G.hand:emplace(copy) + copy:start_materialize() + table.insert(G.playing_cards, copy) + return copy + end):into()) + end) + end, +} + +SMODS.Joker { + key = "temp10", + atlas = "void", + pronouns = "they_them", + pos = {x = 0, y = 0}, + config = {extra = {xmult = 1.5}}, + cost = 8, + rarity = 3, + calculate = function(_, card, context) + if context.individual and + context.cardarea == "unscored" and + SMODS.has_enhancement(context.other_card, "m_wild") then + return {xmult = card.ability.extra.xmult} + end + end, +} + +SMODS.Joker { + key = "negative", + atlas = "void", + pronouns = "they_them", + pos = {x = 0, y = 0}, + cost = 6, + rarity = 2, +} + +SMODS.Joker { + key = "mrsbones", + atlas = "void", + pronouns = "they_them", + pos = {x = 0, y = 0}, + config = {extra = {xmult = 4}}, + cost = 8, + rarity = 3, + calculate = function(_, card, context) + if context.joker_main then + return {xmult = card.ability.extra.xmult} + end + + if context.blind_defeated and G.GAME.chips / card.ability.extra.xmult < G.GAME.blind.chips then + q(function() + G.hand_text_area.blind_chips:juice_up() + G.hand_text_area.game_chips:juice_up() + play_sound("tarot1") + card:start_dissolve() + return true + end) + end + end, +} + SMODS.Joker { key = "martingale", atlas = "martingale", diff --git a/src/main.lua b/src/main.lua index a118262..f10035f 100644 --- a/src/main.lua +++ b/src/main.lua @@ -1,4 +1,4 @@ -local qol = assert(SMODS.load_file("src/functional.lua"))() or require "src.functional" +local qol = assert(SMODS.load_file "src/functional.lua")() or require "src.functional" qol[1] {"challenge", "spectral", "blind", "joker", "back", "seal"}:foreach(function(v) assert(SMODS.load_file("src/" .. v .. ".lua"))(qol) @@ -20,5 +20,5 @@ SMODS.Atlas { } SMODS.current_mod.optional_features = function() - return {cardareas = {deck = true}} + return {cardareas = {deck = true, unscored = true}} end diff --git a/src/seal.lua b/src/seal.lua index a8150ed..2aa0ecb 100644 --- a/src/seal.lua +++ b/src/seal.lua @@ -1,4 +1,4 @@ -local f, _ = unpack(... or require "src.functional") +local f, q = unpack(... or require "src.functional") -- SMODS.Atlas { -- px = 71, @@ -7,30 +7,43 @@ local f, _ = unpack(... or require "src.functional") -- path = "seal.png", -- } SMODS.Seal { - name = "Frost", - key = "frost", - badge_colour = HEX("12f254"), + key = "glass", + name = "RolandGlass", + badge_colour = HEX "12f254", atlas = "void", pos = {x = 0, y = 0}, config = {ready = true}, calculate = function(_, card, context) if context.setting_blind or context.starting_shop then - card.Roland_frost = nil + card.Roland_glass = nil end - if not context.end_of_round or card.area ~= G.deck or card.Roland_frost then + if card.Roland_glass then return end - card.Roland_frost = true - local tag = Tag(get_next_tag_key("Roland_frost")) + if G.STATE == G.STATES.DRAW_TO_HAND and card == context.other_card and card.area == G.hand then + card.Roland_glass = true + + return q(function() + card:shatter() + end) + end + + if not context.end_of_round then + return + end + + card.Roland_glass = true + local tag = Tag(get_next_tag_key "Roland_glass") if tag.name == "Orbital Tag" then tag.ability.orbital_hand = pseudorandom_element( f(G.GAME.hands):filter(function(v) return v.visible end):into(), - pseudoseed("Roland_frost") + + pseudoseed "Roland_glass" ) end diff --git a/src/spectral.lua b/src/spectral.lua index a588b64..b3c49be 100644 --- a/src/spectral.lua +++ b/src/spectral.lua @@ -1,6 +1,9 @@ local f, q, u = unpack(... or require "src.functional") -SMODS.Sound({key = "void", path = "void.ogg"}) +SMODS.Sound { + key = "void", + path = "void.ogg", +} SMODS.Atlas { px = 71, @@ -30,12 +33,12 @@ SMODS.Consumable { can_use = function(_, card) return u() and card.ability.extra.amount == #Bakery_API.get_highlighted() end, - use = function(_, card, _, _) + use = function(_, card) f(Bakery_API.get_highlighted()):foreach(function(v) q { delay = 0.1, func = function() - v:set_edition({negative = true}) + v:set_edition {negative = true} v:juice_up(0.5, 0.5) end, } @@ -51,6 +54,51 @@ SMODS.Consumable { end, } +SMODS.Consumable { + key = "dual", + set = "Spectral", + pos = {x = 0, y = 0}, + cost = 6, + atlas = "afterimage", + pronouns = "he_they", + config = {extra = {amount = 2}}, + loc_vars = function(_, _, card) + return {vars = {card.ability.extra.amount}} + end, + can_use = function() + return u() and #G.hand.cards > 0 + end, + use = function(_, card, _) + local cards = f(G.hand.cards, ipairs):into() + pseudoshuffle(cards, pseudoseed "Roland_two") + + f(cards):take(card.ability.extra.amount):foreach(function(v) + v:set_seal(SMODS.poll_seal {guaranteed = true}) + end) + end, +} + +SMODS.Consumable { + key = "glass", + set = "Spectral", + pos = {x = 0, y = 0}, + cost = 6, + atlas = "afterimage", + pronouns = "he_they", + config = {extra = {amount = 1}}, + loc_vars = function(_, _, card) + return {vars = {card.ability.extra.amount}} + end, + can_use = function(_, card) + return u() and #Bakery_API.get_highlighted() == card.ability.extra.amount + end, + use = function(_, _, _) + f(Bakery_API.get_highlighted()):foreach(function(v) + v:set_seal "Roland_glass" + end) + end, +} + SMODS.Consumable { key = "void", set = "Spectral", @@ -65,10 +113,10 @@ SMODS.Consumable { loc_vars = function(_, _, card) return {vars = {card.ability.extra.amount}} end, - can_use = function(_, _) + can_use = function() return #G.playing_cards > 1 and u() end, - use = function(_, card, _, _) + use = function(_, card) local function destructible(v) return not v.ability or not (v.ability.eternal or v.ability.cry_absolute) end @@ -86,7 +134,7 @@ SMODS.Consumable { local cards = f(G.playing_cards):filter(destructible):into() local function calculate_joker(v) - v:calculate_joker({remove_playing_cards = true, removed = cards}) + v:calculate_joker {remove_playing_cards = true, removed = cards} end f(cards):foreach(destroy)