diff --git a/assets/1x/default/c_jane_omegaplanets.png b/assets/1x/default/c_jane_omegaplanets.png new file mode 100644 index 0000000..2eef9f6 Binary files /dev/null and b/assets/1x/default/c_jane_omegaplanets.png differ diff --git a/assets/1x/default/c_jane_omegaspectrals.png b/assets/1x/default/c_jane_omegaspectrals.png new file mode 100644 index 0000000..66a009c Binary files /dev/null and b/assets/1x/default/c_jane_omegaspectrals.png differ diff --git a/assets/1x/default/c_jane_omegatarots.png b/assets/1x/default/c_jane_omegatarots.png new file mode 100644 index 0000000..b1a982b Binary files /dev/null and b/assets/1x/default/c_jane_omegatarots.png differ diff --git a/assets/2x/default/c_jane_omegaplanets.png b/assets/2x/default/c_jane_omegaplanets.png new file mode 100644 index 0000000..3107f3b Binary files /dev/null and b/assets/2x/default/c_jane_omegaplanets.png differ diff --git a/assets/2x/default/c_jane_omegaspectrals.png b/assets/2x/default/c_jane_omegaspectrals.png new file mode 100644 index 0000000..8b60045 Binary files /dev/null and b/assets/2x/default/c_jane_omegaspectrals.png differ diff --git a/assets/2x/default/c_jane_omegatarots.png b/assets/2x/default/c_jane_omegatarots.png new file mode 100644 index 0000000..22c773a Binary files /dev/null and b/assets/2x/default/c_jane_omegatarots.png differ diff --git a/assets/shaders/crystal.fs b/assets/shaders/crystal.fs new file mode 100644 index 0000000..d4571cf --- /dev/null +++ b/assets/shaders/crystal.fs @@ -0,0 +1,98 @@ +#if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH) + #define MY_HIGHP_OR_MEDIUMP highp +#else + #define MY_HIGHP_OR_MEDIUMP mediump +#endif + +extern MY_HIGHP_OR_MEDIUMP vec2 crystal; +extern MY_HIGHP_OR_MEDIUMP number dissolve; +extern MY_HIGHP_OR_MEDIUMP number time; +extern MY_HIGHP_OR_MEDIUMP vec4 texture_details; +extern MY_HIGHP_OR_MEDIUMP vec2 image_details; +extern bool shadow; +extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_1; +extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_2; + +vec4 dissolve_mask(vec4 tex, vec2 texture_coords, vec2 uv) +{ + if (dissolve < 0.001) { + return vec4(shadow ? vec3(0.,0.,0.) : tex.xyz, shadow ? tex.a*0.3: tex.a); + } + + float adjusted_dissolve = (dissolve*dissolve*(3.-2.*dissolve))*1.02 - 0.01; //Adjusting 0.0-1.0 to fall to -0.1 - 1.1 scale so the mask does not pause at extreme values + + float t = time * 10.0 + 2003.; + vec2 floored_uv = (floor((uv*texture_details.ba)))/max(texture_details.b, texture_details.a); + vec2 uv_scaled_centered = (floored_uv - 0.5) * 2.3 * max(texture_details.b, texture_details.a); + + vec2 field_part1 = uv_scaled_centered + 50.*vec2(sin(-t / 143.6340), cos(-t / 99.4324)); + vec2 field_part2 = uv_scaled_centered + 50.*vec2(cos( t / 53.1532), cos( t / 61.4532)); + vec2 field_part3 = uv_scaled_centered + 50.*vec2(sin(-t / 87.53218), sin(-t / 49.0000)); + + float field = (1.+ ( + cos(length(field_part1) / 19.483) + sin(length(field_part2) / 33.155) * cos(field_part2.y / 15.73) + + cos(length(field_part3) / 27.193) * sin(field_part3.x / 21.92) ))/2.; + vec2 borders = vec2(0.2, 0.8); + + float res = (.5 + .5* cos( (adjusted_dissolve) / 82.612 + ( field + -.5 ) *3.14)) + - (floored_uv.x > borders.y ? (floored_uv.x - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve) + - (floored_uv.y > borders.y ? (floored_uv.y - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve) + - (floored_uv.x < borders.x ? (borders.x - floored_uv.x)*(5. + 5.*dissolve) : 0.)*(dissolve) + - (floored_uv.y < borders.x ? (borders.x - floored_uv.y)*(5. + 5.*dissolve) : 0.)*(dissolve); + + if (tex.a > 0.01 && burn_colour_1.a > 0.01 && !shadow && res < adjusted_dissolve + 0.8*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) { + if (!shadow && res < adjusted_dissolve + 0.5*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) { + tex.rgba = burn_colour_1.rgba; + } else if (burn_colour_2.a > 0.01) { + tex.rgba = burn_colour_2.rgba; + } + } + + return vec4(shadow ? vec3(0.,0.,0.) : tex.xyz, res > adjusted_dissolve ? (shadow ? tex.a*0.3: tex.a) : .0); +} + +vec4 effect( vec4 colour, Image texture, vec2 texture_coords, vec2 screen_coords ) +{ + vec4 tex = Texel( texture, texture_coords); + vec2 uv = (((texture_coords)*(image_details)) - texture_details.xy*texture_details.ba)/texture_details.ba; + + number low = min(tex.r, min(tex.g, tex.b)); + number high = max(tex.r, max(tex.g, tex.b)); + number delta = high-low -0.1; + + number fac = 0.8 + 0.9*sin(11.*uv.x+4.32*uv.y + crystal.r*12. + cos(crystal.r*5.3 + uv.y*4.2 - uv.x*4.)); + number fac2 = 0.5 + 0.5*sin(8.*uv.x+2.32*uv.y + crystal.r*5. - cos(crystal.r*2.3 + uv.x*8.2)); + number fac3 = 0.5 + 0.5*sin(10.*uv.x+5.32*uv.y + crystal.r*6.111 + sin(crystal.r*5.3 + uv.y*3.2)); + number fac4 = 0.5 + 0.5*sin(3.*uv.x+2.32*uv.y + crystal.r*8.111 + sin(crystal.r*1.3 + uv.y*11.2)); + number fac5 = sin(0.9*16.*uv.x+5.32*uv.y + crystal.r*12. + cos(crystal.r*5.3 + uv.y*4.2 - uv.x*4.)); + + number maxfac = 0.7*max(max(fac, max(fac2, max(fac3,0.0))) + (fac+fac2+fac3*fac4), 0.); + + tex.rgb = tex.rgb*0.5 + vec3(0.4, 0.4, 0.8); + + tex.r = tex.r-delta + delta*maxfac*(0.7 + fac5*0.27) - 0.1; + tex.g = tex.g-delta + delta*maxfac*(0.7 - fac5*0.27) - 0.1; + tex.b = tex.b-delta + delta*maxfac*0.7 - 0.1; + tex.a = 0.25+tex.a*(0.5*max(min(1., max(0.,0.3*max(low*0.2, delta)+ min(max(maxfac*0.1,0.), 0.4)) ), 0.) + 0.15*maxfac*(0.1+delta)); + + return dissolve_mask(tex*colour, texture_coords, uv); +} + +extern MY_HIGHP_OR_MEDIUMP vec2 mouse_screen_pos; +extern MY_HIGHP_OR_MEDIUMP float hovering; +extern MY_HIGHP_OR_MEDIUMP float screen_scale; + +#ifdef VERTEX +vec4 position( mat4 transform_projection, vec4 vertex_position ) +{ + if (hovering <= 0.){ + return transform_projection * vertex_position; + } + float mid_dist = length(vertex_position.xy - 0.5*love_ScreenSize.xy)/length(love_ScreenSize.xy); + vec2 mouse_offset = (vertex_position.xy - mouse_screen_pos.xy)/screen_scale; + float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist)) + *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist); + + return transform_projection * vertex_position + vec4(0,0,0,scale); +} +#endif \ No newline at end of file diff --git a/assets/sounds/boost1.ogg b/assets/sounds/boost1.ogg new file mode 100644 index 0000000..981775f Binary files /dev/null and b/assets/sounds/boost1.ogg differ diff --git a/assets/sounds/boost2.ogg b/assets/sounds/boost2.ogg new file mode 100644 index 0000000..3871ed7 Binary files /dev/null and b/assets/sounds/boost2.ogg differ diff --git a/assets/sounds/boost3.ogg b/assets/sounds/boost3.ogg new file mode 100644 index 0000000..f36505d Binary files /dev/null and b/assets/sounds/boost3.ogg differ diff --git a/assets/sounds/boost4.ogg b/assets/sounds/boost4.ogg new file mode 100644 index 0000000..3975315 Binary files /dev/null and b/assets/sounds/boost4.ogg differ diff --git a/assets/sounds/chime.ogg b/assets/sounds/chime.ogg new file mode 100644 index 0000000..c1676c3 Binary files /dev/null and b/assets/sounds/chime.ogg differ diff --git a/assets/sounds/e_crystal.ogg b/assets/sounds/e_crystal.ogg new file mode 100644 index 0000000..63d1c54 Binary files /dev/null and b/assets/sounds/e_crystal.ogg differ diff --git a/assets/sounds/enchant.ogg b/assets/sounds/enchant.ogg new file mode 100644 index 0000000..4e38d68 Binary files /dev/null and b/assets/sounds/enchant.ogg differ diff --git a/assets/sounds/omega_card.ogg b/assets/sounds/omega_card.ogg new file mode 100644 index 0000000..c7f0507 Binary files /dev/null and b/assets/sounds/omega_card.ogg differ diff --git a/assets/sounds/pop.ogg b/assets/sounds/pop.ogg new file mode 100644 index 0000000..b741f8f Binary files /dev/null and b/assets/sounds/pop.ogg differ diff --git a/lovely.toml b/lovely.toml index d823129..396bba8 100644 --- a/lovely.toml +++ b/lovely.toml @@ -45,7 +45,10 @@ match_indent = true target = "functions/misc_functions.lua" pattern = "local AC = G.SETTINGS.ambient_control" position = "before" -payload = '''if Jane and +payload = '''local jane_rgb = G.C.jane_RGB +jane_rgb[1], jane_rgb[2], jane_rgb[3] = Jane.hsv(1 - (G.TIMERS.REAL / 3 % 1), math.sin(G.TIMERS.REAL) / 10 + 0.6, 1) + +if Jane and (type(G.ARGS.score_intensity.required_score) == "table" and G.ARGS.score_intensity.required_score:to_number() or G.ARGS.score_intensity.required_score) ~= 0 then diff --git a/manifest.json b/manifest.json index 715b89e..3e7f742 100644 --- a/manifest.json +++ b/manifest.json @@ -16,5 +16,5 @@ "Bakery (>=3.0.0~*)" ], "conflicts": [], - "version": "1.11.30" + "version": "1.12.0" } \ No newline at end of file diff --git a/src/booster.lua b/src/booster.lua index 956fa04..aa00db6 100644 --- a/src/booster.lua +++ b/src/booster.lua @@ -291,6 +291,7 @@ if Jane.cry then cost = 2, weight = 0.24, create_card = function(_, _) + ---@diagnostic disable-next-line: return-type-mismatch return create_card("Code", G.pack_cards, nil, nil, true, true, nil, "cry_program_3") end, ease_background_colour = function(_) @@ -338,6 +339,7 @@ for i = 1, 2 do return {vars = {card.ability.choose, card.ability.extra}} end, create_card = function(_, _, _) + ---@diagnostic disable-next-line: return-type-mismatch return create_card("jane_tokens", G.pack_cards, nil, nil, true, true, nil, "jane_tokens" .. i) end, create_UIBox = function(_) diff --git a/src/edition.lua b/src/edition.lua index 90130e2..4d37dbe 100644 --- a/src/edition.lua +++ b/src/edition.lua @@ -1,7 +1,10 @@ SMODS.Shader({key = "moire", path = "moire.fs"}) +SMODS.Shader({key = "crystal", path = "crystal.fs"}) SMODS.Shader({key = "polygloss", path = "polygloss.fs"}) + SMODS.Sound({key = "e_jumbo", path = "e_jumbo.ogg"}) SMODS.Sound({key = "e_moire", path = "e_moire.ogg"}) +SMODS.Sound({key = "e_crystal", path = "e_crystal.ogg"}) SMODS.Sound({key = "e_polygloss", path = "e_polygloss.ogg"}) local function get_weight(self) @@ -71,7 +74,49 @@ SMODS.Edition({ get_weight = get_weight, }) -local moire = SMODS.Edition({ +SMODS.Edition({ + key = "crystal", + loc_txt = { + name = "Crystal", + label = "Crystal", + text = { + "{C:blue}+Mult{} Chips", + "{C:red}+Chips{} Mult", + }, + }, + config = {e_chips = 1.2, e_mult = 0.8}, + sound = {sound = "jane_e_crystal", per = 1, vol = 0.7}, + weight = 0, + extra_cost = 10, + in_shop = true, + no_shadow = true, + apply_to_float = false, + shader = "jane_crystal", + disable_base_shader = true, + loc_vars = function(self, _, _) + return {vars = {self.config.e_chips, self.config.e_mult}} + end, + calculate = function(self, card, context) + if not context.post_joker and (not context.main_scoring or context.cardarea ~= G.play) then + return + end + + return { + extra = { + card = card, + chips = mult, + colour = G.C.jane_RGB, + extra = { + card = card, + mult = hand_chips + mult, + colour = G.C.jane_RGB, + }, + }, + } + end, +}) + +SMODS.Edition({ key = "moire", loc_txt = { name = "Moire", @@ -83,12 +128,11 @@ local moire = SMODS.Edition({ }, config = {e_chips = 0.8, e_mult = 1.2}, sound = {sound = "jane_e_moire", per = 1, vol = 0.7}, - weight = 1, + weight = 0, extra_cost = 10, in_shop = true, shader = "jane_moire", apply_to_float = false, - get_weight = get_weight, loc_vars = function(self, _, _) return {vars = {self.config.e_chips, self.config.e_mult}} end, diff --git a/src/main.lua b/src/main.lua index 8df7876..fafb651 100644 --- a/src/main.lua +++ b/src/main.lua @@ -12,9 +12,10 @@ end Jane = { cry = SMODS.Mods.Cryptid and not SMODS.Mods.Cryptid.disabled, config = { + omega_chance = 1 / 301, texture_pack = "default", wee_sizemod = math.sqrt(2), - bans = {"j_cry_crustulum", "c_cry_hammerspace"}, + bans = {"j_Bakery_Lua", "j_cry_crustulum", "c_cry_hammerspace"}, }, } @@ -313,6 +314,10 @@ local orig_start_run = Game.start_run function Game:start_run(...) orig_start_run(self, ...) + self.GAME.modifiers.omegas_found = nil + + self.GAME.modifiers.omega_replacement = + self.GAME.modifiers.omega_replacement or Jane.config.omega_chance if self.GAME.banned_keys then for _, v in pairs(Jane.config.bans) do @@ -362,6 +367,7 @@ for _, v in ipairs({ "challenge", "edition", "joker", + "omega", "slugcat", "spectral", "tarot", diff --git a/src/omega.lua b/src/omega.lua new file mode 100644 index 0000000..538110c --- /dev/null +++ b/src/omega.lua @@ -0,0 +1,1201 @@ +SMODS.Sound({key = "omegacard", path = "omega_card.ogg"}) +SMODS.Sound({key = "enchant", path = "enchant.ogg"}) +SMODS.Sound({key = "chime", path = "chime.ogg"}) +SMODS.Sound({key = "pop", path = "pop.ogg"}) + +for i = 1, 4 do + SMODS.Sound({key = "boost" .. i, path = "boost" .. i .. ".ogg"}) +end + +SMODS.Atlas { + key = "janeomegaplanets", + px = 71, + py = 95, + path = Jane.config.texture_pack .. "/c_jane_omegaplanets.png", +} + +SMODS.Atlas { + key = "janeomegaspectrals", + px = 71, + py = 95, + path = Jane.config.texture_pack .. "/c_jane_omegaspectrals.png", +} + +SMODS.Atlas { + key = "janeomegatarots", + px = 71, + py = 95, + path = Jane.config.texture_pack .. "/c_jane_omegatarots.png", +} + +SMODS.ConsumableType { + key = "jane_omegaconsumable", + loc_txt = {collection = "Omega Cards", name = "Omega"}, + default = "c_jane_pluto_omega", + secondary_colour = G.C.jane_RGB, + primary_colour = G.C.BLACK, + collection_rows = {6, 6}, + shop_rate = 0, +} + +local function create_card_set(needle, edition, amount) + for k, v in pairs(G.P_CARDS) do + if string.find(k, needle) then + for _ = 1, amount do + Jane.q(function() + SMODS.add_card({set = "Base", rank = v.value, suit = v.suit}) + :set_edition(edition, true, true) + + play_sound("card1") + end, 0.1) + end + end + end +end + +---@param hand string? +---@param number number +---@param card Card +local function omega_level_up(hand, number, card) + local factor = 3 ^ number + + update_hand_text( + {sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3}, + { + handname = localize(hand or "k_all_hands", hand and "poker_hands"), + chips = hand and G.GAME.hands[hand].l_chips, + mult = hand and G.GAME.hands[hand].l_mult, + level = hand and G.GAME.hands[hand].level, + } + ) + + for _, v in pairs(hand and {G.GAME.hands[hand]} or G.GAME.hands) do + v.l_chips = v.l_chips * factor + v.l_mult = v.l_mult * factor + end + + Jane.q(function() + play_sound("jane_boost1", 1, 0.4) + card:juice_up(0.8, 0.5) + end, 1, nil, "after") + + update_hand_text({delay = 1}, {chips = "X" .. factor, StatusText = true}) + + Jane.q(function() + play_sound("jane_boost2", 1, 0.4) + card:juice_up(0.8, 0.5) + end, 1, nil, "after") + + update_hand_text({delay = 1}, {mult = "X" .. factor, StatusText = true}) + + update_hand_text( + {sound = "button", volume = 0.7, pitch = 1, delay = 1}, + { + chips = hand and G.GAME.hands[hand].l_chips, + mult = hand and G.GAME.hands[hand].l_mult, + } + ) + + delay(2) + + update_hand_text( + {sound = "button", volume = 0.7, pitch = 0.8, delay = 1}, + { + chips = hand and G.GAME.hands[hand].chips, + mult = hand and G.GAME.hands[hand].mult, + } + ) + + for _, v in pairs(hand and {G.GAME.hands[hand]} or G.GAME.hands) do + v.chips = v.chips * factor + v.mult = v.mult * factor + end + + Jane.q(function() + play_sound("jane_boost3", 1, 0.4) + card:juice_up(0.8, 0.5) + end, 1, nil, "after") + + update_hand_text({delay = 1}, {chips = "X" .. factor, StatusText = true}) + + Jane.q(function() + play_sound("jane_boost4", 1, 0.4) + card:juice_up(0.8, 0.5) + end, 1, nil, "after") + + update_hand_text({delay = 1}, {mult = "X" .. factor, StatusText = true}) + + update_hand_text( + {sound = "button", volume = 0.7, pitch = 1, delay = 1}, + { + chips = hand and G.GAME.hands[hand].chips, + mult = hand and G.GAME.hands[hand].mult, + } + ) + + for k, v in pairs(hand and {[hand] = G.GAME.hands[hand]} or G.GAME.hands) do + SMODS.upgrade_poker_hands({ + hands = {k}, + level_up = v.level * (factor - 1), + }) + end +end + +for _, v in ipairs({ + {n = "Pluto", c = "pluto", h = "High Card", y = 9}, + {n = "Mercury", c = "mercury", h = "Pair", y = 6}, + {n = "Uranus", c = "uranus", h = "Two Pair", y = 11}, + {n = "Venus", c = "venus", h = "Three of a Kind", y = 12}, + {n = "Saturn", c = "saturn", h = "Straight", y = 10}, + {n = "Jupiter", c = "jupiter", h = "Flush", y = 4}, + {n = "Earth", c = "earth", h = "Full House", y = 2}, + {n = "Mars", c = "mars", h = "Four of a Kind", y = 5}, + {n = "Neptune", c = "neptune", h = "Straight Flush", y = 7}, + {n = "Planet X", c = "planet_x", h = "Five of a Kind", y = 8}, + {n = "Ceres", c = "ceres", h = "Flush House", y = 1}, + {n = "Eris", c = "eris", h = "Flush Five", y = 3}, +}) do + SMODS.Consumable { + key = v.c .. "_omega", + loc_txt = { + name = v.n .. " {C:dark_edition}Omega", + text = { + "{C:attention}Triples {C:chips}Chips{}, {C:chips}Level Chips{},", + "{C:mult}Mult{}, {C:mult}Level Mult{}, and", + "{C:planet}planet level {}of {C:attention}" .. v.h, + }, + }, + set = "jane_omegaconsumable", + pos = {x = 0, y = v.y}, + soul_pos = {x = 1, y = v.y}, + cost = 15, + soul_rate = 0, + atlas = "janeomegaplanets", + hidden = true, + can_stack = true, + can_divide = true, + can_bulk_use = true, + can_mass_use = true, + can_use = Jane.can_use, + use = function(self, card, area, copier) + self:bulk_use(card, area, copier, 1) + end, + bulk_use = function(_, card, _, _, number) + omega_level_up(v.h, number, card) + end, + } +end + +SMODS.Consumable { + key = "black_hole_omega", + loc_txt = { + name = "{C:dark_edition}Sagittarius A*", + text = { + "{C:attention}Nonuples {C:chips}Chips{}, {C:chips}Level Chips{},", + "{C:mult}Mult{}, {C:mult}Level Mult{}, and", + "{C:planet}planet level {}of {C:attention}all hands", + }, + }, + set = "jane_omegaconsumable", + pos = {x = 0, y = 0}, + soul_pos = {x = 1, y = 0}, + cost = 15, + soul_rate = 0, + atlas = "janeomegaplanets", + hidden = true, + can_stack = true, + can_divide = true, + can_bulk_use = true, + can_mass_use = true, + can_use = Jane.can_use, + use = function(self, card, area, copier) + self:bulk_use(card, area, copier, 1) + end, + bulk_use = function(_, card, _, _, number) + omega_level_up(nil, number * 2, card) + end, +} + +SMODS.Consumable { + key = "ankh_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "Ankh {C:dark_edition}Omega", + text = {"Create {C:attention}4{} copies of", "a {C:attention}selected Joker"}, + }, + pos = {x = 0, y = 0}, + soul_pos = {x = 1, y = 0}, + cost = 20, + soul_rate = 0, + hidden = true, + atlas = "janeomegaspectrals", + can_use = function() + return Jane.can_use() and ((G.jokers or {}).highlighted or {})[1] + end, + use = function(self, card, area, copier) + self:bulk_use(card, area, copier, 1) + end, + bulk_use = function(_, _, _, _, number) + local joker = ((G.jokers or {}).highlighted or {})[1] + + if not joker then + return + end + + for _ = 1, 4 * number do + SMODS.copy_card(joker):start_materialize() + end + end, +} + +local editions = {"jane_crystal", "jane_moire"} + +SMODS.Consumable { + key = "aura_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "Aura {C:dark_edition}Omega", + text = { + "Apply {C:dark_edition}Crystal {}or {C:dark_edition}Moire", + "to all {C:attention}selected Jokers", + "and {C:attention}playing cards", + }, + }, + pos = {x = 0, y = 1}, + soul_pos = {x = 1, y = 1}, + cost = 20, + soul_rate = 0, + hidden = true, + atlas = "janeomegaspectrals", + loc_vars = function(_, info_queue) + info_queue[#info_queue + 1] = G.P_CENTERS.e_jane_crystal + info_queue[#info_queue + 1] = G.P_CENTERS.e_jane_moire + end, + can_use = function() + return Jane.can_use() and (next(G.jokers.highlighted) or next(G.hand.highlighted)) + end, + use = function() + for _, v in ipairs(G.jokers.highlighted) do + if not v.edition then + v:set_edition({[editions[pseudorandom("auraexrandom", 1, #editions)]] = true}) + end + end + + for _, v in ipairs(G.hand.highlighted) do + if not v.edition then + v:set_edition({[editions[pseudorandom("auraexrandom", 1, #editions)]] = true}) + end + end + end, +} + +SMODS.Consumable { + key = "cryptid_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "Cryptid {C:dark_edition}Omega", + text = { + "Create {C:attention}20{} copies of", + "{C:attention}selected playing cards", + }, + }, + pos = {x = 0, y = 2}, + soul_pos = {x = 1, y = 2}, + cost = 20, + soul_rate = 0, + hidden = true, + atlas = "janeomegaspectrals", + can_use = function() + return Jane.can_use() and next(G.hand.highlighted) + end, + use = function(self, card, area, copier) + self:bulk_use(card, area, copier, 1) + end, + bulk_use = function(_, _, _, _, number) + for _, v in ipairs(G.hand.highlighted) do + for _ = 1, 20 * number do + SMODS.copy_card(v):start_materialize() + end + end + end, +} + +for _, v in ipairs({ + {n = "Deja Vu", c = "deja_vu", s = "Red", y = 3}, + {n = "Medium", c = "medium", s = "Purple", y = 10}, + {n = "Talisman", c = "talisman", s = "Gold", y = 13}, + {n = "Trance", c = "trance", s = "Blue", y = 14}, +}) do + SMODS.Consumable { + key = v.c .. "_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = v.n .. " {C:dark_edition}Omega", + text = { + "Apply a {C:attention}" .. v.s .. " Seal{} to", + "{C:attention}all playing cards", + }, + }, + pos = {x = 0, y = v.y}, + soul_pos = {x = 1, y = v.y}, + atlas = "janeomegaspectrals", + soul_rate = 0, + hidden = true, + cost = 20, + loc_vars = function(_, info_queue) + info_queue[#info_queue + 1] = G.P_SEALS[v.s] + end, + can_use = Jane.can_use, + use = function() + for i, card in pairs(G.hand.cards) do + card:set_seal(v.s, i > 50, i > 50) + end + + for _, card in pairs(G.deck.cards) do + card:set_seal(v.s, true, true) + end + end, + } +end + +SMODS.Consumable { + key = "ectoplasm_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "Ectoplasm {C:dark_edition}Omega", + text = {"Apply {C:dark_edition}Negative", "to {C:attention}all Jokers"}, + }, + pos = {x = 0, y = 4}, + soul_pos = {x = 1, y = 4}, + cost = 100, + soul_rate = 0, + hidden = true, + atlas = "janeomegaspectrals", + loc_vars = function(_, info_queue) + info_queue[#info_queue + 1] = G.P_CENTERS.e_negative + end, + can_use = function() + return Jane.can_use() and next(G.jokers.cards) + end, + use = function() + for k, v in ipairs(G.jokers.cards) do + if not v.edition then + v:set_edition({negative = true}, k > 50, k > 50) + end + end + end, +} + +SMODS.Consumable { + key = "familiar_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "Familiar {C:dark_edition}Omega", + text = { + "Add a {C:attention}full set{} of", + "{C:dark_edition,E:1}Moire {C:attention}Kings{}, {C:dark_edition,E:1}Crystal", + "{C:attention}Queens{}, and {C:dark_edition,E:1}Polygloss", + "{C:attention}Jacks {}to your deck", + }, + }, + pos = {x = 0, y = 5}, + soul_pos = {x = 1, y = 5}, + cost = 100, + soul_rate = 0, + hidden = true, + atlas = "janeomegaspectrals", + loc_vars = function(_, info_queue) + info_queue[#info_queue + 1] = G.P_CENTERS.e_jane_moire + info_queue[#info_queue + 1] = G.P_CENTERS.e_jane_crystal + info_queue[#info_queue + 1] = G.P_CENTERS.e_jane_polygloss + end, + can_use = Jane.can_use, + use = function(self, card, area, copier) + self:bulk_use(card, area, copier, 1) + end, + bulk_use = function(_, _, _, _, number) + create_card_set("_K", "e_jane_moire", number) + create_card_set("_Q", "e_jane_crystal", number) + create_card_set("_J", "e_jane_polygloss", number) + end, +} + +SMODS.Consumable { + key = "grim_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "Grim {C:dark_edition}Omega", + text = { + "Add 2 {C:attention}full sets", + "of {C:dark_edition,E:1}Moire {C:attention}Aces", + "to your deck", + }, + }, + pos = {x = 0, y = 6}, + soul_pos = {x = 1, y = 6}, + cost = 80, + soul_rate = 0, + hidden = true, + atlas = "janeomegaspectrals", + loc_vars = function(_, info_queue) + info_queue[#info_queue + 1] = G.P_CENTERS.e_jane_moire + end, + can_use = Jane.can_use, + use = function(self, card, area, copier) + self:bulk_use(card, area, copier, 1) + end, + bulk_use = function(_, _, _, _, number) + create_card_set("_A", "e_jane_moire", number * 2) + end, +} + +SMODS.Consumable { + key = "hex_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "Hex {C:dark_edition}Omega", + text = { + "Apply {C:dark_edition,E:1}Crystal {}or", + "{C:dark_edition,E:1}Moire {}to all {C:attention}Jokers", + }, + }, + pos = {x = 0, y = 7}, + soul_pos = {x = 1, y = 7}, + cost = 150, + soul_rate = 0, + hidden = true, + atlas = "janeomegaspectrals", + loc_vars = function(_, info_queue) + info_queue[#info_queue + 1] = G.P_CENTERS.e_jane_crystal + info_queue[#info_queue + 1] = G.P_CENTERS.e_jane_moire + end, + can_use = function() + return Jane.can_use() and next(G.jokers.cards) + end, + use = function() + for _, v in ipairs(G.jokers.cards) do + if not v.edition then + v:set_edition({[editions[pseudorandom("hexexrandom", 1, #editions)]] = true}) + end + end + end, +} + +SMODS.Consumable { + key = "immolate_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "Immolate {C:dark_edition}Omega", + text = { + "{C:red}Destroys{} {C:attention}selected playing cards", + "Each card destroyed multiplies", + "{C:money}money{} by its {C:attention}rank", + }, + }, + pos = {x = 0, y = 8}, + soul_pos = {x = 1, y = 8}, + cost = 200, + soul_rate = 0, + hidden = true, + atlas = "janeomegaspectrals", + can_use = function() + return Jane.can_use() and next(G.hand.highlighted) + end, + use = function(self, card, area, copier) + for _, v in pairs(G.hand.highlighted) do + ease_dollars((v:norank() and 1 or v:get_id()) * G.GAME.dollars - G.GAME.dollars) + end + + SMODS.destroy_cards(G.hand.highlighted) + end, +} + +SMODS.Consumable { + key = "incantation_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "Incantation {C:dark_edition}Omega", + text = { + "Add a {C:attention}full set{} of cards", + "{C:attention}2{} through {C:attention}10 {}to your deck", + "{C:dark_edition,E:1}Polygloss{} on {C:attention}odd ranks", + "{C:dark_edition,E:1}Crystal{} on {C:attention}even ranks", + }, + }, + pos = {x = 0, y = 9}, + soul_pos = {x = 1, y = 9}, + cost = 175, + soul_rate = 0, + hidden = true, + atlas = "janeomegaspectrals", + loc_vars = function(_, info_queue) + info_queue[#info_queue + 1] = G.P_CENTERS.e_jane_polygloss + info_queue[#info_queue + 1] = G.P_CENTERS.e_jane_crystal + end, + can_use = Jane.can_use, + use = function(self, card, area, copier) + self:bulk_use(card, area, copier, 1) + end, + bulk_use = function(_, _, _, _, number) + create_card_set("_2", "e_jane_crystal", number) + create_card_set("_3", "e_jane_polygloss", number) + create_card_set("_4", "e_jane_crystal", number) + create_card_set("_5", "e_jane_polygloss", number) + create_card_set("_6", "e_jane_crystal", number) + create_card_set("_7", "e_jane_polygloss", number) + create_card_set("_8", "e_jane_crystal", number) + create_card_set("_9", "e_jane_polygloss", number) + create_card_set("_T", "e_jane_crystal", number) + end, +} + +SMODS.Consumable { + key = "ouija_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "Ouija {C:dark_edition}Omega", + text = { + "{C:attention}Playing cards {}whose rank", + "does not match any of the", + "{C:attention}selected cards {}will be {C:money}sold", + }, + }, + pos = {x = 0, y = 11}, + soul_pos = {x = 1, y = 11}, + cost = 175, + soul_rate = 0, + hidden = true, + atlas = "janeomegaspectrals", + can_use = function() + return Jane.can_use() and next(G.hand.highlighted) + end, + use = function() + if not next(G.hand.highlighted) then + return + end + + for _, c in pairs(G.playing_cards) do + local safe = c.highlighted + + if not safe then + for _, h in pairs(G.hand.highlighted) do + if h:get_id() == c:get_id() or + (h:norank() and c:norank()) then + safe = true + break + end + end + end + + if not safe then + c:sell_card() + end + end + end, +} + +SMODS.Consumable { + key = "sigil_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "Sigil {C:dark_edition}Omega", + text = { + "{C:attention}Playing cards {}whose suit", + "does not match any of the", + "{C:attention}selected {C:attention}cards {}will be {C:money}sold", + }, + }, + pos = {x = 0, y = 12}, + soul_pos = {x = 1, y = 12}, + soul_rate = 0, + cost = 175, + atlas = "janeomegaspectrals", + can_use = function() + return Jane.can_use() and next(G.hand.highlighted) + end, + use = function() + if not next(G.hand.highlighted) then + return + end + + for _, c in pairs(G.playing_cards) do + local safe = c.highlighted + + if not safe then + for _, h in pairs(G.hand.highlighted) do + if SMODS.has_any_suit(h) or + h.base.suit == c.base.suit or + (h:norank() and c:norank()) then + safe = true + break + end + end + end + + if not safe then + c:sell_card() + end + end + end, +} + +SMODS.Consumable { + key = "wraith_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "Wraith {C:dark_edition}Omega", + text = { + "Create all {C:legendary,E:1}Legendary", + "{C:dark_edition,E:1}Jane {C:attention}Jokers", + }, + }, + pos = {x = 0, y = 15}, + soul_pos = {x = 1, y = 15}, + cost = 175, + soul_rate = 0, + hidden = true, + atlas = "janeomegaspectrals", + loc_vars = function(self, info_queue) + for _, v in ipairs(self.jokers()) do + info_queue[#info_queue + 1] = v + end + end, + can_use = function(self) + return Jane.can_use() and #G.jokers.cards + #self.jokers() <= G.jokers.config.card_limit + end, + use = function(self) + for _, v in ipairs(self.jokers()) do + SMODS.add_card {key = v.key, set = "Joker"} + end + end, + jokers = function() + local out = {} + + for _, v in pairs(G.P_CENTERS) do + if v.set == "Joker" and + v.mod and + v.mod.id == "jane" and + type(v.rarity) == "number" and + v.rarity == 4 then + out[#out + 1] = v + end + end + + return out + end, +} + +SMODS.Consumable { + key = "fool_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "The Fool {C:dark_edition}Omega", + text = { + "Create {C:attention}2{} random", + "{C:red,E:1}Omega{} cards", + }, + }, + pos = {x = 0, y = 0}, + soul_pos = {x = 1, y = 0}, + cost = 175, + soul_rate = 0, + hidden = true, + atlas = "janeomegatarots", + can_use = Jane.can_use, + use = function() + local omega_consumables = { + "pluto", "mercury", "uranus", "venus", "saturn", "jupiter", "earth", "mars", "neptune", "planet_x", "ceres", + "eris", "black_hole", "ankh", "aura", "cryptid", "deja_vu", "medium", "talisman", "trance", "ectoplasm", + "familiar", "grim", "hex", "immolate", "incantation", "ouija", "sigil", "wraith", "fool", "magician", + "empress", "hierophant", "lovers", "chariot", "justice", "devil", "tower", "high_priestess", "emperor", + "hermit", "wheel_of_fortune", "star", "moon", "sun", "world", "soul", + } + + for _ = 1, 2 do + if G.consumeables.config.card_limit > #G.consumeables.cards then + local key = "c_jane_" .. pseudorandom_element(omega_consumables, pseudoseed("fool_omega")) .. "_omega" + SMODS.add_card({key = key, set = "jane_omegaconsumable"}) + end + end + end, +} + +local omega_copyamount = 10 + +for _, v in ipairs({ + { + b = "magician", + n = "The Scientist", + o = "The Magician", + c = "Lucky", + e = G.P_CENTERS.m_lucky, + p = {x = 8, y = 2}, + omega = 1, + }, + { + b = "empress", + n = "The Peasant", + o = "The Empress", + c = "Mult", + e = G.P_CENTERS.m_mult, + p = {x = 6, y = 2}, + omega = 3, + }, + { + b = "hierophant", + n = "The Adversary", + o = "The Hierophant", + c = "Bonus", + e = G.P_CENTERS.m_bonus, + p = {x = 4, y = 2}, + omega = 5, + }, + { + b = "lovers", + n = "The Rivals", + o = "The Lovers", + c = "Wild", + e = G.P_CENTERS.m_wild, + p = {x = 3, y = 2}, + omega = 6, + }, + { + b = "chariot", + n = "The Hitchhiker", + o = "The Chariot", + c = "Steel", + e = G.P_CENTERS.m_steel, + p = {x = 2, y = 2}, + omega = 7, + }, + { + b = "justice", + n = "Injustice", + o = "Justice", + c = "Glass", + e = G.P_CENTERS.m_glass, + p = {x = 1, y = 2}, + omega = 8, + }, + { + b = "devil", + n = "The Angel", + o = "The Devil", + c = "Gold", + e = G.P_CENTERS.m_gold, + p = {x = 4, y = 1}, + omega = 15, + }, + { + b = "tower", + n = "The Collapse", + o = "The Tower", + c = "Stone", + e = G.P_CENTERS.m_stone, + p = {x = 3, y = 1}, + omega = 16, + }, +}) do + SMODS.Consumable { + key = v.b .. "_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = v.o .. " {C:dark_edition}Omega", + text = { + "Enhance {C:attention}selected playing", + "{C:attention}cards {}to {C:attention}" .. v.c .. "{} cards,", + "{C:red}Destroy{} all other cards", + "{C:attention}Duplicate {}each card {C:attention}" .. omega_copyamount .. " times", + }, + }, + pos = {x = 0, y = v.omega}, + soul_pos = {x = 1, y = v.omega}, + cost = 35, + soul_rate = 0, + hidden = true, + atlas = "janeomegatarots", + loc_vars = function(_, info_queue) + info_queue[#info_queue + 1] = v.e + end, + can_use = function() + return Jane.can_use() and next(G.hand.highlighted) + end, + use = function(_, card) + if not next(G.hand.highlighted) then + return + end + + Jane.q(function() + play_sound("tarot1") + card:juice_up(0.3, 0.5) + end, 0.4, nil, "after") + + local to_copy = {} + + for i = 1, #G.hand.highlighted do + local percent = 1.15 - (i - 0.999) / (#G.hand.highlighted - 0.998) * 0.3 + local h = G.hand.highlighted[i] + table.insert(to_copy, h) + + Jane.q(function() + h:flip() + play_sound("card1", percent) + h:juice_up(0.3, 0.3) + end, 0.15, nil, "after") + end + + delay(0.2) + + for i = 1, #G.hand.highlighted do + local percent = 0.85 + (i - 0.999) / (#G.hand.highlighted - 0.998) * 0.3 + local h = G.hand.highlighted[i] + + Jane.q(function() + G.hand:remove_from_highlighted(h) + h:flip() + h:set_ability(v.e, true, nil) + play_sound("tarot2", percent) + h:juice_up(0.3, 0.3) + end, 0.15, nil, "after") + end + + for _, c in ipairs(G.playing_cards) do + if not c.highlighted then + SMODS.destroy_cards({c}) + end + end + + delay(1) + + Jane.q(function() + for _, h in ipairs(to_copy) do + for _ = 1, omega_copyamount do + SMODS.copy_card(h):start_materialize() + end + end + end) + end, + } +end + +SMODS.Consumable { + key = "high_priestess_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "The High Priestess {C:dark_edition}Omega", + text = { + "Every {C:attention}Joker{}, {C:attention}consumable{},", + "and {C:attention}playing card{} will", + "trigger {C:spectral}Black Hole", + }, + }, + pos = {x = 0, y = 2}, + soul_pos = {x = 1, y = 2}, + cost = 200, + soul_rate = 0, + hidden = true, + atlas = "janeomegatarots", + loc_vars = function(_, info_queue) + info_queue[#info_queue + 1] = G.P_CENTERS.c_black_hole + end, + can_use = Jane.can_use, + use = function() + SMODS.upgrade_poker_hands({ + hands = G.handlist, + level_up = #G.jokers.cards + #G.consumeables.cards + #G.playing_cards, + }) + end, +} + +local function create_many(set, count, rarity) + local showman = SMODS.add_card({key = "j_ring_master", set = "Joker"}) + showman:set_perishable(true) + + for _ = 1, count do + Jane.q(function() + SMODS.add_card({set = set, rarity = rarity, key_append = "jane_" .. set}):juice_up(0.3, 0.5) + play_sound("timpani") + end, 0.4, nil, "after") + end + + Jane.q(function() + SMODS.destroy_cards({showman}) + end) +end + +SMODS.Consumable { + key = "emperor_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "The Emperor {C:dark_edition}Omega", + text = { + "Create a random {C:red}Rare", + "{C:attention}Joker {}for every {C:attention}King", + "in your deck", + "{C:inactive}(Adds a temporary Showman)", + }, + }, + pos = {x = 0, y = 4}, + soul_pos = {x = 1, y = 4}, + cost = 300, + soul_rate = 0, + hidden = true, + atlas = "janeomegatarots", + can_use = Jane.can_use, + use = function() + local count = 0 + + for _, v in pairs(G.playing_cards) do + if not v:norank() and v:get_id() == 13 then + count = count + 1 + end + end + + create_many("Joker", count, "Rare") + end, +} + +SMODS.Consumable { + key = "hermit_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "The Hermit {C:dark_edition}Omega", + text = { + "Gain {X:money,C:dark_edition,s:1.25}+$^2", + "{C:inactive,s:0.75}(+$#1#)", + }, + }, + pos = {x = 0, y = 9}, + soul_pos = {x = 1, y = 9}, + cost = 50, + soul_rate = 0, + hidden = true, + atlas = "janeomegatarots", + can_use = Jane.can_use, + loc_vars = function() + return {vars = {((G.GAME or {}).dollars or 0) ^ 2}} + end, + use = function() + ease_dollars(G.GAME.dollars ^ 2) + end, +} + +SMODS.Consumable { + key = "wheel_of_fortune_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "The Wheel of Fortune {C:dark_edition}Omega", + text = { + "Create {C:dark_edition,E:1}50 {C:attention}consumables", + "{C:inactive}(Adds a temporary Showman)", + "{C:inactive}(Does not require room)", + }, + }, + pos = {x = 0, y = 10}, + soul_pos = {x = 1, y = 10}, + cost = 50, + soul_rate = 0, + hidden = true, + atlas = "janeomegatarots", + can_use = Jane.can_use, + loc_vars = function() + return {vars = {((G.GAME or {}).dollars or 0) ^ 2}} + end, + use = function() + create_many("Consumeables", 50, "Rare") + end, +} + +for _, vv in pairs({ + {b = "star", n = "The Flash", s = "Diamonds", p = {x = 2, y = 1}, o = 17}, + {b = "moon", n = "The Eclipse", s = "Clubs", p = {x = 1, y = 1}, o = 18}, + {b = "sun", n = "The Darkness", s = "Hearts", p = {x = 0, y = 1}, o = 19}, + {b = "world", n = "Desolate", s = "Spades", p = {x = 8, y = 0}, o = 21}, +}) do + SMODS.Consumable { + key = vv.b .. "_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "The " .. string.upper(string.sub(vv.b, 1, 1)) .. string.sub(vv.b, 2, string.len(vv.b)) .. " {C:dark_edition}Omega", + text = { + "Convert {C:attention}all {C:" .. string.lower(vv.s) .. "}" .. vv.s, + "to {C:dark_edition,E:1}Crystal {}or {C:dark_edition,E:1}Moire", + }, + }, + pos = {x = 0, y = vv.o}, + soul_pos = {x = 1, y = vv.o}, + cost = 250, + soul_rate = 0, + hidden = true, + atlas = "janeomegatarots", + loc_vars = function(_, info_queue) + info_queue[#info_queue + 1] = G.P_CENTERS.e_jane_crystal + info_queue[#info_queue + 1] = G.P_CENTERS.e_jane_moire + end, + can_use = Jane.can_use, + use = function() + play_sound("jane_pop") + + for _, v in ipairs(G.playing_cards) do + if v:is_suit(vv.s) and not v:nosuit() then + if v.area == G.hand then + Jane.q(function() + v:set_edition({[editions[pseudorandom("auraexrandom", 1, #editions)]] = true}) + play_sound("jane_pop") + v:juice_up(1, 0.5) + end, 0.75) + else + v:set_edition({[editions[pseudorandom("auraexrandom", 1, #editions)]] = true}) + end + end + end + end, + } +end + +local function obfuscated_text(length) + local chars = "ABCDEFGHIJKLMNOPQRSTU,VWXYZ abcdefghijklmnopq,rstuvwxyz0123456789+-?!,$%[]()" + local ret = "" + + for _ = 0, length do + local r = math.random(#chars) + ret = ret .. chars:sub(r, r + 1) + end + + return ret +end + +SMODS.Consumable { + key = "soul_omega", + set = "jane_omegaconsumable", + loc_txt = { + name = "{C:red,s:3}Balatro\'s Soul", + text = {"{C:red,s:5,E:1}?????"}, + }, + pos = {x = 0, y = 22}, + soul_pos = {x = 1, y = 22, extra = {x = 2, y = 22}}, + cost = 0, + soul_rate = 0, + hidden = true, + atlas = "janeomegatarots", + can_use = Jane.can_use, + use = function(_, card) + Jane.q(function() end, 0.25, "REAL", "after") + + for i = 1, 60 do + Jane.card_status_text( + card, + obfuscated_text(math.random(6 * (i / 15), 18 * (i / 15))), + nil, + card.T.h * 0.05, + G.C.RED, + 0.6, + 0.5 - (i / 125), + 0.4, + 0.4, + "bm", + "generic1" + ) + end + + if not G.P_CENTERS.j_Bakery_Lua then + return + end + + Jane.q(function() + SMODS.destroy_cards(G.jokers.cards, {bypass_eternal = true}) + G.jokers:change_size(1 - G.jokers.config.card_limit) + G.GAME.banned_keys.j_Bakery_Lua = nil + + SMODS.add_card { + set = "Joker", + key = "j_Bakery_Lua", + force_stickers = {"eternal", "rental"}, + } + + G.GAME.banned_keys.j_Bakery_Lua = true + G.GAME.banned_keys.c_jane_soul_omega = true + play_sound("jane_enchant", 0.75, 1) + end, 0.75, "REAL", "after") + end, +} + +local orig_can_reroll = G.FUNCS.can_reroll +local orig_create_card = create_card + +function G.FUNCS.can_reroll(e, ...) + if Talisman and Talisman.config_file and Talisman.config_file.disable_anims or + not G.GAME.modifiers.omegas_found or + G.GAME.modifiers.omegas_found <= 0 then + return orig_can_reroll(e, ...) + end + + e.config.colour = G.C.UI.BACKGROUND_INACTIVE + e.config.button = nil +end + +---@diagnostic disable-next-line: lowercase-global +function create_card(...) + local card = orig_create_card(...) + + if not card.gc or + G.STATE == G.STATES.MENU or + G.STATE ~= G.STATES.SHOP and card:gc().set ~= "Spectral" then + return card + end + + for _, v in pairs(G.P_CENTER_POOLS.jane_omegaconsumable) do + local key = v.key + + if not G.GAME.banned_keys[key] and + card:gc().key:sub(2) == key:sub(#"c_jane_", #key - #"_omega") and + pseudorandom("omega_replacement") < G.GAME.modifiers.omega_replacement then + local copy = G.GAME.modifiers.omegas_found + G.GAME.modifiers.omegas_found = (G.GAME.modifiers.omegas_found or 0) + 1 + + Jane.q(function() + card:set_ability(G.P_CENTERS[key]) + card:juice_up(1.5, 1.5) + card:set_cost() + + if not copy or copy <= 0 then + local pitch = math.pow(2 ^ (1 / 6), G.GAME.modifiers.omegas_found - 1) + play_sound("jane_omegacard", pitch, 0.4) + + Jane.q(function() + Jane.q(function() + local handy_speed = ((Handy or {}).speed_multiplier or {}).value or 1 + + local text = "Omega!" .. (G.GAME.modifiers.omegas_found > 1 and + (" X" .. number_format(G.GAME.modifiers.omegas_found)) or + "") + + attention_text({ + text = text, + scale = 1.4, + align = "cm", + major = G.play, + colour = G.C.jane_RGB, + offset = {x = 0, y = -2.7}, + hold = G.SETTINGS.GAMESPEED * handy_speed * 2, + }) + end) + + if key == "c_jane_soul_omega" then + play_sound("jane_chime", 1, 0.65) + end + + local anims = Talisman and Talisman.config_file and Talisman.config_file.disable_anims or nil + + Jane.q(function() + G.GAME.modifiers.omegas_found = 0 + end, anims and 1, anims and "REAL", anims and "after") + end) + end + end, nil, nil, "after", false, false) + break + end + end + + return card +end diff --git a/src/slugcat.lua b/src/slugcat.lua index 904bac1..5240239 100644 --- a/src/slugcat.lua +++ b/src/slugcat.lua @@ -412,6 +412,7 @@ SMODS.Joker { return not card.debuff and Jane.can_use() and next(G.hand.highlighted) end, Bakery_use_joker = function(_, card) + ---@diagnostic disable-next-line: deprecated local removed = {unpack(G.hand.highlighted)} for _, v in pairs(removed) do @@ -642,9 +643,6 @@ SMODS.Joker { } end, draw = function(_, card) - local rgb = G.C.jane_RGB - rgb[1], rgb[2], rgb[3] = Jane.hsv(1 - (G.TIMERS.REAL / 3 % 1), math.sin(G.TIMERS.REAL) / 10 + 0.6, 1) - local _ = card and card.children.floating_sprite and card.children.floating_sprite:set_sprite_pos({x = card.ability.extra.is_attuned and 2 or 1, y = 0}) @@ -811,7 +809,7 @@ SMODS.Joker { loc_txt = { name = "The Rot", text = { - Jane.cry and "{C:attention}Duplicates itself{} at the" or "{C:inactive,E:1}Does nothing", + Jane.cry and "{C:attention}Duplicates itself{} at the" or "{C:inactive,E:1}Does nothing?", Jane.cry and "end of {C:attention}every ante" or nil, }, }, @@ -823,6 +821,12 @@ SMODS.Joker { in_pool = function() return true, {allow_duplicates = true} end, + add_to_deck = function() + G.GAME.modifiers.omega_replacement = G.GAME.modifiers.omega_replacement * 2 + end, + remove_from_deck = function() + G.GAME.modifiers.omega_replacement = G.GAME.modifiers.omega_replacement / 2 + end, calculate = Jane.cry and function(_, card, context) local function has_room() return G.jokers.config.card_count < G.jokers.config.card_limit