local f, q = unpack(... or require "lib.shared") SMODS.Shader { key = "frozen", path = "frozen.fs", } ---@param suffix string local function frozen_sound(suffix) local key = "frozen" .. suffix return SMODS.Sound {key = key, path = key .. ".ogg"} end frozen_sound "_click" local frozen_sounds = f(4):map(frozen_sound):map("key"):table() local needs_chip_mult_override = { Bull = true, Erosion = true, Misprint = true, TierList = true, Bootstraps = true, ["Blue Joker"] = true, ["Abstract Joker"] = true, ["Fortune Teller"] = true, } local current_round_overrides = { Castle = "castle_card", Farmer = "farmer_card", Tuxedo = "tuxedo_card", ["Go Fish"] = "fish_rank", ["The Idol"] = "idol_card", ["Mail-In Rebate"] = "mail_card", Obelisk = "most_played_poker_hand", ["Ancient Joker"] = "ancient_card", Wherewolf = "Bakery_Wherewolf_card", j_Roland_suitable = "Roland_suitable", } SMODS.current_mod.frozen_chip_mult = needs_chip_mult_override SMODS.current_mod.frozen_current_round = current_round_overrides local function freeze(card) ---@generic T ---@param x T ---@return T local function copy(x) return type(x) == "table" and f(x):map(copy):where(function(v, k) return k ~= "Roland_frozen_proxy" and (k ~= "nine_tally" or v ~= 0) end):table() or x end card.Roland_frozen_ability = card.Roland_frozen_ability or copy(card.ability) card.ability = card.Roland_frozen_ability and copy(card.Roland_frozen_ability) or card.ability local ability, ret = card.ability, card.Roland_frozen_ability if type(ability) ~= "table" then return ret end ability.seal = ability.seal or {} if not ability.name or not G.GAME.current_round then return ret end local key = current_round_overrides[ability.name] if not key then return ret end card.Roland_frozen_current_round = card.Roland_frozen_current_round or copy(G.GAME.current_round[key]) G.GAME.current_round[key] = copy(card.Roland_frozen_current_round) return ret end SMODS.Edition { key = "frozen", shader = "frozen", sound = {sound = "Roland_frozen", per = 1, vol = 0.8}, attributes = {"passive", "scaling"}, weight = 8, extra_cost = 4, in_shop = true, apply_to_float = false, calculate = function(_, card) freeze(card) end, on_remove = function(card) card.Roland_frozen_proxy = nil card.Roland_frozen_estate = nil card.Roland_frozen_ability = nil end, get_weight = function(self) return G.GAME.edition_rate * self.weight end, } local orig_play_sound = play_sound function play_sound(sound, pitch, ...) if sound ~= "Roland_frozen" and sound ~= "Roland_frozen_click" then return orig_play_sound(sound, pitch, ...) end local overriden_sound = sound == "Roland_frozen" and pseudorandom_element(frozen_sounds, pseudoseed "Roland_frozen") or sound local added_pitch = pseudorandom(pseudoseed "Roland_frozen_pitch") / 4 + 0.8 return orig_play_sound(overriden_sound, pitch + added_pitch, ...) end local orig_click = Card.click function Card:click(...) local highlight = self.highlighted local ret = orig_click(self, ...) if self.edition and self.edition.Roland_frozen and highlight ~= self.highlighted then play_sound("Roland_frozen_click", highlight and 0 or 0.5, 0.6) end return ret end local orig_calculate_joker = Card.calculate_joker ---@param self Card|{Roland_frozen_ability?: table} function Card:calculate_joker(context, ...) local is_frozen = self.edition and self.edition.Roland_frozen if is_frozen and self.ability.name == "Loyalty Card" then return (context.joker_main and self.ability.loyalty_remaining == 0) and {xmult = self.ability.extra.Xmult} or nil end if is_frozen and self.ability.name == "Turtle Bean" then return end local ret = {orig_calculate_joker(self, context, ...)} if not is_frozen or not ret[1] then return unpack(ret) end local ability = freeze(self) if not needs_chip_mult_override[ability.name] then return unpack(ret) end ability.Roland_frozen_mult_mod = ability.Roland_frozen_mult_mod or ret[1].mult_mod ability.Roland_frozen_chip_mod = ability.Roland_frozen_chip_mod or ret[1].chip_mod ability.Roland_frozen_xmult = ability.Roland_frozen_xmult or ret[1].xmult return { chip_mod = ability.Roland_frozen_chip_mod, mult_mod = ability.Roland_frozen_mult_mod, xmult = ability.Roland_frozen_xmult, message = localize { type = "variable", key = "a_mult", vars = { ability.Roland_frozen_mult_mod or ability.Roland_frozen_chip_mod or ability.Roland_frozen_xmult, }, }, } end local orig_calculate_dollar_bonus = Card.calculate_dollar_bonus ---@param self Card|{Roland_frozen_ability?: table} function Card:calculate_dollar_bonus(...) if not self.edition or not self.edition.Roland_frozen then return orig_calculate_dollar_bonus(self, ...) end local ability = freeze(self) if ability.name == "Satellite" then ability.Roland_frozen_planets_used = ability.Roland_frozen_planets_used or orig_calculate_dollar_bonus(self, ...) return self.ability.extra * ability.Roland_frozen_planets_used end return orig_calculate_dollar_bonus(self, ...) end q(function() local estate = G.P_CENTERS.j_Bakery_Estate if not estate then return end ---@param card Card|{ Roland_frozen_estate: integer } local function estate_pos(card) if card.area ~= G.jokers and card.area.config.type ~= "title" then return 1 end card.Roland_frozen_estate = card.Roland_frozen_estate and card.Roland_frozen_estate or (f(card.area.cards):swap():any(function(_, k) return k == card end) or 1) return card.Roland_frozen_estate end local orig_calculate = estate.calculate function estate:calculate(card, context, ...) if not card or not card.edition or not card.edition.Roland_frozen then return orig_calculate(self, card, context, ...) end if not context.joker_main then return end local joker_count = estate_pos(card) local extra = card.ability.extra or {} return {chips = extra.chips * joker_count, mult = extra.mult * joker_count} end local orig_loc_vars = estate.loc_vars function estate:loc_vars(info_queue, card, ...) if not card or not card.edition or not card.edition.Roland_frozen then return orig_loc_vars(self, info_queue, card, ...) end local joker_count = estate_pos(card) local extra = card.ability.extra or {} return {vars = {extra.chips * joker_count, extra.mult * joker_count}} end end) q(function() local proxy = G.P_CENTERS.j_Bakery_Proxy if not proxy then return end ---@param card Card|{ Roland_frozen_proxy: number } local function get_proxied_joker(card) if not G.jokers or not G.jokers.cards then return end card.Roland_frozen_proxy = card.Roland_frozen_proxy or (Bakery_API.get_proxied_joker() or card).unique_val ---@param v Card local function eq(v) return v.unique_val == card.Roland_frozen_proxy end return f(G.jokers.cards):any(eq) ---@type Card? end local orig_calculate = proxy.calculate function proxy:calculate(card, context, ...) if not card or not card.edition or not card.edition.Roland_frozen then return orig_calculate(self, card, context, ...) end return SMODS.blueprint_effect(card, get_proxied_joker(card), context) end local orig_loc_vars = proxy.loc_vars function proxy:loc_vars(info_queue, card, ...) if not card or not card.edition or not card.edition.Roland_frozen then return orig_loc_vars(self, info_queue, card, ...) end local other = get_proxied_joker(card) local var = (other and other ~= card) and localize { type = "name_text", set = other.config.center.set, key = other.config.center.key, } or localize "k_none" return {vars = {var}} end end) q(function() local orig_flip_double_sided = (Bakery_API or {}).flip_double_sided if not orig_flip_double_sided then return end function Bakery_API.flip_double_sided(card, ...) if not card.edition or not card.edition.Roland_frozen then return orig_flip_double_sided(card, ...) end end end)