diff --git a/assets/1x/iphone.png b/assets/1x/iphone.png new file mode 100644 index 0000000..53e0818 Binary files /dev/null and b/assets/1x/iphone.png differ diff --git a/assets/2x/Pasted image.png b/assets/2x/Pasted image.png new file mode 100644 index 0000000..9ce76c1 Binary files /dev/null and b/assets/2x/Pasted image.png differ diff --git a/assets/2x/afterimage.png b/assets/2x/afterimage.png index 7fdce19..48fcf2c 100644 Binary files a/assets/2x/afterimage.png and b/assets/2x/afterimage.png differ diff --git a/assets/2x/blind.png b/assets/2x/blind.png index c064748..c3c8dcb 100644 Binary files a/assets/2x/blind.png and b/assets/2x/blind.png differ diff --git a/assets/2x/escapey.png b/assets/2x/escapey.png index a3dfde0..14bfd6b 100644 Binary files a/assets/2x/escapey.png and b/assets/2x/escapey.png differ diff --git a/assets/2x/icon.png b/assets/2x/icon.png index 11ace88..45adea8 100644 Binary files a/assets/2x/icon.png and b/assets/2x/icon.png differ diff --git a/assets/2x/iphone.png b/assets/2x/iphone.png new file mode 100644 index 0000000..9059d4f Binary files /dev/null and b/assets/2x/iphone.png differ diff --git a/assets/2x/martingale.png b/assets/2x/martingale.png index 1ce9b94..630fa5e 100644 Binary files a/assets/2x/martingale.png and b/assets/2x/martingale.png differ diff --git a/assets/2x/void.png b/assets/2x/void.png index 8fb66fe..1d5845f 100644 Binary files a/assets/2x/void.png and b/assets/2x/void.png differ diff --git a/assets/sounds/milestone.ogg b/assets/sounds/milestone.ogg new file mode 100644 index 0000000..3def76f Binary files /dev/null and b/assets/sounds/milestone.ogg differ diff --git a/localization/en-us.lua b/localization/en-us.lua index fdc583a..a9208e6 100644 --- a/localization/en-us.lua +++ b/localization/en-us.lua @@ -10,8 +10,22 @@ return { }, }, b_Roland_go = { - name = "placeholder", - text = {"grr"}, + name = "Pass GO Deck", + text = { + "Start with a {C:attention}Credit Card", + "Set money to {C:money}0$", + "when entering the shop", + }, + }, + }, + BakeryCharm = { + BakeryCharm_Roland_iphone = { + name = "fat i phone", + text = { + "Enter the shop", + "when any {C:attention}Blind", + "is {C:attention}skipped", + }, }, }, Blind = { @@ -37,6 +51,14 @@ return { }, }, Joker = { + j_Roland_bulldozer = { + name = "Bulldozer", + text = { + "Give {X:red,C:white}XMult{} equal to", + "the current {C:attention}Blind Size{C:attention}", + "{C:inactive}(Currently {X:red,C:white}X#1#{C:inactive})", + }, + }, j_Roland_escapey = { name = "Escapey", text = { @@ -63,6 +85,46 @@ return { }, }, }, + j_Roland_estrogen = { + name = "Estrogen", + text = {"{C:mult}+Chips{} Mult"}, + }, + j_Roland_hexagon = { + name = "Hexagon", + text = { + "Earn {C:money}#1#${} if", + "played hand is a", + "{C:attention}Four of a Kind", + }, + }, + j_Roland_hexagoner = { + name = "Hexagoner", + text = { + "This Joker gains the", + "rank of {C:attention}unscored cards", + "if played hand is a", + "{C:attention}Four of a Kind", + "{C:inactive}(Currently {C:red}+#1#{C:inactive} Mult)", + }, + }, + j_Roland_hexagonest = { + name = "Hexagonest", + text = { + "{C:attention}Unscored cards{} add a", + "permanent copy to deck", + "and draw it to {C:blue}hand", + "if played hand is a", + "{C:attention}Four of a Kind", + }, + }, + j_Roland_misfortune = { + name = "Misfortune Cookie", + text = { + "{C:tarot}Tarot{} cards created", + "by {C:tarot}Purple Seals", + "become {C:dark_edition}Negative", + }, + }, j_Roland_martingale = { name = "Martingale", text = { @@ -76,6 +138,72 @@ return { "{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", }, }, + j_Roland_mrsbones = { + name = "Mrs. Bones", + text = { + "{X:red,C:white}X#1#{} Mult", + "{C:red,E:1}Self destructs{} if {C:chips}chips", + "scored at the end of", + "the {C:attention}Blind{} are less than", + "{C:attention}#2#%{} of required {C:chips}chips", + }, + }, + j_Roland_msjoker = { + name = "Ms. Joker", + text = {"{C:chips}+#1#{} Chips"}, + }, + j_Roland_oops = { + name = "Oops! All 7s", + text = { + "Listed {C:green,E:1}probabilities", + "{C:attention}increase{} for each", + "{C:hand}hand played this round", + "{C:inactive}(Currently {C:green}X#1#{C:inactive})", + }, + }, + j_Roland_rigged = { + name = "Rigged", + text = { + "{C:blue}#1#{}#2#{C:green}#3#{}#4#{C:red}#5#{}#6#{C:edition}#7#{}#8#{C:legendary}#9#{}#10#{C:dark_edition}#11#", + "jokers cannot appear", + "{C:attention}Upgrade{} this card by", + "obtaining another {C:attention}Rigged", + }, + }, + j_Roland_sunny = { + name = "Sunny Side Up", + text = { + "Sell this Joker to", + "{C:attention}draw{} the bottom", + "card of the {C:hand}deck", + "{C:inactive}(Currently {V:1}#1##2#{V:2}#3#{C:inactive})", + }, + }, + j_Roland_temple = { + name = "Temple", + text = { + "{C:attention}Unscored {C:enhanced}wild{} cards", + "give {X:red,C:white}X#1#{} Mult", + }, + }, + j_Roland_yard = { + name = "Yard Sale", + text = { + "Gain {C:money}#1#${} when a", + "card is {C:attention}removed", + "from the deck", + }, + }, + }, + Other = { + Roland_glass_seal = { + name = "Glass Seal", + text = { + "Gives a random tag at", + "the end of the {C:attention}Blind", + "{C:red,E:1}Self destructs{} if {C:attention}drawn", + }, + }, }, Spectral = { c_Roland_afterimage = { @@ -86,6 +214,22 @@ return { "{C:red}#2#{} hand size", }, }, + c_Roland_dual = { + name = "Dual", + text = { + "Add random seals", + "to {C:attention}#1#{} random", + "cards in {C:hands}hand", + }, + }, + c_Roland_mirror = { + name = "Mirror", + text = { + "Add a {C:dark_edition}Glass Tag", + "to {C:attention}#1#{} selected", + "card in {C:hands}hand", + }, + }, c_Roland_void = { name = "Void", text = { @@ -102,7 +246,13 @@ return { c_Roland_Pastries = "Sweet Pastries", }, v_dictionary = { + b_Roland_comma = ", ", + b_Roland_of = " of ", b_Roland_most_common_card = "(Rank)", + b_Roland_na = "N/A", + }, + labels = { + Roland_glass_seal = "Glass Seal", }, v_text = { ch_c_Roland_Jokerful = {"Only the {C:common}default Joker{} can appear in shops"}, diff --git a/lovely.toml b/lovely.toml index f79db91..8311a94 100644 --- a/lovely.toml +++ b/lovely.toml @@ -71,7 +71,7 @@ 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 + (next(SMODS.find_card "j_Roland_misfortune") or #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit) then""" match_indent = true @@ -81,7 +81,7 @@ 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 +payload = """if next(SMODS.find_card "j_Roland_misfortune") then card:set_edition "e_negative" end""" match_indent = true diff --git a/src/charm.lua b/src/charm.lua index f316df4..1a12e65 100644 --- a/src/charm.lua +++ b/src/charm.lua @@ -1,8 +1,15 @@ local _, q = unpack(... or require "src.functional") +SMODS.Atlas { + key = "iphone", + path = "iphone.png", + px = 68, + py = 68, +} + Bakery_API.Charm { - key = "tags", - atlas = "void", + key = "iphone", + atlas = "iphone", pos = {x = 0, y = 0}, calculate = function(_, _, context) local _ = context.skip_blind and q(function() diff --git a/src/functional.lua b/src/functional.lua index 9080bc6..f7493a6 100644 --- a/src/functional.lua +++ b/src/functional.lua @@ -23,7 +23,9 @@ local function protect_ev(fun) return fun end +local origf = F local luaf = assert(SMODS.load_file "src/LuaFunctional/functional.lua")() or require "src.LuaFunctional.functional" +F = origf -- We do not condone globals as side effects! if false then ---Returns the elements from the given `list`. This function is equivalent to @@ -70,7 +72,7 @@ end --- Queues an event to be run. --- Note that events added this way implicitly `return true` unless you explicitly `return false`, unlike the vanilla ones. ---- @param fun (fun():boolean?)|Event The event or a function to run turn into an event. +--- @param fun (fun():false|nil)|Event The event or a function to run turn into an event. --- @param front boolean|nil `true` to add the event to the front of the queue, rather than the end. local function q(fun, front) G.E_MANAGER:add_event(protect_ev(fun), nil, front) diff --git a/src/joker.lua b/src/joker.lua index 37f8516..ea29805 100644 --- a/src/joker.lua +++ b/src/joker.lua @@ -45,6 +45,11 @@ local function level_up(hand, by, card) update("", 0, 0, "", 1.1) end +SMODS.Sound { + key = "milestone", + path = "milestone.ogg", +} + SMODS.Atlas { px = 71, py = 95, @@ -67,8 +72,8 @@ SMODS.Joker { sinis = {x = 2, y = 0}, soul_pos = {x = 1, y = 0}, config = {extra = {hands = 2}}, - cost = 8, - rarity = 3, + cost = 6, + rarity = 2, eternal_compat = true, perishable_compat = true, blueprint_compat = false, @@ -203,10 +208,14 @@ SMODS.Joker { level_up(v, 1, card) end) end, + debug_export = function(self, obj) + local to = obj or self + to.f, to.q, to.u = f, q, u + end, } SMODS.Joker { - key = "temp", + key = "msjoker", -- Blue bow atlas = "void", pronouns = "they_them", pos = {x = 0, y = 0}, @@ -222,7 +231,7 @@ SMODS.Joker { } SMODS.Joker { - key = "temp2", + key = "bulldozer", atlas = "void", pronouns = "they_them", pos = {x = 0, y = 0}, @@ -240,52 +249,84 @@ SMODS.Joker { } SMODS.Joker { - key = "temp3", + key = "oops", -- Slot machine atlas = "void", pronouns = "they_them", pos = {x = 0, y = 0}, cost = 8, rarity = 3, - config = {extra = {probability = 1}}, + config = {extra = {probability = 1, delta = 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.blind_defeated then + card.ability.extra.probability = card.ability.extra.delta elseif context.after and not context.blueprint then - card.ability.extra.probability = card.ability.extra.probability + 1 + card.ability.extra.probability = card.ability.extra.probability + card.ability.extra.delta end end, } SMODS.Joker { - key = "temp4", + key = "estrogen", atlas = "void", pronouns = "they_them", pos = {x = 0, y = 0}, - cost = 8, - rarity = 3, + cost = 6, + rarity = 2, calculate = function(_, _, context) return context.joker_main and {mult = hand_chips} or nil end, } SMODS.Joker { - key = "temp5", + key = "sunny", -- Cracked egg atlas = "void", pronouns = "they_them", pos = {x = 0, y = 0}, cost = 2, rarity = 1, + eternal_compat = false, + loc_vars = function(_, _, card) + local last = ((G.deck or {}).cards or {})[1] + + if last or card.area ~= G.jokers then + return { + vars = { + "", + localize {type = "variable", key = "b_Roland_na"}, + "", + colours = {G.C.JOKER_GREY, G.C.JOKER_GREY}, + }, + } + end + + local suit = last.base.suit + local value = last.base.value + local name = last.ability.name or "" + local no_rank = SMODS.has_no_rank(last) + local no_suit = SMODS.has_no_suit(last) + + return { + vars = { + value and not no_rank and localize(value or 14, "ranks") or name, + not no_rank and not no_suit and localize {type = "variable", key = "b_Roland_of"} or "", + no_suit and "" or localize(suit, "suits_plural"), + colours = {G.C.IMPORTANT, G.C.SUITS[suit] or G.C.JOKER_GREY}, + }, + } + end, calculate = function(_, _, context) local _ = context.selling_self and - draw_card(G.deck, G.hand, 100, "up", false, G.deck.cards[#G.deck.cards]) + draw_card(G.deck, G.hand, 100, "up", false, G.deck.cards[1]) end, } SMODS.Joker { - key = "temp6", + key = "yard", atlas = "void", pronouns = "they_them", pos = {x = 0, y = 0}, @@ -302,12 +343,12 @@ SMODS.Joker { } SMODS.Joker { - key = "temp7", + key = "hexagon", atlas = "void", pronouns = "they_them", pos = {x = 0, y = 0}, config = {extra = {money = 2}}, - cost = 3, + cost = 4, rarity = 1, loc_vars = function(_, _, card) return {vars = {card.ability.extra.money}} @@ -320,13 +361,16 @@ SMODS.Joker { } SMODS.Joker { - key = "temp8", + key = "hexagoner", atlas = "void", pronouns = "they_them", pos = {x = 0, y = 0}, config = {extra = {mult = 0}}, - cost = 8, + cost = 6, rarity = 2, + loc_vars = function(_, _, card) + return {vars = {card.ability.extra.mult}} + end, calculate = function(_, card, context) if context.joker_main then return {mult = card.ability.extra.mult} @@ -341,7 +385,7 @@ SMODS.Joker { } SMODS.Joker { - key = "temp9", + key = "hexagonest", atlas = "void", pronouns = "they_them", pos = {x = 0, y = 0}, @@ -371,13 +415,16 @@ SMODS.Joker { } SMODS.Joker { - key = "temp10", + key = "temple", atlas = "void", pronouns = "they_them", pos = {x = 0, y = 0}, config = {extra = {xmult = 1.5}}, - cost = 8, - rarity = 3, + cost = 6, + rarity = 2, + loc_vars = function(_, _, card) + return {vars = {card.ability.extra.xmult}} + end, calculate = function(_, card, context) if context.individual and context.cardarea == "unscored" and @@ -388,7 +435,7 @@ SMODS.Joker { } SMODS.Joker { - key = "negative", + key = "misfortune", atlas = "void", pronouns = "they_them", pos = {x = 0, y = 0}, @@ -396,26 +443,125 @@ SMODS.Joker { rarity = 2, } +SMODS.Joker { + key = "rigged", + atlas = "void", + config = {extra = {level = "1"}}, -- Strings do not get mutated by other mods, hopefully. + pos = {x = 0, y = 0}, + eternal_compat = false, + cost = 8, + rarity = 2, + loc_vars = function(_, _, card) + return {vars = {}} + end, +} + +---@diagnostic disable-next-line: undefined-global +local rarities = Cryptid and + {{1, "Common"}, {2, "Uncommon"}, {3, "Rare"}, {"cry_epic"}, {4, "Legendary"}, {"cry_exotic"}} or + {{1, "Common"}, {2, "Uncommon"}, {3, "Rare"}, {4, "Legendary"}} + +local orig_poll_rarity = SMODS.poll_rarity + +---@diagnostic disable-next-line: duplicate-set-field +function SMODS.poll_rarity(_pool_key, _rand_key) + local rarity = orig_poll_rarity(_pool_key, _rand_key) + + local max = f(SMODS.find_card "j_Roland_rigged"):reduce(0, function(a, n) + return n.debuff and a or math.max(a, tonumber(n.ability.extra.level)) + end) + + if f(rarities, ipairs):take(max):filter(function(v) + return f(v):any(function(vv) + return vv == rarity + end) + end):any() then + return rarities[max + 1][1] or rarities[#rarities][1] + end + + return rarity +end + +local orig_update = Game.update + +---@diagnostic disable-next-line: duplicate-set-field +function Game:update(dt) + orig_update(self, dt) + + if not G.GAME then + return + end + + local candidates = {} + + local max = f(SMODS.find_card "j_Roland_rigged"):reduce(1, function(a, n) + local level = tonumber(n.ability.extra.level) or 1 + + if not candidates[level] then + candidates[level] = n + elseif level == 1 then + candidates[0] = n + end + + return math.max(a, level) + end) + + for i = math.min(max, #rarities - 2), 1, -1 do + if not candidates[i] then + goto continue + end + + local skip = true + + for j = i - 1, i == 1 and 0 or 1, -1 do + if not candidates[j] then + break + end + + skip = j > 1 + end + + if skip then + goto continue + end + + for j = i - 1, i == 1 and 0 or 1, -1 do + candidates[i].sell_cost = candidates[i].sell_cost + candidates[j].sell_cost + candidates[j].ability.extra.level = "-1" + candidates[j]:start_dissolve() + end + + local extra = candidates[i].ability.extra + local level = tonumber(extra.level) + extra.level = tostring(level + 1) + candidates[i].children.center:set_sprite_pos({x = 0, y = math.min(level or 0, 2)}) + play_sound("Roland_milestone", 0.9 ^ (level - 2)) + ::continue:: + end +end + SMODS.Joker { key = "mrsbones", atlas = "void", pronouns = "they_them", pos = {x = 0, y = 0}, - config = {extra = {xmult = 4}}, - cost = 8, - rarity = 3, + config = {extra = {xmult = 4, requirement = 4}}, + cost = 4, + rarity = 2, + loc_vars = function(_, _, card) + return {vars = {card.ability.extra.xmult, card.ability.extra.requirement * 100}} + end, 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 + if context.blind_defeated and G.GAME.chips / card.ability.extra.requirement < 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, diff --git a/src/seal.lua b/src/seal.lua index 2aa0ecb..2a86a0f 100644 --- a/src/seal.lua +++ b/src/seal.lua @@ -8,11 +8,9 @@ local f, q = unpack(... or require "src.functional") -- } SMODS.Seal { key = "glass", - name = "RolandGlass", - badge_colour = HEX "12f254", atlas = "void", pos = {x = 0, y = 0}, - config = {ready = true}, + badge_colour = HEX "f6f6f6", calculate = function(_, card, context) if context.setting_blind or context.starting_shop then card.Roland_glass = nil diff --git a/src/spectral.lua b/src/spectral.lua index 0435f04..ec47bba 100644 --- a/src/spectral.lua +++ b/src/spectral.lua @@ -79,7 +79,7 @@ SMODS.Consumable { } SMODS.Consumable { - key = "glass", + key = "mirror", set = "Spectral", pos = {x = 0, y = 0}, cost = 6,