diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..906cf67 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +**/lovely*.log \ No newline at end of file diff --git a/Cryptid/Cryptid.lua b/Cryptid/Cryptid.lua index 9f7f8ac..6094964 100644 --- a/Cryptid/Cryptid.lua +++ b/Cryptid/Cryptid.lua @@ -5,9 +5,9 @@ --- MOD_AUTHOR: [MathIsFun_, Cryptid and Balatro Discords] --- MOD_DESCRIPTION: Adds unbalanced ideas to Balatro. --- BADGE_COLOUR: 708b91 ---- DEPENDENCIES: [Talisman>=2.0.0-beta8, Steamodded>=1.0.0~ALPHA-1216c] ---- VERSION: 0.5.3a ---- PRIORITY: 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 +--- DEPENDENCIES: [Talisman>=2.0.0-beta8<=2.0.9, Steamodded>=1.0.0~ALPHA-1225a<=1.0.0~ALPHA-1304a] +--- VERSION: 0.5.3c +--- PRIORITY: 2147483647 ---------------------------------------------- ------------MOD CODE ------------------------- @@ -40,7 +40,7 @@ SMODS.Rarity{ SMODS.Rarity{ key = "epic", loc_txt = {}, - badge_colour = HEX('571d91'), + badge_colour = HEX('ef0098'), default_weight = 0.003, pools = {["Joker"] = true}, get_weight = function(self, weight, object_type) @@ -56,7 +56,7 @@ SMODS.Rarity{ SMODS.Rarity{ key = "candy", loc_txt = {}, - badge_colour = HEX("e91ff0"), + badge_colour = HEX("e275e6"), } SMODS.Rarity{ @@ -389,6 +389,44 @@ function cry_edition_to_table(edition) -- look mom i figured it out (this does N end end +-- just dumping this garbage here +-- this just ensures that extra voucher slots work as expected +function cry_bonusvouchermod(mod) + if not G.GAME.shop then return end + G.GAME.cry_bonusvouchercount = G.GAME.cry_bonusvouchercount + mod + if G.shop_jokers and G.shop_jokers.cards then + G.shop:recalculate() + if mod > 0 then -- not doing minus mod because it'd be janky and who really cares + for i = 1, G.GAME.cry_bonusvouchercount+1 - #G.shop_vouchers.cards do + local curr_bonus = G.GAME.current_round.cry_bonusvouchers + curr_bonus[#curr_bonus+1] = get_next_voucher_key() + + + -- this could be a function but it's done like what... 3 times? it doesn't matter rn + + local card = Card(G.shop_vouchers.T.x + G.shop_vouchers.T.w/2, + G.shop_vouchers.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS[curr_bonus[#curr_bonus]],{bypass_discovery_center = true, bypass_discovery_ui = true}) + card.shop_cry_bonusvoucher = #curr_bonus + cry_misprintize(card) + if G.GAME.events.ev_cry_choco2 then + card.misprint_cost_fac = (card.misprint_cost_fac or 1) * 2 + card:set_cost() + end + if G.GAME.modifiers.cry_enable_flipped_in_shop and pseudorandom('cry_flip_vouch'..G.GAME.round_resets.ante) > 0.7 then + card.cry_flipped = true + end + create_shop_card_ui(card, 'Voucher', G.shop_vouchers) + card:start_materialize() + if G.GAME.current_round.cry_voucher_edition then + card:set_edition(G.GAME.current_round.cry_voucher_edition, true, true) + end + G.shop_vouchers.config.card_limit = G.shop_vouchers.config.card_limit + 1 + G.shop_vouchers:emplace(card) + end + end + end +end + -- check if Director's Cut or Retcon offers a cheaper reroll price function cry_cheapest_boss_reroll() local dcut = G.GAME.cry_voucher_centers["v_directors_cut"].config.extra or 1e308 @@ -587,7 +625,7 @@ function update_cry_member_count() GLOBAL_cry_member_update_thread = love.thread.newThread(file_data) GLOBAL_cry_member_update_thread:start() end - local old = GLOBAL_cry_member_count or 5624 + local old = GLOBAL_cry_member_count or 8830 -- get the HTTPS thread's value for Cryptid members local ret = love.thread.getChannel("member_count"):pop() if ret then @@ -603,7 +641,7 @@ function update_cry_member_count() end else -- Use a fallback value if HTTPS is disabled (you all are awesome) - GLOBAL_cry_member_count = 5624 + GLOBAL_cry_member_count = 8830 end end -- deal with Rigged and Fragile when scoring a playing card @@ -1137,7 +1175,9 @@ function Card:calculate_joker(context) if active_side.ability.cry_rigged then G.GAME.probabilities.normal = ggpn end + active_side:cry_double_scale_calc(orig_ability, in_context_scaling) + --Calculate events if self == G.jokers.cards[#G.jokers.cards] then for k, v in pairs(SMODS.Events) do @@ -2004,12 +2044,26 @@ function create_card(_type, area, legendary, _rarity, skip_materialize, soulable center = G.P_CENTERS[center] end - + + + + -- handle banned keys for playing cards + -- can cache this if it's too much of a performance hit + local _cardlist = {} + for k, v in pairs(G.P_CARDS) do + local add = true + if G.GAME and G.GAME.cry_banned_pcards and G.GAME.cry_banned_pcards[k] then + add = false + end + if add then _cardlist[#_cardlist+1] = k end + end + if #_cardlist <= 0 then _cardlist[#_cardlist+1] = 'S_A' end + local front = ( (_type == "Base" or _type == "Enhanced") - and pseudorandom_element(G.P_CARDS, ps("front" .. (key_append or "") .. G.GAME.round_resets.ante)) + and G.P_CARDS[pseudorandom_element(_cardlist, ps("front" .. (key_append or "") .. G.GAME.round_resets.ante))] ) or nil - + if area == "ERROR" then local ret = (front or center) if not ret.config then @@ -2212,7 +2266,8 @@ function create_card(_type, area, legendary, _rarity, skip_materialize, soulable end end if - G.GAME.modifiers.cry_enable_flipped_in_shop + not card.ability.eternal + and G.GAME.modifiers.cry_enable_flipped_in_shop and pseudorandom("cry_flip" .. (key_append or "") .. G.GAME.round_resets.ante) > 0.7 then card.cry_flipped = true @@ -2245,6 +2300,11 @@ function create_card(_type, area, legendary, _rarity, skip_materialize, soulable if not (card.edition and (card.edition.cry_oversat or card.edition.cry_glitched)) then cry_misprintize(card) end + if _type == "Joker" and G.GAME.modifiers.cry_common_value_quad then + if card.config.center.rarity == 1 then + cry_misprintize(card,{min = 4, max = 4}, nil, true) + end + end if card.ability.consumeable and card.pinned then -- counterpart is in Sticker.toml G.GAME.cry_pinned_consumeables = G.GAME.cry_pinned_consumeables + 0 end @@ -2274,7 +2334,7 @@ function create_card(_type, area, legendary, _rarity, skip_materialize, soulable card:update(0.016) -- dt is unused in the base game, but we're providing a realistic value anyway --Debuff jokers if certain boss blinds are active - if G.GAME and G.GAME.blind and not G.GAME.blind.disabled then + if _type == "Joker" and G.GAME and G.GAME.blind and not G.GAME.blind.disabled then if G.GAME.blind.name == "cry-box" or (G.GAME.blind.name == "cry-Obsidian Orb" and G.GAME.defeated_blinds["bl_cry_box"] == true) then if card.config.center.rarity == 1 and not card.debuff then @@ -2494,6 +2554,7 @@ function cry_sanity_check(val) return val end function cry_misprintize(card, override, force_reset, stack) + if Card.no(card, "immutable", true) then force_reset = true end --infinifusion compat if card.infinifusion then if card.config.center == card.infinifusion_center or card.config.center.key == 'j_infus_fused' then @@ -2505,7 +2566,7 @@ function cry_misprintize(card, override, force_reset, stack) if (not force_reset or G.GAME.modifiers.cry_jkr_misprint_mod) and (G.GAME.modifiers.cry_misprint_min or override or card.ability.set == "Joker") - and not stack or (not Card.no(card, "immune_to_chemach", true) and not Card.no(card, "immutable", true)) + and not stack or not Card.no(card, "immutable", true) then if G.GAME.modifiers.cry_jkr_misprint_mod and card.ability.set == "Joker" then if not override then @@ -2686,11 +2747,11 @@ function G.FUNCS.get_poker_hand_info(_cards) ['Pair'] = G.GAME.used_vouchers.v_cry_hyperspacetether and 2 or nil, ['Two Pair'] = 4, ['Three of a Kind'] = G.GAME.used_vouchers.v_cry_hyperspacetether and 3 or nil, - ['Straight'] = 5, - ['Flush'] = 5, + ['Straight'] = next(SMODS.find_card('j_four_fingers')) and 4 or 5, + ['Flush'] = next(SMODS.find_card('j_four_fingers')) and 4 or 5, ['Full House'] = 5, ['Four of a Kind'] = G.GAME.used_vouchers.v_cry_hyperspacetether and 4 or nil, - ['Straight Flush'] = 5, + ['Straight Flush'] = next(SMODS.find_card('j_four_fingers')) and 4 or 5, -- debatable ['cry_Bulwark'] = 5, ['Five of a Kind'] = 5, ['Flush House'] = 5, @@ -2714,7 +2775,7 @@ function G.FUNCS.get_poker_hand_info(_cards) end function cry_ascend(num) -- edit this function at your leisure - return num*((1.25 + (0.05 * (G.GAME.sunnumber or 0)))^G.GAME.current_round.current_hand.cry_asc_num or 0) + return math.max(num, num*((1.25 + (0.05 * (G.GAME.sunnumber or 0)))^G.GAME.current_round.current_hand.cry_asc_num or 0)) end function cry_pulse_flame(duration, intensity) -- duration is in seconds, intensity is in idfk honestly, but it increases pretty quickly @@ -3271,7 +3332,7 @@ SMODS.Sticker:take_ownership("rental", { local ec = eval_card function eval_card(card, context) local ret = ec(card, context) - if card and card.area == G.hand or card.area == G.play or card.area == G.discard or card.area == G.deck then + if card and (card.area == G.hand or card.area == G.play or card.area == G.discard or card.area == G.deck) then for k, v in pairs(SMODS.Stickers) do if card.ability[k] and v.calculate and type(v.calculate) == "function" then context.from_playing_card = true diff --git a/Cryptid/Items/Antimatter.lua b/Cryptid/Items/Antimatter.lua index 243028e..3050dec 100644 --- a/Cryptid/Items/Antimatter.lua +++ b/Cryptid/Items/Antimatter.lua @@ -58,6 +58,7 @@ local antimatter = { cry_force_seal = "random", cry_boss_blocked = { "bl_goad", "bl_window", "bl_club", "bl_head" }, cry_forced_draw_amount = 5, + cry_common_value_quad = true, }, pos = { x = 2, y = 0 }, trigger_effect = function(self, args) diff --git a/Cryptid/Items/Blinds.lua b/Cryptid/Items/Blinds.lua index b4941f5..6567bc6 100644 --- a/Cryptid/Items/Blinds.lua +++ b/Cryptid/Items/Blinds.lua @@ -182,9 +182,9 @@ local oldserpent = { order = 9, boss_colour = HEX("4f6367"), modify_hand = function(self, cards, poker_hands, text, mult, hand_chips) - if G.GAME.hands[text].level > 1 then + if to_big(G.GAME.hands[text].level) > to_big(1) then G.GAME.blind.triggered = true - return math.floor(mult / G.GAME.hands[text].level), hand_chips, true + return math.floor( mult / to_big(G.GAME.hands[text].level) ), hand_chips, true end return mult, hand_chips, false end, @@ -270,6 +270,12 @@ local tax = { atlas = "blinds", order = 2, boss_colour = HEX("40ff40"), + loc_vars = function(self, info_queue, card) + return { vars = { 0.4 * get_blind_amount(G.GAME.round_resets.ante)*2*G.GAME.starting_params.ante_scaling } } -- no bignum? + end, + collection_loc_vars = function(self) + return { vars = { localize("cry_tax_placeholder") }} + end, cry_cap_score = function(self, score) return math.floor(math.min(0.4 * G.GAME.blind.chips, score) + 0.5) end, @@ -369,9 +375,12 @@ local joke = { atlas = "blinds", order = 15, boss_colour = HEX("00ffaa"), - loc_vars = function(self, info_queue, card) - return { vars = { G.GAME.win_ante or 8 } } + loc_vars = function(self) + return { vars = { G.GAME.win_ante or 8, (G.GAME.win_ante and G.GAME.round_resets.ante) and math.floor(G.GAME.round_resets.ante + (G.GAME.win_ante - G.GAME.round_resets.ante % G.GAME.win_ante)) or 8 } } end, + collection_loc_vars = function(self) + return { vars = { '8', localize('cry_joke_placeholder') }} + end, cry_calc_ante_gain = function(self) if to_big(G.GAME.chips) >= to_big(G.GAME.blind.chips) * 2 then if G.GAME.round_resets.ante == 1 then @@ -493,6 +502,7 @@ local shackle = { order = 18, boss_colour = HEX("010466"), in_pool = function() + if G.GAME.modifiers.cry_force_edition and G.GAME.modifiers.cry_force_edition == "negative" then return false end if not G.jokers then return false end @@ -1415,6 +1425,7 @@ return { end if self.name ~= "cry-Obsidian Orb" + and self.name ~= "The Sink" and (self.name ~= "cry-oldarm" or not G.GAME.defeated_blinds["bl_psychic"]) and (self.name ~= "The Psychic" or not G.GAME.defeated_blinds["bl_cry_oldarm"]) and (self.name ~= "The Eye" or not G.GAME.defeated_blinds["bl_mouth"]) diff --git a/Cryptid/Items/CodeCards.lua b/Cryptid/Items/CodeCards.lua index 2cf11da..776ccab 100644 --- a/Cryptid/Items/CodeCards.lua +++ b/Cryptid/Items/CodeCards.lua @@ -215,10 +215,18 @@ local payload = { end, can_bulk_use = true, use = function(self, card, area, copier) - G.GAME.cry_payload = (G.GAME.cry_payload or 1) * card.ability.interest_mult + if G.GAME.dollars > 1e10 then + G.GAME.cry_payload = 3 + else + G.GAME.cry_payload = (G.GAME.cry_payload or 1) * card.ability.interest_mult + end end, bulk_use = function(self, card, area, copier, number) - G.GAME.cry_payload = (G.GAME.cry_payload or 1) * card.ability.interest_mult ^ number + if G.GAME.dollars > 1e10 then + G.GAME.cry_payload = 3 + else + G.GAME.cry_payload = (G.GAME.cry_payload or 1) * card.ability.interest_mult ^ number + end end, } local reboot = { @@ -433,14 +441,25 @@ local seed = { local rigged = { object_type = "Sticker", atlas = "sticker", - pos = { x = 5, y = 1 }, + pos = { x = 6, y = 1 }, key = "cry_rigged", no_sticker_sheet = true, prefix_config = { key = false }, badge_colour = HEX("14b341"), draw = function(self, card) --don't draw shine + if not G.shared_stickers["cry_rigged2"] then + G.shared_stickers["cry_rigged2"] = Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS["cry_sticker"], { x = 5, y = 1 }) + end -- no matter how late i init this, it's always late, so i'm doing it in the damn draw function + G.shared_stickers[self.key].role.draw_major = card + G.shared_stickers["cry_rigged2"].role.draw_major = card + G.shared_stickers[self.key]:draw_shader("dissolve", nil, nil, nil, card.children.center) + + card.hover_tilt = card.hover_tilt/2 -- call it spaghetti, but it's what hologram does so... + G.shared_stickers["cry_rigged2"]:draw_shader("dissolve", nil, nil, nil, card.children.center) + G.shared_stickers["cry_rigged2"]:draw_shader("hologram", nil, card.ARGS.send_to_shader, nil, card.children.center) -- this doesn't really do much tbh, but the slight effect is nice + card.hover_tilt = card.hover_tilt*2 end, } @@ -457,6 +476,7 @@ local hook = { cost = 4, atlas = "code", order = 14, + no_pool_flag = "beta_deck", can_use = function(self, card) return #G.jokers.highlighted == 2 end, @@ -512,7 +532,7 @@ local variable = { order = 8, config = { max_highlighted = 2, extra = { enteredrank = "" } }, loc_vars = function(self, info_queue, card) - return { vars = { self.config.max_highlighted } } + return { vars = { card and card.ability.max_highlighted or self.config.max_highlighted } } end, use = function(self, card, area, copier) G.GAME.USING_CODE = true @@ -546,7 +566,7 @@ local class = { order = 16, config = { max_highlighted = 1, extra = { enteredrank = "" } }, loc_vars = function(self, info_queue, card) - return { vars = { self.config.max_highlighted } } + return { vars = { card and card.ability.max_highlighted or self.config.max_highlighted } } end, use = function(self, card, area, copier) G.GAME.USING_CODE = true @@ -819,9 +839,14 @@ local delete = { if not G.GAME.banned_keys then G.GAME.banned_keys = {} end -- i have no idea if this is always initialised already tbh + if not G.GAME.cry_banned_pcards then + G.GAME.cry_banned_pcards = {} + end local a = nil local c = nil + local _p = nil if G.shop_jokers.highlighted[1] then + _p = not not G.shop_jokers.highlighted[1].base.value a = G.shop_jokers c = G.shop_jokers.highlighted[1] end @@ -843,6 +868,13 @@ local delete = { check_for_unlock({ type = "what_have_you_done" }) end G.GAME.banned_keys[c.config.center.key] = true + if _p then + for k, v in pairs(G.P_CARDS) do + if v.value == c.base.value and v.suit == c.base.suit then + G.GAME.cry_banned_pcards[k] = true + end + end + end c:start_dissolve() end, } @@ -895,12 +927,50 @@ local machinecode = { return true end, can_bulk_use = true, + loc_vars = function(self, info_queue, center) + return { + main_start = { + randomchar(codechars6), + randomchar(codechars6), + randomchar(codechars6), + randomchar(codechars6), + randomchar(codechars6), + randomchar(codechars6), + } + } + end, use = function(self, card, area, copier) - local card = create_card("Consumeables", G.consumables, nil, nil, nil, nil, nil, "cry_machinecode") + local card = create_card("Consumeables", G.consumables, nil, nil, nil, nil, get_random_consumable("cry_machinecode", nil, "c_cry_machinecode").key, c_cry_machinecode) card:set_edition({ cry_glitched = true }) card:add_to_deck() G.consumeables:emplace(card) end, + bulk_use = function(self, card, area, copier, number) + local a = {} + local b + for i = 1, number do + b = get_random_consumable("cry_machinecode", nil, "c_cry_machinecode") + a[b] = (a[b] or 0) + 1 + end + for k, v in pairs(a) do + local card = create_card("Consumeables", G.consumables, nil, nil, nil, nil, k.key) + card:set_edition({ cry_glitched = true }) + card:add_to_deck() + if Incantation then + card:setQty(v) + end + G.consumeables:emplace(card) + end + G.E_MANAGER:add_event( + Event({ + trigger = "after", + func = function() + a = nil + return true + end, + }) + ) + end, } local run = { object_type = "Consumable", @@ -938,6 +1008,7 @@ local run = { G.GAME.shop_free = nil G.GAME.shop_d6ed = nil G.STATE_COMPLETE = false + G.GAME.current_round.used_packs = {} return true end, })) @@ -1014,6 +1085,7 @@ local rework = { name = "cry-Rework", atlas = "code", order = 25, + no_pool_flag = "beta_deck", pos = { x = 3, y = 3, @@ -1282,6 +1354,7 @@ local ctrl_v = { G.E_MANAGER:add_event(Event({ func = function() local card = copy_card(G.consumeables.highlighted[1]) + if card.ability.name and card.ability.name == "cry-Chambered" then card.ability.extra.num_copies = 1 end card:add_to_deck() if Incantation then card:setQty(1) @@ -1311,6 +1384,7 @@ local ctrl_v = { G.E_MANAGER:add_event(Event({ func = function() local card = copy_card(G.consumeables.highlighted[1]) + if card.ability.name and card.ability.name == "cry-Chambered" then card.ability.extra.num_copies = 1 end card:add_to_deck() if Incantation then card:setQty(1) @@ -1351,29 +1425,33 @@ local inst = { return #selected_cards == 1 end, use = function(self, card, area, copier) + local same = 0 for i = 1, #G.deck.cards do if G.deck.cards[i].base.value == G.hand.highlighted[1].base.value then + same = i draw_card(G.deck,G.hand,nil,nil,false,G.deck.cards[i]) break end end for i = 1, #G.deck.cards do - if G.deck.cards[i].base.suit == G.hand.highlighted[1].base.suit then + if G.deck.cards[i].base.suit == G.hand.highlighted[1].base.suit and i ~= same then draw_card(G.deck,G.hand,nil,nil,false,G.deck.cards[i]) break end end end, bulk_use = function(self, card, area, copier, number) - for i = 1, number do + for j = 1, number do + local same = 0 for i = 1, #G.deck.cards do if G.deck.cards[i].base.value == G.hand.highlighted[1].base.value then + same = i draw_card(G.deck,G.hand,nil,nil,false,G.deck.cards[i]) break end end for i = 1, #G.deck.cards do - if G.deck.cards[i].base.suit == G.hand.highlighted[1].base.suit then + if G.deck.cards[i].base.suit == G.hand.highlighted[1].base.suit and i ~= same then draw_card(G.deck,G.hand,nil,nil,false,G.deck.cards[i]) break end @@ -1381,6 +1459,74 @@ local inst = { end end, } +local alttab = { + object_type = "Consumable", + set = "Code", + key = "alttab", + name = "cry-Alttab", + atlas = "code", + order = 28, + config = { }, + pos = { + x = 4, + y = 4, + }, + cost = 4, + can_bulk_use = true, + loc_vars = function(self, info_queue, card) + local ret = localize("k_none") + if G.GAME and G.GAME.blind and G.GAME.blind.in_blind then + if G.GAME.blind:get_type() == 'Small' then + ret = localize{type = 'name_text', key = G.GAME.round_resets.blind_tags.Small, set = 'Tag'} + elseif G.GAME.blind:get_type() == 'Big' then + ret = localize{type = 'name_text', key = G.GAME.round_resets.blind_tags.Big, set = 'Tag'} + elseif G.GAME.blind:get_type() == 'Boss' then + ret = '???' + end + end + return { vars = { ret } } + end, + can_use = function(self, card) + return G.GAME.blind and G.GAME.blind.in_blind + end, + use = function(self, card, area, copier) + local used_consumable = copier or card + delay(0.4) + G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function() + play_sound('tarot1') + local tag = nil + local type = G.GAME.blind:get_type() + if type == 'Boss' then + tag = Tag(get_next_tag_key()) + else + tag = Tag(G.GAME.round_resets.blind_tags[type]) + end + add_tag(tag) + used_consumable:juice_up(0.8, 0.5) + return true end })) + delay(1.2) + end, + bulk_use = function(self, card, area, copier, number) + local used_consumable = copier or card + delay(0.4) + G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function() + for j = 1, number do + play_sound('tarot1') + local tag = nil + local type = G.GAME.blind:get_type() + if type == 'Boss' then + tag = Tag(get_next_tag_key()) + else + tag = Tag(G.GAME.round_resets.blind_tags[type]) + end + add_tag(tag) + used_consumable:juice_up(0.8, 0.5) + delay(0.1) + end + return true end })) + delay(1.1) + end, +} local automaton = { object_type = "Consumable", @@ -1392,7 +1538,7 @@ local automaton = { order = 5, atlas = "code", loc_vars = function(self, info_queue, card) - return { vars = { self.config.create } } + return { vars = { card and card.ability and card.ability.create or self.config.create } } end, can_use = function(self, card) return #G.consumeables.cards < G.consumeables.config.card_limit or card.area == G.consumeables @@ -1597,6 +1743,28 @@ local CodeJoker = { "Kailen" } }, + unlocked = false, + check_for_unlock = function(self, args) + if G.P_CENTER_POOLS['Code'] then + local count = 0 + local count2 = 0 + for k,v in pairs(G.P_CENTER_POOLS['Code']) do + count2 = count2+1 + if v and v.discovered == true then + count = count + 1 + end + end + if count == count2 then + unlock_card(self) + end + end + if args.type == 'cry_lock_all' then + lock_card(self) + end + if args.type == 'cry_unlock_all' then + unlock_card(self) + end + end, } local copypaste = { @@ -1606,13 +1774,13 @@ local copypaste = { pos = { x = 3, y = 4 }, order = 110, immune_to_chemach = true, - config = { extra = { odds = 2, ckt = 0 } }, + config = { extra = { odds = 2, ckt = 0 } }, -- what is a ckt rarity = "cry_epic", cost = 14, blueprint_compat = true, - loc_vars = function(self, info_queue, center) + loc_vars = function(self, info_queue, card) return { - vars = { "" .. (G.GAME and G.GAME.probabilities.normal or 1), (center and center.ability.extra.odds or 2) }, + vars = { card and cry_prob(math.min(card.ability.extra.odds/2, card.ability.cry_prob), card.ability.extra.odds, card.ability.cry_rigged) or 1, card and card.ability.extra.odds or 2 }, -- this effectively prevents a copypaste from ever initially misprinting at above 50% odds. still allows rigging/oops } end, atlas = "atlasepic", @@ -1623,7 +1791,7 @@ local copypaste = { and not context.consumeable.beginning_end then if #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then - if pseudorandom("cry_copypaste_joker") < G.GAME.probabilities.normal / card.ability.extra.odds then + if pseudorandom("cry_copypaste_joker") < cry_prob(math.min(card.ability.extra.odds/2, card.ability.cry_prob), card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds then G.E_MANAGER:add_event(Event({ func = function() local cards = copy_card(context.consumeable) @@ -2208,7 +2376,7 @@ G.FUNCS.variable_apply = function() { "J", "Jack" }, { "Q", "Queen" }, { "K", "King" }, - { "A", "Ace", "One" }, + { "A", "Ace", "One", "1", "I" }, { "M" }, { "nil" }, } @@ -2431,6 +2599,7 @@ G.FUNCS.class_apply = function() m_gold = { "gold", "money", "yellow" }, m_lucky = { "lucky", "rng" }, m_cry_echo = { "echo", "retrigger", "retriggers" }, + m_cry_light = { "light" }, ccd = { "ccd" }, null = { "nil" }, } @@ -2875,6 +3044,7 @@ G.FUNCS.pointer_apply = function() and not G.GAME.banned_keys[current_card] then local card = create_card("Consumeable", G.consumeables, nil, nil, nil, nil, current_card) + if card.ability.name and card.ability.name == "cry-Chambered" then card.ability.extra.num_copies = 1 end card:add_to_deck() G.consumeables:emplace(card) created = true @@ -3046,6 +3216,203 @@ G.FUNCS.pointer_apply = function() G.GAME.USING_POINTER = false end end + if not current_card then -- if card isn't created yet, try playing cards + local words = {} + for i in string.gmatch(string.lower(entered_card), "%S+") do -- not using apply_lower because we actually want the spaces here + table.insert(words, i) + end + + local rank_table = { + { "stone" }, + { "2", "Two", "II" }, + { "3", "Three", "III" }, + { "4", "Four", "IV" }, + { "5", "Five", "V" }, + { "6", "Six", "VI" }, + { "7", "Seven", "VII" }, + { "8", "Eight", "VIII" }, + { "9", "Nine", "IX" }, + { "10", "1O", "Ten", "X", "T" }, + { "J", "Jack" }, + { "Q", "Queen" }, + { "K", "King" }, + { "A", "Ace", "One", "1", "I" }, + } -- ty variable + local _rank = nil + for m = #words, 1, -1 do -- the legendary TRIPLE LOOP, checking from end since rank is most likely near the end + for i, v in pairs(rank_table) do + for j, k in pairs(v) do + if words[m] == string.lower(k) then + _rank = i + break + end + end + if _rank then break end + end + if _rank then break end + end + if _rank then -- a playing card is going to get created at this point, but we can find additional descriptors + local suit_table = { + ["Spades"] = { "spades" }, + ["Hearts"] = { "hearts" }, + ["Clubs"] = { "clubs" }, + ["Diamonds"] = { "diamonds" }, + } + for k, v in pairs(SMODS.Suits) do + local index = v.key + local current_name = G.localization.misc.suits_plural[index] + if not suit_table[v.key] then + suit_table[v.key] = { string.lower(current_name) } + end + end + -- i'd rather be pedantic and not forgive stuff like "spade", there's gonna be a lot of checks + -- can change that if need be + local enh_table = { + ["m_lucky"] = { "lucky" }, + ["m_mult"] = { "mult" }, + ["m_bonus"] = { "bonus" }, + ["m_wild"] = { "wild" }, + ["m_steel"] = { "steel" }, + ["m_glass"] = { "glass" }, + ["m_gold"] = { "gold" }, + ["m_stone"] = { "stone" }, + ["m_cry_echo"] = { "echo" }, + } + for k, v in pairs(G.P_CENTER_POOLS.Enhanced) do + local index = v.key + local current_name = G.localization.descriptions.Enhanced[index].name + current_name = current_name:gsub(" Card$", "") + if not enh_table[v.key] then + enh_table[v.key] = { string.lower(current_name) } + end + end + local ed_table = { + ["e_base"] = { "base" }, + ["e_foil"] = { "foil" }, + ["e_holo"] = { "holo" }, + ["e_polychrome"] = { "polychrome" }, + ["e_negative"] = { "negative" }, + ["e_cry_mosaic"] = { "mosaic" }, + ["e_cry_oversat"] = { "oversat" }, + ["e_cry_glitched"] = { "glitched" }, + ["e_cry_astral"] = { "astral" }, + ["e_cry_blur"] = { "blurred" }, + ["e_cry_gold"] = { "golden" }, + ["e_cry_glass"] = { "fragile" }, + ["e_cry_m"] = { "jolly" }, + ["e_cry_noisy"] = { "noisy" }, + ["e_cry_double_sided"] = { "double-sided", "double_sided", "double" }, -- uhhh sure + } + for k, v in pairs(G.P_CENTER_POOLS.Edition) do + local index = v.key + local current_name = G.localization.descriptions.Edition[index].name + if not ed_table[v.key] then + ed_table[v.key] = { string.lower(current_name) } + end + end + local seal_table = { + ["Red"] = { "red" }, + ["Blue"] = { "blue" }, + ["Purple"] = { "purple" }, + ["Gold"] = { "gold", "golden" }, -- don't worry we're handling seals differently + ["cry_azure"] = { "azure" }, + ["cry_green"] = { "green" }, + } + local sticker_table = { + ["eternal"] = { "eternal" }, + ["perishable"] = { "perishable" }, + ["rental"] = { "rental" }, + ["pinned"] = { "pinned" }, + ["banana"] = { "banana" }, + ["cry_rigged"] = { "rigged" }, + } + local function parsley(_table, _word) + for i, v in pairs(_table) do + for j, k in pairs(v) do + if _word == string.lower(k) then + return i + end + end + end + return "" + end + local function to_rank(rrank) + if rrank <= 10 then return tostring(rrank) + elseif rrank == 11 then return "Jack" + elseif rrank == 12 then return "Queen" + elseif rrank == 13 then return "King" + elseif rrank == 14 then return "Ace" + end + end + + -- ok with all that fluff out the way now we can figure out what on earth we're creating + + local _seal_att = false + local _suit = "" + local _enh = "" + local _ed = "" + local _seal = "" + local _stickers = {} + for m = #words, 1, -1 do + -- we have a word. figure out what that word is + -- this is dodgy spaghetti but w/ever + local wword = words[m] + if _suit == "" then _suit = parsley(suit_table, wword) end + if _enh == "" then + _enh = parsley(enh_table, wword) + if _enh == "m_gold" and _seal_att == true then _enh = "" end + end + if _ed == "" then + _ed = parsley(ed_table, wword) + if _ed == "e_cry_gold" and _seal_att == true then _ed = "" end + end + if _seal == "" then + _seal = parsley(seal_table, wword) + if _seal == "Gold" and _seal_att == false then _seal = "" end + end + local _st = parsley(sticker_table, wword) + if _st then _stickers[#_stickers+1] = _st end + if wword == "seal" or wword == "sealed" then + _seal_att = true + else + _seal_att = false + end -- from end so the next word should describe the seal + end + + -- now to construct the playing card + -- i'm doing this by applying everything but maybe it's a bit janky? + + G.CHOOSE_CARD:remove() + G.GAME.USING_CODE = false + G.GAME.USING_POINTER = false + + G.E_MANAGER:add_event(Event({ + func = function() + G.playing_card = (G.playing_card and G.playing_card + 1) or 1 + local _card = create_card("Base", G.play, nil, nil, nil, nil, nil, "pointer") + SMODS.change_base(_card, _suit ~= "" and _suit or pseudorandom_element({'Spades','Hearts','Diamonds','Clubs'}, pseudoseed('sigil')), _rank > 1 and to_rank(_rank) or nil) + if _enh ~= "" then _card:set_ability(G.P_CENTERS[_enh]) end + if _rank == 1 then _card:set_ability(G.P_CENTERS['m_stone']) end + if _seal ~= "" then _card:set_seal(_seal, true, true) end + if _ed ~= "" then _card:set_edition(_ed, true, true) end + for i = 1, #_stickers do + _card.ability[_stickers[i]] = true + if _stickers[i] == "pinned" then _card.pinned = true end + end + _card:start_materialize() + G.play:emplace(_card) + table.insert(G.playing_cards, _card) + playing_card_joker_effects({ _card }) + return true + end})) + G.E_MANAGER:add_event(Event({ + func = function() + G.deck.config.card_limit = G.deck.config.card_limit + 1 + return true + end})) + draw_card(G.play,G.deck, 90,'up', nil) + end + end end crashes = { function() @@ -3469,9 +3836,13 @@ crashes = { blockable = false, no_delete = true, func = function() - local c = create_card("Code", nil, nil, nil, nil, nil, "c_cry_crash") - c.T.x = math.random(-G.CARD_W, G.TILE_W) - c.T.y = math.random(-G.CARD_H, G.TILE_H) + G.GAME.accel = G.GAME.accel or 1.1 + for i = 1, G.GAME.accel do + local c = create_card("Code", nil, nil, nil, nil, nil, "c_cry_crash") + c.T.x = math.random(-G.CARD_W, G.TILE_W) + c.T.y = math.random(-G.CARD_H, G.TILE_H) + end + G.GAME.accel = G.GAME.accel^(1.005 + G.GAME.accel/20000) return false end, }), @@ -3544,7 +3915,7 @@ local code_cards = { malware, seed, rigged, - hook, + --hook, hooked, variable, class, @@ -3562,8 +3933,11 @@ local code_cards = { --patch, ctrl_v, inst, - encoded, + alttab, } +if Cryptid.enabled["Misc. Decks"] then + code_cards[#code_cards + 1] = encoded +end if Cryptid.enabled["Misc."] then code_cards[#code_cards + 1] = spaghetti end @@ -4042,8 +4416,9 @@ return { local gfco = G.FUNCS.can_open G.FUNCS.can_open = function(e) if G.GAME.USING_RUN then - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil + gfco(e) + -- e.config.colour = G.C.UI.BACKGROUND_INACTIVE + -- e.config.button = nil else gfco(e) end @@ -4069,6 +4444,7 @@ return { trigger = "after", delay = 0.5, func = function() + G.GAME.current_round.used_packs = {} G.cry_runarea:remove() G.cry_runarea = nil G.STATE = G.STATES.SELECTING_HAND @@ -4170,7 +4546,12 @@ return { local results = evaluate_poker_hand_ref(hand) if G.GAME.cry_exploit_override then if not results[G.GAME.cry_exploit_override][1] then - results[G.GAME.cry_exploit_override] = results["High Card"] -- i would do results.top here but it just doesn't work, if someone could get that working that would be great + for _, v in ipairs(G.handlist) do + if results[v][1] then + results[G.GAME.cry_exploit_override] = results[v] + break + end + end end end return results @@ -4210,7 +4591,6 @@ return { end local Cardstart_dissolveRef = Card.start_dissolve function Card:start_dissolve(dissolve_colours, silent, dissolve_time_fac, no_juice) - Cardstart_dissolveRef(self,dissolve_colours, silent, dissolve_time_fac, no_juice) if G.jokers then for i = 1, #G.jokers.cards do if G.jokers.cards[i].hook_id == self.sort_id then @@ -4219,6 +4599,7 @@ return { end end end + Cardstart_dissolveRef(self,dissolve_colours, silent, dissolve_time_fac, no_juice) end end, items = code_cards, diff --git a/Cryptid/Items/Decks.lua b/Cryptid/Items/Decks.lua index 1bc5cbb..2b538bc 100644 --- a/Cryptid/Items/Decks.lua +++ b/Cryptid/Items/Decks.lua @@ -204,7 +204,7 @@ local glowing = { trigger_effect = function(self, args) if args.context == "eval" and G.GAME.last_blind and G.GAME.last_blind.boss then for i = 1, #G.jokers.cards do - if G.jokers.cards[i].ability.name ~= "Ace Aequilibrium" then --Same Reason as Gemini/Multiply + if not Card.no(G.jokers.cards[i], "immutable", true) then cry_with_deck_effects(G.jokers.cards[i], function(card) cry_misprintize(card, { min = 1.25, max = 1.25 }, nil, true) end) @@ -227,9 +227,18 @@ local bountiful = { name = "cry-Bountiful", key = "bountiful", config = { cry_forced_draw_amount = 5 }, - pos = { x = 4, y = 2 }, + pos = { x = 2, y = 6 }, order = 14, - atlas = "placeholders", + atlas = "atlasdeck", +} +local beige = { + object_type = "Back", + name = "cry-Beige", + key = "beige", + config = { cry_common_value_quad = true }, + pos = { x = 1, y = 6 }, + order = 15, + atlas = "atlasdeck", } return { name = "Misc. Decks", @@ -247,8 +256,8 @@ return { G.GAME.modifiers.cry_conveyor = true end if self.effect.config.cry_misprint_min then - G.GAME.modifiers.cry_misprint_min = self.effect.config.cry_misprint_min - G.GAME.modifiers.cry_misprint_max = self.effect.config.cry_misprint_max + G.GAME.modifiers.cry_misprint_min = (G.GAME.modifiers.cry_misprint_min or 1) * self.effect.config.cry_misprint_min + G.GAME.modifiers.cry_misprint_max = (G.GAME.modifiers.cry_misprint_max or 1) * self.effect.config.cry_misprint_max end if self.effect.config.cry_highlight_limit then G.GAME.modifiers.cry_highlight_limit = self.effect.config.cry_highlight_limit @@ -258,6 +267,7 @@ return { end if self.effect.config.cry_beta then G.GAME.modifiers.cry_beta = true + G.GAME.pool_flags.beta_deck = true end if self.effect.config.cry_legendary then G.E_MANAGER:add_event(Event({ @@ -295,6 +305,9 @@ return { if self.effect.config.cry_forced_draw_amount then G.GAME.modifiers.cry_forced_draw_amount = self.effect.config.cry_forced_draw_amount end + if self.effect.config.cry_common_value_quad then + G.GAME.modifiers.cry_common_value_quad = true + end end --equilibrium deck patches local gcp = get_current_pool @@ -312,22 +325,26 @@ return { and t ~= "Seal" and t ~= "Stake" then - if not P_CRY_ITEMS then + if true then -- if not P_CRY_ITEMS then + -- we're regenerating the pool every time because of banned keys but it's fine tbh P_CRY_ITEMS = {} local valid_pools = { "Joker", "Consumeables", "Voucher", "Booster" } for _, id in ipairs(valid_pools) do for k, v in pairs(G.P_CENTER_POOLS[id]) do - if v.unlocked == true and not center_no(v, "doe", k) then + if v.unlocked == true and not center_no(v, "doe", k) and not G.GAME.banned_keys[v.key] then P_CRY_ITEMS[#P_CRY_ITEMS + 1] = v.key end end end + --[[ this doesn't seem to be working for k, v in pairs(G.P_CARDS) do if v.unlocked == true and not center_no(v, "doe", k) then P_CRY_ITEMS[#P_CRY_ITEMS + 1] = v.key end end + ]] end + if #P_CRY_ITEMS <= 0 then P_CRY_ITEMS[#P_CRY_ITEMS + 1] = 'v_blank' end return P_CRY_ITEMS, "cry_equilibrium" .. G.GAME.round_resets.ante end end @@ -464,5 +481,6 @@ return { glowing, beta, bountiful, + beige, }, } diff --git a/Cryptid/Items/Enhanced.lua b/Cryptid/Items/Enhanced.lua index 73c4c50..858bf8d 100644 --- a/Cryptid/Items/Enhanced.lua +++ b/Cryptid/Items/Enhanced.lua @@ -56,6 +56,7 @@ local typed_decks = { -- todo: work with mod config better here { "cry", "Enhancement", "The Eclipse's Deck", "Echo", "echo", nil, "atlasenhanced", 1, 5, "" }, + { "cry", "Enhancement", "The Seraph's Deck", "Light", "light", nil, "cry_misc", 0, 3, "" }, { "cry", "Edition", nil, "Fragile", "glass", nil, nil, 5, 2, "" }, { "cry", "Edition", nil, "Golden", "gold", nil, nil, 5, 2, "" }, @@ -400,8 +401,7 @@ return { if center.name == "Fortune Teller" or center.name == "Shoot the Moon" - or center.name == "Riff-raff" - or center.name == "Business Card" + or center.name == "Riff-raff" or center.name == "Chaos the Clown" or center.name == "Dusk" or center.name == "Mime" diff --git a/Cryptid/Items/EpicJokers.lua b/Cryptid/Items/EpicJokers.lua index fee15bc..d1de8c2 100644 --- a/Cryptid/Items/EpicJokers.lua +++ b/Cryptid/Items/EpicJokers.lua @@ -102,12 +102,12 @@ local googol_play = { blueprint_compat = true, atlas = "atlasepic", soul_pos = { x = 10, y = 0, extra = { x = 4, y = 0 } }, - loc_vars = function(self, info_queue, center) + loc_vars = function(self, info_queue, card) return { vars = { - "" .. (G.GAME and G.GAME.probabilities.normal or 1), - center.ability.extra.odds, - center.ability.extra.Xmult, + cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), + card.ability.extra.odds, + card.ability.extra.Xmult, }, } end, @@ -116,7 +116,7 @@ local googol_play = { context.cardarea == G.jokers and not context.before and not context.after - and pseudorandom("cry_googol_play") < G.GAME.probabilities.normal / card.ability.extra.odds + and pseudorandom("cry_googol_play") < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds then return { message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.Xmult } }), @@ -135,6 +135,18 @@ local googol_play = { "Math" } }, + unlocked = false, + check_for_unlock = function(self, args) + if args.type == 'chip_score' and to_big(args.chips) >= to_big(1e100) then + unlock_card(self) + end + if args.type == 'cry_lock_all' then + lock_card(self) + end + if args.type == 'cry_unlock_all' then + unlock_card(self) + end + end, } local sync_catalyst = { object_type = "Joker", @@ -271,6 +283,21 @@ local error_joker = { blueprint_compat = false, eternal_compat = false, atlas = "atlasepic", + loc_vars = function(self, info_queue, center) + if G.GAME and G.GAME.pseudorandom and G.STAGE == G.STAGES.RUN then + cry_error_msgs[#cry_error_msgs].string = "%%" .. predict_card_for_shop() + else + cry_error_msgs[#cry_error_msgs].string = "%%J6" + end + return { + main_start = { + {n=G.UIT.O, config={object = DynaText({string = cry_error_operators, colours = {G.C.DARK_EDITION,},pop_in_rate = 9999999, silent = true, random_element = true, pop_delay = 0.30, scale = 0.32, min_cycle_time = 0})}}, + {n=G.UIT.O, config={object = DynaText({string = cry_error_numbers, colours = {G.C.DARK_EDITION,},pop_in_rate = 9999999, silent = true, random_element = true, pop_delay = 0.33, scale = 0.32, min_cycle_time = 0})}}, + {n=G.UIT.O, config={object = DynaText({string = cry_error_msgs, + colours = {G.C.UI.TEXT_DARK},pop_in_rate = 9999999, silent = true, random_element = true, pop_delay = 0.4011, scale = 0.32, min_cycle_time = 0})}}, + } + } + end, add_to_deck = function(self, card, from_debuff) if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_edition_from_deck then G.GAME.modifiers.cry_force_edition_from_deck = G.GAME.modifiers.cry_force_edition @@ -411,13 +438,15 @@ local m = { local vc = self.calculate self.calculate = function(self, card, context) local ret, trig = vc(self, card, context) - local reps = get_m_retriggers(self, card, context) - if context.retrigger_joker_check and context.other_card == card and reps > 0 then - return { - message = localize("k_again_ex"), - repetitions = reps + (ret and ret.repetitions or 0), - card = card, - } + if context.retrigger_joker_check and context.other_card == card then + local reps = get_m_retriggers(self, card, context) + if reps > 0 then + return { + message = localize("k_again_ex"), + repetitions = reps + (ret and ret.repetitions or 0), + card = card, + } + end end return ret, trig end @@ -474,13 +503,15 @@ local M = { local vc = self.calculate self.calculate = function(self, card, context) local ret, trig = vc(self, card, context) - local reps = get_m_retriggers(self, card, context) - if context.retrigger_joker_check and context.other_card == card and reps > 0 then - return { - message = localize("k_again_ex"), - repetitions = reps + (ret and ret.repetitions or 0), - card = card, - } + if context.retrigger_joker_check and context.other_card == card then + local reps = get_m_retriggers(self, card, context) + if reps > 0 then + return { + message = localize("k_again_ex"), + repetitions = reps + (ret and ret.repetitions or 0), + card = card, + } + end end return ret, trig end @@ -509,13 +540,13 @@ local boredom = { order = 32, cost = 14, blueprint_compat = true, - loc_vars = function(self, info_queue, center) - return { vars = { "" .. (G.GAME and G.GAME.probabilities.normal or 1), center.ability.extra.odds } } + loc_vars = function(self, info_queue, card) + return { vars = { cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), card.ability.extra.odds } } end, atlas = "atlasepic", calculate = function(self, card, context) if context.retrigger_joker_check and not context.retrigger_joker and context.other_card ~= self then - if pseudorandom("cry_boredom_joker") < G.GAME.probabilities.normal / card.ability.extra.odds then + if pseudorandom("cry_boredom_joker") < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds then return { message = localize("k_again_ex"), repetitions = 1, @@ -528,7 +559,7 @@ local boredom = { if context.repetition and context.cardarea == G.play - and pseudorandom("cry_boredom_card") < G.GAME.probabilities.normal / card.ability.extra.odds + and pseudorandom("cry_boredom_card") < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds then return { message = localize("k_again_ex"), @@ -771,6 +802,27 @@ local circus = { "Jevonn" } }, + unlocked = false, + check_for_unlock = function(self, args) + if G and G.jokers and G.GAME and G.GAME.round_resets and G.GAME.round_resets.ante and G.GAME.round_resets.ante < 9 then + local rarities = { + + } + for i = 1, #G.jokers.cards do + local card = G.jokers.cards[i] + rarities[card.config.center.rarity .. '_rarity'] = true + end + if rarities['3_rarity'] and rarities['4_rarity'] and rarities['cry_epic_rarity'] then + unlock_card(self) + end + end + if args.type == 'cry_lock_all' then + lock_card(self) + end + if args.type == 'cry_unlock_all' then + unlock_card(self) + end + end, } local caramel = { object_type = "Joker", @@ -908,8 +960,7 @@ local curse_sob = { if not from_debuff then local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_obelisk") card:set_edition("e_negative", true, nil, true) - card.sob = true - card:set_eternal(true) + card.ability.cry_absolute = true card:add_to_deck() G.jokers:emplace(card) return { @@ -931,29 +982,44 @@ local curse_sob = { "Jevonn" } }, + unlocked = false, + check_for_unlock = function(self, args) + if G and G.jokers then + for i = 1, #G.jokers.cards do + if G.jokers.cards[i].config.center.key == 'j_obelisk' and G.jokers.cards[i].ability.eternal then + unlock_card(self) + end + end + end + if args.type == 'cry_lock_all' then + lock_card(self) + end + if args.type == 'cry_unlock_all' then + unlock_card(self) + end + end, } local bonusjoker = { object_type = "Joker", name = "cry-Bonus Joker", key = "bonusjoker", pos = { x = 3, y = 2 }, - config = { extra = { odds = 8, check = 0 } }, - immutable = true, + config = { extra = { odds = 8, check = 0, add = 1 } }, rarity = "cry_epic", cost = 11, order = 75, blueprint_compat = true, enhancement_gate = "m_bonus", - loc_vars = function(self, info_queue, center) + loc_vars = function(self, info_queue, card) info_queue[#info_queue + 1] = G.P_CENTERS.m_bonus - return { vars = { "" .. (G.GAME and G.GAME.probabilities.normal or 1), center.ability.extra.odds } } + return { vars = { cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), card.ability.extra.odds, card.ability.extra.add } } end, atlas = "atlasepic", calculate = function(self, card, context) if context.individual and context.cardarea == G.play then if context.other_card.ability.effect == "Bonus Card" then if - pseudorandom("bonusjoker") < G.GAME.probabilities.normal / card.ability.extra.odds + pseudorandom("bonusjoker") < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds and card.ability.extra.check < 2 and not context.retrigger_joker then @@ -962,12 +1028,12 @@ local bonusjoker = { if not context.blueprint then card.ability.extra.check = card.ability.extra.check + 1 end - G.jokers.config.card_limit = G.jokers.config.card_limit + 1 + G.jokers.config.card_limit = G.jokers.config.card_limit + card.ability.extra.add else if not context.blueprint then card.ability.extra.check = card.ability.extra.check + 1 end - G.consumeables.config.card_limit = G.consumeables.config.card_limit + 1 + G.consumeables.config.card_limit = G.consumeables.config.card_limit + card.ability.extra.add end return { extra = { focus = card, message = localize("k_upgrade_ex") }, @@ -1015,10 +1081,10 @@ local multjoker = { cost = 11, blueprint_compat = true, enhancement_gate = "m_mult", - loc_vars = function(self, info_queue, center) + loc_vars = function(self, info_queue, card) info_queue[#info_queue + 1] = G.P_CENTERS.m_mult info_queue[#info_queue + 1] = G.P_CENTERS.c_cryptid - return { vars = { "" .. (G.GAME and G.GAME.probabilities.normal or 1), center.ability.extra.odds } } + return { vars = { cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), card.ability.extra.odds } } end, atlas = "atlasepic", calculate = function(self, card, context) @@ -1027,7 +1093,7 @@ local multjoker = { context.other_card.ability.effect == "Mult Card" and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then - if pseudorandom("multjoker") < G.GAME.probabilities.normal / card.ability.extra.odds then + if pseudorandom("multjoker") < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds then G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 G.E_MANAGER:add_event(Event({ func = function() @@ -1105,7 +1171,11 @@ local goldjoker = { calc_dollar_bonus = function(self, card) local bonus = math.max(0, math.floor(0.01 * card.ability.extra.percent * (G.GAME.dollars or 0))) if bonus > 0 then - return bonus + if G.GAME.dollars > 1e10 then + return 1 + else + return bonus + end end end, cry_credits = { @@ -1124,8 +1194,8 @@ local altgoogol = { object_type = "Joker", name = "cry-altgoogol", key = "altgoogol", + config = { extra = { jokers = 2 } }, pos = { x = 4, y = 3 }, - immutable = true, rarity = "cry_epic", cost = 10, order = 60, @@ -1133,6 +1203,9 @@ local altgoogol = { eternal_compat = false, atlas = "atlasepic", soul_pos = { x = 10, y = 0, extra = { x = 5, y = 3 } }, + loc_vars = function(self, info_queue, card) + return { vars = { math.floor(math.min(20, card.ability.extra.jokers)) } } + end, calculate = function(self, card, context) if context.selling_self and not context.retrigger_joker then local jokers = {} @@ -1146,7 +1219,7 @@ local altgoogol = { local spawn = {G.jokers.cards[1]} G.E_MANAGER:add_event(Event({ func = function() - for i = 1, 2 do + for i = 1, math.floor(math.min(20, card.ability.extra.jokers)) do local card = copy_card(pseudorandom_element(spawn, pseudoseed("cry_ngpc")), nil) card:add_to_deck() G.jokers:emplace(card) @@ -1214,34 +1287,36 @@ local soccer = { key = "soccer", pos = { x = 1, y = 4 }, config = { extra = { holygrail = 1 } }, - immutable = true, rarity = "cry_epic", order = 58, cost = 20, atlas = "atlasepic", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.holygrail } } + return { vars = { math.floor(math.min(15, center.ability.extra.holygrail)) } } end, add_to_deck = function(self, card, from_debuff) --TODO: Card in booster packs, Voucher slots - card.ability.extra.holygrail = math.floor(card.ability.extra.holygrail) - G.jokers.config.card_limit = G.jokers.config.card_limit + card.ability.extra.holygrail - G.consumeables.config.card_limit = G.consumeables.config.card_limit + card.ability.extra.holygrail - G.hand:change_size(card.ability.extra.holygrail) + local holy = math.floor(math.min(15, card.ability.extra.holygrail)) + G.jokers.config.card_limit = G.jokers.config.card_limit + holy + G.consumeables.config.card_limit = G.consumeables.config.card_limit + holy + G.hand:change_size(holy) if not G.GAME.modifiers.cry_booster_packs then G.GAME.modifiers.cry_booster_packs = 2 end - G.GAME.modifiers.cry_booster_packs = G.GAME.modifiers.cry_booster_packs + card.ability.extra.holygrail - change_shop_size(card.ability.extra.holygrail) + G.GAME.modifiers.cry_booster_packs = G.GAME.modifiers.cry_booster_packs + holy + change_shop_size(holy) + cry_bonusvouchermod(holy) end, remove_from_deck = function(self, card, from_debuff) - G.jokers.config.card_limit = G.jokers.config.card_limit - card.ability.extra.holygrail - G.consumeables.config.card_limit = G.consumeables.config.card_limit - card.ability.extra.holygrail - G.hand:change_size(-card.ability.extra.holygrail) + local holy = math.floor(math.min(15, card.ability.extra.holygrail)) + G.jokers.config.card_limit = G.jokers.config.card_limit - holy + G.consumeables.config.card_limit = G.consumeables.config.card_limit - holy + G.hand:change_size(-holy) if not G.GAME.modifiers.cry_booster_packs then G.GAME.modifiers.cry_booster_packs = 2 end - G.GAME.modifiers.cry_booster_packs = G.GAME.modifiers.cry_booster_packs - card.ability.extra.holygrail - change_shop_size(card.ability.extra.holygrail * -1) + G.GAME.modifiers.cry_booster_packs = G.GAME.modifiers.cry_booster_packs - holy + change_shop_size(holy * -1) + cry_bonusvouchermod(-1*holy) end, cry_credits = { idea = { @@ -1254,6 +1329,24 @@ local soccer = { "Jevonn" } }, + unlocked = false, + check_for_unlock = function(self, args) + if args.type == 'win' then + + for k,v in pairs(G.GAME.hands) do + if k ~= 'High Card' and G.GAME.hands[k].played ~= 0 then + return + end + end + return true + end + if args.type == 'cry_lock_all' then + lock_card(self) + end + if args.type == 'cry_unlock_all' then + unlock_card(self) + end + end, } local fleshpanopticon = { object_type = "Joker", @@ -1261,7 +1354,6 @@ local fleshpanopticon = { key = "fleshpanopticon", pos = { x = 0, y = 5 }, config = { extra = { boss_size = 20 } }, - immutable = true, rarity = "cry_epic", cost = 15, order = 146, @@ -1335,6 +1427,54 @@ local fleshpanopticon = { } }, } +local spectrogram = { + object_type = "Joker", + name = "cry-Spectrogram", + key = "spectrogram", + pos = { x = 1, y = 5 }, + config = { extra = {} }, + rarity = "cry_epic", + cost = 9, + order = 133, + atlas = "atlasepic", + loc_vars = function(self, info_queue, center) + info_queue[#info_queue + 1] = G.P_CENTERS.m_cry_echo + + return { vars = {} } + end, + calculate = function(self, card, context) + if context.retrigger_joker_check and not context.retrigger_joker and context.other_card ~= self then + if context.other_context.scoring_hand then + if context.other_card == G.jokers.cards[#G.jokers.cards] then + local echonum = 0 + for i, v in pairs (context.other_context.scoring_hand) do + if v.config.center_key == 'm_cry_echo' then + echonum = echonum + 1 + end + end + if echonum > 0 then + return { + message = localize("k_again_ex"), + repetitions = echonum, + card = card, + } + end + end + end + end + end, + cry_credits = { + idea = { + "AlexZGreat" + }, + art = { + "SMG9000" + }, + code = { + "AlexZGreat" + } + }, +} return { name = "Epic Jokers", init = function() @@ -1364,6 +1504,13 @@ return { "pi", "1e9", "???", + "114", + "leet", + "666", + "eee6", + "21", + "365", + "2024", } cry_error_msgs = { { string = "rand()", colour = G.C.RARITY["cry_exotic"] }, @@ -1378,7 +1525,11 @@ return { { string = "ERROR", colour = G.C.UI.TEXT_INACTIVE }, { string = "Tarots", colour = G.C.SECONDARY_SET.Tarot }, { string = "Planets", colour = G.C.SECONDARY_SET.Planet }, + { string = "Codes", colour = G.C.SECONDARY_SET.Code }, { string = "Specls", colour = G.C.SECONDARY_SET.Spectral }, + { string = "Jolly", colour = G.C.CRY_JOLLY }, + { string = "Tags", colour = G.C.RED }, + { string = "Cryptids", colour = G.C.SECONDARY_SET.Spectral }, { string = "%%ERROR", colour = G.C.CRY_ASCENDANT }, --temp string, this will be modified } @@ -1524,5 +1675,6 @@ return { altgoogol, soccer, fleshpanopticon, + spectrogram, }, } diff --git a/Cryptid/Items/Exotic.lua b/Cryptid/Items/Exotic.lua index 93b142c..18d616b 100644 --- a/Cryptid/Items/Exotic.lua +++ b/Cryptid/Items/Exotic.lua @@ -224,7 +224,6 @@ local redeo = { } end, pos = { x = 3, y = 0 }, - immutable = true, rarity = "cry_exotic", cost = 50, order = 506, @@ -441,7 +440,7 @@ local primus = { } local big_num_whitelist = { j_ride_the_bus = true, - j_egg = true, + j_egg = false, j_runner = true, j_ice_cream = true, j_constellation = true, @@ -699,12 +698,11 @@ local aequilibrium = { config = { extra = { jokers = 2, card = nil } }, rarity = "cry_exotic", pos = { x = 7, y = 0 }, - soul_pos = { x = 69, y = 0, extra = { x = 8, y = 0 } }, + soul_pos = { x = 6, y = 0, extra = { x = 8, y = 0 } }, atlas = "atlasexotic", cost = 50, order = 512, blueprint_compat = true, - immutable = true, eternal_compat = true, perishable_compat = true, loc_vars = function(self, info_queue, center) @@ -719,11 +717,11 @@ local aequilibrium = { key = G.P_CENTER_POOLS["Joker"][math.floor(G.GAME.aequilibriumkey or 1) - 1].key, }) end - return { vars = { center.ability.extra.jokers, joker_generated } } + return { vars = { math.floor(math.min(25, center.ability.extra.jokers)), joker_generated } } end, calculate = function(self, card, context) if context.cardarea == G.jokers and context.before and not context.retrigger_joker then - for i = 1, math.min(200, card.ability.extra.jokers) do + for i = 1, math.floor(math.min(25, card.ability.extra.jokers)) do local newcard = create_card("Joker", G.jokers, nil, nil, nil, nil, nil) newcard:add_to_deck() G.jokers:emplace(newcard) @@ -732,6 +730,7 @@ local aequilibrium = { return nil, true end end, + --[[ add_to_deck = function(self, card, from_debuff) if not from_debuff then if card.ability.extra.card then @@ -801,6 +800,7 @@ local aequilibrium = { card.ability.extra.card:start_dissolve() end end, + ]]-- cry_credits = { idea = {"Elial2"}, art = {"Elial2"}, @@ -900,6 +900,28 @@ local gemino = { cost = 50, order = 515, atlas = "atlasexotic", + loc_vars = function(self, info_queue, card) + card.ability.blueprint_compat_ui = card.ability.blueprint_compat_ui or ''; card.ability.blueprint_compat_check = nil + return { + main_end = (card.area and card.area == G.jokers) and { + {n=G.UIT.C, config={align = "bm", minh = 0.4}, nodes={ + {n=G.UIT.C, config={ref_table = card, align = "m", colour = G.C.JOKER_GREY, r = 0.05, padding = 0.06, func = 'blueprint_compat'}, nodes={ + {n=G.UIT.T, config={ref_table = card.ability, ref_value = 'blueprint_compat_ui',colour = G.C.UI.TEXT_LIGHT, scale = 0.32*0.8}}, + }} + }} + } or nil + } + end, + update = function(self, card, front) + if G.STAGE == G.STAGES.RUN then + other_joker = G.jokers.cards[1] + if other_joker and other_joker ~= card and not (Card.no(other_joker, "immutable", true)) then + card.ability.blueprint_compat = 'compatible' + else + card.ability.blueprint_compat = 'incompatible' + end + end + end, calculate = function(self, card2, context) if context.end_of_round and not context.repetition and not context.individual then local check = false diff --git a/Cryptid/Items/M.lua b/Cryptid/Items/M.lua index b91a44b..a6a8cb5 100644 --- a/Cryptid/Items/M.lua +++ b/Cryptid/Items/M.lua @@ -407,14 +407,13 @@ local notebook = { pos = { x = 1, y = 0 }, order = 255, config = { - extra = { odds = 7, slot = 0, jollies = 4, check = true, active = "Active", inactive = "" }, + extra = { odds = 7, slot = 0, jollies = 4, check = true, active = "Active", inactive = "", add = 1 }, jolly = { t_mult = 8, type = "Pair" }, }, - immutable = true, rarity = 3, cost = 9, perishable_compat = false, - loc_vars = function(self, info_queue, center) + loc_vars = function(self, info_queue, card) info_queue[#info_queue + 1] = { set = "Joker", key = "j_jolly", @@ -422,11 +421,12 @@ local notebook = { } return { vars = { - "" .. (G.GAME and G.GAME.probabilities.normal or 1), - center.ability.extra.odds, - center.ability.extra.slot, - center.ability.extra.active, - center.ability.extra.jollies, + cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), + card.ability.extra.odds, + card.ability.extra.slot, + card.ability.extra.active, + card.ability.extra.jollies, + card.ability.extra.add, }, } end, @@ -448,10 +448,10 @@ local notebook = { end if jollycount >= card.ability.extra.jollies --if there are 5 or more jolly jokers - or pseudorandom("cry_notebook") < G.GAME.probabilities.normal / card.ability.extra.odds + or pseudorandom("cry_notebook") < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds then - card.ability.extra.slot = card.ability.extra.slot + 1 - G.jokers.config.card_limit = G.jokers.config.card_limit + 1 + card.ability.extra.slot = card.ability.extra.slot + card.ability.extra.add + G.jokers.config.card_limit = G.jokers.config.card_limit + card.ability.extra.add card.ability.extra.check = false card.ability.extra.active = localize("cry_inactive") return { @@ -657,20 +657,20 @@ local scrabble = { cost = 8, blueprint_compat = true, atlas = "atlasone", - loc_vars = function(self, info_queue, center) + loc_vars = function(self, info_queue, card) info_queue[#info_queue + 1] = G.P_CENTERS.e_cry_m - return { vars = { "" .. (G.GAME and G.GAME.probabilities.normal or 1), center.ability.extra.odds } } + return { vars = { cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), card.ability.extra.odds } } end, calculate = function(self, card, context) if context.cardarea == G.jokers and context.before and not context.retrigger_joker then local check = false - --if pseudorandom('scrabble') < G.GAME.probabilities.normal/card.ability.extra.odds then + --if pseudorandom('scrabble') < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged)/card.ability.extra.odds then --check = true --local card = create_card('Joker', G.jokers, nil, nil, nil, nil, 'j_jolly') --card:add_to_deck() --G.jokers:emplace(card) --end - if pseudorandom("scrabbleother") < G.GAME.probabilities.normal / card.ability.extra.odds then + if pseudorandom("scrabbleother") < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds then check = true local card = create_card("Joker", G.jokers, nil, 0.9, nil, nil, nil, "scrabbletile") card:set_edition({ cry_m = true }) @@ -700,10 +700,9 @@ local sacrifice = { name = "cry-sacrifice", key = "sacrifice", effect = "M Joker", - config = { extra = { text = localize("k_active_ex"), spawn = true }, jolly = { t_mult = 8, type = "Pair" } }, + config = { extra = { jollies = 3, unc = 1, text = localize("k_active_ex"), spawn = true }, jolly = { t_mult = 8, type = "Pair" } }, pos = { x = 5, y = 2 }, order = 259, - immutable = true, rarity = 1, cost = 4, blueprint_compat = true, @@ -714,27 +713,34 @@ local sacrifice = { key = "j_jolly", specific_vars = { self.config.jolly.t_mult, localize(self.config.jolly.type, "poker_hands") }, } - return { vars = { center.ability.extra.text } } + return { vars = { center.ability.extra.text, math.min(30, center.ability.extra.jollies), math.min(30, center.ability.extra.unc) } } end, calculate = function(self, card, context) if context.using_consumeable and card.ability.extra.spawn and not context.retrigger_joker then if context.consumeable.ability.set == "Spectral" then if not context.blueprint then - card.ability.extra.spawn = false + G.E_MANAGER:add_event(Event({ + func = function() + card.ability.extra.spawn = false + return true + end, + })) end if not card.ability.extra.spawn then - card.ability.extra.text = localize("cry_no_triggers") + -- card.ability.extra.text = localize("cry_no_triggers") what is going on here? end - for i = 1, 3 do + for i = 1, math.min(30, card.ability.extra.jollies) do local jolly = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") jolly:add_to_deck() G.jokers:emplace(jolly) end - local card = create_card("Joker", G.jokers, nil, 0.9, nil, nil, nil, "sacrifice") - card:add_to_deck() - G.jokers:emplace(card) - card:start_materialize() - card_eval_status_text(card, "extra", nil, nil, nil, { message = localize("cry_m_ex"), colour = G.C.SPECTRAL }) + for i = 1, math.min(30, card.ability.extra.unc) do + local unc = create_card("Joker", G.jokers, nil, 0.9, nil, nil, nil, "sacrifice") + unc:add_to_deck() + G.jokers:emplace(unc) + unc:start_materialize() + end + card_eval_status_text(context.blueprint_card or card, "extra", nil, nil, nil, { message = localize("cry_m_ex"), colour = G.C.SPECTRAL }) return nil, true end end @@ -853,9 +859,8 @@ local doodlem = { key = "doodlem", atlas = "atlasepic", effect = "M Joker", - config = { jolly = { t_mult = 8, type = "Pair" } }, + config = { extra = {add = 1, init = 2}, jolly = { t_mult = 8, type = "Pair" } }, pos = { x = 2, y = 0 }, - immutable = true, rarity = "cry_epic", cost = 13, order = 266, @@ -867,19 +872,20 @@ local doodlem = { specific_vars = { self.config.jolly.t_mult, localize(self.config.jolly.type, "poker_hands") }, } info_queue[#info_queue + 1] = { key = "e_negative_consumable", set = "Edition", config = { extra = 1 } } + return { vars = { center.ability.extra.add, center.ability.extra.init } } end, calculate = function(self, card, context) if context.setting_blind and not (context.blueprint_card or self).getting_sliced then - local jollycount = 2 + local jollycount = card.ability.extra.init for i = 1, #G.jokers.cards do if G.jokers.cards[i]:is_jolly() then - jollycount = jollycount + 1 + jollycount = jollycount + card.ability.extra.add end end - if jollycount > 18 then - jollycount = 18 + if jollycount > 25 then + jollycount = 25 end --reduce excessive consumeable spam (Lag) for i = 1, jollycount do local card = create_card("Consumeables", G.consumeables, nil, nil, nil, nil, nil, "cry_doodlem") @@ -1209,14 +1215,14 @@ local macabre = { effect = "M Joker", order = 263, pos = { x = 1, y = 2 }, - immutable = true, - config = { jolly = { t_mult = 8, type = "Pair" } }, + config = { extra = {add = 1}, jolly = { t_mult = 8, type = "Pair" } }, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = { set = "Joker", key = "j_jolly", specific_vars = { self.config.jolly.t_mult, localize(self.config.jolly.type, "poker_hands") }, } + return { vars = { math.min(15, center.ability.extra.add) } } end, rarity = 1, cost = 5, @@ -1248,9 +1254,11 @@ local macabre = { triggered = true v.getting_sliced = true v:start_dissolve({ HEX("57ecab") }, nil, 1.6) - local jolly_card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") - jolly_card:add_to_deck() - G.jokers:emplace(jolly_card) + for i = 1, math.min(15, card.ability.extra.add) do + local jolly_card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") + jolly_card:add_to_deck() + G.jokers:emplace(jolly_card) + end end if triggered then card:juice_up(0.8, 0.8) @@ -1473,13 +1481,15 @@ return { local vc = ret_items[i].calculate ret_items[i].calculate = function(self, card, context) local ret, trig = vc(self, card, context) - local reps = get_m_retriggers(self, card, context) - if context.retrigger_joker_check and context.other_card == card and reps > 0 then - return { - message = localize("k_again_ex"), - repetitions = reps + (ret and ret.repetitions or 0), - card = card, - } + if context.retrigger_joker_check and context.other_card == card then + local reps = get_m_retriggers(self, card, context) + if reps > 0 then + return { + message = localize("k_again_ex"), + repetitions = reps + (ret and ret.repetitions or 0), + card = card, + } + end end return ret, trig end diff --git a/Cryptid/Items/Misc.lua b/Cryptid/Items/Misc.lua index b9dcf0d..480cd49 100644 --- a/Cryptid/Items/Misc.lua +++ b/Cryptid/Items/Misc.lua @@ -956,8 +956,8 @@ local echo = { atlas = "cry_misc", pos = { x = 2, y = 0 }, config = { retriggers = 2, extra = 2 }, - loc_vars = function(self, info_queue) - return { vars = { self.config.retriggers, G.GAME.probabilities.normal, self.config.extra } } + loc_vars = function(self, info_queue, card) + return { vars = { self.config.retriggers, card and cry_prob(card.ability.cry_prob or 1, card.ability.extra, card.ability.cry_rigged) or 1, self.config.extra } } -- note that the check for (card.ability.cry_prob or 1) is probably unnecessary due to cards being initialised with ability.cry_prob end, } local eclipse = { @@ -969,9 +969,49 @@ local eclipse = { pos = { x = 4, y = 0 }, config = { mod_conv = "m_cry_echo", max_highlighted = 1 }, atlas = "atlasnotjokers", - loc_vars = function(self, info_queue) + loc_vars = function(self, info_queue, card) info_queue[#info_queue + 1] = G.P_CENTERS.m_cry_echo + return { vars = { card and card.ability.max_highlighted or self.config.max_highlighted } } + end, +} +local light = { + object_type = "Enhancement", + key = "light", + atlas = "cry_misc", + pos = { x = 0, y = 3 }, + config = {extra = {a_x_mult = 0.2, current_x_mult = 1, req = 5, current = 5}}, + loc_vars = function(self, info_queue, card) + return { vars = { card and card.ability.extra.a_x_mult or self.config.extra.a_x_mult, card and card.ability.extra.current_x_mult or self.config.extra.current_x_mult, card and card.ability.extra.current or self.config.extra.current, card and card.ability.extra.req or self.config.extra.req } } + end, + calculate = function(self,card,context,effect) + if context.cardarea == G.play and not context.repetition then + if #context.scoring_hand > 1 then + card.ability.extra.current = card.ability.extra.current - (#context.scoring_hand - 1) + while card.ability.extra.current <= 0 do + card.ability.extra.req = card.ability.extra.req +5 + card.ability.extra.current = card.ability.extra.current + card.ability.extra.req + card.ability.extra.current_x_mult = card.ability.extra.current_x_mult + card.ability.extra.a_x_mult + end + end + if card.ability.extra.current_x_mult > 1 then + effect.x_mult = card.ability.extra.current_x_mult + end + end + end, +} +local seraph = { + object_type = "Consumable", + set = "Tarot", + name = "cry-Seraph", + key = "seraph", + order = 2, + pos = { x = 1, y = 2 }, + config = { mod_conv = "m_cry_light", max_highlighted = 2 }, + atlas = "placeholders", + loc_vars = function(self, info_queue) + info_queue[#info_queue + 1] = G.P_CENTERS.m_cry_light + return { vars = { self.config.max_highlighted } } end, } @@ -1119,11 +1159,18 @@ local meld = { cost = 4, atlas = "atlasnotjokers", can_use = function(self, card) - if #G.jokers.highlighted - + #G.hand.highlighted - - (G.hand.highlighted[1] and G.hand.highlighted[1] == self and 1 or 0) - == 1 then - if #G.jokers.highlighted == 1 and Card.no(G.jokers.highlighted[1], "dbl") then return false end + if #G.jokers.highlighted + #G.hand.highlighted - (G.hand.highlighted[1] and G.hand.highlighted[1] == self and 1 or 0) == 1 then + if + #G.jokers.highlighted == 1 and + ( + Card.no(G.jokers.highlighted[1], "dbl") + or G.jokers.highlighted[1].edition + ) + then return false end + if + #G.hand.highlighted == 1 + and G.hand.highlighted[1].edition + then return false end return true end end, @@ -1261,10 +1308,10 @@ local fulldeck = { object_type = "PokerHand", key = 'WholeDeck', visible = false, - chips = 5200, - mult = 520, - l_chips = 520, - l_mult = 52, + chips = 525252525252525252525252525252, + mult = 52525252525252525252525252525, + l_chips = 52525252525252525252525252525, + l_mult = 5252525252525252525252525252, example = { { 'S_A', true }, { 'H_A', true }, @@ -1486,6 +1533,22 @@ local universe = { end, generate_ui = 0, } +local absolute = { + object_type = "Sticker", + badge_colour = HEX('c75985'), + prefix_config = { key = false }, + key = "cry_absolute", + atlas = "sticker", + pos = { x = 1, y = 5 }, + should_apply = false, + no_sticker_sheet = true, + draw = function(self, card, layer) + G.shared_stickers["cry_absolute"].role.draw_major = card + G.shared_stickers["cry_absolute"]:draw_shader('dissolve', nil, nil, nil, card.children.center) + G.shared_stickers["cry_absolute"]:draw_shader('polychrome', nil, card.ARGS.send_to_shader, nil, card.children.center) + G.shared_stickers["cry_absolute"]:draw_shader('voucher', nil, card.ARGS.send_to_shader, nil, card.children.center) + end, +} local miscitems = { memepack_atlas, meme_object_type, @@ -1523,6 +1586,9 @@ local miscitems = { void, marsmoons, universe, + absolute, + light, + seraph, } if Cryptid.enabled["M Jokers"] then miscitems[#miscitems + 1] = jollyeditionshader @@ -1539,7 +1605,7 @@ return { local total_repetitions = ret and ret.repetitions or 0 if self.config.center == G.P_CENTERS.m_cry_echo then - if pseudorandom("echo") < G.GAME.probabilities.normal / (self.ability.extra or 2) then --hacky crash fix + if pseudorandom("echo") < cry_prob(self.ability.cry_prob, self.ability.extra or 2, self.ability.cry_rigged) / (self.ability.extra or 2) then --hacky crash fix total_repetitions = total_repetitions + self.ability.retriggers end end @@ -1802,6 +1868,13 @@ return { end self:dbl_side_flip() end + if self.ability.cry_absolute then -- feedback loop... may be problematic + self.cry_absolute = true + end + if self.cry_absolute then + self.ability.cry_absolute = true + self.ability.eternal = true + end end function copy_dbl_card(C, c, deck_effects) if not deck_effects then diff --git a/Cryptid/Items/MiscJokers.lua b/Cryptid/Items/MiscJokers.lua index 4b31cb2..074d737 100644 --- a/Cryptid/Items/MiscJokers.lua +++ b/Cryptid/Items/MiscJokers.lua @@ -180,7 +180,6 @@ local potofjokes = { key = "pot_of_jokes", config = { extra = { h_size = -2, h_mod = 1 } }, pos = { x = 5, y = 0 }, - immutable = true, rarity = 3, order = 104, cost = 10, @@ -189,15 +188,15 @@ local potofjokes = { loc_vars = function(self, info_queue, center) return { vars = { - center.ability.extra.h_size < 0 and center.ability.extra.h_size or "+" .. center.ability.extra.h_size, + center.ability.extra.h_size < 0 and center.ability.extra.h_size or "+" .. math.min(1000, center.ability.extra.h_size), center.ability.extra.h_mod, }, } end, calculate = function(self, card, context) if context.end_of_round and not context.individual and not context.repetition and not context.blueprint then + G.hand:change_size(math.min(1000-card.ability.extra.h_size, card.ability.extra.h_mod)) card.ability.extra.h_size = card.ability.extra.h_size + card.ability.extra.h_mod - G.hand:change_size(card.ability.extra.h_mod) return { message = localize({ type = "variable", key = "a_handsize", vars = { card.ability.extra.h_mod } }), colour = G.C.FILTER, @@ -206,10 +205,10 @@ local potofjokes = { end end, add_to_deck = function(self, card, from_debuff) - G.hand:change_size(card.ability.extra.h_size) + G.hand:change_size(math.min(1000, card.ability.extra.h_size)) end, remove_from_deck = function(self, card, from_debuff) - G.hand:change_size(-card.ability.extra.h_size) + G.hand:change_size(-1*math.min(1000, card.ability.extra.h_size)) end, cry_credits = { idea = { @@ -222,6 +221,18 @@ local potofjokes = { "Math" } }, + unlocked = false, + check_for_unlock = function(self, args) + if G and G.hand and G.hand.config and G.hand.config.card_limit and G.hand.config.card_limit >= 12 then + unlock_card(self) + end + if args.type == 'cry_lock_all' then + lock_card(self) + end + if args.type == 'cry_unlock_all' then + unlock_card(self) + end + end, } local queensgambit = { object_type = "Joker", @@ -350,36 +361,55 @@ local whip = { end, calculate = function(self, card, context) if context.cardarea == G.jokers and context.before and not context.blueprint then + local two = false + local seven = false + local twosuits = {} + local sevensuits = {} for i = 1, #context.full_hand do - if SMODS.Ranks[context.full_hand[i].base.value].key == "2" then - for j = 1, #context.full_hand do - if SMODS.Ranks[context.full_hand[j].base.value].key == "7" then - --Different suits - for k, v in pairs(SMODS.Suits) do - if - context.full_hand[i]:is_suit(k, nil, true) - and context.full_hand[j]:is_suit(k, nil, true) - then - return + if context.full_hand[i]:get_id() == 2 or context.full_hand[i]:get_id() == 7 then + if context.full_hand[i]:get_id() == 2 then + if not two then two = true end + for k, v in pairs(SMODS.Suits) do + if context.full_hand[i]:is_suit(k, nil, true) then + local contained = false + for i = 1, #twosuits do + if k == twosuits[i] then contained = true end end + if not contained then twosuits[#twosuits + 1] = k end end - card.ability.extra.x_mult = card.ability.extra.x_mult + card.ability.extra.Xmult_mod - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { - message = localize({ - type = "variable", - key = "a_xmult", - vars = { card.ability.extra.x_mult }, - }), - } - ) - return nil, true end + else + if not seven then seven = true end + for k, v in pairs(SMODS.Suits) do + if context.full_hand[i]:is_suit(k, nil, true) then + local contained = false + for i = 1, #sevensuits do + if k == sevensuits[i] then contained = true end + end + if not contained then sevensuits[#sevensuits + 1] = k end + end + end + end + end + if two and seven then + if (#twosuits > 1 or #sevensuits > 1) + or (#twosuits == 1 and #sevensuits == 1 and twosuits[1] ~= sevensuits[1]) then + card.ability.extra.x_mult = card.ability.extra.x_mult + card.ability.extra.Xmult_mod + card_eval_status_text( + card, + "extra", + nil, + nil, + nil, + { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { card.ability.extra.x_mult }, + }), + } + ) + return nil, true end end end @@ -510,7 +540,6 @@ local pickle = { key = "pickle", config = { extra = { tags = 3, tags_mod = 1 } }, pos = { x = 3, y = 3 }, - immutable = true, rarity = 2, order = 45, cost = 6, @@ -693,25 +722,24 @@ local booster = { config = { extra = { booster_slots = 1 } }, pos = { x = 2, y = 0 }, order = 34, - immutable = true, rarity = 2, cost = 6, blueprint_compat = false, atlas = "atlastwo", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.booster_slots } } + return { vars = { math.min(25, center.ability.extra.booster_slots) } } end, add_to_deck = function(self, card, from_debuff) if not G.GAME.modifiers.cry_booster_packs then G.GAME.modifiers.cry_booster_packs = 2 end - G.GAME.modifiers.cry_booster_packs = G.GAME.modifiers.cry_booster_packs + card.ability.extra.booster_slots + G.GAME.modifiers.cry_booster_packs = G.GAME.modifiers.cry_booster_packs + math.min(25, card.ability.extra.booster_slots) end, remove_from_deck = function(self, card, from_debuff) if not G.GAME.modifiers.cry_booster_packs then G.GAME.modifiers.cry_booster_packs = 2 end - G.GAME.modifiers.cry_booster_packs = G.GAME.modifiers.cry_booster_packs - card.ability.extra.booster_slots + G.GAME.modifiers.cry_booster_packs = G.GAME.modifiers.cry_booster_packs - math.min(25, card.ability.extra.booster_slots) end, cry_credits = { idea = { @@ -825,12 +853,20 @@ local compound_interest = { return { vars = { center.ability.extra.percent, center.ability.extra.percent_mod } } end, calc_dollar_bonus = function(self, card) - local bonus = math.max(0, math.floor(0.01 * card.ability.extra.percent * (G.GAME.dollars or 1))) - local old = card.ability.extra.percent - card.ability.extra.percent = card.ability.extra.percent + card.ability.extra.percent_mod - compound_interest_scale_mod(card, card.ability.extra.percent_mod, old, card.ability.extra.percent) - if bonus > 0 then - return bonus + if G.GAME.dollars > 0 then + local bonus = math.max(0, math.floor(0.01 * card.ability.extra.percent * (G.GAME.dollars or 1))) + local old = card.ability.extra.percent + card.ability.extra.percent = card.ability.extra.percent + card.ability.extra.percent_mod + compound_interest_scale_mod(card, card.ability.extra.percent_mod, old, card.ability.extra.percent) + if bonus > 0 then + if G.GAME.dollars > 1e10 then + return 1 + else + return bonus + end + end + else + return 0 end end, cry_credits = { @@ -992,29 +1028,23 @@ local seal_the_deal = { immutable = true, atlas = "atlasone", calculate = function(self, card, context) - if context.individual and context.cardarea == G.play and not context.blueprint and not context.retrigger_joker then - if G.GAME.current_round.hands_left == 0 and not context.other_card.seal then - G.E_MANAGER:add_event(Event({ - func = function() - local seal_type = pseudorandom(pseudoseed("seal_the_deal")) - if seal_type > 0.75 then - context.other_card:set_seal("Red", true) - elseif seal_type > 0.5 then - context.other_card:set_seal("Blue", true) - elseif seal_type > 0.25 then - context.other_card:set_seal("Gold", true) - else - context.other_card:set_seal("Purple", true) + if context.after and G.GAME.current_round.hands_left == 0 and not context.blueprint and not context.retrigger_joker then + G.E_MANAGER:add_event(Event({ + trigger = 'before', + delay = 1.3, + func = function() -- i can't figure out how to split these events without making em look bad so you get this? + for j = 1, #context.scoring_hand do + if not context.scoring_hand[j].seal then + context.scoring_hand[j]:set_seal(SMODS.poll_seal({guaranteed = true, type_key = 'sealthedeal'}), true, false) + context.scoring_hand[j]:juice_up() end - card:juice_up(0.3, 0.4) - context.other_card:juice_up(0.3, 0.3) - play_sound("gold_seal", 1.2, 0.4) - return true - end, - })) - delay(0.5) - return nil, true - end + end + play_sound('gold_seal', 1.2, 0.4) + card:juice_up() + return true + end, + })) + return nil, true end end, set_ability = function(self, card, initial, delay_sprites) @@ -1022,18 +1052,20 @@ local seal_the_deal = { if Cryptid.enabled["Misc."] then sealtable[#sealtable + 1] = "azure" end if Cryptid.enabled["Code Cards"] then sealtable[#sealtable + 1] = "green" end card.ability.extra = pseudorandom_element(sealtable, pseudoseed('abc')) - --Gold (ULTRA RARE!!!!!!!!) - if pseudorandom('xyz') <= 0.000001 and not (card.area and card.area.config.collection) then - card.children.center:set_sprite_pos({x = 6, y = 4}) - --Others - elseif card.ability.extra == "red" then - card.children.center:set_sprite_pos({x = 6, y = 0}) - elseif card.ability.extra == "azure" then - card.children.center:set_sprite_pos({x = 6, y = 2}) - elseif card.ability.extra == "purple" then - card.children.center:set_sprite_pos({x = 6, y = 3}) - elseif card.ability.extra == "green" then - card.children.center:set_sprite_pos({x = 6, y = 1}) + if G.P_CENTERS["j_cry_seal_the_deal"].discovered then + --Gold (ULTRA RARE!!!!!!!!) + if pseudorandom('xyz') <= 0.000001 and not (card.area and card.area.config.collection) then + card.children.center:set_sprite_pos({x = 6, y = 4}) + --Others + elseif card.ability.extra == "red" then + card.children.center:set_sprite_pos({x = 6, y = 0}) + elseif card.ability.extra == "azure" then + card.children.center:set_sprite_pos({x = 6, y = 2}) + elseif card.ability.extra == "purple" then + card.children.center:set_sprite_pos({x = 6, y = 3}) + elseif card.ability.extra == "green" then + card.children.center:set_sprite_pos({x = 6, y = 1}) + end end end, cry_credits = { @@ -1055,13 +1087,12 @@ local chad = { pos = { x = 0, y = 3 }, order = 71, config = { extra = { retriggers = 2 } }, - immutable = true, pools = {["Meme"] = true}, rarity = 3, cost = 10, blueprint_compat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.retriggers } } + return { vars = { math.min(25, center.ability.extra.retriggers) } } end, atlas = "atlasone", calculate = function(self, card, context) @@ -1069,7 +1100,7 @@ local chad = { if context.other_card == G.jokers.cards[1] then return { message = localize("k_again_ex"), - repetitions = card.ability.extra.retriggers, + repetitions = math.min(25, card.ability.extra.retriggers), card = card, } else @@ -1144,6 +1175,28 @@ local jimball = { "Math" } }, + unlocked = false, + check_for_unlock = function(self, args) + if args.type == 'win' then + local hand = nil + for k,v in pairs(G.GAME.hands) do + if G.GAME.hands[k].played ~= 0 then + if not hand then + hand = G.GAME.hands[k] + else + return + end + end + end + return true + end + if args.type == 'cry_lock_all' then + lock_card(self) + end + if args.type == 'cry_unlock_all' then + unlock_card(self) + end + end, } G.FUNCS.notif_jimball = function() Cryptid_config.Cryptid.jimball_music = false @@ -1313,50 +1366,7 @@ local fspinner = { } }, } -local luigi = { - object_type = "Joker", - name = "cry-luigi", - key = "luigi", - pos = { x = 0, y = 3 }, - soul_pos = { x = 1, y = 3 }, - config = { extra = { x_chips = 3 } }, - loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.x_chips } } - end, - rarity = 4, - cost = 20, - order = 86, - blueprint_compat = true, - calculate = function(self, card, context) - if context.other_joker and context.other_joker.ability.set == "Joker" then - if not Talisman.config_file.disable_anims then - G.E_MANAGER:add_event(Event({ - func = function() - context.other_joker:juice_up(0.5, 0.5) - return true - end, - })) - end - return { - message = localize({ type = "variable", key = "a_xchips", vars = { card.ability.extra.x_chips } }), - colour = G.C.CHIPS, - Xchip_mod = card.ability.extra.x_chips, - } - end - end, - atlas = "atlasthree", - cry_credits = { - idea = { - "Auto Watto" - }, - art = { - "Linus Goof Balls" - }, - code = { - "Auto Watto" - } - }, -} + local waluigi = { object_type = "Joker", name = "cry-Waluigi", @@ -1400,43 +1410,7 @@ local waluigi = { } }, } -local mario = { - object_type = "Joker", - name = "cry-mario", - key = "mario", - config = { extra = { retriggers = 2 } }, - pos = { x = 4, y = 3 }, - soul_pos = { x = 5, y = 3 }, - rarity = 4, - order = 85, - cost = 20, - blueprint_compat = true, - immutable = true, - loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.retriggers } } - end, - atlas = "atlasthree", - calculate = function(self, card, context) - if context.retrigger_joker_check and not context.retrigger_joker and context.other_card ~= self then - return { - message = localize("k_again_ex"), - repetitions = card.ability.extra.retriggers, - card = card, - } - end - end, - cry_credits = { - idea = { - "Auto Watto" - }, - art = { - "Linus Goof Balls" - }, - code = { - "Auto Watto" - } - }, -} + local wario = { object_type = "Joker", name = "cry-wario", @@ -1833,7 +1807,6 @@ local redbloon = { key = "redbloon", config = { extra = { money = 20, rounds_remaining = 2 } }, pos = { x = 5, y = 1 }, - immutable = true, rarity = 1, cost = 4, order = 97, @@ -2389,7 +2362,6 @@ local sapling = { key = "sapling", pos = { x = 3, y = 2 }, config = { extra = { score = 0, req = 18, check = nil } }, - immutable = true, rarity = 2, cost = 6, order = 42, @@ -3347,7 +3319,7 @@ local rnjoker = { or (card.ability.extra and card.ability.extra.value) or 0, card.ability.extra and card.ability.extra.cond_value or 0, - G.GAME and G.GAME.probabilities.normal or 1, + cry_prob(card.ability.cry_prob, card.ability.extra and card.ability.extra.cond_value or 0, card.ability.cry_rigged), }, } if card.ability.extra and card.ability.extra.color then @@ -3580,7 +3552,7 @@ local rnjoker = { elseif j.cond == "odds" then if pseudorandom("rnj") - < ((G.GAME and G.GAME.probabilities.normal or 1) / card.ability.extra.cond_value) + < (cry_prob(card.ability.cry_prob, card.ability.extra.cond_value, card.ability.cry_rigged) / card.ability.extra.cond_value) then cond_passed = true end @@ -3857,7 +3829,7 @@ local rnjoker = { elseif j.cond == "odds" then if pseudorandom("rnj") - < ((G.GAME and G.GAME.probabilities.normal or 1) / card.ability.extra.cond_value) + < (cry_prob(card.ability.cry_prob, card.ability.extra.cond_value, card.ability.cry_rigged) / card.ability.extra.cond_value) then cond_passed = true end @@ -3941,7 +3913,7 @@ local rnjoker = { elseif j.cond == "odds" then if pseudorandom("rnj") - < ((G.GAME and G.GAME.probabilities.normal or 1) / card.ability.extra.cond_value) + < (cry_prob(card.ability.cry_prob, card.ability.extra.cond_value, card.ability.cry_rigged) / card.ability.extra.cond_value) then cond_passed = true end @@ -4133,6 +4105,8 @@ local duos = { "Mathguy" } }, + unlocked = false, + unlock_condition = {type = 'win_no_hand',extra = 'Two Pair'}, } local home = { object_type = "Joker", @@ -4175,6 +4149,8 @@ local home = { "Mathguy" } }, + unlocked = false, + unlock_condition = {type = 'win_no_hand',extra = 'Full House'}, } local nuts = { object_type = "Joker", @@ -4217,6 +4193,8 @@ local nuts = { "Mathguy" } }, + unlocked = false, + unlock_condition = {type = 'win_no_hand',extra = 'Straight Flush'}, } local quintet = { object_type = "Joker", @@ -4254,6 +4232,9 @@ local quintet = { end return false end, + check_for_unlock = function(self, args) + if args.type == 'cry_win_with_hand' and args.hand == 'Five of a Kind' then return true end + end, cry_credits = { idea = { "Mathguy" @@ -4265,6 +4246,7 @@ local quintet = { "Mathguy" } }, + unlocked = false, } local unity = { object_type = "Joker", @@ -4302,6 +4284,9 @@ local unity = { end return false end, + check_for_unlock = function(self, args) + if args.type == 'cry_win_with_hand' and args.hand == 'Flush House' then return true end + end, cry_credits = { idea = { "Mathguy" @@ -4313,6 +4298,7 @@ local unity = { "Mathguy" } }, + unlocked = false, } local swarm = { object_type = "Joker", @@ -4350,6 +4336,9 @@ local swarm = { end return false end, + check_for_unlock = function(self, args) + if args.type == 'cry_win_with_hand' and args.hand == 'Flush Five' then return true end + end, cry_credits = { idea = { "Mathguy" @@ -4361,6 +4350,7 @@ local swarm = { "Mathguy" } }, + unlocked = false, } local stronghold = { object_type = "Joker", @@ -4398,6 +4388,10 @@ local stronghold = { end return false end, + check_for_unlock = function(self, args) + if args.type == 'cry_win_with_hand' and args.hand == 'cry_Bulwark' then return true end + end, + unlocked = false, } local wtf = { object_type = "Joker", @@ -4435,6 +4429,10 @@ local wtf = { end return false end, + check_for_unlock = function(self, args) + if args.type == 'cry_win_with_hand' and args.hand == 'cry_Clusterfuck' then return true end + end, + unlocked = false, } local clash = { object_type = "Joker", @@ -4472,6 +4470,10 @@ local clash = { end return false end, + check_for_unlock = function(self, args) + if args.type == 'cry_win_with_hand' and args.hand == 'cry_UltPair' then return true end + end, + unlocked = false, } local filler = { object_type = "Joker", @@ -4479,7 +4481,7 @@ local filler = { key = "filler", pos = { x = 0, y = 1 }, pools = {["Meme"] = true}, - config = { Xmult = 1.00000000000001, type = "High Card" }, + config = { Xmult = 1.00000000000003, type = "High Card" }, loc_vars = function(self, info_queue, card) return { vars = { card.ability.x_mult, localize(card.ability.type, "poker_hands") } } end, @@ -4508,6 +4510,8 @@ local filler = { "Mathguy" } }, + unlocked = false, + unlock_condition = {type = 'win_no_hand',extra = 'High Card'}, } local giggly = { object_type = "Joker", @@ -5347,8 +5351,30 @@ local oldblueprint = { rarity = 1, cost = 6, order = 83, - loc_vars = function(self, info_queue, center) - return { vars = { "" .. (G.GAME and G.GAME.probabilities.normal or 1), center.ability.extra.odds } } + update = function(self, card, front) + if G.STAGE == G.STAGES.RUN then + for i = 1, #G.jokers.cards do + if G.jokers.cards[i] == card then other_joker = G.jokers.cards[i+1] end + end + if other_joker and other_joker ~= card and other_joker.config.center.blueprint_compat then + card.ability.blueprint_compat = 'compatible' + else + card.ability.blueprint_compat = 'incompatible' + end + end + end, + loc_vars = function(self, info_queue, card) + card.ability.blueprint_compat_ui = card.ability.blueprint_compat_ui or ''; card.ability.blueprint_compat_check = nil + return { + vars = { cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), card.ability.extra.odds }, + main_end = (card.area and card.area == G.jokers) and { + {n=G.UIT.C, config={align = "bm", minh = 0.4}, nodes={ + {n=G.UIT.C, config={ref_table = card, align = "m", colour = G.C.JOKER_GREY, r = 0.05, padding = 0.06, func = 'blueprint_compat'}, nodes={ + {n=G.UIT.T, config={ref_table = card.ability, ref_value = 'blueprint_compat_ui',colour = G.C.UI.TEXT_LIGHT, scale = 0.32*0.8}}, + }} + }} + } or nil + } end, blueprint_compat = true, eternal_compat = false, @@ -5361,7 +5387,7 @@ local oldblueprint = { and not context.blueprint and not context.retrigger_joker then - if pseudorandom("oldblueprint") < G.GAME.probabilities.normal / card.ability.extra.odds then + if pseudorandom("oldblueprint") < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds then G.E_MANAGER:add_event(Event({ func = function() play_sound("tarot1") @@ -5409,7 +5435,7 @@ local oldblueprint = { other_joker = G.jokers.cards[i + 1] end end - if other_joker and other_joker ~= self then + if other_joker and other_joker ~= card then context.blueprint = (context.blueprint and (context.blueprint + 1)) or 1 context.blueprint_card = context.blueprint_card or card @@ -5526,18 +5552,20 @@ local busdriver = { key = "busdriver", config = { extra = { mult = 50, odds = 4 } }, pos = { x = 5, y = 1 }, - immutable = true, rarity = 2, cost = 7, order = 46, atlas = "atlasthree", blueprint_compat = true, - loc_vars = function(self, info_queue, center) + loc_vars = function(self, info_queue, card) + local prob = cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) + local oddy = math.max(1, card.ability.extra.odds) return { vars = { - "" .. ((G.GAME and G.GAME.probabilities.normal or 1) * 3), - center.ability.extra.mult, - center.ability.extra.odds, + ( oddy - 1/prob ), + card.ability.extra.mult, + oddy, + ( 1/prob ), }, } end, @@ -5548,7 +5576,8 @@ local busdriver = { and not context.before and not context.after then - if pseudorandom("busdriver") < G.GAME.probabilities.normal / card.ability.extra.odds * 3 then + local oddy = math.max(1, card.ability.extra.odds) + if pseudorandom("busdriver") < 1-(1/(cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged)*oddy)) then return { message = localize({ type = "variable", key = "a_mult", vars = { card.ability.extra.mult } }), mult_mod = card.ability.extra.mult, @@ -5795,11 +5824,11 @@ local flipside = { object_type = "Joker", name = "cry-Flip Side", key = "flip_side", - pos = { x = 1, y = 0 }, + pos = { x = 3, y = 6 }, rarity = 2, cost = 7, order = 107, - atlas = "placeholders", + atlas = "atlastwo", no_dbl = true, loc_vars = function(self, info_queue) info_queue[#info_queue + 1] = G.P_CENTERS.e_cry_double_sided @@ -5840,7 +5869,7 @@ local flipside = { "Axolotus" }, art = { - ":(" + "Pyrocreep" }, code = { "Math" @@ -6039,6 +6068,7 @@ local astral_bottle = { object_type = "Joker", name = "cry-astral_bottle", key = "astral_bottle", + eternal_compat = false, pos = { x = 7, y = 0 }, atlas = "atlasthree", rarity = 2, @@ -6206,14 +6236,14 @@ local exposed = { return { vars = { center.ability.extra } } end, update = function(self, card, dt) - if G.deck and not (card.area and card.area.config.collection) then + if G.deck and card.added_to_deck then for i, v in pairs (G.deck.cards) do if v:is_face() then v:set_debuff(true) end end end - if G.hand and not (card.area and card.area.config.collection) then + if G.hand and card.added_to_deck then for i, v in pairs (G.hand.cards) do if v:is_face() then v:set_debuff(true) @@ -6248,14 +6278,14 @@ local mask = { return { vars = { center.ability.extra } } end, update = function(self, card, dt) - if G.deck and not (card.area and card.area.config.collection) then + if G.deck and card.added_to_deck then for i, v in pairs (G.deck.cards) do if not v:is_face() then v:set_debuff(true) end end end - if G.hand and not (card.area and card.area.config.collection) then + if G.hand and card.added_to_deck then for i, v in pairs (G.hand.cards) do if not v:is_face() then v:set_debuff(true) @@ -6280,24 +6310,26 @@ local tropical_smoothie = { name = "cry-Tropical Smoothie", key = "tropical_smoothie", pos = { x = 2, y = 5 }, - config = {}, + config = { extra = 1.5 }, rarity = 3, + eternal_compat = false, cost = 5, order = 125, atlas = "atlastwo", - immutable = true, loc_vars = function(self, info_queue, center) return { vars = { center.ability.extra } } end, calculate = function(self, card, context) if context.selling_self then local check = false - for i, v in pairs (G.jokers.cards) do - if not Card.no(v, "immutable", true) then - cry_with_deck_effects(G.jokers.cards[1], function(card) - cry_misprintize(v, { min = 1.5, max = 1.5}, nil, true) - end) - check = true + for i, v in pairs(G.jokers.cards) do + if v ~= card then + if not Card.no(v, "immutable", true) then + cry_with_deck_effects(v, function(cards) + cry_misprintize(cards, { min = card.ability.extra, max = card.ability.extra }, nil, true) + end) + check = true + end end end if check then @@ -6313,6 +6345,192 @@ local tropical_smoothie = { end end, } +local pumpkin = { + object_type = "Joker", + key = "pumpkin", + pos = { x = 0, y = 6 }, + rarity = 3, + cost = 10, + atlas = "atlastwo", + order = 131, + config = {extra = {scoreReq = 50, enabled = true}}, + blueprint_compat = true, + eternal_compat = false, + perishable_compat = false, + loc_vars = function(self, info_queue, center) + return { vars = { center.ability.extra.scoreReq} } + end, + calculate = function(self, card, context) + if context.game_over and G.GAME.chips/G.GAME.blind.chips >= to_big(card.ability.extra.scoreReq/100) then + G.E_MANAGER:add_event(Event({ + func = function() + G.hand_text_area.blind_chips:juice_up() + G.hand_text_area.game_chips:juice_up() + play_sound('tarot1') + return true + end + })) + return { + message = localize('k_saved_ex'), + saved = true, + colour = G.C.RED + } + end + + if context.selling_self then + card.ability.extra.enabled = false + end + + if context.cry_start_dissolving and context.card == card and card.ability.extra.enabled == true then + local newcard = create_card( + "Joker", + G.jokers, + nil, + nil, + nil, + nil, + 'j_cry_carved_pumpkin' + ) + newcard:add_to_deck() + G.jokers:emplace(newcard) + end + end, + cry_credits = { + idea = { + "Squiddy" + }, + art = { + "B" + }, + code = { + "wawa person" + } + }, +} +local carved_pumpkin = { + object_type = "Joker", + key = "carved_pumpkin", + pos = { x = 1, y = 6 }, + rarity = 3, + cost = 10, + atlas = "atlastwo", + order = 132, + config = {extra = {disables = 5}}, + blueprint_compat = true, + eternal_compat = false, + perishable_compat = false, + loc_vars = function(self, info_queue, center) + return { vars = { center.ability.extra.disables} } + end, + calculate = function(self, card, context) + if context.end_of_round and not context.blueprint and not context.individual and not context.repetition then + if G.GAME.blind:get_type() == 'Boss' then + card.ability.extra.disables = card.ability.extra.disables - 1 + card:juice_up() + if card.ability.extra.disables <= 0 then + card:start_dissolve() + end + end + end + if context.setting_blind and G.GAME.blind:get_type() == 'Boss' and not G.GAME.blind.disabled then + card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = localize('ph_boss_disabled')}) + G.GAME.blind:disable() + end + end, + in_pool = function(self,wawa,wawa2) + return false + end, + cry_credits = { + idea = { + "Squiddy" + }, + art = { + "B" + }, + code = { + "wawa person" + } + }, +} +local cookie = { + object_type = "Joker", + key = "clicked_cookie", + pos = { x = 2, y = 6 }, + rarity = 1, + cost = 4, + atlas = "atlastwo", + order = 133, + config = {extra = {chips = 150, chip_mod = 1}}, + blueprint_compat = true, + eternal_compat = false, + loc_vars = function(self, info_queue, center) + return { vars = { center.ability.extra.chips, center.ability.extra.chip_mod} } + end, + calculate = function(self, card, context) + if context.joker_main then + return{ + card = card, + chip_mod = card.ability.extra.chips, + message = '+' .. card.ability.extra.chips, + colour = G.C.CHIPS + } + end + if context.cry_press then + if card.ability.extra.chips - card.ability.extra.chip_mod <= 0 then + G.E_MANAGER:add_event(Event({ + func = function() + play_sound("tarot1") + card.T.r = -0.2 + card:juice_up(0.3, 0.4) + card.states.drag.is = true + card.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.3, + blockable = false, + func = function() + G.jokers:remove_card(card) + card:remove() + card = nil + return true + end, + })) + return true + end, + })) + card_eval_status_text( + card, + "extra", + nil, + nil, + nil, + { message = localize("k_eaten_ex") , colour = G.C.CHIPS } + ) + else + card.ability.extra.chips = card.ability.extra.chips - card.ability.extra.chip_mod + card_eval_status_text( + card, + "extra", + nil, + nil, + nil, + { message = "-" ..card.ability.extra.chip_mod , colour = G.C.CHIPS } + ) + end + end + end, + cry_credits = { + idea = { + "playerrWon" + }, + art = { + "lolxDdj" + }, + code = { + "wawa person" + } + }, +} local necromancer = { object_type = "Joker", name = "cry-Necromancer", @@ -6358,15 +6576,39 @@ local oil_lamp = { --You want it? It's yours my friend cost = 10, order = 127, atlas = "atlastwo", - loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.increase } } + loc_vars = function(self, info_queue, card) + card.ability.blueprint_compat_ui = card.ability.blueprint_compat_ui or ''; card.ability.blueprint_compat_check = nil + return { + vars = { card.ability.extra.increase }, + main_end = (card.area and card.area == G.jokers) and { + {n=G.UIT.C, config={align = "bm", minh = 0.4}, nodes={ + {n=G.UIT.C, config={ref_table = card, align = "m", colour = G.C.JOKER_GREY, r = 0.05, padding = 0.06, func = 'blueprint_compat'}, nodes={ + {n=G.UIT.T, config={ref_table = card.ability, ref_value = 'blueprint_compat_ui',colour = G.C.UI.TEXT_LIGHT, scale = 0.32*0.8}}, + }} + }} + } or nil + } + end, + update = function(self, card, front) + if G.STAGE == G.STAGES.RUN then + for i = 1, #G.jokers.cards do + if G.jokers.cards[i] == card then other_joker = G.jokers.cards[i+1] end + end + if other_joker and other_joker ~= card and not (Card.no(other_joker, "immutable", true)) then + card.ability.blueprint_compat = 'compatible' + else + card.ability.blueprint_compat = 'incompatible' + end + end end, calculate = function(self, card, context) - if context.end_of_round and not context.repetition and not context.individual then + if context.end_of_round and not context.repetition and not context.individual and not context.blueprint then + local check = false for i = 1, #G.jokers.cards do if G.jokers.cards[i] == card then if i < #G.jokers.cards then if not Card.no(G.jokers.cards[i+1], "immutable", true) then + check = true cry_with_deck_effects(G.jokers.cards[i+1], function(cards) cry_misprintize(cards, { min = card.ability.extra.increase, max = card.ability.extra.increase }, nil, true) end) @@ -6374,6 +6616,16 @@ local oil_lamp = { --You want it? It's yours my friend end end end + if check then + card_eval_status_text( + card, + "extra", + nil, + nil, + nil, + { message = localize("k_upgrade_ex"), colour = G.C.GREEN } + ) + end end end, cry_credits = { @@ -6468,6 +6720,208 @@ local pity_prize = { } }, } +local digitalhallucinations = { + object_type = "Joker", + name = "cry-Digital Hallucinations", + key = "digitalhallucinations", + pos = { x = 0, y = 7 }, + order = 130, + config = { odds = 2 }, + loc_vars = function(self, info_queue, card) + return { vars = { cry_prob(card.ability.cry_prob, card.ability.odds, card.ability.cry_rigged), card.ability.odds } } + end, + atlas = "atlasthree", + rarity = 2, + cost = 8, + blueprint_compat = true, + calculate = function(self, card, context) + + -- you know, i was totally ready to do something smart here but vanilla hardcodes this stuff, so i will too + -- some cards need to be handled slightly differently anyway, adding mod support can't really be automatic in some circumstances + + if context.open_booster and (pseudorandom("digi") < cry_prob(card.ability.cry_prob, card.ability.odds, card.ability.cry_rigged)/card.ability.odds) then + local boosty = context.card + local consums = {'Arcana', 'Celestial', 'Spectral'} + local short1 = {'tarot', 'planet', 'spectral'} + local short2 = {'Tarot', 'Planet', 'Spectral'} + for i = 1, #consums do + if boosty.ability.name:find(consums[i]) then + G.E_MANAGER:add_event(Event({ + trigger = 'before', + delay = 0.0, + func = (function() + local ccard = create_card(short2[i], G.consumables, nil, nil, nil, nil, nil, "diha") + ccard:set_edition({ negative = true }, true) + ccard:add_to_deck() + G.consumeables:emplace(ccard) + return true + end) + })) + card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = localize('k_plus_'..short1[i]), colour = G.C.SECONDARY_SET[short2[i]]}) + return true -- this triggers BEFORE a retrigger joker and looks like jank. i can't get a message showing up without status text so this is the best option rn + end + end + if boosty.ability.name:find('code') then + G.E_MANAGER:add_event(Event({ + trigger = 'before', + delay = 0.0, + func = function() + local ccard = create_card("Code", G.consumables, nil, nil, nil, nil, nil, "diha") + ccard:set_edition({ negative = true }, true) + ccard:add_to_deck() + G.consumeables:emplace(ccard) + return true + end + })) + card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = localize('cry_plus_code'), colour = G.C.SET.Code}) + return true + end + if boosty.ability.name:find('Buffoon') then + G.E_MANAGER:add_event(Event({ + trigger = 'before', + delay = 0.0, + func = function() + local ccard = create_card("Joker", G.jokers, nil, nil, nil, nil, nil, "diha") + ccard:set_edition({ negative = true }, true) + ccard:add_to_deck() + G.jokers:emplace(ccard) + ccard:start_materialize() + return true + end + })) + card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = localize('k_plus_joker'), colour = G.C.FILTER}) + return true + end + if boosty.ability.name:find('Standard') then + G.E_MANAGER:add_event(Event({ + func = function() + local front = pseudorandom_element(G.P_CARDS, pseudoseed('diha_p')) + G.playing_card = (G.playing_card and G.playing_card + 1) or 1 + local ccard = Card(G.play.T.x + G.play.T.w/2, G.play.T.y, G.CARD_W, G.CARD_H, front, G.P_CENTERS.c_base, {playing_card = G.playing_card}) + ccard:set_edition({ negative = true }, true) + ccard:start_materialize({G.C.SECONDARY_SET.Enhanced}) + G.play:emplace(ccard) + table.insert(G.playing_cards, ccard) + return true + end + })) + card_eval_status_text(context.blueprint_card or card, 'extra', nil, nil, nil, {message = localize('cry_plus_card'), colour = G.C.FILTER}) + + G.E_MANAGER:add_event(Event({ + func = function() + G.deck.config.card_limit = G.deck.config.card_limit + 1 + return true + end + })) + draw_card(G.play,G.deck, 90,'up', nil) + + playing_card_joker_effects({true}) -- who knows what most this stuff does, i just copied it from marble jonkler + return true + end + end + end, + cry_credits = { + idea = { + "lolxddj" + }, + art = { + "lolxddj" + }, + code = { + "toneblock" + } + }, +} +local arsonist = { + object_type = "Joker", + name = "cry-Arsonist", + key = "arsonist", + pos = { x = 0, y = 5 }, + config = { }, + rarity = 3, + cost = 5, + atlas = "atlasone", + order = 131, + loc_vars = function(self, info_queue, center) + return { vars = { } } + end, + calculate = function(self, card, context) + if context.destroying_card then + local eval = evaluate_poker_hand(context.full_hand) + if next(eval['Full House']) then + return true + end + end + end, + cry_credits = { + idea = { + "AlexZGreat" + }, + art = { + "Darren_the_frog" + }, + code = { + "AlexZGreat" + } + }, +} +local zooble = { + object_type = "Joker", + name = "cry-Zooble", + key = "zooble", + pos = { x = 1, y = 5 }, + config = {extra = {mult = 0, a_mult = 1}}, + rarity = 2, + cost = 6, + atlas = "atlasone", + order = 132, + loc_vars = function(self, info_queue, center) + return { vars = {center.ability.extra.mult,center.ability.extra.a_mult }} + end, + calculate = function(self, card, context) + if context.before and context.cardarea == G.jokers then + if not (next(context.poker_hands['Straight']) or next(context.poker_hands['Straight Flush'])) then + local unique_ranks = {} + for i, v in pairs (context.scoring_hand) do + local not_unique = false + for i = 1, #unique_ranks do + if unique_ranks[i] == v:get_id() then + not_unique = true + end + end + if not not_unique then + unique_ranks[#unique_ranks + 1] = v:get_id() + end + end + if #unique_ranks >= 1 then + card.ability.extra.mult = card.ability.extra.mult + (#unique_ranks * card.ability.extra.a_mult) + return { + message = localize('k_upgrade_ex'), + colour = G.C.RED, + card = card + } + end + end + end + if context.joker_main and context.cardarea == G.jokers then + return { + message = localize{type='variable',key='a_mult',vars={card.ability.extra.mult}}, + mult_mod = card.ability.extra.mult + } + end + end, + cry_credits = { + idea = { + "lolxDdj" + }, + art = { + "lolxDdj" + }, + code = { + "AlexZGreat" + } + }, +} local miscitems = { jimball_sprite, dropshot, @@ -6490,9 +6944,7 @@ local miscitems = { sus, chad, jimball, - luigi, waluigi, - mario, wario, eternalflame, seal_the_deal, @@ -6557,10 +7009,16 @@ local miscitems = { exposed, mask, tropical_smoothie, + pumpkin, + carved_pumpkin, + cookie, necromancer, oil_lamp, tax_fraud, pity_prize, + digitalhallucinations, + arsonist, + zooble, } if Cryptid.enabled["Misc."] then miscitems[#miscitems+1] = flipside @@ -6671,6 +7129,26 @@ return { end end end + + local oldfunc = Card.start_dissolve + function Card:start_dissolve(dissolve_colours, silent, dissolve_time_fac, no_juice) + if G and G.jokers and G.jokers.cards then + for i = 1, #G.jokers.cards do + G.jokers.cards[i]:calculate_joker({cry_start_dissolving = true, card = self}) + end + end + return oldfunc(self,dissolve_colours, silent, dissolve_time_fac, no_juice) + end + + local lcpref = Controller.L_cursor_press + function Controller:L_cursor_press(x, y) + lcpref(self,x,y) + if G and G.jokers and G.jokers.cards and not G.SETTINGS.paused then + for i = 1, #G.jokers.cards do + G.jokers.cards[i]:calculate_joker({cry_press = true}) + end + end + end end, items = miscitems, } diff --git a/Cryptid/Items/Planets.lua b/Cryptid/Items/Planets.lua index d763e7b..9262004 100644 --- a/Cryptid/Items/Planets.lua +++ b/Cryptid/Items/Planets.lua @@ -344,15 +344,15 @@ local planetlua = { aurinko = true, atlas = "atlasnotjokers", order = 1, - loc_vars = function(self, info_queue, center) - return { vars = { "" .. (G.GAME and G.GAME.probabilities.normal or 1), self.config.extra.odds } } + loc_vars = function(self, info_queue, card) + return { vars = { card and cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) or 1, card and card.ability.extra.odds or self.config.extra.odds} } end, can_use = function(self, card) return true end, use = function(self, card, area, copier) local used_consumable = copier or card - if pseudorandom("planetlua") < G.GAME.probabilities.normal / card.ability.extra.odds then --Code "borrowed" from black hole + if pseudorandom("planetlua") < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds then --Code "borrowed" from black hole update_hand_text( { sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3 }, { handname = localize("k_all_hands"), chips = "...", mult = "...", level = "" } @@ -495,7 +495,7 @@ local planetlua = { else for i = 1, number do quota = quota - + (pseudorandom("planetlua") < G.GAME.probabilities.normal / card.ability.extra.odds and 1 or 0) + + (pseudorandom("planetlua") < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds and 1 or 0) end if quota > 0 then update_hand_text( @@ -593,7 +593,7 @@ local planetlua = { calculate = function(self, card, context) --Observatory effect: (G.GAME.probabilities.normal) in (odds) chance for (G.P_CENTERS.v_observatory.config.extra) Mult if G.GAME.used_vouchers.v_observatory - and (pseudorandom("nstar") < G.GAME.probabilities.normal / card.ability.extra.odds) + and (pseudorandom("nstar") < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds) then local value = G.P_CENTERS.v_observatory.config.extra return { @@ -691,15 +691,15 @@ local nstar = { }) ) end, - calculate = function(self, card, context) --Observatory effect: X0.04 mult for each neutron star used this run + calculate = function(self, card, context) --Observatory effect: X0.1 mult for each neutron star used this run if G.GAME.used_vouchers.v_observatory and G.GAME.neutronstarsusedinthisrun ~= nil then return { message = localize({ type = "variable", key = "a_xmult", - vars = { 1 + (0.04 * G.GAME.neutronstarsusedinthisrun) }, + vars = { 1 + (0.10 * G.GAME.neutronstarsusedinthisrun) }, }), - Xmult_mod = 1 + (0.04 * G.GAME.neutronstarsusedinthisrun), + Xmult_mod = 1 + (0.10 * G.GAME.neutronstarsusedinthisrun), } end end, diff --git a/Cryptid/Items/Sleeves.lua b/Cryptid/Items/Sleeves.lua index a098887..88e6aa3 100644 --- a/Cryptid/Items/Sleeves.lua +++ b/Cryptid/Items/Sleeves.lua @@ -3,7 +3,7 @@ if CardSleeves then object_type = "Atlas", key = "atlasSleeves", path = "atlasSleeves.png", - px = 71, + px = 73, py = 95, }) @@ -78,18 +78,10 @@ if CardSleeves then config = { cry_misprint_min = 0.1, cry_misprint_max = 10 }, unlocked = true, unlock_condition = { deck = "Misprint Deck", stake = 1 }, - trigger_effect = function(self, args) - if args.context.create_card then - cry_misprintize( - args.context.card, - { min = 0.1 * (G.GAME.modifiers.cry_misprint_min or 1), max = 10 - * (G.GAME.modifiers.cry_misprint_max or 1) } - ) - end - end, apply = function(self) G.GAME.modifiers.cry_misprint_min = self.config.cry_misprint_min G.GAME.modifiers.cry_misprint_max = self.config.cry_misprint_max + if self.get_current_deck_key() == "b_cry_antimatter" then G.GAME.modifiers.cry_misprint_min = 1 end end, }) @@ -132,7 +124,6 @@ if CardSleeves then name = "CCD Sleeve", atlas = "atlasSleeves", pos = { x = 6, y = 0 }, - config = { cry_conveyor = true }, unlocked = true, unlock_condition = { deck = "CCD Deck", stake = 1 }, loc_vars = function(self) diff --git a/Cryptid/Items/Spectrals.lua b/Cryptid/Items/Spectrals.lua index 08085e6..7b28cab 100644 --- a/Cryptid/Items/Spectrals.lua +++ b/Cryptid/Items/Spectrals.lua @@ -678,10 +678,21 @@ local ritual = { cost = 5, atlas = "atlasnotjokers", pos = { x = 5, y = 1 }, + can_use = function(self, card) + --TODO: CCD card compat + if #G.hand.highlighted > card.ability.max_highlighted then return false end + for _, v in ipairs(G.hand.highlighted) do + if v.edition then + return false + end + end + return true + end, use = function(self, card, area, copier) local used_consumable = copier or card for i = 1, #G.hand.highlighted do local highlighted = G.hand.highlighted[i] + if highlighted ~= card then G.E_MANAGER:add_event(Event({ func = function() play_sound("tarot1") @@ -717,6 +728,7 @@ local ritual = { return true end, })) + end end end, } diff --git a/Cryptid/Items/Spooky.lua b/Cryptid/Items/Spooky.lua index 2ea2032..936721b 100644 --- a/Cryptid/Items/Spooky.lua +++ b/Cryptid/Items/Spooky.lua @@ -159,9 +159,15 @@ local choco1 = { end end --create a ghost - local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_cry_ghost") - card:add_to_deck() - G.jokers:emplace(card) + if not (SMODS.Mods["jen"] or {}).can_load then + local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_cry_ghost") + card:add_to_deck() + G.jokers:emplace(card) + else + if G.GAME.dollars ~= 0 then + ease_dollars(((-G.GAME.dollars) - 1e6), true) + end + end end } local choco2 = { @@ -804,7 +810,7 @@ local ghost = { no_dbl = true, calculate = function(self, card, context) if context.end_of_round and not context.individual and not context.repetition and not context.blueprint and not context.retrigger_joker then - if pseudorandom(pseudoseed("cry_ghost_destroy")) < G.GAME.probabilities.normal/card.ability.extra.destroy_rate then + if pseudorandom(pseudoseed("cry_ghost_destroy")) < cry_prob(card.ability.cry_prob, card.ability.extra.destroy_rate, card.ability.cry_rigged)/card.ability.extra.destroy_rate then G.E_MANAGER:add_event(Event({ func = function() card:start_dissolve() @@ -823,7 +829,7 @@ local ghost = { return end --todo: let multiple ghosts possess multiple jokers - if pseudorandom(pseudoseed("cry_ghost_possess")) < G.GAME.probabilities.normal/card.ability.extra.possess_rate then + if pseudorandom(pseudoseed("cry_ghost_possess")) < cry_prob(card.ability.cry_prob, card.ability.extra.possess_rate, card.ability.cry_rigged)/card.ability.extra.possess_rate then for i = 1, #G.jokers.cards do G.jokers.cards[i].ability.cry_possessed = nil end @@ -840,9 +846,9 @@ local ghost = { end end end, - loc_vars = function(self, info_queue, center) + loc_vars = function(self, info_queue, card) info_queue[#info_queue + 1] = { set = "Other", key = "cry_possessed"} - return { vars = { G.GAME.probabilities.normal or 1, center.ability.extra.possess_rate, center.ability.extra.destroy_rate } } + return { vars = { cry_prob(card.ability.cry_prob, card.ability.extra.destroy_rate, card.ability.cry_rigged), card.ability.extra.possess_rate, card.ability.extra.destroy_rate } } end, } local possessed = { @@ -1218,7 +1224,7 @@ local monopoly_money = { no_dbl = true, calculate = function(self, card, context) if context.buying_card and not context.blueprint_card and not context.retrigger_joker and not (context.card == card) then - if pseudorandom(pseudoseed("cry_monopoly")) < G.GAME.probabilities.normal/card.ability.extra.fail_rate then + if pseudorandom(pseudoseed("cry_monopoly")) < cry_prob(card.ability.cry_prob, card.ability.extra.fail_rate, card.ability.cry_rigged)/card.ability.extra.fail_rate then G.E_MANAGER:add_event(Event({ func = function() context.card:start_dissolve() @@ -1242,8 +1248,8 @@ local monopoly_money = { return nil, true end end, - loc_vars = function(self, info_queue, center) - return { vars = { G.GAME.probabilities.normal or 1, center.ability.extra.fail_rate} } + loc_vars = function(self, info_queue, card) + return { vars = { cry_prob(card.ability.cry_prob, card.ability.extra.fail_rate, card.ability.cry_rigged), card.ability.extra.fail_rate} } end, } local candy_sticks = { diff --git a/Cryptid/Items/Tags.lua b/Cryptid/Items/Tags.lua index 982634b..dad77ad 100644 --- a/Cryptid/Items/Tags.lua +++ b/Cryptid/Items/Tags.lua @@ -60,18 +60,27 @@ local schematic = { apply = function(self, tag, context) if context.type == "store_joker_create" then local card - card = create_card("Joker", context.area, nil, nil, nil, nil, "j_brainstorm") - create_shop_card_ui(card, "Joker", context.area) - card.states.visible = false - tag:yep("+", G.C.RED, function() - card:start_materialize() - card:set_cost() - return true - end) + if not G.GAME.banned_keys["j_brainstorm"] then + card = create_card("Joker", context.area, nil, nil, nil, nil, "j_brainstorm") + create_shop_card_ui(card, "Joker", context.area) + card.states.visible = false + tag:yep("+", G.C.RED, function() + card:start_materialize() + card:set_cost() + return true + end) + else + tag:nope() + end tag.triggered = true return card end end, + in_pool = function() + if (G.GAME.used_jokers["j_brainstorm"] and not next(find_joker("Showman"))) then return false end + if G.GAME.banned_keys["j_brainstorm"] then return false end + return true + end, } local empoweredPack = { object_type = "Booster", @@ -143,28 +152,27 @@ local empowered = { end, apply = function(self, tag, context) if context.type == "new_blind_choice" then - if G.STATE ~= G.STATES.SPECTRAL_PACK then - G.GAME.PACK_INTERRUPT = G.STATE - end - tag:yep("+", G.C.SECONDARY_SET.Spectral, function() - local key = "p_cry_empowered" - local card = Card( - G.play.T.x + G.play.T.w / 2 - G.CARD_W * 1.27 / 2, - G.play.T.y + G.play.T.h / 2 - G.CARD_H * 1.27 / 2, - G.CARD_W * 1.27, - G.CARD_H * 1.27, - G.P_CARDS.empty, - G.P_CENTERS[key], - { bypass_discovery_center = true, bypass_discovery_ui = true } - ) - card.cost = 0 - card.from_tag = true - G.FUNCS.use_card({ config = { ref_table = card } }) - card:start_materialize() - return true - end) - tag.triggered = true - return true + local lock = tag.ID + G.CONTROLLER.locks[lock] = true + tag:yep('+', G.C.SECONDARY_SET.Spectral,function() + local key = "p_cry_empowered" + local card = Card(G.play.T.x + G.play.T.w/2 - G.CARD_W*1.27/2, + G.play.T.y + G.play.T.h/2-G.CARD_H*1.27/2, G.CARD_W*1.27, G.CARD_H*1.27, G.P_CARDS.empty, G.P_CENTERS[key], {bypass_discovery_center = true, bypass_discovery_ui = true}) + card.cost = 0 + card.from_tag = true + G.FUNCS.use_card({config = {ref_table = card}}) + if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_random_edition then + card:set_edition(nil, true, true) + elseif G.GAME.modifiers.cry_force_random_edition then + local edition = cry_poll_random_edition() + card:set_edition(edition, true, true) + end + card:start_materialize() + G.CONTROLLER.locks[lock] = nil + return true + end) + tag.triggered = true + return true end end, in_pool = function() @@ -188,27 +196,18 @@ local gambler = { if context.type == "immediate" then if pseudorandom("cry_gambler_tag") < G.GAME.probabilities.normal / tag.config.odds then local lock = tag.ID - G.CONTROLLER.locks[lock] = true - tag:yep("+", G.C.RARITY.cry_exotic, function() - add_tag(Tag("tag_cry_empowered")) - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.3, - func = function() - if not G.GAME.PACK_INTERRUPT then - G.GAME.tags[#G.GAME.tags]:apply_to_run({ type = "new_blind_choice" }) - end - G.CONTROLLER.locks[lock] = nil - return true - end, - })) - return true - end) + G.CONTROLLER.locks[lock] = true + tag:yep('+', G.C.SECONDARY_SET.Spectral,function() + local tag = Tag("tag_cry_empowered") + add_tag(tag) + G.CONTROLLER.locks[lock] = nil + return true + end) else tag:nope() end - tag.triggered = true - return true + tag.triggered = true + return true end end, } @@ -563,8 +562,6 @@ local m_tag = { end end, } ---This is fully funcional but unobtainable without pointer at the moment ---I have plans for this soon, very soon... local double_m_tag = { object_type = "Tag", atlas = "tag_cry", @@ -956,6 +953,7 @@ return { and self.key ~= "tag_cry_triple" and self.key ~= "tag_cry_quadruple" and self.key ~= "tag_cry_quintuple" + and self.key ~= "tag_ortalab_rewind" then G.GAME.cry_last_tag_used = self.key G.GAME.cry_memory_orbital = self.ability.orbital_hand diff --git a/Cryptid/Items/Vouchers.lua b/Cryptid/Items/Vouchers.lua index 6665403..e566c91 100644 --- a/Cryptid/Items/Vouchers.lua +++ b/Cryptid/Items/Vouchers.lua @@ -203,7 +203,7 @@ local double_down = { --After every round, X1.5 to all values on the back of Dou }, }, } -local overstock_multi = { --+1 card slot[s] and +1 booster pack slot[s] available in the shop +local overstock_multi = { --+1 card slot[s], +1 booster pack slot[s] and +1 voucher slot[s] available in the shop object_type = "Voucher", key = "overstock_multi", config = { extra = 1 }, @@ -226,6 +226,7 @@ local overstock_multi = { --+1 card slot[s] and +1 booster pack slot[s] availabl return true end, })) + cry_bonusvouchermod(math.floor(self.config.extra)) end, unredeem = function(self) if not G.GAME.modifiers.cry_booster_packs then @@ -239,6 +240,7 @@ local overstock_multi = { --+1 card slot[s] and +1 booster pack slot[s] availabl return true end, })) + cry_bonusvouchermod(-1*math.floor(self.config.extra)) end, } local massproduct = { --All cards and packs in the shop cost $1 @@ -495,6 +497,18 @@ local fabric = { --+2 Joker slot[s] end, })) end, + unlocked = false, + check_for_unlock = function(self, args) + if G.PROFILES[G.SETTINGS.profile].voucher_usage['v_antimatter'] and G.PROFILES[G.SETTINGS.profile].voucher_usage['v_antimatter'].count >= 10 then + unlock_card(self) + end + if args.type == 'cry_lock_all' then + lock_card(self) + end + if args.type == 'cry_unlock_all' then + unlock_card(self) + end + end, } --Order 87 reserved for Fake-out (unimplemented) local function asteroglyph_ante() @@ -529,7 +543,19 @@ local asteroglyph = { --Set Ante to 0 return true end, })) - end + end, + unlocked = false, + check_for_unlock = function(self, args) + if G and G.GAME and G.GAME.round_resets and G.GAME.round_resets.ante and G.GAME.round_resets.ante >= 36 then + unlock_card(self) + end + if args.type == 'cry_lock_all' then + lock_card(self) + end + if args.type == 'cry_unlock_all' then + unlock_card(self) + end + end, } --Order 89 reserved for Ivory Script (unimplemented) local blankcanvas = { --+2 hand size @@ -549,6 +575,18 @@ local blankcanvas = { --+2 hand size unredeem = function(self) G.hand:change_size(-1*math.max(1, math.floor(self.config.extra))) end, + unlocked = false, + check_for_unlock = function(self, args) + if G and G.hand and G.hand.config and G.hand.config.card_limit and G.hand.config.card_limit <= 0 then + unlock_card(self) + end + if args.type == 'cry_lock_all' then + lock_card(self) + end + if args.type == 'cry_unlock_all' then + unlock_card(self) + end + end, } local stickyhand = { --+1 card selection limit diff --git a/Cryptid/README.md b/Cryptid/README.md index 3d39599..bf4c4ff 100644 --- a/Cryptid/README.md +++ b/Cryptid/README.md @@ -1,7 +1,7 @@ # Cryptid An unbalanced Balatro mod. -Note: Cryptid requires [Steamodded **1.0.0-Alpha**](https://github.com/Steamopollys/Steamodded/archive/refs/heads/main.zip) and [Talisman](https://github.com/MathIsFun0/Talisman/releases/latest). +Note: Cryptid requires [Steamodded **1.0.0-Alpha** (old calc)](https://github.com/Steamodded/smods/archive/refs/tags/old-calc.zip) and [Talisman](https://github.com/MathIsFun0/Talisman/releases/latest). Cryptid currently adds: ![image](https://github.com/user-attachments/assets/0a03d6b2-d57f-4f92-9f42-a9ff201c5f2f) diff --git a/Cryptid/assets/1x/atlasSleeves.png b/Cryptid/assets/1x/atlasSleeves.png index 5ba0b75..a5fd82d 100644 Binary files a/Cryptid/assets/1x/atlasSleeves.png and b/Cryptid/assets/1x/atlasSleeves.png differ diff --git a/Cryptid/assets/1x/atlasdeck.png b/Cryptid/assets/1x/atlasdeck.png index f1afe6d..43ab466 100644 Binary files a/Cryptid/assets/1x/atlasdeck.png and b/Cryptid/assets/1x/atlasdeck.png differ diff --git a/Cryptid/assets/1x/atlasepic.png b/Cryptid/assets/1x/atlasepic.png index f28df34..7fe18ae 100644 Binary files a/Cryptid/assets/1x/atlasepic.png and b/Cryptid/assets/1x/atlasepic.png differ diff --git a/Cryptid/assets/1x/atlasexotic.png b/Cryptid/assets/1x/atlasexotic.png index 60be5af..e97a2da 100644 Binary files a/Cryptid/assets/1x/atlasexotic.png and b/Cryptid/assets/1x/atlasexotic.png differ diff --git a/Cryptid/assets/1x/atlasnotjokers.png b/Cryptid/assets/1x/atlasnotjokers.png index 627067c..d5230c5 100644 Binary files a/Cryptid/assets/1x/atlasnotjokers.png and b/Cryptid/assets/1x/atlasnotjokers.png differ diff --git a/Cryptid/assets/1x/atlasone.png b/Cryptid/assets/1x/atlasone.png index 6942d8b..b782bbc 100644 Binary files a/Cryptid/assets/1x/atlasone.png and b/Cryptid/assets/1x/atlasone.png differ diff --git a/Cryptid/assets/1x/atlasthree.png b/Cryptid/assets/1x/atlasthree.png index 8a3392f..6513191 100644 Binary files a/Cryptid/assets/1x/atlasthree.png and b/Cryptid/assets/1x/atlasthree.png differ diff --git a/Cryptid/assets/1x/atlastwo.png b/Cryptid/assets/1x/atlastwo.png index fe9bf04..1ee7684 100644 Binary files a/Cryptid/assets/1x/atlastwo.png and b/Cryptid/assets/1x/atlastwo.png differ diff --git a/Cryptid/assets/1x/c_cry_code.png b/Cryptid/assets/1x/c_cry_code.png index d560e95..1a01d1a 100644 Binary files a/Cryptid/assets/1x/c_cry_code.png and b/Cryptid/assets/1x/c_cry_code.png differ diff --git a/Cryptid/assets/1x/cry_misc.png b/Cryptid/assets/1x/cry_misc.png index c3680ee..e91183b 100644 Binary files a/Cryptid/assets/1x/cry_misc.png and b/Cryptid/assets/1x/cry_misc.png differ diff --git a/Cryptid/assets/1x/sticker_cry.png b/Cryptid/assets/1x/sticker_cry.png index 07f9d45..07c37c4 100644 Binary files a/Cryptid/assets/1x/sticker_cry.png and b/Cryptid/assets/1x/sticker_cry.png differ diff --git a/Cryptid/assets/1x/tag_cry.png b/Cryptid/assets/1x/tag_cry.png index 86589d7..d7da3ba 100644 Binary files a/Cryptid/assets/1x/tag_cry.png and b/Cryptid/assets/1x/tag_cry.png differ diff --git a/Cryptid/assets/2x/atlasSleeves.png b/Cryptid/assets/2x/atlasSleeves.png index 4087301..45ded79 100644 Binary files a/Cryptid/assets/2x/atlasSleeves.png and b/Cryptid/assets/2x/atlasSleeves.png differ diff --git a/Cryptid/assets/2x/atlasdeck.png b/Cryptid/assets/2x/atlasdeck.png index b1c8c7e..815eae1 100644 Binary files a/Cryptid/assets/2x/atlasdeck.png and b/Cryptid/assets/2x/atlasdeck.png differ diff --git a/Cryptid/assets/2x/atlasepic.png b/Cryptid/assets/2x/atlasepic.png index 205699e..cbfc46c 100644 Binary files a/Cryptid/assets/2x/atlasepic.png and b/Cryptid/assets/2x/atlasepic.png differ diff --git a/Cryptid/assets/2x/atlasexotic.png b/Cryptid/assets/2x/atlasexotic.png index 2df7a33..6a3be46 100644 Binary files a/Cryptid/assets/2x/atlasexotic.png and b/Cryptid/assets/2x/atlasexotic.png differ diff --git a/Cryptid/assets/2x/atlasnotjokers.png b/Cryptid/assets/2x/atlasnotjokers.png index e573310..292b8a0 100644 Binary files a/Cryptid/assets/2x/atlasnotjokers.png and b/Cryptid/assets/2x/atlasnotjokers.png differ diff --git a/Cryptid/assets/2x/atlasone.png b/Cryptid/assets/2x/atlasone.png index a538f88..40a13c8 100644 Binary files a/Cryptid/assets/2x/atlasone.png and b/Cryptid/assets/2x/atlasone.png differ diff --git a/Cryptid/assets/2x/atlasthree.png b/Cryptid/assets/2x/atlasthree.png index e9f54ac..3932388 100644 Binary files a/Cryptid/assets/2x/atlasthree.png and b/Cryptid/assets/2x/atlasthree.png differ diff --git a/Cryptid/assets/2x/atlastwo.png b/Cryptid/assets/2x/atlastwo.png index 8bfbfc6..43430a3 100644 Binary files a/Cryptid/assets/2x/atlastwo.png and b/Cryptid/assets/2x/atlastwo.png differ diff --git a/Cryptid/assets/2x/c_cry_code.png b/Cryptid/assets/2x/c_cry_code.png index 9f47d09..8ab62f3 100644 Binary files a/Cryptid/assets/2x/c_cry_code.png and b/Cryptid/assets/2x/c_cry_code.png differ diff --git a/Cryptid/assets/2x/cry_misc.png b/Cryptid/assets/2x/cry_misc.png index f139154..ce1186d 100644 Binary files a/Cryptid/assets/2x/cry_misc.png and b/Cryptid/assets/2x/cry_misc.png differ diff --git a/Cryptid/assets/2x/sticker_cry.png b/Cryptid/assets/2x/sticker_cry.png index a52de86..66429b7 100644 Binary files a/Cryptid/assets/2x/sticker_cry.png and b/Cryptid/assets/2x/sticker_cry.png differ diff --git a/Cryptid/assets/2x/tag_cry.png b/Cryptid/assets/2x/tag_cry.png index 1730544..d7c0e16 100644 Binary files a/Cryptid/assets/2x/tag_cry.png and b/Cryptid/assets/2x/tag_cry.png differ diff --git a/Cryptid/localization/en-us.lua b/Cryptid/localization/en-us.lua index 417b00e..d416d3f 100644 --- a/Cryptid/localization/en-us.lua +++ b/Cryptid/localization/en-us.lua @@ -10,6 +10,13 @@ return { "of {C:attention}every{} deck", }, }, + b_cry_beige = { + name = "Beige Deck", + text = { + "{C:attention}Common{} Jokers have", + "{C:attention}quadrupled{} values", + }, + }, b_cry_beta = { name = "Nostalgic Deck", text = { @@ -167,7 +174,7 @@ return { name = "The Joke", text = { "If score is >2X requirements,", - "set ante to multiple of #1#", + "set ante to #2#", }, }, bl_cry_magic = { @@ -288,8 +295,8 @@ return { bl_cry_tax = { name = "The Tax", text = { - "Score per hand capped at", - "0.4X blind requirements", + "Score per hand capped", + "at #1#", }, }, bl_cry_tornado = { @@ -322,6 +329,14 @@ return { }, }, Code = { + c_cry_alttab = { + name = "://ALTTAB", + text = { + "Create the {C:cry_code}current{}", + "blind's skip tag", + "{C:inactive}(Current: {C:cry_code}#1#{C:inactive})", + }, + }, c_cry_class = { name = "://CLASS", text = { @@ -383,14 +398,14 @@ return { "{C:inactive,s:0.8}such as Joker and The Duo (both post-scoring)", }, }, - c_cry_inst = { - name = "://INSTANTIATE", - text = { - "Draw a card with selected card's {C:cry_code}rank{}", - "and one with selected card's {C:cry_code}suit{}", - "{C:inactive}(if possible){}", - }, - }, + c_cry_inst = { + name = "://INSTANTIATE", + text = { + "Draw a card with selected card's {C:cry_code}rank{}", + "and one with selected card's {C:cry_code}suit{}", + "{C:inactive}(if possible){}", + }, + }, c_cry_machinecode = { name = "://MACHINECODE", text = { @@ -590,6 +605,15 @@ return { "times when scored", }, }, + m_cry_light = { + name = "Light Card", + text = { + "When played with {C:attention}#4#{} {C:inactive}(#3#){} other", + "scoring cards, gain {X:mult,C:white}X#1#{} Mult and", + "increase requirement by {C:attention}5{}", + "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)" + }, + }, }, Joker = { j_cry_adroit = { @@ -604,7 +628,7 @@ return { name = "Nostalgic Googol Play Card", text = { "Sell this card to create", - "{C:attention}2{} copies of the leftmost {C:attention}Joker{}", + "{C:attention}#1#{} copies of the leftmost {C:attention}Joker{}", "{C:inactive,s:0.8}Does not copy Nostalgic Googol Play Cards{}", }, }, @@ -621,6 +645,15 @@ return { name = "AP Joker", text = { "{X:mult,C:white} X#1# {} Mult against {C:attention}Boss Blinds{}" }, }, + j_cry_arsonist = { + name = "Arsonist", + text = { + "If played hand", + "contains a {C:attention}Full House{},", + "{C:red}destroy{} all cards", + "after scoring", + } + }, j_cry_astral_bottle = { name = "Astral in a Bottle", text = { @@ -693,7 +726,7 @@ return { "{C:green}#1# in #2#{} chance for each", "played {C:attention}Bonus{} card to increase", "{C:attention}Joker{} or {C:attention}Consumable slots", - "by {C:dark_edition}1{} when scored", + "by {C:dark_edition}#3#{} when scored", "{C:red}Works twice per round", "{C:inactive,s:0.8}(Equal chance for each){}", }, @@ -713,6 +746,11 @@ return { "or {C:attention}played card{}", "{C:inactive,s:0.8}Does not affect other Boredom{}", }, + unlock = { + "AFK in the title", + 'screen for', + '{C:attention}10 minutes' + }, }, j_cry_brittle = { name = "Brittle Candy", @@ -736,7 +774,7 @@ return { text = { "{C:green}#1# in #3#{} chance", "for {C:mult}+#2#{} Mult", - "{C:green}1 in 4{} chance", + "{C:green}#4# in #3#{} chance", "for {C:mult}-#2#{} Mult", }, }, @@ -785,6 +823,11 @@ return { "once for {C:attention}every{} non-{C:blue}Common{C:attention} Joker{}", "to the right of this Joker", }, + unlock = { + "Retrigger a {C:attention}Joker", + '{C:attention}114{} times', + 'in one hand' + }, }, j_cry_caramel = { name = "Caramel", @@ -835,6 +878,11 @@ return { "{C:legendary}Legendary{} Jokers each give {X:mult,C:white} X#3# {} Mult", "{C:cry_exotic}Exotic{} Jokers each give {X:mult,C:white} X#4# {} Mult", }, + unlock = { + 'Obtain a {C:red}Rare{},', + '{C:cry_epic}Epic{} and {C:legendary}Legendary{}', + 'Joker before {C:attention}Ante 9' + } }, j_cry_clash = { name = "The Clash", @@ -843,6 +891,19 @@ return { "hand contains", "an {C:attention}#2#", }, + unlock = { + "Win a run with", + "your final hand being", + "an {E:1,C:attention}Ultimate Pair" + }, + }, + j_cry_clicked_cookie = { + name = "Clicked Cookie", + text = { + "{C:chips}+#1#{} Chips", + "{C:chips}-#2#{} Chips when", + "you {C:attention}click", + }, }, j_cry_CodeJoker = { name = "Code Joker", @@ -851,6 +912,10 @@ return { "{C:cry_code}Code Card{} when", "{C:attention}Blind{} is selected", }, + unlock = { + "Discover {C:attention}every", + '{C:cry_code}Code Card' + }, }, j_cry_coin = { name = "Crypto Coin", @@ -916,6 +981,10 @@ return { "{C:dark_edition,E:1}you cannot escape...{}", "{C:inactive}(Must have room){}", }, + unlock = { + "Obtain an {C:purple}Eternal{}", + "{C:attention}Obelisk" + }, }, j_cry_cursor = { name = "Cursor", @@ -943,6 +1012,15 @@ return { "a {C:attention}#2#" } }, + j_cry_digitalhallucinations = { + name = "Digital Hallucinations", + text = { + "When a {C:attention}Booster Pack{} is opened,", + "{C:green}#1# in #2#{} chance to create", + "a random {C:dark_edition}Negative{} card", + "corresponding to its {C:attention}type{}", + }, + }, j_cry_discreet = { name = "Discreet Joker", text = { @@ -954,13 +1032,13 @@ return { j_cry_doodlem = { name = "Doodle M", text = { - "Create 2 {C:dark_edition}Negative{} {C:attention}consumables{}", + "Create #2# {C:dark_edition}Negative{} {C:attention}consumables{}", "when {C:attention}Blind{} is selected", - "Create 1 more {C:attention}consumable", + "Create #1# more {C:attention}consumable", "for each {C:attention}Jolly Joker{}", }, }, - ["j_cry_Double Scale"] = { + ["j_cry_Double Scale"] = { -- ????????????? name = "Double Scale", text = { "Scaling {C:attention}Jokers{}", @@ -977,6 +1055,11 @@ return { "suit changes every round", "{C:inactive}(Currently {X:mult,C:white} X#3# {C:inactive} Mult)", }, + unlock = { + "Play a {C:attention}High Card{}", + 'with {C:attention}4{} cards', + 'of the {C:attention}same suit' + }, }, j_cry_dubious = { name = "Dubious Joker", @@ -993,6 +1076,11 @@ return { "hand contains", "a {C:attention}#2#", }, + unlock = { + "Win a run", + "without playing", + "a {E:1,C:attention}Two Pair" + }, }, j_cry_duplicare = { name = 'Duplicare', @@ -1084,12 +1172,22 @@ return { "hand contains", "a {C:attention}#2#", }, + unlock = { + "Win a run", + "without playing", + "a {E:1,C:attention}High Card" + }, }, j_cry_fractal = { name = "Fractal Fingers", text = { "{C:attention}+#1#{} card selection limit", }, + unlock = { + "Play a {C:attention}Straight Flush{}", + 'without the {C:attention}Straight', + 'being a {C:attention}Flush' + }, }, j_cry_flip_side = { name = "On the Flip Side", @@ -1202,6 +1300,10 @@ return { "{C:green}#1# in #2#{} chance for", "{X:red,C:white} X#3# {} Mult", }, + unlock = { + "Score {C:attention}1.0e100{} Chips", + "in a single hand" + }, }, j_cry_happy = { name = ":D", @@ -1229,6 +1331,11 @@ return { "hand contains", "a {C:attention}#2#", }, + unlock = { + "Win a run", + "without playing", + "a {E:1,C:attention}Full House" + }, }, j_cry_hunger = { name = "Consume-able", @@ -1263,6 +1370,12 @@ return { "most played {C:attention}poker hand", "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", }, + unlock = { + "Win a run", + "while playing a", + " {C:attention}single type of{}", + '{C:attention}poker hand' + }, }, j_cry_jollysus = { name = "Jolly Joker?", @@ -1307,6 +1420,12 @@ return { "a random {C:attention}Joker{} when", "{C:attention}Boss Blind{} is defeated", }, + unlock = { + "Defeat a {C:attention}Boss Blind", + 'with {C:attention}5{} or more', + '{C:attention}Editioned Cards{} or', + '{C:attention}Jokers' + }, }, j_cry_lightupthenight = { name = "Light Up the Night", @@ -1371,7 +1490,7 @@ return { "When {C:attention}Blind{} is selected,", "destroys each {C:attention}Joker{} except", "{C:legendary}M Jokers{} and {C:attention}Jolly Jokers{}", - "and create 1 {C:attention}Jolly Joker{}", + "and create #1# {C:attention}Jolly Joker{}", "for each destroyed card", }, }, @@ -1414,6 +1533,10 @@ return { "all {C:attention}numbered{} cards", "are considered {C:attention}10s{}", }, + unlock = { + "Play a {C:attention}Flush Five{}", + 'of {C:attention}Kings' + }, }, j_cry_maze = { name = "Labyrinth", @@ -1580,7 +1703,7 @@ return { j_cry_notebook = { name = "Notebook", text = { - "{C:green} #1# in #2#{} chance to gain {C:dark_edition}+1{} Joker", + "{C:green} #1# in #2#{} chance to gain {C:dark_edition}+#6#{} Joker", "slot per {C:attention}reroll{} in the shop", "{C:green}Always triggers{} if there are", "{C:attention}#5#{} or more {C:attention}Jolly Jokers{}", @@ -1604,6 +1727,11 @@ return { "hand contains", "a {C:attention}#2#", }, + unlock = { + "Win a run", + "without playing", + "a {E:1,C:attention}Straight Flush" + }, }, j_cry_nutty = { name = "Nutty Joker", @@ -1681,12 +1809,13 @@ return { "{C:inactive}(Currently {X:chips,C:white} X#1# {C:inactive} Chips)", }, }, - j_cry_pity_prize = { - name = "Pity Prize", - text = { - "When you skip a {C:attention}Booster Pack{} gain a random {C:attention}Tag{}" - }, - }, + j_cry_pity_prize = { + name = "Pity Prize", + text = { + "On skipping a {C:attention}Booster Pack{},", + "gain a random {C:attention}Tag{}", + }, + }, j_cry_pot_of_jokes = { name = "Pot of Jokes", text = { @@ -1694,6 +1823,10 @@ return { "increases by", "{C:blue}#2#{} every round", }, + unlock = { + 'Increase your {C:attention}handsize', + 'to {C:attention}12' + }, }, j_cry_primus = { name = "Primus", @@ -1704,6 +1837,23 @@ return { "{C:inactive}(Currently {X:dark_edition,C:white} ^#2# {C:inactive} Mult)", }, }, + j_cry_pumpkin = { + name = "Pumpkin", + text = { + "Prevents Death if chips scored", + "are atleast {C:attention}50%{} of required chips", + "{C:attention}Turns into Carved Pumpkin", + "{C:attention}when{} {C:red}destroyed" + }, + }, + j_cry_carved_pumpkin = { + name = "Carved Pumpkin", + text = { + "The next {C:attention}#1#{} Boss Blinds", + 'will have their abilities', + '{C:attention}disabled' + }, + }, j_cry_python = { name = "Python", text = { @@ -1729,6 +1879,11 @@ return { "hand contains", "a {C:attention}#2#", }, + unlock = { + "Win a run with", + "your final hand being", + "a {E:1,C:attention}Five of a Kind" + }, }, j_cry_redbloon = { name = "Red Bloon", @@ -1771,12 +1926,17 @@ return { text = { "Randomize abilities each {C:attention}Ante{}", }, + unlock = { + "{C:green}1 in 20{} chance", + 'to unlock this card', + 'on {C:attention}Game Over' + }, }, j_cry_sacrifice = { name = "Sacrifice", text = { - "Create an {C:green}Uncommon{} Joker", - "and 3 {C:attention}Jolly Jokers{} when", + "Create #3# {C:green}Uncommon{} Joker", + "and #2# {C:attention}Jolly Jokers{} when", "a {C:spectral}Spectral{} card is used", "{C:red}Works once per round{}", "{C:inactive}#1#{}", @@ -1858,6 +2018,11 @@ return { "{C:attention}+#1#{} hand size", "{C:attention}+#1#{} consumable slot", "{C:attention}+#1#{} card in shop", + "{C:attention}+#1#{} voucher slot", + }, + unlock = { + 'Win a run with', + 'only {C:attention}High Card' }, }, j_cry_fleshpanopticon = { @@ -1879,6 +2044,14 @@ return { "{C:inactive}(Currently{} {X:chips,C:white}X#1#{} {C:inactive}Chips){}", }, }, + j_cry_spectrogram = { + name = "Spectrogram", + text = { + "{C:attention}Retriggers{} rightmost Joker", + "once for every {C:attention}Echo Card", + "that is played and scored", + }, + }, j_cry_speculo = { name = "Speculo", text = { @@ -1919,6 +2092,11 @@ return { "hand contains", "a {C:attention}#2#", }, + unlock = { + "Win a run with", + "your final hand being", + "a {E:1,C:attention}Bulwark" + }, }, j_cry_subtle = { name = "Subtle Joker", @@ -1954,6 +2132,11 @@ return { "hand contains", "a {C:attention}#2#", }, + unlock = { + "Win a run with", + "your final hand being", + "a {E:1,C:attention}Flush Five" + }, }, j_cry_sync_catalyst = { name = "Sync Catalyst", @@ -2022,7 +2205,7 @@ return { text = { "Sell this card", "to {C:attention}multiply{} values", - "of owned jokers by {C:attention}X1.5{}", + "of owned jokers by {C:attention}X#1#{}", }, }, j_cry_unity = { @@ -2032,6 +2215,11 @@ return { "hand contains", "a {C:attention}#2#", }, + unlock = { + "Win a run with", + "your final hand being", + "a {E:1,C:attention}Flush House" + }, }, j_cry_universe = { name = "Universe", @@ -2151,11 +2339,26 @@ return { "hand contains", "a {C:attention}#2#", }, + unlock = { + "Win a run with", + "your final hand being", + "a {E:1,C:attention}Clusterfuck" + }, + }, + j_cry_zooble = { + name = "Zooble", + text = { + "If played hand does", + "{C:attention}not{} contain a {C:attention}Straight{},", + "this Joker gains {C:mult}+#2#{} Mult for every", + "{C:attention}unique rank{} in scoring hand", + "{C:inactive}(Currently {C:mult}+#1#{C:inactive} Mult)", + }, }, }, Planet = { c_cry_Klubi = { - name = "Klubi", + name = "Risti", text = { "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", "Level up", @@ -2165,7 +2368,7 @@ return { }, }, c_cry_Lapio = { - name = "Lapio", + name = "Pata", text = { "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", "Level up", @@ -2205,7 +2408,7 @@ return { }, }, c_cry_Sydan = { - name = "Sydan", + name = "Hertta", text = { "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", "Level up", @@ -2215,7 +2418,7 @@ return { }, }, c_cry_Timantti = { - name = "Timantti", + name = "Ruutu", text = { "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", "Level up", @@ -2391,6 +2594,7 @@ return { "Create {C:attention}#1#{} {C:dark_edition}Negative{}", "copies of a", "{C:attention}random{} consumable", + "in your possession", "{C:inactive,s:0.8}Does not copy Chambered{}" }, }, @@ -2930,6 +3134,13 @@ return { "{C:inactive}(Must have room){}", }, }, + c_cry_seraph = { + name = "The Seraph", + text = { + "Enhances {C:attention}#1#{} selected card", + "into a {C:attention}Light Card", + }, + }, }, Voucher = { v_cry_asteroglyph = { @@ -2937,12 +3148,19 @@ return { text = { "Set Ante to {C:attention}#1#{}", }, + unlock = { + 'Reach Ante {C:attention}36' + }, }, v_cry_blankcanvas = { name = "Blank Canvas", text = { "{C:attention}+#1#{} hand size", }, + unlock = { + 'Reduce your {C:attention}handsize', + 'to {C:attention}0' + }, }, v_cry_clone_machine = { name = "Clone Machine", @@ -2975,6 +3193,10 @@ return { "appear with", "an {C:dark_edition}Edition{}", }, + unlock = { + "Discover", + 'all {C:attention}Editions' + }, }, v_cry_dexterity = { name = "Dexterity", @@ -2983,6 +3205,11 @@ return { "gain {C:blue}+#1#{} hand(s)", "each round", }, + unlock = { + "Play {C:attention}5000{}", + '{C:attention}Playing Cards{}', + 'in total', + }, }, v_cry_double_down = { name = "Double Down", @@ -3013,6 +3240,10 @@ return { text = { "{C:dark_edition}+#1#{} Joker slot(s)", }, + unlock = { + 'Redeem {C:dark_edition}Antimatter', + '{C:attention}10{} times' + }, }, v_cry_massproduct = { name = "Mass Production", @@ -3020,6 +3251,11 @@ return { "All cards and packs", "in shop cost {C:attention}$1{}", }, + unlock = { + "Redeem {C:attention}25", + '{C:attention}Vouchers', + 'in one run' + }, }, v_cry_moneybean = { name = "Money Beanstalk", @@ -3028,14 +3264,25 @@ return { "interest earned in", "each round to {C:money}$#1#{}", }, + unlock = { + "Max out the", + '{C:attention}interest earnings{}', + 'for the {C:attention}whole run', + }, }, v_cry_overstock_multi = { name = "Multistock", text = { - "{C:attention}+#1#{} card slot(s) and", - "{C:attention}+#1#{} booster pack slot(s)", + "{C:attention}+#1#{} card slot(s),", + "{C:attention}+#1#{} booster pack slot(s),", + "and {C:attention}+#1#{} voucher slot(s),", "available in shop", }, + unlock = { + "Spend {C:attention}1000$", + 'in shop', + 'in one run' + }, }, v_cry_pacclimator = { name = "Planet Acclimator", @@ -3046,6 +3293,11 @@ return { "All future {C:planet}Planet{}", "cards are {C:green}free{}", }, + unlock = { + "Buy {C:attention}100{} {C:planet}Planet", + 'cards total in', + 'the shop', + }, }, v_cry_pairamount_plus = { name = "Pairamount Plus", @@ -3082,6 +3334,12 @@ return { "All rerolls", "cost {C:attention}$2{}", }, + unlock = { + "{C:attention}Reroll{} the shop", + 'a total of', + '{C:attention}250 times{}', + 'in one run' + }, }, v_cry_satellite_uplink = { name = "Satellite Uplink", @@ -3099,6 +3357,12 @@ return { "{C:attention}poker hand{}", "{C:inactive}(Must have room){}", }, + unlock = { + "Use {C:attention}50{} {C:planet}Planet", + 'cards from', + '{C:attention}Booster Packs{}', + 'in one run' + }, }, v_cry_tacclimator = { name = "Tarot Acclimator", @@ -3109,6 +3373,11 @@ return { "All future {C:tarot}Tarot{}", "cards are {C:green}free{}", }, + unlock = { + "Buy {C:attention}100{} {C:tarot}Tarot", + 'cards total in', + 'the shop', + }, }, v_cry_tag_printer = { name = "Tag Printer", @@ -3125,6 +3394,11 @@ return { "gain {C:red}+#1#{} discard(s)", "each round", }, + unlock = { + "Discard {C:attention}5000{}", + '{C:attention}Playing Cards{}', + 'in total', + }, }, v_cry_stickyhand = { name = "Sticky Hand", @@ -3156,6 +3430,14 @@ return { "destroyed each round", }, }, + cry_absolute = { + name = "Absolute", + text = { + "Can't be sold", + "or destroyed", + "{C:attention}Unremovable{}", + }, + }, cry_rigged = { name = "Rigged", text = { @@ -3660,6 +3942,9 @@ return { cry_debuff_oldmark = "No hands containing a Pair", cry_debuff_obsidian_orb = "Applies abilities of all defeated bosses", + cry_tax_placeholder = "(X0.4 blind requirement)", + cry_joke_placeholder = "(multiple of 8)", + k_code = "Code", k_unique = "Unique", b_code_cards = "Code Cards", @@ -3705,6 +3990,8 @@ return { cry_m_ex = "M!", cry_minus_round = "-1 Round", cry_plus_cryptid = "+1 Cryptid", + cry_plus_card = "+1 Card", + cry_plus_code = "+1 Code", cry_no_triggers = "No triggers left!", cry_unredeemed = "Unredeemed...", cry_active = "Active", @@ -3729,6 +4016,7 @@ return { labels = { food_jokers = "Food Jokers", banana = "Banana", + cry_absolute = "Absolute", code = "Code", unique = "Unique", cry_rigged = "Rigged", diff --git a/Cryptid/localization/zh_CN.lua b/Cryptid/localization/zh_CN.lua index 98d8400..77db510 100644 --- a/Cryptid/localization/zh_CN.lua +++ b/Cryptid/localization/zh_CN.lua @@ -14,6 +14,13 @@ return { "拥有{C:legendary,E:1}所有牌组的{}增益效果" } }, + b_cry_beige = { + name = "四重卡组", + text = { + "{C:attention}普通{}小丑具有", + "{C:attention}四倍{}的效果", + }, + }, b_cry_beta = { name = "怀旧牌组", text = { @@ -29,7 +36,7 @@ return { } }, b_cry_bountiful = { - name = "丰饶的露台", + name = "丰饶牌组", text = { "每次{C:attention}出牌{} 或 {C:attention}弃牌{}后", "固定抽五张牌" @@ -94,7 +101,7 @@ return { } }, ["b_cry_cry-club_deck"] = { - name = "梅花卡组", + name = "梅花牌组", text = { "所有的牌都是{C:dark_edition}黑桃{}", "不能改变花色", @@ -104,7 +111,7 @@ return { ["b_cry_cry-eternal_deck"] = { name = "永恒牌组", text = { - "所有的牌都是{C:attention}永恒卡{}", + "所有的牌都带有{C:attention}永恒{}贴纸", "{s:0.8,C:inactive}" } }, @@ -147,8 +154,7 @@ return { text = { "所有的牌都是{C:dark_edition}红桃{}", "不能改变花色", - "", - "{C:attention}头部{}不会出现" + "boss不会出现{C:attention}头部{}" } }, ["b_cry_cry-holo_deck"] = { @@ -260,7 +266,7 @@ return { b_cry_cryazure_deck = { name = "台风牌组", text = { - "所有牌都带有一个{C:dark_edition}蔚蓝火漆{}", + "所有牌都带有{C:dark_edition}蔚蓝蜡封{}", "卡牌不能更改蜡封类型", "{s:0.8,C:inactive}" } @@ -283,7 +289,7 @@ return { b_cry_cryecho_deck = { name = "日食牌组", text = { - "所有的的牌都是{C:attention,T:m_cry_echo}回响版本{}", + "所有的的牌都是{C:attention,T:m_cry_echo}回响牌{}", "不能更改增强类型", "{s:0.8,C:inactive}" } @@ -312,10 +318,18 @@ return { "{s:0.8,C:inactive}" } }, + b_cry_crylight_deck = { + name = "明亮牌组", + text = { + "所有的的牌都是{C:attention,T:m_cry_light}明亮牌{}", + "不能更改增强类型", + "{s:0.8,C:inactive}" + } + }, b_cry_crym_deck = { name = "M", text = { - "所有的牌都是{C:dark_edition,T:cry_m}愉快版本{}", + "所有的牌都是{C:dark_edition,T:cry_m}欢愉版本{}", "不能更改版本类型", "{s:0.8,C:inactive}" } @@ -400,7 +414,7 @@ return { b_cry_source_deck = { name = "源代码牌组", text = { - "所有牌都带有一个{C:dark_edition}绿色蜡封{}", + "所有牌都带有{C:dark_edition}绿色蜡封{}", "卡牌不能更改蜡封类型", "{s:0.8,C:inactive}" } @@ -454,14 +468,14 @@ return { name = "笑料", text = { "如果得分超过要求的2倍,", - "将盲注设置为下一个8的倍数", - "8,16,24...以此类推" + "将盲注设置为 #2#" } }, bl_cry_lavender_loop = { name = "薰衣草环", text = { - "在boss回合中每经过1.5秒,盲注要求增加1.25倍" + "在boss回合中每经过1.5秒", + "盲注要求增加1.25倍" } }, bl_cry_magic = { @@ -498,7 +512,7 @@ return { bl_cry_oldhouse = { name = "怀旧 房屋", text = { - "包含同花顺的出牌不计分" + "包含葫芦的出牌不计分" } }, bl_cry_oldmanacle = { @@ -598,13 +612,20 @@ return { } }, Code = { + c_cry_alttab = { + name = "://ALT+TAB", + text = { + "创建{C:cry_code}当前盲注{}的跳过时标签", + "{C:inactive}(当前:{C:cry_code}#1#{C:inactive})", + }, + }, c_cry_class = { name = "://类别", text = { "将 {C:cry_code}#1#{} 选中的牌", - "转换为 {C:cry_code}指令下的{} 增强", + "转换为 {C:cry_code}指令{} 下的增强", "可用指令:{C:cry_code}bonus{},{C:cry_code}mult{},{C:cry_code}wild{},{C:cry_code}glass{}", - "{C:cry_code}steel{},{C:cry_code}stone{},{C:cry_code}gold{},{C:cry_code}lucky{},{C:cry_code}echo{}" + "{C:cry_code}steel{},{C:cry_code}stone{},{C:cry_code}gold{},{C:cry_code}lucky{},{C:cry_code}echo{},{C:cry_code}light{}" } }, c_cry_commit = { @@ -648,7 +669,7 @@ return { "", "被计算为", "", - "{C:cry_code}指令下的{} 牌型", + "{C:cry_code}指令{} 下的牌型", "", "{C:inactive,s:0.8}必须是已发现的手牌类型", "", @@ -660,14 +681,14 @@ return { c_cry_hook = { name = "://钩子", text = { - "选择两张小丑牌", - "使它们 {C:cry_code}钩住{}" + "选择两张小丑牌,使它们 {C:cry_code}钩住{}", + "{C:inactive,s:0.8}其中一张被触发时,触发另一张(仅当两个效果的触发时机相同时有效)" } }, c_cry_inst = { name = "://实例化", text = { - "抽取与选中的牌同{C:cry_code}点数{}", + "抽取与选中的牌{C:cry_code}同点数{}", "以及{C:cry_code}同花色{}的牌各一张", "{C:inactive}(如果有可能的话){}" } @@ -702,7 +723,7 @@ return { c_cry_oboe = { name = "://偏差1", text = { - "下一包 {C:cry_code}增强包{} 有", + "打开的下一个 {C:cry_code}补充包{} 有", "{C:cry_code}#1#{} 张额外卡牌和", "{C:cry_code}#1#{} 次额外选择", "{C:inactive}(当前为 {C:cry_code}+#2#{C:inactive})" @@ -725,9 +746,9 @@ return { c_cry_reboot = { name = "://重启", text = { - "补充 {C:blue}手牌{} 和 {C:red}弃牌{},", - "将 {C:cry_code}所有{} 牌返回牌堆", - "并抽取一组 {C:cry_code}新的{} 手牌" + "补充 {C:blue}手牌{} 和 {C:red}弃牌{} 次数,", + "将{C:cry_code}所有{}牌返回牌堆", + "并抽取一组{C:cry_code}新的{}手牌" } }, c_cry_revert = { @@ -743,9 +764,9 @@ return { "摧毁一张 {C:cry_code}选中的{} 小丑牌,", "创造该小丑牌的 {C:cry_code}重制标签{},并", "获得一个 {C:cry_code}升级的{} 版本", - "{C:inactive,s:0.8}版本通过收藏中的顺序升级", - "基础,闪箔,镭射,多彩,负片,故障,马赛克,过曝,", - "灰质琉璃,鎏金,模糊,噪声,星界,欢愉,双面,基础" + "{C:inactive,s:0.8}版本通过收藏中的顺序升级{}", + "{C:inactive,s:0.8}基础,闪箔,镭射,多彩,负片,故障,马赛克,过曝,{}", + "{C:inactive,s:0.8}灰质琉璃,鎏金,模糊,噪声,星界,欢愉,双面,基础{}" } }, c_cry_run = { @@ -758,8 +779,7 @@ return { c_cry_seed = { name = "://种子", text = { - "选择一张小丑牌", - "或扑克牌", + "选择一张小丑牌或手牌", "使它们获得 {C:cry_code}灌铅{}效果", "概率效果必然被触发" } @@ -774,7 +794,7 @@ return { c_cry_spaghetti = { name = "://意面", text = { - "生成一张 {C:cry_code}故障版本的{}", + "生成一张 {C:cry_code}故障版本{}的", "食物小丑牌" } }, @@ -782,7 +802,7 @@ return { name = "://变量", text = { "将 {C:cry_code}#1#{} 张选中的牌", - "转换为 {C:cry_code}指令下的{} 牌型", + "转换为 {C:cry_code}指令{} 下的牌型", "可用指令:{C:cry_code}1~13,A,J,Q,K{}" } } @@ -805,9 +825,8 @@ return { e_cry_double_sided = { name = "双面", text = { - "此卡可以被", - "{C:attention}翻转{}以展示", - "另一张不同的卡牌" + "此卡可以被{C:attention}翻转{},", + "以展示另一张不同的卡牌" } }, e_cry_glass = { @@ -815,7 +834,7 @@ return { name = "灰质琉璃", text = { "{C:white,X:mult} X#3# {} 倍率", - "触发时{C:green}#1# / #2#{} 的概率率不会被摧毁" + "触发时{C:green}#1# / #2#{} 的概率不会被摧毁" } }, e_cry_glitched = { @@ -855,8 +874,7 @@ return { e_cry_oversat = { name = "过曝", text = { - "此卡上的所有数值", - "都被 {C:attention}翻倍{}", + "此卡上的所有数值都被{C:attention}翻倍{}", "{C:inactive}(如果可能的话)" } } @@ -869,7 +887,16 @@ return { "{C:green}#2# / #3#{} 几率", "{C:attention}重新触发{} #1# 次" } - } + }, + m_cry_light = { + name = "明亮牌", + text = { + "当该牌计分时,每有{C:attention}#4#{} {C:inactive}(剩余#3#){}张", + "其他计分牌,获得{X:mult,C:white}X#1#{}倍率,并", + "将下次提升所需的数字增加{C:attention}5{}", + "{C:inactive}(当前 {X:mult,C:white}X#2#{C:inactive} 倍率)" + }, + }, }, Joker = { j_cry_CodeJoker = { @@ -893,14 +920,14 @@ return { text = { "当选择{C:attention}盲注{}时", "创造一张{C:dark_edition}负片{}", - "{C:attention}欢乐小丑{}" + "{C:attention}开心小丑{}" } }, j_cry_Megg = { name = "M蛋", text = { "出售这张小丑来创造", - "{C:attention}#2#{} 开心小丑", + "{C:attention}#2#{} 张开心小丑", "在回合结束时增加 {C:attention}#1#{}" } }, @@ -945,10 +972,14 @@ return { "对boss盲注提供{X:mult,C:white} X#1# {} 倍率" } }, + j_cry_arsonist = { + name = "纵火犯", + text = { "打出{C:attention}葫芦{}牌型时,摧毁所有计分牌", }, + }, j_cry_astral_bottle = { name = "瓶中星球", text = { - "当出售时, 应用 {C:dark_edition}界星{}", + "当出售时, 应用 {C:dark_edition}星界{}", "和{C:attention}易腐{} 到一张", "随机的 {C:attention}小丑牌{}" } @@ -972,7 +1003,7 @@ return { j_cry_blacklist = { name = "黑名单", text = { - "当手牌中有{C:attention}#1#{}或打出", + "当手牌中有或者打出{C:attention}#1#{}时", "{C:chips}筹码{} 和 {C:mult}倍率{} 变为0", "如果牌组中没有{C:attention}#1#{},自毁", "{C:inactive,s:0.8}不会改变牌型等级" @@ -996,8 +1027,8 @@ return { name = "咚~", text = { "每个{C:attention}小丑{}给予{C:chips}+#1#{}筹码", - "如果{C:attention}牌型{}是{C:attention}#3#{}增加{C:chips}+#2#{}", - "{C:inactive,s:0.8}欢乐小丑转而给予{} {C:chips,s:0.8}+#4#{} {C:inactive,s:0.8}筹码{}" + "如果{C:attention}牌型{}是{C:attention}#3#{},额外给予{C:chips}+#2#{}筹码", + "{C:inactive,s:0.8}开心小丑转而给予{} {C:chips,s:0.8}+#4#{} {C:inactive,s:0.8}筹码{}" } }, j_cry_bonkers = { @@ -1042,7 +1073,7 @@ return { name = "泡泡 M", text = { "如果打出的手牌包含{C:attention}#1#{}", - "生成一张{C:dark_edition}闪箔{C:attention}欢乐小丑{}", + "生成一张{C:dark_edition}闪箔{C:attention}开心小丑{}", "{C:red,E:2}自毁{}" } }, @@ -1065,27 +1096,27 @@ return { name = "纽扣糖", text = { "之后的 {C:attention}#1#{} 次重掷", - "之花 {C:money}$1{}" + "只花 {C:money}$1{}" } }, j_cry_candy_cane = { name = "拐杖糖", text = { "之后 {C:attention}#1#{} 回合", - " 打出的牌{C:attention}重新触发{}获得{C:money}$#2#" + " 打出的牌被{C:attention}重新触发{}时获得{C:money}$#2#" } }, j_cry_candy_dagger = { name = "糖果匕首", text = { "选择 {C:attention}盲注{} 后", - "摧毁最左边的小丑创建一张{C:cry_candy}糖果{}" + "摧毁它左边的小丑,创造一张{C:cry_candy}糖果{}小丑" } }, j_cry_candy_sticks = { name = "棒棒糖", text = { - "直到你打出 {C:attention}#1#{}", + "直到你打出 {C:attention}#1#{} 手牌", "下个Boss盲注的效果失效" } }, @@ -1117,11 +1148,11 @@ return { "回合结束时", "这个小丑获得{X:mult,C:white} X#2# {} 倍率", "{C:attention}#3#{}回合后自毁", - "(当前{X:mult,C:white} X#1# {C:inactive}倍率)" + "(当前{X:mult,C:white} X#1# {C:inactive}倍率)" } }, j_cry_chocolate_dice = { - name = "巧克力骰", + name = "巧克力十面骰", text = { "击败Boss盲注后", "投掷一个{C:green}d10{} 的判定", @@ -1154,6 +1185,13 @@ return { "{X:mult,C:white} X#1# {} 倍率" } }, + j_cry_clicked_cookie = { + name = "被点击的饼干", + text = { + "{C:chips}+#1#{} 筹码", + "每当该小丑被{C:attention}点击{}时,{C:chips}-#2#{} 筹码", + }, + }, j_cry_coin = { name = "加密货币", text = { @@ -1248,7 +1286,7 @@ return { text = { "当{C:attention}选择盲注{}时", "创造2个随机{C:dark_edition}负片{} {C:attention}消耗牌{}", - "每有1个{C:attention}欢乐小丑{}创造1个额外的{C:attention}消耗牌" + "每有1个{C:attention}开心小丑{}创造1个额外的{C:attention}消耗牌" } }, j_cry_dropshot = { @@ -1347,8 +1385,9 @@ return { j_cry_facile = { name = "简易", text = { - "{C:attention}#2#{} 及一下的牌得分", - "{X:dark_edition,C:white}^#1#{} 倍率" + "{C:attention}#2#{} 张及以下的牌得分", + "{X:dark_edition,C:white}^#1#{} 倍率", + "(重复触发算作多张)" } }, j_cry_filler = { @@ -1359,20 +1398,20 @@ return { } }, j_cry_fleshpanopticon = { - name = "肉体监狱", + name = "血肉监牢", text = { - "{C:red}X#1#{} {C:attention}Boss 盲注{} 需求", + "{C:attention}Boss 盲注{} 得分需求 {C:red}X#1#{}", "当 {C:attention}Boss 盲注{} 被击败后,", "{C:red}自毁{}, 然后创建", "一张 {C:dark_edition}负片{} {C:spectral}真理之门{} ", - "{C:inactive,s:0.8}This prison... to hold... me?" + "{C:inactive,s:0.8}此等监牢……囚禁于吾?" } }, j_cry_flip_side = { name = "两副面孔", text = { - "{C:dark_edition}双面{}小丑使用", - "它们反面的效果代替正面效果", + "{C:dark_edition}双面{}小丑不触发正面效果", + "转而触发反面效果", "{C:attention}重新触发{}所有{C:dark_edition}双面{}小丑" } }, @@ -1380,14 +1419,14 @@ return { name = "M当劳", text = { "{C:mult}+#1#{} 倍率", - "{C:red,E:2}在 {C:attention}#2#{} 回合#3#中自毁{}", - "当{C:attention}欢乐小丑{}被{C:attention}出售{}时增加{C:attention}#4#{}回合", - "{C:inactive,s:0.8}2 麦双层,2 麦鸡{}", - "{C:inactive,s:0.8}大薯条,20 块和大蛋糕{}" + "在 {C:attention}#2#{} 回合中{C:red,E:2}自毁{}", + "当{C:attention}开心小丑{}被{C:attention}出售{}时增加{C:attention}#3#{}回合", + "{C:inactive,s:0.8}2 双层芝士,2 麦香鸡{}", + "{C:inactive,s:0.8}1 大薯条,20 大蛋糕{}" } }, j_cry_foolhardy = { - name = "鲁莽x小丑", + name = "鲁莽小丑", text = { "如果打出的手牌包含", "一个 {C:attention}#2#", @@ -1397,9 +1436,9 @@ return { j_cry_formidiulosus = { name = "驱邪", text = { - "When a {X:cry_cursed,C:white}{} Joker is obtained, destroy it", - "商店结束后创建 {C:attention}#1#{}张 {C:dark_edition}负片{C:cry_candy}糖果{} ", - " 每有一个 {C:cry_candy}糖果{} 被作祟{X:dark_edition,C:white}+^#2#{} 倍率", + "获得 {X:cry_cursed,C:white}诅咒{} 小丑时,将其摧毁", + "离开商店时创造 {C:attention}#1#{}张 {C:dark_edition}负片{C:cry_candy}糖果{} ", + "每有一张 {C:cry_candy}糖果{}小丑,{X:dark_edition,C:white}+^#2#{} 倍率", "{C:inactive}(当前 {X:dark_edition,C:white}^#3#{C:inactive} 倍率)" } }, @@ -1538,7 +1577,7 @@ return { } }, j_cry_jollysus = { - name = "开心小丑…吗?", + name = "欢愉小丑…吗?", text = { "当一张小丑被{C:attention}出售{}时", "创造一张{C:dark_edition}欢愉{}小丑", @@ -1555,7 +1594,7 @@ return { } }, j_cry_kooky = { - name = "古怪小丑", + name = "怪诞小丑", text = { "如果出的牌中包含 {C:attention}#2#", "{C:red}+#1#{} 倍率" @@ -1564,10 +1603,9 @@ return { j_cry_krustytheclown = { name = "小丑库斯提", text = { - "当出的每张牌都计分时", + "当一张打出的牌被计分时", "这张牌增加{X:mult,C:white} X#1# {}倍率", - "{C:inactive}(当前{X:mult,C:white} X#2# {C:inactive}倍率)", - "{C:inactive,s:0.8}(捏他辛普森一家)" + "{C:inactive}(当前{X:mult,C:white} X#2# {C:inactive}倍率)" } }, j_cry_kscope = { @@ -1595,7 +1633,7 @@ return { } }, j_cry_loopy = { - name = "环弯愉悦", + name = "环弯欢愉", text = { "本回合每出售一张{C:attention}开心{}{C:attention}小丑{}", "{C:attention}重新触发一次{}所有小丑", @@ -1620,7 +1658,7 @@ return { j_cry_m = { name = "m", text = { - "当{C:attention}欢乐小丑{}被售出时", + "当{C:attention}开心小丑{}被售出时", "这张小丑获得 {X:mult,C:white} X#1# {} 倍率", "{C:inactive}(当前 {X:mult,C:white} X#2# {C:inactive} 倍率)" } @@ -1628,7 +1666,7 @@ return { j_cry_macabre = { name = "毛骨悚然", text = { - "当选择{C:attention}盲注{}时,除了{C:attention}开心小丑{}和{C:legendary}M系小丑{}", + "当选择{C:attention}盲注{}时,除了{C:attention}开心小丑{}和{C:legendary}M 小丑{}", "其余小丑全部摧毁,每摧毁一张小丑就获得一张{C:attention}开心小丑{}" } }, @@ -1657,9 +1695,8 @@ return { j_cry_mask = { name = "面具", text = { - "重新触发 {C:attention}人头牌{} cards", - "{C:attention}#1#{} additional 次", - "所有{C:attention}非人头牌{} 被削弱" + "{C:attention}人头牌{}额外触发 {C:attention}#1#{} 次", + "所有{C:attention}非人头牌{}被削弱" } }, j_cry_maximized = { @@ -1711,8 +1748,8 @@ return { name = "霓虹 M", text = { "在回合结束时获得{C:money}$#2#{}", - "回合结束时每持有一张{C:attention}欢乐小丑{}或者{C:legendary}M 小丑{}", - "增加{C:money}$#1#{}" + "回合结束时,每持有一张{C:attention}开心小丑{}或者{C:legendary}M 小丑{}", + "每回合报酬增加{C:money}$#1#{}。" } }, j_cry_mondrian = { @@ -1734,11 +1771,11 @@ return { } }, j_cry_monopoly_money = { - name = "垄断", + name = "大富翁纸币", text = { "{C:green}#1# / #2#{} 几率", - "时购买的牌{C:attention}摧毁{}", - "并且售出时 {C:attention}售价减半" + "{C:attention}摧毁{}购买的牌", + "并且售出时 {C:attention}金钱减半" } }, j_cry_morse = { @@ -1752,8 +1789,8 @@ return { name = "使徒·十三", text = { "每回合结束时", - "创造一张{C:attention}M小丑{}", - "每个 {C:attention}开心小丑{}或者{C:attention}M小丑{} 提供 {X:dark_edition,C:white}^#1#{} 倍率", + "创造一张{C:attention}M 小丑{}", + "每个 {C:attention}开心小丑{}或者{C:attention}M 小丑{} 提供 {X:dark_edition,C:white}^#1#{} 倍率", "每 {C:attention}卖出{}一张 {C:attention}开心小丑{}", "额外提供 {X:dark_edition,C:white}^#2#{}倍率", "{C:inactive,s:0.8}(使徒·十三 除外)" @@ -1762,7 +1799,7 @@ return { j_cry_mstack = { name = "堆叠 M", text = { - "每出售{C:attention}#2#{} {C:inactive}[#3#]{} {C:attention}欢乐小丑{}", + "每出售{C:attention}#2#{} {C:inactive}[#3#]{} {C:attention}开心小丑{}", "重新触发所有已打出的牌", "{C:inactive}(当前{}{C:attention:} #1#{}{C:inactive} 次重新触发){}" } @@ -1779,7 +1816,7 @@ return { j_cry_necromancer = { name = "死灵法师", text = { - "当{C:attention}售出{}一张小丑且其售价大于 {C:attention}$0{} ", + "当{C:attention}售出{}一张小丑且其售价大于 {C:attention}$0{} 时", "获得一张 {C:attention}本局游戏售出过的{} {C:attention}随机小丑牌{} ", "并将其 {C:attention}售价{} 变为 {C:attention}$0{}" } @@ -1817,7 +1854,7 @@ return { name = "M记事本=)", text = { "每次{C:attention}重掷{}商店有{C:green} #1# / #2#{} 几率增加{C:dark_edition}+1{}个小丑牌槽位", - "如果有{C:attention}#5#{}或以上{C:attention}欢乐小丑{}{C:green}百分百触发{}", + "如果有{C:attention}#5#{}或以上{C:attention}开心小丑{}{C:green}百分百触发{}", "{C:red}每回合只触发一次{}", "{C:inactive}(当前{C:dark_edition}+#3#{}{C:inactive} 并且#4#){}" } @@ -1850,7 +1887,7 @@ return { name = "油灯", text = { "回合结束后", - "右边 {C:attention}小丑牌{}的售价 {C:attention}x#1#{}" + "右边 {C:attention}小丑牌{}的数值 {C:attention}x#1#{}" } }, j_cry_oldblueprint = { @@ -1956,7 +1993,7 @@ return { j_cry_redbloon = { name = "红色气球", text = { - "{C:attention}#2#{}回合#3#后{C:red,E:2}自毁{}并获得{C:money}$#1#{}" + "{C:attention}#2#{}回合后{C:red,E:2}自毁{},并获得{C:money}$#1#{}" } }, j_cry_redeo = { @@ -1981,7 +2018,7 @@ return { name = "反转牌", text = { "如果{C:attention}弃牌牌型{}是{C:attention}#1#{}", - "用{C:dark_edition}闪箔{C:attention}开心小丑{}", + "用{C:dark_edition}镭射{C:attention}开心小丑{}", "填满所有空的小丑槽位 {C:inactive}(最多 100){}", "{C:red,E:2}自毁{}", "{C:inactive,s:0.8}终极逆袭{}" @@ -2023,8 +2060,8 @@ return { name = "拼M游戏", text = { "当打出手牌时,", - "会有{C:green}#1#/#2#{}几率生成一张", - "{C:dark_edition}欢愉{C:green}罕见{}小丑" + "会有{C:green}#1#/#2#{}几率生成一张", + "{C:dark_edition}欢愉 {C:green}罕见{}小丑" } }, j_cry_seal_the_deal = { @@ -2051,9 +2088,8 @@ return { j_cry_smallestm = { name = "超小M", text = { - "如果 {C:attention}扑克手牌{}", - "是一个 {C:attention}#1#{}", - "创造两个 a {C:cry_jolly}M 标签", + "打出 {C:attention}#1#{} 时", + "创造一个 {C:cry_jolly}M 标签{}", "{C:inactive,s:0.8}好吧,基本上我很小" } }, @@ -2076,6 +2112,13 @@ return { "{C:inactive}(当前{} {X:chips,C:white}X#1#{} {C:inactive}筹码){}" } }, + j_cry_spectrogram = { + name = "频谱", + text = { + "每当一张{C:attention}回响牌{}被打出并计分时", + "{C:attention}重新触发{}最右边的小丑", + }, + }, j_cry_speculo = { name = "镜像", text = { @@ -2123,7 +2166,7 @@ return { } }, j_cry_supercell = { - name = "supercell", + name = "Supercell", text = { "{C:chips}+#1#{} 筹码, {C:mult}+#1#{} 倍率,", "{X:chips,C:white}X#2#{} 筹码, {X:mult,C:white}X#2#{} 倍率", @@ -2226,12 +2269,12 @@ return { j_cry_universe = { name = "宇宙", text = { - "每张{C:dark_edition}界星{} ", + "每张{C:dark_edition}星界{} ", "提供 {X:dark_edition,C:white}^#1#{} 倍率" } }, j_cry_universum = { - name = "宇宙", + name = "寰宇", text = { "{C:attention}牌型{}升级时获得", "{X:red,C:white} X#1# {} 倍率和 {X:blue,C:white} X#1# {} 筹码" @@ -2261,14 +2304,14 @@ return { name = "室女座", text = { "如果 {C:attention}果出牌牌型{} 包含一个 {C:attention}#2#{}", - "该小丑增加 {C:money}$#1#{} {C:attention}售价{}", + "该小丑增加 {C:money}$#1#{} {C:attention}售价{}", "出售这张牌时", "每 {C:money}$4{} 的 {C:attention}出售价值{}{C:dark_edition}创造一张多彩{} {C:attention}开心小丑{},", " {C:inactive}(至少 1){}" } }, j_cry_wacky = { - name = "疯狂小丑", + name = "搞怪小丑", text = { "如果出的牌中包含 {C:attention}#2#", "{C:red}+#1#{} 倍率" @@ -2326,8 +2369,8 @@ return { j_cry_wrapped = { name = "包裹糖果", text = { - "每回合创建一个随机的{C:attention}食物小丑{}", - " {C:attention}#1#{} 回合后", + "{C:attention}#1#{} 回合后", + "创建一个随机的{C:attention}食物小丑{}", "{C:red,E:2}自毁{}" } }, @@ -2338,7 +2381,16 @@ return { "一个 {C:attention}#2#", "{X:mult,C:white} X#1# {} 倍率" } - } + }, + j_cry_zooble = { + name = "祖波", + text = { + "打出并计分的牌中,", + "每有一个{C:attention}不同点数{},获得{C:mult}+#2#{}倍率", + "{C:inactive}(当前{C:mult}+#1#{C:inactive}倍率)", + "{C:inactive}(包含顺子的出牌不触发)" + }, + }, }, Other = { banana = { @@ -2355,9 +2407,9 @@ return { } }, cry_azure_seal = { - name = "蔚蓝火漆", + name = "蔚蓝蜡封", text = { - "打出附带该火漆的牌时", + "打出附带该蜡封的牌时", "{C:red}摧毁{}这张牌", "之后创造 {C:attention}#1#{} 张 {C:dark_edition}负片{}{C:planet}对应牌型的星球牌{}" } @@ -2410,7 +2462,7 @@ return { } }, cry_green_seal = { - name = "秩绿火漆", + name = "秩绿蜡封", text = { "仅当被打出且不计分时", "创造一张 {C:cry_code}代码{} 卡牌", @@ -2446,8 +2498,7 @@ return { cry_perishable_voucher = { name = "易腐优惠券", text = { - "一定回合后被削弱", - "{C:attention}#1#{} 回合", + "{C:attention}#1#{} 回合后被削弱", "{C:inactive}({C:attention}#2#{C:inactive} 剩余)" } }, @@ -2502,7 +2553,7 @@ return { cry_rigged = { name = "灌铅", text = { - "这个小丑上{C:cry_code}所有的{}概率效果", + "这张小丑或手牌上{C:cry_code}所有的{}概率效果", "都{C:cry_code}必定触发" } }, @@ -2518,7 +2569,7 @@ return { text = { "{C:attention}小丑牌{} 和打出的牌有", "{C:green}1 / 3{} 几率获得闪烁", - "创建一个 {C:attention}幽灵", + "创造一张 {C:attention}幽灵", "{C:inactive,s:0.7}你被幽灵附身了", "{C:inactive,s:0.7}意识时而清醒,时而模糊" } @@ -2546,9 +2597,9 @@ return { ev_cry_choco3 = { name = "3: 女巫药剂", text = { - "创建3个 {C:attention}魔药", - " {C:attention}小盲注{}之后使用一个", - "或者 {C:attention}所有的{} 减益效果都会在这个{C:attention}底注{}生效", + "创造3个 {C:attention}魔药", + "在{C:attention}小盲注{}结束前使用其中之一", + "否则 {C:attention}所有的{} 减益效果都会在这个{C:attention}底注{}生效", "{C:inactive,s:0.7}你被女巫绑架了!", "{C:inactive,s:0.7}她盯着你,递上三瓶药剂", "{C:inactive,s:0.7}选一个吧,不然她可要替你做决定了。" @@ -2560,8 +2611,8 @@ return { "打出的牌有 {C:green}1 / 4{} 几率", "变为随机的 {C:club}梅花{} 人头牌", "将 {C:attention}倍率{} 除以打出人头牌的数量", - "{C:inactive,s:0.7}即使是一个心地善良、", - "{C:inactive,s:0.7}夜晚祈祷的男人……" + "{C:inactive,s:0.7}即便是心地善良、", + "{C:inactive,s:0.7}夜晚虔诚祈祷之人……" } }, ev_cry_choco5 = { @@ -2569,9 +2620,9 @@ return { text = { "移除所有打出的牌的 {C:attention}增强{} ", "并有{C:green}1 / 3{} 几率摧毁", - "{C:heart}红桃{} 和 {C:diamond}方块{} cards", - "{C:inactive,s:0.7}在夜深人静时要小心", - "{C:inactive,s:0.7,E:1}因为它们在阴影中{C:inactive,s:0.7} 寻找机会来满足自己的欲望……" + "{C:heart}红桃{} 和 {C:diamond}方块{} 卡牌", + "{C:inactive,s:0.7}夜深人静时,你必须更加谨慎,", + "{C:inactive,s:0.7,E:1}因为它们在阴影中{C:inactive,s:0.7} 伺机满足自己的饥渴……" } }, ev_cry_choco6 = { @@ -2587,7 +2638,7 @@ return { text = { "创建三个 {C:attention}不给糖就捣蛋{} 和一个 {C:attention}糖果篮子", "每回合商店有一个 {C:attention}不给糖就捣蛋{}", - "获得{C:cry_candy}糖果{} 可以得到{C:money}$3{}", + "获得{C:cry_candy}糖果{} 时,得到{C:money}$3{}", "{C:inactive,s:0.7}整个社区都为恐怖的盛会装饰一新,", "{C:inactive,s:0.7}快来享受这节日气氛吧!" } @@ -2606,7 +2657,7 @@ return { text = { "获得 {C:money}$20", "所有赚到的 {C:money}钱{} 都变为 {C:attention}双倍", - "{C:inactive,s:0.7}你已故的亲戚们的幽灵在午夜时分来访!", + "{C:inactive,s:0.7}你已故亲戚的幽灵在午夜时分来访!", "{C:inactive,s:0.7}他们默默地将一袋钱放在你的手中,", "{C:inactive,s:0.7}温暖一笑,随即化为虚影消散在空气中~" } @@ -2617,7 +2668,7 @@ return { "{s:0.8}Gros Michel,鸡蛋,冰淇淋,卡文迪许,", "{s:0.8}乌龟豆,饮料可乐,爆米花,拉面,", "{s:0.8}苏打水,泡菜,辣椒,焦糖,", - "{s:0.8}怀旧糖果,快餐M,", + "{s:0.8}怀旧糖果,M当劳,", "{s:0.8}切奶酪,咖啡馆美食,樱桃,", "{s:0.8}全糖可乐,星果,火锅,", "{s:0.8}幸运饼干,瑞士小丑,塔利亚费罗,", @@ -2665,7 +2716,7 @@ return { } }, p_cry_meme_1 = { - name = "玩梗包", + name = "玩梗包1", text = { "选择 {C:attention}#1#{} 张,最多", "可达 {C:attention}#2# 张玩梗的小丑{}" @@ -2711,7 +2762,7 @@ return { "{C:attention}#1#{},", "{C:attention}#2#{},", "以及 {C:attention}#3#{}", - "(芬兰语)" + "(芬兰语万物)" } }, c_cry_Klubi = { @@ -2794,7 +2845,7 @@ return { } }, c_cry_universe = { - name = "该死的宇宙", + name = "TM的整个宇宙!", text = { "{S:0.8}({S:0.8,V:1}等级.#1#{S:0.8}){} 升级", "{C:attention}#2#", @@ -2803,18 +2854,27 @@ return { } }, c_cry_void = { - name = "空", + name = "虚空", text = { "{S:0.8}({S:0.8,V:1}等级.#1#{S:0.8}){} 升级", "{C:attention}#2#", "{C:mult}+#3#{} 倍率和", "{C:chips}+#4#{} 筹码" } - } + }, + c_cry_sunplanet = { + name = '太阳', + text = { + "{S:0.8}({S:0.8,V:1}等级.#1#{S:0.8}){}", + "使{C:attention}晋升{}牌型的指数", + "增加{X:gold,C:white}0.05{}", + "{C:inactive}(目前指数 {X:gold,C:white}X(#2#^晋升数){C:inactive})" + } + }, }, Sleeve = { sleeve_cry_bountiful_sleeve = { - name = "丰饶的露台牌套", + name = "丰饶牌套", text = { "每次{C:attention}出牌{} 或 {C:attention}弃牌{}后", "固定抽五张牌" @@ -2853,7 +2913,7 @@ return { } }, sleeve_cry_equilibrium_sleeve = { - name = "平衡牌套", + name = "均衡牌套", text = { "所有卡牌在", "商店中的 {C:attention}出现几率相同{}", @@ -2911,9 +2971,9 @@ return { }, Spectral = { c_cry_adversary = { - name = "对敌者", + name = "敌手", text = { - "{C:red}所有{} {C:attention}小丑牌{} 变为 {C:dark_edition}负片{},", + "拥有的{C:red}所有{} {C:attention}小丑牌{} 变为 {C:dark_edition}负片{},", "本局游戏的小丑牌购买价格{C:red}翻倍{}" } }, @@ -2926,17 +2986,16 @@ return { } }, c_cry_chambered = { - name = "腔体", + name = "腔室", text = { - "复制 {C:attention}#1#{}张 {C:attention}随机{}", - "的{C:dark_edition}负片{}", - "消耗牌" + "随机复制 {C:attention}#1#{}张 {C:dark_edition}负片{}版本", + "的{C:attention}持有{}的消耗牌" } }, c_cry_conduit = { - name = "导水管", + name = "渠道", text = { - "交换两张所选择的(小丑)牌的 {C:attention}版本{}" + "交换两张所选择的小丑或手牌的 {C:attention}版本{}" } }, c_cry_gateway = { @@ -2983,7 +3042,7 @@ return { name = "仪典", text = { "增强 {C:attention}#1#{} 张选定的卡牌", - "为 {C:dark_edition}负片{}, {C:dark_edition}马赛克{}", + "为 {C:dark_edition}负片{}, {C:dark_edition}马赛克{}", "或 {C:dark_edition}星界{} " } }, @@ -3014,7 +3073,7 @@ return { name = "台风", text = { "向手中 {C:attention}#1#{} 选择的", - "牌中添加 {C:cry_azure}天蓝火漆{}" + "牌中添加 {C:cry_azure}蔚蓝蜡封{}" } }, c_cry_vacuum = { @@ -3302,7 +3361,7 @@ return { name = "控制台标签", text = { "给予一个免费", - "{C:cry_code}程序包" + "{C:cry_code}代码包" } }, tag_cry_double_m = { @@ -3333,7 +3392,7 @@ return { } }, tag_cry_glass = { - name = "灰质标签", + name = "琉璃标签", text = { "下一张在商店里的小丑", "增加 {C:dark_edition}灰质琉璃{}版本并且免费" @@ -3364,15 +3423,14 @@ return { name = "loss", text = { "给予一个免费", - "的{C:cry_ascendant}玩梗{} 包", - "(标签名是个外网梗)" + "的{C:cry_ascendant}玩梗{}包" } }, tag_cry_m = { - name = "愉悦~标签", + name = "欢愉~标签", text = { "下一张在商店里的小丑", - "增加 {C:dark_edition}愉悦~{}版本并且免费" + "增加 {C:dark_edition}欢愉{}版本并且免费" } }, tag_cry_memory = { @@ -3456,7 +3514,7 @@ return { c_cry_eclipse = { name = "日食", text = { - "增强 {C:attention}#1#{} 选定的卡牌", + "增强 {C:attention}#1#{} 张选定的卡牌", "为 {C:attention}回响卡" } }, @@ -3475,7 +3533,14 @@ return { "随机 {C:attention}消耗牌{}", "{C:inactive}(必须有空间){}" } - } + }, + c_cry_seraph = { + name = "六翼天使", + text = { + "增强 {C:attention}#1#{} 张选定的手牌", + "为 {C:attention}明亮牌", + }, + }, }, Unique = { c_cry_potion = { @@ -3725,7 +3790,7 @@ return { ach_cry_blurred_blurred_joker = "法律盲点", ach_cry_break_infinity = "突破无限", ach_cry_bullet_hell = "子弹地狱", - ach_cry_cryptid_the_cryptid = "Cryptid the Cryptid", + ach_cry_cryptid_the_cryptid = "神秘神秘生物", ach_cry_exodia = "艾克佐迪亚", ach_cry_freak_house = "怪物之家", ach_cry_googol_play_pass = "Googol Play Pass", @@ -3759,10 +3824,10 @@ return { b_code_cards = "代码牌", b_flip = "翻转", b_merge = "融合", - b_pull = "拉", - b_unique_cards = "特殊牌", - cry_active = "Active", - cry_again_q = "还想试一次 ", + b_pull = "拉取", + b_unique_cards = "独特牌", + cry_active = "激活", + cry_again_q = "再来?", cry_code_apply = "应用", cry_code_apply_previous = "应用之前的", cry_code_cancel = "取消", @@ -3777,8 +3842,8 @@ return { cry_code_rank = "输入等级", cry_critical_hit_ex = "致命一击!", cry_critical_miss_ex = "致命失误!", - cry_curse = "祸根", - cry_curse_ex = "祸根!", + cry_curse = "诅咒", + cry_curse_ex = "诅咒!", cry_debuff_obsidian_orb = "拥有所有已击败 Boss 的能力", cry_debuff_oldarm = "必须打4张或更少的牌", cry_debuff_oldflint = "同花不计分", @@ -3816,6 +3881,8 @@ return { cry_hand_bulwark = "碉堡", cry_hand_clusterfuck = "一坨", cry_hand_ultpair = "至尊对子", + cry_asc_hands = "晋升牌型", + cry_p_star = "星星", cry_hooked_ex = "被勾住!", cry_inactive = "Inactive", cry_jolly_ex = "红红火火恍恍惚惚红红火火恍恍惚惚!", @@ -3853,16 +3920,16 @@ return { k_disable_music = "禁用音乐", k_end_blind = "结束盲注", k_hooked_ex = "钩住了!", - k_planet_disc = "恒星环盘", - k_planet_satellite = "人造卫星", - k_planet_universe = "真实的宇宙", - k_unique = "特殊" + k_planet_disc = "星周盘", + k_planet_satellite = "天然卫星", + k_planet_universe = "整个TMD宇宙", + k_unique = "独特" }, labels = { banana = "香蕉", code = "代码", cry_astral = "星界", - cry_azure_seal = "蔚蓝火漆", + cry_azure_seal = "蔚蓝蜡封", cry_blur = "模糊", cry_double_sided = "双面", cry_epic = "史诗", @@ -3871,9 +3938,9 @@ return { cry_glass = "易碎", cry_glitched = "故障", cry_gold = "鎏金", - cry_green_seal = "绿色火漆", + cry_green_seal = "秩绿蜡封", cry_hooked = "钩住", - cry_m = "愉快", + cry_m = "欢愉", cry_mosaic = "马赛克", cry_noisy = "噪声", cry_oversat = "过曝", @@ -3884,7 +3951,7 @@ return { k_cry_cursed = "诅咒", k_cry_epic = "史诗", k_cry_exotic = "域外", - unique = "特殊" + unique = "独特" }, poker_hand_descriptions = { cry_Bulwark = { @@ -3895,7 +3962,7 @@ return { "对子、同花或顺子的牌" }, cry_UltPair = { - "两个两对,其中,他们之间共有两种花色", + "两个两对,共两种花色", "每对两对是一种花色", "他们之间共有两种花色" }, @@ -4546,4 +4613,4 @@ return { } } } -} \ No newline at end of file +} diff --git a/Cryptid/localization/zh_TW.lua b/Cryptid/localization/zh_TW.lua index 65b3b86..bb5d5f5 100644 --- a/Cryptid/localization/zh_TW.lua +++ b/Cryptid/localization/zh_TW.lua @@ -1172,13 +1172,17 @@ return { }, }, j_cry_macabre = { - name = "Macabre Joker", + name = "悚小丑", text = { - "When {C:attention}Blind{} is selected,", - "destroys each {C:attention}Joker{} except", - "{C:legendary}M Jokers{} and {C:attention}Jolly Jokers{}", - "and create 1 {C:attention}Jolly Joker{}", - "for each destroyed card", + "當{C:attention}盲注{}被選擇,", + "摧毀{C:legendary}M小丑{}和{C:attention}快樂小丑{}", + "以外的{C:attention}小丑{}和", + "生成被摧毀卡數量的{C:attention}快樂小丑{}", + --"When {C:attention}Blind{} is selected,", + --"destroys each {C:attention}Joker{} except", + --"{C:legendary}M Jokers{} and {C:attention}Jolly Jokers{}", + --"and create 1 {C:attention}Jolly Joker{}", + --"for each destroyed card", }, }, j_cry_magnet = { diff --git a/Cryptid/lovely.toml b/Cryptid/lovely.toml index 87afbef..aec7cd7 100644 --- a/Cryptid/lovely.toml +++ b/Cryptid/lovely.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Make the splash screen more jolly # Requires "Custom Main Menu" config to be enabled @@ -22,12 +22,12 @@ if Cryptid.enabled["Menu"] then local option = math.random(#mcard) local chosenoption = mcard[option] if chosenoption == "j_cry_biggestm" or chosenoption == "j_cry_reverse" then --These don't render properly; replace these with loopy instead - SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS['j_cry_loopy']) + SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS['j_cry_loopy'],{bypass_discovery_center = true, bypass_discovery_ui = true}) else - SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS[chosenoption]) + SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS[chosenoption],{bypass_discovery_center = true, bypass_discovery_ui = true}) end else - SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS['j_jolly']) + SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS['j_jolly'],{bypass_discovery_center = true, bypass_discovery_ui = true}) end end ''' @@ -83,9 +83,9 @@ match_indent = true [[patches]] [patches.pattern] target = "card.lua" -pattern = '''if k ~= 'focused_ui' and k ~= "front" and k ~= "back" and k ~= "soul_parts" and k ~= "center" and k ~= 'floating_sprite' and k~= "shadow" and k~= "use_button" and k ~= 'buy_button' and k ~= 'buy_and_use_button' and k~= "debuff" and k ~= 'price' and k~= 'particles' and k ~= 'h_popup' then v:draw() end''' +pattern = '''if not v.custom_draw and k ~= 'focused_ui' and k ~= "front" and k ~= "back" and k ~= "soul_parts" and k ~= "center" and k ~= 'floating_sprite' and k~= "shadow" and k~= "use_button" and k ~= 'buy_button' and k ~= 'buy_and_use_button' and k~= "debuff" and k ~= 'price' and k~= 'particles' and k ~= 'h_popup' then v:draw() end''' position = "at" -payload = '''if k ~= 'focused_ui' and k ~= "front" and k ~= "back" and k ~= "soul_parts" and k ~= "center" and k ~= 'floating_sprite' and k ~= 'floating_sprite2' and k~= "shadow" and k~= "use_button" and k ~= 'buy_button' and k ~= 'buy_and_use_button' and k~= "debuff" and k ~= 'price' and k~= 'particles' and k ~= 'h_popup' then v:draw() end''' +payload = '''if not v.custom_draw and k ~= 'focused_ui' and k ~= "front" and k ~= "back" and k ~= "soul_parts" and k ~= "center" and k ~= 'floating_sprite' and k ~= 'floating_sprite2' and k~= "shadow" and k~= "use_button" and k ~= 'buy_button' and k ~= 'buy_and_use_button' and k~= "debuff" and k ~= 'price' and k~= 'particles' and k ~= 'h_popup' then v:draw() end''' match_indent = true @@ -291,6 +291,7 @@ target = "functions/UI_definitions.lua" pattern = "voucher_areas[#voucher_areas]:emplace(card)" position = "before" payload = ''' +if not G.GAME.voucher_edition_index then G.GAME.voucher_edition_index = {} end if G.GAME.voucher_edition_index[card.ability.name] then -- i just made it a function so i can look at it less local edition = cry_edition_to_table(G.GAME.voucher_edition_index[card.ability.name]) if edition then @@ -659,6 +660,7 @@ match_indent = true # init Cryptid global through lovely # so other mods can add things to memepack pool +# and define some stub functions so that the game does not immediately crash when talisman isn't loaded [[patches]] [patches.pattern] target = "main.lua" @@ -666,11 +668,15 @@ pattern = '''function love.load()''' position = "before" payload = ''' Cryptid = {} +Cryptid.enabled = {} Cryptid.memepack = {} Cryptid.aliases = {} Cryptid.food = {} Cryptid.M_jokers = {} Cryptid.Megavouchers = {} +function cry_format(...) + return ... +end ''' match_indent = true @@ -737,3 +743,44 @@ if self.config.center.set == 'Joker' then end ''' match_indent = true + +# fix crashing from the source +# well, not from the real source, but close enough +[[patches]] +[patches.pattern] +target = "tag.lua" +pattern = '''update_hand_text({sound = 'button', volume = 0.7, pitch = 0.8, delay = 0.3}, {''' +position = "before" +payload = ''' +if (not self.ability.orbital_hand) or (not G.GAME.hands[self.ability.orbital_hand]) then + local _poker_hands = {} + for k, v in pairs(G.GAME.hands) do + if v.visible then _poker_hands[#_poker_hands+1] = k end + end + + self.ability.orbital_hand = pseudorandom_element(_poker_hands, pseudoseed('orbital')) +end +''' +match_indent = true + +# add check for unlock with winning hand +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = '''check_for_unlock({type = 'win'})''' +position = "after" +payload = ''' +check_for_unlock({type = 'cry_win_with_hand', hand = G.GAME.last_hand_played}) +''' +match_indent = true + +# (scuffed) remove filler from rare tag pool +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = '''if v.yes_pool_flag and not G.GAME.pool_flags[v.yes_pool_flag] then add = nil end''' +position = "after" +payload = ''' +if v.key == 'j_cry_filler' and _append == 'rta' then add = nil end +''' +match_indent = true diff --git a/Cryptid/lovely/Achievements.toml b/Cryptid/lovely/Achievements.toml index 939e745..6309e69 100644 --- a/Cryptid/lovely/Achievements.toml +++ b/Cryptid/lovely/Achievements.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 ## Cryptid Achievements diff --git a/Cryptid/lovely/Blinds.toml b/Cryptid/lovely/Blinds.toml index ec88e8f..e1cbd1d 100644 --- a/Cryptid/lovely/Blinds.toml +++ b/Cryptid/lovely/Blinds.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # The Tax effect [[patches]] diff --git a/Cryptid/lovely/CCD.toml b/Cryptid/lovely/CCD.toml index 47d4631..4839fe7 100644 --- a/Cryptid/lovely/CCD.toml +++ b/Cryptid/lovely/CCD.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # This is sacrilegious [[patches]] diff --git a/Cryptid/lovely/CatMerge.toml b/Cryptid/lovely/CatMerge.toml index 146e9f8..118da20 100644 --- a/Cryptid/lovely/CatMerge.toml +++ b/Cryptid/lovely/CatMerge.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # what in ze fuck am i cooking [[patches]] diff --git a/Cryptid/lovely/Challenges.toml b/Cryptid/lovely/Challenges.toml index 857cddc..4d6cfe8 100644 --- a/Cryptid/lovely/Challenges.toml +++ b/Cryptid/lovely/Challenges.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Rush Hour - remove tags [[patches]] diff --git a/Cryptid/lovely/Code.toml b/Cryptid/lovely/Code.toml index 0a65605..83f604a 100644 --- a/Cryptid/lovely/Code.toml +++ b/Cryptid/lovely/Code.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Code UI disables hold R shortcut [[patches]] @@ -158,9 +158,72 @@ match_indent = true target = "game.lua" pattern = '''if self.STATE == self.STATES.SELECTING_HAND then''' position = "before" -payload = '''if G.GAME.USING_RUN then self.STATE = self.STATES.SHOP end''' +payload = ''' +if G.GAME.USING_RUN then + if not (self.STATE == self.STATES.STANDARD_PACK or self.STATE == self.STATES.BUFFOON_PACK or self.STATE == self.STATES.PLANET_PACK or self.STATE == self.STATES.TAROT_PACK or self.STATE == self.STATES.SPECTRAL_PACK or self.STATE == self.STATES.SMODS_BOOSTER_OPENED) then -- do you are have stupid + self.STATE = self.STATES.SHOP + end + if G.GAME.blind then G.GAME.blind:change_colour() end -- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if G.load_cry_runarea then + G.cry_runarea = CardArea( + G.discard.T.x, + G.discard.T.y, + G.discard.T.w, + G.discard.T.h, + { type = "discard", card_limit = 1e100 } + ) + G.cry_runarea:load(G.load_cry_runarea) + G.load_cry_runarea = nil + end +end +''' match_indent = true +# Run - handle packs (this is incredibly invasive) +# we can't do "draw from run to hand" because modded packs presumably don't get ovewritten like that +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = '''for i=1, hand_space do --draw cards from deckL''' +position = "before" +payload = '''if not G.GAME.USING_RUN then''' +match_indent = true + +# the inconsistency hurts +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = '''G.FUNCS.draw_from_hand_to_deck()''' +position = "at" +payload = '''if not G.GAME.USING_RUN then + G.FUNCS.draw_from_hand_to_deck() +else + G.FUNCS.draw_from_hand_to_run() +end''' +match_indent = true + +[[patches]] +[patches.regex] +target = "functions/state_events.lua" +pattern = '''end\n\s+G\.FUNCS\.discard_cards_from_highlighted \= function\(e, hook\)''' +position = "before" +payload = ''' +else + for i = 1, #G.cry_runarea.cards do + draw_card(G.cry_runarea,G.hand, i*100/#G.cry_runarea.cards,'up', true) + end +end + +G.FUNCS.draw_from_hand_to_run = function(e) -- might as well just slap this here + local hand_count = #G.hand.cards + for i=1, hand_count do --draw cards from deck + draw_card(G.hand, G.cry_runarea, i*100/hand_count,'down', nil, nil, 0.08) + end +end +''' +match_indent = true + + [[patches]] [patches.pattern] target = "game.lua" diff --git a/Cryptid/lovely/Conveyor.toml b/Cryptid/lovely/Conveyor.toml index 40421ec..c81f283 100644 --- a/Cryptid/lovely/Conveyor.toml +++ b/Cryptid/lovely/Conveyor.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Don't sort cards [[patches]] diff --git a/Cryptid/lovely/Cube.toml b/Cryptid/lovely/Cube.toml index 1875da7..6f8162c 100644 --- a/Cryptid/lovely/Cube.toml +++ b/Cryptid/lovely/Cube.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Joker Lock [[patches]] diff --git a/Cryptid/lovely/Enhanced.toml b/Cryptid/lovely/Enhanced.toml index 29d075e..1af1299 100644 --- a/Cryptid/lovely/Enhanced.toml +++ b/Cryptid/lovely/Enhanced.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Show edition on Edition Decks [[patches]] diff --git a/Cryptid/lovely/Equilibrium.toml b/Cryptid/lovely/Equilibrium.toml index 2e0f771..65cef87 100644 --- a/Cryptid/lovely/Equilibrium.toml +++ b/Cryptid/lovely/Equilibrium.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # non-pack scaling in pack slots [[patches]] diff --git a/Cryptid/lovely/Error.toml b/Cryptid/lovely/Error.toml index 36fa4b0..5cb354b 100644 --- a/Cryptid/lovely/Error.toml +++ b/Cryptid/lovely/Error.toml @@ -1,28 +1,17 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 -# Misprint-like description + +# putting this here since lovely crashes with a file that has no uncommented patches +# note to self get rid of this file later [[patches]] [patches.pattern] -target = "card.lua" -pattern = "elseif self.ability.name == 'Misprint' then" -position = "before" -payload = ''' -elseif self.ability.name == 'cry-Error' then - if G.GAME and G.GAME.pseudorandom and G.STAGE == G.STAGES.RUN then - cry_error_msgs[#cry_error_msgs].string = "%%" .. predict_card_for_shop() - else - cry_error_msgs[#cry_error_msgs].string = "%%J6" - end - main_start = { - {n=G.UIT.O, config={object = DynaText({string = cry_error_operators, colours = {G.C.DARK_EDITION,},pop_in_rate = 9999999, silent = true, random_element = true, pop_delay = 0.30, scale = 0.32, min_cycle_time = 0})}}, - {n=G.UIT.O, config={object = DynaText({string = cry_error_numbers, colours = {G.C.DARK_EDITION,},pop_in_rate = 9999999, silent = true, random_element = true, pop_delay = 0.33, scale = 0.32, min_cycle_time = 0})}}, - {n=G.UIT.O, config={object = DynaText({string = cry_error_msgs, - colours = {G.C.UI.TEXT_DARK},pop_in_rate = 9999999, silent = true, random_element = true, pop_delay = 0.4011, scale = 0.32, min_cycle_time = 0})}}, - } -''' +target = "functions/common_events.lua" +pattern = "bbbbb" +position = "at" +payload = "aaaaa" match_indent = true # Patch get_current_pool to predict for ERROR desc @@ -35,23 +24,3 @@ match_indent = true # position = "at" # payload = "local rarity = _rarity or pseudorandom(_G[gcparea == 'ERROR' and 'predict_pseudoseed' or 'pseudoseed']('rarity'..G.GAME.round_resets.ante..(_append or '')))" # match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = "local main_start, main_end = nil,nil" -position = "after" -payload = ''' -if self.ability.name == 'cry-Machine Code' then - --"Create a random // glitched consumable" - main_start = { - randomchar(codechars6), - randomchar(codechars6), - randomchar(codechars6), - randomchar(codechars6), - randomchar(codechars6), - randomchar(codechars6), - } -end -''' -match_indent = true \ No newline at end of file diff --git a/Cryptid/lovely/Exponentia.toml b/Cryptid/lovely/Exponentia.toml index f4b0b61..4767222 100644 --- a/Cryptid/lovely/Exponentia.toml +++ b/Cryptid/lovely/Exponentia.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Increment Exponentia on Joker XMult [[patches]] diff --git a/Cryptid/lovely/Gateway.toml b/Cryptid/lovely/Gateway.toml index 3cff6b7..64d302c 100644 --- a/Cryptid/lovely/Gateway.toml +++ b/Cryptid/lovely/Gateway.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # 3-layer drawing for Gateway [[patches]] diff --git a/Cryptid/lovely/Misc.toml b/Cryptid/lovely/Misc.toml index a2b94ee..df7864c 100644 --- a/Cryptid/lovely/Misc.toml +++ b/Cryptid/lovely/Misc.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Shine on Oversaturated to make it more noticable [[patches]] @@ -219,37 +219,8 @@ end match_indent = true # Compat UI for Old Blueprint and Gemini -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = "elseif self.ability.name == 'Blueprint' then" -position = "at" -payload = '''elseif self.ability.name == 'Blueprint' or self.ability.name == 'cry-oldblueprint' then''' -match_indent = true -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = "elseif self.ability.name == 'Brainstorm' then" -position = "at" -payload = '''elseif self.ability.name == 'Brainstorm' or self.config.center.key == 'j_cry_gemino' then''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = "if self.ability.name == 'Blueprint' or self.ability.name == 'Brainstorm' then" -position = "at" -payload = ''' -if self.config.center.key == 'j_cry_gemino' then -other_joker = G.jokers.cards[1] -if other_joker and other_joker ~= self and not (Card.no(other_joker, "immutable", true)) then - self.ability.blueprint_compat = 'compatible' -else - self.ability.blueprint_compat = 'incompatible' -end end -if self.ability.name == 'Blueprint' or self.ability.name == 'cry-oldblueprint' or self.ability.name == 'Brainstorm' then''' -match_indent = true +# I deleted the patches --Jevonn (test) # calculate wheel fail (for Wheel of Hope) [[patches]] diff --git a/Cryptid/lovely/Misprint.toml b/Cryptid/lovely/Misprint.toml index a1563b9..6203237 100644 --- a/Cryptid/lovely/Misprint.toml +++ b/Cryptid/lovely/Misprint.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Randomize poker hands after RNG is set up [[patches]] @@ -43,6 +43,7 @@ target = "card.lua" pattern = "G.GAME.pack_choices = self.config.center.config.choose or 1" position = "after" payload = ''' +G.GAME.pack_choices = ((self.ability.choose and self.ability.extra) and math.min(math.floor(self.ability.extra), self.ability.choose)) or 1 if G.GAME.modifiers.cry_misprint_min then G.GAME.pack_size = self.ability.extra if G.GAME.pack_size < 1 then G.GAME.pack_size = 1 end @@ -285,7 +286,7 @@ match_indent = true [[patches]] [patches.pattern] target = "game.lua" -pattern = "G.GAME.chips_text = ''" +pattern = "self.GAME.selected_back_key = selected_back" position = "after" payload = ''' G.GAME.cry_voucher_centers = {} @@ -317,7 +318,7 @@ target = "card.lua" pattern = "extra = center and center.config.extra or self and self.ability.extra" position = "at" payload = ''' -extra = self and self.config and self.config.center_key and G.GAME and G.GAME.cry_voucher_centers and G.GAME.cry_voucher_centers[self.config.center_key] and G.GAME.cry_voucher_centers[self.config.center_key].config.extra +extra = self and G.GAME.cry_voucher_centers[self.config.center_key].config.extra or center and center.config.extra ''' match_indent = true @@ -461,7 +462,7 @@ target = "functions/button_callbacks.lua" pattern = '''if ((G.GAME.dollars-G.GAME.bankrupt_at) - 10 >= 0) and''' position = "at" payload = ''' -if ((G.GAME.dollars-G.GAME.bankrupt_at) - cry_cheapest_boss_reroll() >= 0) and +if ((to_big(G.GAME.dollars)-to_big(G.GAME.bankrupt_at)) - to_big(cry_cheapest_boss_reroll()) >= to_big(0)) and ''' match_indent = true diff --git a/Cryptid/lovely/Planets.toml b/Cryptid/lovely/Planets.toml index 7521952..8b26260 100644 --- a/Cryptid/lovely/Planets.toml +++ b/Cryptid/lovely/Planets.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Lapio softlock mechanic [[patches]] diff --git a/Cryptid/lovely/Probability.toml b/Cryptid/lovely/Probability.toml new file mode 100644 index 0000000..0f1220e --- /dev/null +++ b/Cryptid/lovely/Probability.toml @@ -0,0 +1,288 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = 5 + +# there's gonna be a lot of this +# init all cards with ability.cry_prob +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "self.base_cost = center.cost or 1" +position = "before" +payload = ''' +self.ability.cry_prob = 1 +''' +match_indent = true + +# define function in lovely +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "function save_run()" +position = "before" +payload = ''' +function cry_prob(owned, den, rigged) + prob = G.GAME and G.GAME.probabilities.normal or 1 + if rigged then + return den + else + return prob*owned + end +end +''' +match_indent = true + +# lucky +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = '''elseif _c.effect == 'Lucky Card' then loc_vars = {G.GAME.probabilities.normal, cfg.mult, 5, cfg.p_dollars, 15}''' +position = "at" +payload = ''' +elseif _c.effect == 'Lucky Card' then loc_vars = {cfg.cry_prob and cry_prob(cfg.cry_prob, 15, cfg.cry_rigged) or G.GAME.probabilities.normal, cfg.mult, 5, cfg.p_dollars, 15} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if pseudorandom('lucky_money') < G.GAME.probabilities.normal/15 then''' +position = "at" +payload = ''' +if pseudorandom('lucky_money') < cry_prob(self.ability.cry_prob, 15, self.ability.cry_rigged)/15 then +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if pseudorandom('lucky_mult') < G.GAME.probabilities.normal/5 then''' +position = "at" +payload = ''' +if pseudorandom('lucky_mult') < cry_prob(self.ability.cry_prob, 5, self.ability.cry_rigged)/5 then +''' +match_indent = true + +# glass +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = '''elseif _c.effect == 'Glass Card' then loc_vars = {cfg.Xmult, G.GAME.probabilities.normal, cfg.extra}''' +position = "at" +payload = ''' +elseif _c.effect == 'Glass Card' then loc_vars = {cfg.Xmult, cfg.cry_prob and cry_prob(cfg.cry_prob, cfg.extra, cfg.cry_rigged) or G.GAME.probabilities.normal, cfg.extra} +''' +match_indent = true + +# wow this is a fat line +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = '''if SMODS.has_enhancement(scoring_hand[i], 'm_glass') and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/(scoring_hand[i].ability.name == 'Glass Card' and scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) then''' +position = "at" +payload = ''' +if SMODS.has_enhancement(scoring_hand[i], 'm_glass') and not scoring_hand[i].debuff and pseudorandom('glass') < cry_prob(scoring_hand[i].ability.cry_prob, scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra, scoring_hand[i].ability.cry_rigged)/(scoring_hand[i].ability.name == 'Glass Card' and scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) then +''' +match_indent = true + +# wheeeeeeeeeeel +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = '''elseif _c.name == "The Wheel of Fortune" then loc_vars = {G.GAME.probabilities.normal, cfg.extra}; info_queue[#info_queue+1] = G.P_CENTERS.e_foil; info_queue[#info_queue+1] = G.P_CENTERS.e_holo; info_queue[#info_queue+1] = G.P_CENTERS.e_polychrome;''' +position = "at" +payload = ''' +elseif _c.name == "The Wheel of Fortune" then loc_vars = {cfg.cry_prob and cry_prob(cfg.cry_prob, cfg.extra, cfg.cry_rigged) or G.GAME.probabilities.normal, cfg.extra}; info_queue[#info_queue+1] = G.P_CENTERS.e_foil; info_queue[#info_queue+1] = G.P_CENTERS.e_holo; info_queue[#info_queue+1] = G.P_CENTERS.e_polychrome; +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if self.ability.name == 'Ectoplasm' or self.ability.name == 'Hex' or pseudorandom('wheel_of_fortune') < G.GAME.probabilities.normal/self.ability.extra then''' +position = "at" +payload = ''' +if self.ability.name == 'Ectoplasm' or self.ability.name == 'Hex' or pseudorandom('wheel_of_fortune') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then +''' +match_indent = true + +# ok now onto jonklers + +# space +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''elseif self.ability.name == 'Space Joker' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra}''' +position = "at" +payload = ''' +elseif self.ability.name == 'Space Joker' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged), self.ability.extra} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if self.ability.name == 'Space Joker' and pseudorandom('space') < G.GAME.probabilities.normal/self.ability.extra then''' +position = "at" +payload = ''' +if self.ability.name == 'Space Joker' and pseudorandom('space') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then +''' +match_indent = true + +# 8ball +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''elseif self.ability.name == '8 Ball' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1),self.ability.extra}''' +position = "at" +payload = ''' +elseif self.ability.name == '8 Ball' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged),self.ability.extra} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if (context.other_card:get_id() == 8) and (pseudorandom('8ball') < G.GAME.probabilities.normal/self.ability.extra) then''' +position = "at" +payload = ''' +if (context.other_card:get_id() == 8) and (pseudorandom('8ball') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra) then +''' +match_indent = true + +# business +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''elseif self.ability.name == 'Business Card' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra}''' +position = "at" +payload = ''' +elseif self.ability.name == 'Business Card' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged),self.ability.extra} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''pseudorandom('business') < G.GAME.probabilities.normal/self.ability.extra then''' +position = "at" +payload = ''' +pseudorandom('business') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then +''' +match_indent = true + +# gros michel + cavendish +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''elseif self.ability.name == 'Gros Michel' then loc_vars = {self.ability.extra.mult, ''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra.odds}''' +position = "at" +payload = ''' +elseif self.ability.name == 'Gros Michel' then loc_vars = {self.ability.extra.mult, cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged), self.ability.extra.odds} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''elseif self.ability.name == 'Cavendish' then loc_vars = {self.ability.extra.Xmult, ''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra.odds}''' +position = "at" +payload = ''' +elseif self.ability.name == 'Cavendish' then loc_vars = {self.ability.extra.Xmult, cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged), self.ability.extra.odds} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if pseudorandom(self.ability.name == 'Cavendish' and 'cavendish' or 'gros_michel') < G.GAME.probabilities.normal/self.ability.extra.odds then''' +position = "at" +payload = ''' +if pseudorandom(self.ability.name == 'Cavendish' and 'cavendish' or 'gros_michel') < cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged)/self.ability.extra.odds then +''' +match_indent = true + +# business +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''elseif self.ability.name == 'Business Card' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra}''' +position = "at" +payload = ''' +elseif self.ability.name == 'Business Card' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged),self.ability.extra} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''pseudorandom('business') < G.GAME.probabilities.normal/self.ability.extra then''' +position = "at" +payload = ''' +pseudorandom('business') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then +''' +match_indent = true + +# bloodstone +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''elseif self.ability.name == 'Bloodstone' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra.odds, self.ability.extra.Xmult}''' +position = "at" +payload = ''' +elseif self.ability.name == 'Bloodstone' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged), self.ability.extra.odds, self.ability.extra.Xmult} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''pseudorandom('bloodstone') < G.GAME.probabilities.normal/self.ability.extra.odds then''' +position = "at" +payload = ''' +pseudorandom('bloodstone') < cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged)/self.ability.extra.odds then +''' +match_indent = true + +# reserved parking +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''elseif self.ability.name == 'Reserved Parking' then loc_vars = {self.ability.extra.dollars, ''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra.odds}''' +position = "at" +payload = ''' +elseif self.ability.name == 'Reserved Parking' then loc_vars = {self.ability.extra.dollars, cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged), self.ability.extra.odds} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''pseudorandom('parking') < G.GAME.probabilities.normal/self.ability.extra.odds then''' +position = "at" +payload = ''' +pseudorandom('parking') < cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged)/self.ability.extra.odds then +''' +match_indent = true + +# hallucination +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''elseif self.ability.name == 'Hallucination' then loc_vars = {G.GAME.probabilities.normal, self.ability.extra}''' +position = "at" +payload = ''' +elseif self.ability.name == 'Hallucination' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged), self.ability.extra} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if pseudorandom('halu'..G.GAME.round_resets.ante) < G.GAME.probabilities.normal/self.ability.extra then''' +position = "at" +payload = ''' +if pseudorandom('halu'..G.GAME.round_resets.ante) < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then +''' +match_indent = true diff --git a/Cryptid/lovely/ResizedJokers.toml b/Cryptid/lovely/ResizedJokers.toml index 544523c..f5cdb21 100644 --- a/Cryptid/lovely/ResizedJokers.toml +++ b/Cryptid/lovely/ResizedJokers.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Wee Fibonacci rendering [[patches]] diff --git a/Cryptid/lovely/Spooky.toml b/Cryptid/lovely/Spooky.toml index e30eccf..d29c547 100644 --- a/Cryptid/lovely/Spooky.toml +++ b/Cryptid/lovely/Spooky.toml @@ -28,16 +28,22 @@ target = "game.lua" pattern = '''if G.load_shop_booster then''' position = "before" payload = ''' -if G.GAME.events.ev_cry_choco10 and not G.load_shop_vouchers then - local card = create_card('Joker', G.jokers, true, nil, nil, nil, nil, 'cry_antique') - cry_misprintize(card) - card.misprint_cost_fac = 50/card.cost - card:set_cost() - create_shop_card_ui(card, 'Voucher', G.shop_vouchers) - card:start_materialize() - card.ability.cry_antique = true - G.shop_vouchers.config.card_limit = G.shop_vouchers.config.card_limit + 1 - G.shop_vouchers:emplace(card) +if G.GAME.events.ev_cry_choco10 then + local add = true + for k, v in pairs(G.shop_vouchers.cards) do -- G.load_shop_vouchers is already set to nil here, just do a normal check + if v.ability.cry_antique then add = false end + end + if add then + local card = create_card('Joker', G.jokers, true, nil, nil, nil, nil, 'cry_antique') + cry_misprintize(card) + card.misprint_cost_fac = 50/card.cost + card:set_cost() + create_shop_card_ui(card, 'Voucher', G.shop_vouchers) + card:start_materialize() + card.ability.cry_antique = true + G.shop_vouchers.config.card_limit = G.shop_vouchers.config.card_limit + 1 + G.shop_vouchers:emplace(card) + end end ''' match_indent = true \ No newline at end of file diff --git a/Cryptid/lovely/Stakes.toml b/Cryptid/lovely/Stakes.toml index 041d084..6d31df7 100644 --- a/Cryptid/lovely/Stakes.toml +++ b/Cryptid/lovely/Stakes.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Yellow Stake - perishable and rental effects on consumable @@ -151,9 +151,9 @@ match_indent = true [[patches]] [patches.pattern] target = "functions/state_events.lua" -pattern = "if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then" +pattern = "if SMODS.has_enhancement(scoring_hand[i], 'm_glass') and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then" position = "at" -payload = "if ((scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra) or (G.GAME.modifiers.cry_shatter_rate and pseudorandom('cry_shatter') < 1/G.GAME.modifiers.cry_shatter_rate)) and not scoring_hand[i].ability.eternal then" +payload = "if ((SMODS.has_enhancement(scoring_hand[i], 'm_glass') and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra) or (G.GAME.modifiers.cry_shatter_rate and pseudorandom('cry_shatter') < 1/G.GAME.modifiers.cry_shatter_rate)) and not scoring_hand[i].ability.eternal then" match_indent = true diff --git a/Cryptid/lovely/Sticker.toml b/Cryptid/lovely/Sticker.toml index 02eefdd..30764db 100644 --- a/Cryptid/lovely/Sticker.toml +++ b/Cryptid/lovely/Sticker.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # ok it seems i still have to use the dumb fix for pinned, smods please overwrite [[patches]] @@ -310,3 +310,14 @@ payload = ''' if self.ability.rental and (not (self.ability.set == "Planet" and #find_joker('Astronomer') > 0) and self.ability.set ~= "Booster") then self.cost = 1 end ''' match_indent = true + +# hmm +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if self.ability.eternal then badges[#badges + 1] = 'eternal' end" +position = "at" +payload = ''' +if self.ability.eternal and not self.ability.cry_absolute then badges[#badges + 1] = 'eternal' end +''' +match_indent = true diff --git a/Cryptid/lovely/Universum.toml b/Cryptid/lovely/Universum.toml index 73165b3..6153322 100644 --- a/Cryptid/lovely/Universum.toml +++ b/Cryptid/lovely/Universum.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Level up modifier [[patches]] diff --git a/Cryptid/lovely/VeryFair.toml b/Cryptid/lovely/VeryFair.toml index 0b88063..a75c432 100644 --- a/Cryptid/lovely/VeryFair.toml +++ b/Cryptid/lovely/VeryFair.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -1 # Remove voucher at start of run (also for Crimson Stake) [[patches]] diff --git a/Cryptid/lovely/Voucher.toml b/Cryptid/lovely/Voucher.toml new file mode 100644 index 0000000..c298d12 --- /dev/null +++ b/Cryptid/lovely/Voucher.toml @@ -0,0 +1,134 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = 0 + +# first we need to fix what on earth is going on with card.shop_voucher +# for some reason it's not saved/loaded so... that's what's gonna happen +# also adding another variable here that will be useful later +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''ability = self.ability,''' +position = "before" +payload = ''' +shop_voucher = self.shop_voucher, +shop_cry_bonusvoucher = self.shop_cry_bonusvoucher, +''' +match_indent = true + +# water is wet +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''self.ability = cardTable.ability''' +position = "before" +payload = ''' +self.shop_voucher = cardTable.shop_voucher +self.shop_cry_bonusvoucher = cardTable.shop_cry_bonusvoucher +''' +match_indent = true + + + + +# get rid of this dumb hackfix in :redeem() +# also track vouchers redeemed +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''G.GAME.current_round.voucher = nil''' +position = "at" +payload = ''' +-- G.GAME.current_round.voucher = nil +if self.shop_cry_bonusvoucher then G.GAME.cry_bonusvouchersused[self.shop_cry_bonusvoucher] = true end +''' +match_indent = true + +# create the table +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = '''used_packs = {},''' +position = "after" +payload = ''' +cry_bonusvouchers = {}, +cry_voucher_stickers = {eternal = false, perishable = false, rental = false, pinned = false, banana = false}, +cry_voucher_edition = {}, +''' +match_indent = true + +# initialise the other helpful variables +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = '''ecto_minus = 1,''' +position = "after" +payload = ''' +cry_bonusvouchercount = 0, +cry_bonusvouchersused = {}, +voucher_edition_index = {}, +voucher_sticker_index = {eternal = {}, perishable = {}, rental = {}, pinned = {}, banana = {}}, -- might as well +''' +match_indent = true + +# populate the table with keys +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = '''G.GAME.current_round.voucher = get_next_voucher_key()''' +position = "after" +payload = ''' +G.GAME.current_round.cry_bonusvouchers = {} +G.GAME.cry_bonusvouchersused = {} -- i'm not sure why i'm putting these in two separate tables but it doesn't matter much +for i = 1, G.GAME.cry_bonusvouchercount do + G.GAME.current_round.cry_bonusvouchers[i] = get_next_voucher_key() +end +''' +match_indent = true + +# fire is hot +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = '''self.GAME.current_round.voucher = G.SETTINGS.tutorial_progress and G.SETTINGS.tutorial_progress.forced_voucher or get_next_voucher_key()''' +position = "after" +payload = ''' +for i = 1, self.GAME.cry_bonusvouchercount do + self.GAME.current_round.cry_bonusvouchers[i] = get_next_voucher_key() +end +''' +match_indent = true + +# add the vouchers to the shop. couldn't be more simple +# use a simple regex to snipe the correct position +[[patches]] +[patches.regex] +target = "game.lua" +pattern = '''end\n\s+G\.shop_vouchers\:emplace\(card\)\n\s+end''' +position = "after" +payload = ''' +for i = 1, #G.GAME.current_round.cry_bonusvouchers do + if not G.GAME.cry_bonusvouchersused[i] then + local card = Card(G.shop_vouchers.T.x + G.shop_vouchers.T.w/2, + G.shop_vouchers.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS[G.GAME.current_round.cry_bonusvouchers[i]],{bypass_discovery_center = true, bypass_discovery_ui = true}) + card.shop_cry_bonusvoucher = i + cry_misprintize(card) + if G.GAME.events.ev_cry_choco2 then + card.misprint_cost_fac = (card.misprint_cost_fac or 1) * 2 + card:set_cost() + end + if G.GAME.modifiers.cry_enable_flipped_in_shop and pseudorandom('cry_flip_vouch'..G.GAME.round_resets.ante) > 0.7 then + card.cry_flipped = true + end + create_shop_card_ui(card, 'Voucher', G.shop_vouchers) + card:start_materialize() + if G.GAME.current_round.cry_voucher_edition then -- eh why not + card:set_edition(G.GAME.current_round.cry_voucher_edition, true, true) + end + G.shop_vouchers.config.card_limit = G.shop_vouchers.config.card_limit + 1 -- does this actually matter/even get reset??? i'm confused but whatever + G.shop_vouchers:emplace(card) + end +end +''' +match_indent = true \ No newline at end of file diff --git a/Steamodded/assets/1x/mod_tags.png b/Steamodded/assets/1x/mod_tags.png deleted file mode 100644 index 95114c8..0000000 Binary files a/Steamodded/assets/1x/mod_tags.png and /dev/null differ diff --git a/Steamodded/assets/2x/mod_tags.png b/Steamodded/assets/2x/mod_tags.png deleted file mode 100644 index 02879b1..0000000 Binary files a/Steamodded/assets/2x/mod_tags.png and /dev/null differ diff --git a/Steamodded/libs/nativefs/nativefs.lua b/Steamodded/libs/nativefs/nativefs.lua deleted file mode 100644 index f8c2b18..0000000 --- a/Steamodded/libs/nativefs/nativefs.lua +++ /dev/null @@ -1,495 +0,0 @@ ---[[ -Copyright 2020 megagrump@pm.me - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]]-- - --- module("nativefs", package.seeall) - -local ffi, bit = require('ffi'), require('bit') -local C = ffi.C - -local fopen, getcwd, chdir, unlink, mkdir, rmdir -local BUFFERMODE, MODEMAP -local ByteArray = ffi.typeof('unsigned char[?]') -local function _ptr(p) return p ~= nil and p or nil end -- NULL pointer to nil - -local File = { - getBuffer = function(self) return self._bufferMode, self._bufferSize end, - getFilename = function(self) return self._name end, - getMode = function(self) return self._mode end, - isOpen = function(self) return self._mode ~= 'c' and self._handle ~= nil end, -} - -function File:open(mode) - if self._mode ~= 'c' then return false, "File " .. self._name .. " is already open" end - if not MODEMAP[mode] then return false, "Invalid open mode for " .. self._name .. ": " .. mode end - - local handle = _ptr(fopen(self._name, MODEMAP[mode])) - if not handle then return false, "Could not open " .. self._name .. " in mode " .. mode end - - self._handle, self._mode = ffi.gc(handle, C.fclose), mode - self:setBuffer(self._bufferMode, self._bufferSize) - - return true -end - -function File:close() - if self._mode == 'c' then return false, "File is not open" end - C.fclose(ffi.gc(self._handle, nil)) - self._handle, self._mode = nil, 'c' - return true -end - -function File:setBuffer(mode, size) - local bufferMode = BUFFERMODE[mode] - if not bufferMode then - return false, "Invalid buffer mode " .. mode .. " (expected 'none', 'full', or 'line')" - end - - if mode == 'none' then - size = math.max(0, size or 0) - else - size = math.max(2, size or 2) -- Windows requires buffer to be at least 2 bytes - end - - local success = self._mode == 'c' or C.setvbuf(self._handle, nil, bufferMode, size) == 0 - if not success then - self._bufferMode, self._bufferSize = 'none', 0 - return false, "Could not set buffer mode" - end - - self._bufferMode, self._bufferSize = mode, size - return true -end - -function File:getSize() - -- NOTE: The correct way to do this would be a stat() call, which requires a - -- lot more (system-specific) code. This is a shortcut that requires the file - -- to be readable. - local mustOpen = not self:isOpen() - if mustOpen and not self:open('r') then return 0 end - - local pos = mustOpen and 0 or self:tell() - C.fseek(self._handle, 0, 2) - local size = self:tell() - if mustOpen then - self:close() - else - self:seek(pos) - end - return size -end - -function File:read(containerOrBytes, bytes) - if self._mode ~= 'r' then return nil, 0 end - - local container = bytes ~= nil and containerOrBytes or 'string' - if container ~= 'string' and container ~= 'data' then - error("Invalid container type: " .. container) - end - - bytes = not bytes and containerOrBytes or 'all' - bytes = bytes == 'all' and self:getSize() - self:tell() or math.min(self:getSize() - self:tell(), bytes) - - if bytes <= 0 then - local data = container == 'string' and '' or love.data.newFileData('', self._name) - return data, 0 - end - - local data = love.data.newByteData(bytes) - local r = tonumber(C.fread(data:getFFIPointer(), 1, bytes, self._handle)) - - if container == 'data' then - -- FileData from ByteData requires LÖVE 11.4+ - local ok, fd = pcall(love.filesystem.newFileData, data, self._name) - if ok then return fd end - end - - local str = data:getString() - data:release() - data = container == 'data' and love.filesystem.newFileData(str, self._name) or str - return data, r -end - -local function lines(file, autoclose) - local BUFFERSIZE = 4096 - local buffer, bufferPos = ByteArray(BUFFERSIZE), 0 - local bytesRead = tonumber(C.fread(buffer, 1, BUFFERSIZE, file._handle)) - - local offset = file:tell() - return function() - file:seek(offset) - - local line = {} - while bytesRead > 0 do - for i = bufferPos, bytesRead - 1 do - if buffer[i] == 10 then -- end of line - bufferPos = i + 1 - return table.concat(line) - end - - if buffer[i] ~= 13 then -- ignore CR - table.insert(line, string.char(buffer[i])) - end - end - - bytesRead = tonumber(C.fread(buffer, 1, BUFFERSIZE, file._handle)) - offset, bufferPos = offset + bytesRead, 0 - end - - if not line[1] then - if autoclose then file:close() end - return nil - end - return table.concat(line) - end -end - -function File:lines() - if self._mode ~= 'r' then error("File is not opened for reading") end - return lines(self) -end - -function File:write(data, size) - if self._mode ~= 'w' and self._mode ~= 'a' then - return false, "File " .. self._name .. " not opened for writing" - end - - local toWrite, writeSize - if type(data) == 'string' then - writeSize = (size == nil or size == 'all') and #data or size - toWrite = data - else - writeSize = (size == nil or size == 'all') and data:getSize() or size - toWrite = data:getFFIPointer() - end - - if tonumber(C.fwrite(toWrite, 1, writeSize, self._handle)) ~= writeSize then - return false, "Could not write data" - end - return true -end - -function File:seek(pos) - return self._handle and C.fseek(self._handle, pos, 0) == 0 -end - -function File:tell() - if not self._handle then return nil, "Invalid position" end - return tonumber(C.ftell(self._handle)) -end - -function File:flush() - if self._mode ~= 'w' and self._mode ~= 'a' then - return nil, "File is not opened for writing" - end - return C.fflush(self._handle) == 0 -end - -function File:isEOF() - return not self:isOpen() or C.feof(self._handle) ~= 0 or self:tell() == self:getSize() -end - -function File:release() - if self._mode ~= 'c' then self:close() end - self._handle = nil -end - -function File:type() return 'File' end - -function File:typeOf(t) return t == 'File' end - -File.__index = File - ------------------------------------------------------------------------------ - -local nativefs = {} -local loveC = ffi.os == 'Windows' and ffi.load('love') or C - -function nativefs.newFile(name) - if type(name) ~= 'string' then - error("bad argument #1 to 'newFile' (string expected, got " .. type(name) .. ")") - end - return setmetatable({ - _name = name, - _mode = 'c', - _handle = nil, - _bufferSize = 0, - _bufferMode = 'none' - }, File) -end - -function nativefs.newFileData(filepath) - local f = nativefs.newFile(filepath) - local ok, err = f:open('r') - if not ok then return nil, err end - - local data, err = f:read('data', 'all') - f:close() - return data, err -end - -function nativefs.mount(archive, mountPoint, appendToPath) - return loveC.PHYSFS_mount(archive, mountPoint, appendToPath and 1 or 0) ~= 0 -end - -function nativefs.unmount(archive) - return loveC.PHYSFS_unmount(archive) ~= 0 -end - -function nativefs.read(containerOrName, nameOrSize, sizeOrNil) - local container, name, size - if sizeOrNil then - container, name, size = containerOrName, nameOrSize, sizeOrNil - elseif not nameOrSize then - container, name, size = 'string', containerOrName, 'all' - else - if type(nameOrSize) == 'number' or nameOrSize == 'all' then - container, name, size = 'string', containerOrName, nameOrSize - else - container, name, size = containerOrName, nameOrSize, 'all' - end - end - - local file = nativefs.newFile(name) - local ok, err = file:open('r') - if not ok then return nil, err end - - local data, size = file:read(container, size) - file:close() - return data, size -end - -local function writeFile(mode, name, data, size) - local file = nativefs.newFile(name) - local ok, err = file:open(mode) - if not ok then return nil, err end - - ok, err = file:write(data, size or 'all') - file:close() - return ok, err -end - -function nativefs.write(name, data, size) - return writeFile('w', name, data, size) -end - -function nativefs.append(name, data, size) - return writeFile('a', name, data, size) -end - -function nativefs.lines(name) - local f = nativefs.newFile(name) - local ok, err = f:open('r') - if not ok then return nil, err end - return lines(f, true) -end - -function nativefs.load(name) - local chunk, err = nativefs.read(name) - if not chunk then return nil, err end - return loadstring(chunk, name) -end - -function nativefs.getWorkingDirectory() - return getcwd() -end - -function nativefs.setWorkingDirectory(path) - if not chdir(path) then return false, "Could not set working directory" end - return true -end - -function nativefs.getDriveList() - if ffi.os ~= 'Windows' then return { '/' } end - local drives, bits = {}, C.GetLogicalDrives() - for i = 0, 25 do - if bit.band(bits, 2 ^ i) > 0 then - table.insert(drives, string.char(65 + i) .. ':/') - end - end - return drives -end - -function nativefs.createDirectory(path) - local current = path:sub(1, 1) == '/' and '/' or '' - for dir in path:gmatch('[^/\\]+') do - current = current .. dir .. '/' - local info = nativefs.getInfo(current, 'directory') - if not info and not mkdir(current) then return false, "Could not create directory " .. current end - end - return true -end - -function nativefs.remove(name) - local info = nativefs.getInfo(name) - if not info then return false, "Could not remove " .. name end - if info.type == 'directory' then - if not rmdir(name) then return false, "Could not remove directory " .. name end - return true - end - if not unlink(name) then return false, "Could not remove file " .. name end - return true -end - -local function withTempMount(dir, fn, ...) - local mountPoint = _ptr(loveC.PHYSFS_getMountPoint(dir)) - if mountPoint then return fn(ffi.string(mountPoint), ...) end - if not nativefs.mount(dir, '__nativefs__temp__') then return false, "Could not mount " .. dir end - local a, b = fn('__nativefs__temp__', ...) - nativefs.unmount(dir) - return a, b -end - -function nativefs.getDirectoryItems(dir) - local result, err = withTempMount(dir, love.filesystem.getDirectoryItems) - return result or {} -end - -local function getDirectoryItemsInfo(path, filtertype) - local items = {} - local files = love.filesystem.getDirectoryItems(path) - for i = 1, #files do - local filepath = string.format('%s/%s', path, files[i]) - local info = love.filesystem.getInfo(filepath, filtertype) - if info then - info.name = files[i] - table.insert(items, info) - end - end - return items -end - -function nativefs.getDirectoryItemsInfo(path, filtertype) - local result, err = withTempMount(path, getDirectoryItemsInfo, filtertype) - return result or {} -end - -local function getInfo(path, file, filtertype) - local filepath = string.format('%s/%s', path, file) - return love.filesystem.getInfo(filepath, filtertype) -end - -local function leaf(p) - p = p:gsub('\\', '/') - local last, a = p, 1 - while a do - a = p:find('/', a + 1) - if a then - last = p:sub(a + 1) - end - end - return last -end - -function nativefs.getInfo(path, filtertype) - local dir = path:match("(.*[\\/]).*$") or './' - local file = leaf(path) - local result, err = withTempMount(dir, getInfo, file, filtertype) - return result or nil -end - ------------------------------------------------------------------------------ - -MODEMAP = { r = 'rb', w = 'wb', a = 'ab' } -local MAX_PATH = 4096 - -ffi.cdef([[ - int PHYSFS_mount(const char* dir, const char* mountPoint, int appendToPath); - int PHYSFS_unmount(const char* dir); - const char* PHYSFS_getMountPoint(const char* dir); - - typedef struct FILE FILE; - - FILE* fopen(const char* path, const char* mode); - size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream); - size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream); - int fclose(FILE* stream); - int fflush(FILE* stream); - size_t fseek(FILE* stream, size_t offset, int whence); - size_t ftell(FILE* stream); - int setvbuf(FILE* stream, char* buffer, int mode, size_t size); - int feof(FILE* stream); -]]) - -if ffi.os == 'Windows' then - ffi.cdef([[ - int MultiByteToWideChar(unsigned int cp, uint32_t flags, const char* mb, int cmb, const wchar_t* wc, int cwc); - int WideCharToMultiByte(unsigned int cp, uint32_t flags, const wchar_t* wc, int cwc, const char* mb, - int cmb, const char* def, int* used); - int GetLogicalDrives(void); - int CreateDirectoryW(const wchar_t* path, void*); - int _wchdir(const wchar_t* path); - wchar_t* _wgetcwd(wchar_t* buffer, int maxlen); - FILE* _wfopen(const wchar_t* path, const wchar_t* mode); - int _wunlink(const wchar_t* path); - int _wrmdir(const wchar_t* path); - ]]) - - BUFFERMODE = { full = 0, line = 64, none = 4 } - - local function towidestring(str) - local size = C.MultiByteToWideChar(65001, 0, str, #str, nil, 0) - local buf = ffi.new('wchar_t[?]', size + 1) - C.MultiByteToWideChar(65001, 0, str, #str, buf, size) - return buf - end - - local function toutf8string(wstr) - local size = C.WideCharToMultiByte(65001, 0, wstr, -1, nil, 0, nil, nil) - local buf = ffi.new('char[?]', size + 1) - C.WideCharToMultiByte(65001, 0, wstr, -1, buf, size, nil, nil) - return ffi.string(buf) - end - - local nameBuffer = ffi.new('wchar_t[?]', MAX_PATH + 1) - - fopen = function(path, mode) return C._wfopen(towidestring(path), towidestring(mode)) end - getcwd = function() return toutf8string(C._wgetcwd(nameBuffer, MAX_PATH)) end - chdir = function(path) return C._wchdir(towidestring(path)) == 0 end - unlink = function(path) return C._wunlink(towidestring(path)) == 0 end - mkdir = function(path) return C.CreateDirectoryW(towidestring(path), nil) ~= 0 end - rmdir = function(path) return C._wrmdir(towidestring(path)) == 0 end -else - BUFFERMODE = { full = 0, line = 1, none = 2 } - - ffi.cdef([[ - char* getcwd(char *buffer, int maxlen); - int chdir(const char* path); - int unlink(const char* path); - int mkdir(const char* path, int mode); - int rmdir(const char* path); - ]]) - - local nameBuffer = ByteArray(MAX_PATH) - - fopen = C.fopen - unlink = function(path) return ffi.C.unlink(path) == 0 end - chdir = function(path) return ffi.C.chdir(path) == 0 end - mkdir = function(path) return ffi.C.mkdir(path, 0x1ed) == 0 end - rmdir = function(path) return ffi.C.rmdir(path) == 0 end - - getcwd = function() - local cwd = _ptr(C.getcwd(nameBuffer, MAX_PATH)) - return cwd and ffi.string(cwd) or nil - end -end - -return nativefs diff --git a/Steamodded/lovely/keybind.toml b/Steamodded/lovely/keybind.toml deleted file mode 100644 index 6001bb6..0000000 --- a/Steamodded/lovely/keybind.toml +++ /dev/null @@ -1,47 +0,0 @@ -[manifest] -version = "1.0.0" -dump_lua = true -priority = 0 - -# Check all registered keybinds -# inserted inside Controller:key_press_update - -[[patches]] -[patches.pattern] -target = 'engine/controller.lua' -pattern = "if not _RELEASE_MODE then" -position = "before" -payload = ''' -for _, keybind in pairs(SMODS.Keybinds) do - if keybind.action and keybind.key_pressed == key then - local execute = true - for _, other_key in pairs(keybind.held_keys) do - if not self.held_keys[other_key] then - execute = false - break - end - end - if execute then - keybind.action(self) - end - end -end -''' -match_indent = true -overwrite = false - -[[patches]] -[patches.regex] -target = 'engine/controller.lua' -pattern = 'if key == "r"' -position = 'at' -line_prepend = '$indent' -payload = ''' -if key == 'm' then - if self.held_key_times[key] > 1.1 then - SMODS.save_all_config() - SMODS.restart_game() - else - self.held_key_times[key] = self.held_key_times[key] + dt - end -elseif key == "r"''' \ No newline at end of file diff --git a/Steamodded/lovely/ui.toml b/Steamodded/lovely/ui.toml deleted file mode 100644 index 8c0c527..0000000 --- a/Steamodded/lovely/ui.toml +++ /dev/null @@ -1,359 +0,0 @@ -[manifest] -version = "1.0.0" -dump_lua = true -priority = 0 - -### Addition Tab - -## Jokers tab -# create_UIBox_your_collection_jokers() -[[patches]] -[patches.pattern] -target = "functions/UI_definitions.lua" -pattern = '''local joker_options = {}''' -position = "before" -payload = ''' -local joker_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Joker)''' -match_indent = true - -# create_UIBox_your_collection_jokers() -[[patches]] -[patches.regex] -target = 'functions/UI_definitions.lua' -pattern = '''(?[\t ]*)for i = 1, math\.ceil\(#G\.P_CENTER_POOLS\.Joker\/\(5\*#G\.your_collection\)\) do\n[\s\S]{4}table\.insert\(joker_options, localize\('k_page'\)..' '..tostring\(i\)..'\/'..tostring\(math\.ceil\(#G\.P_CENTER_POOLS\.Joker\/\(5\*#G\.your_collection\)\)\)\)''' -position = 'at' -payload = ''' -for i = 1, math.ceil(#joker_pool/(5*#G.your_collection)) do - table.insert(joker_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#joker_pool/(5*#G.your_collection))))''' -line_prepend = '$indent' - -# create_UIBox_your_collection_jokers() -[[patches]] -[patches.pattern] -target = "functions/UI_definitions.lua" -pattern = '''local center = G.P_CENTER_POOLS["Joker"][i+(j-1)*5]''' -position = "at" -payload = ''' -local center = joker_pool[i+(j-1)*5] -if not center then break end''' -match_indent = true - -# create_UIBox_your_collection_jokers() -[[patches]] -[patches.pattern] -target = "functions/UI_definitions.lua" -pattern = '''local t = create_UIBox_generic_options({ back_func = 'your_collection', contents = {''' -position = "at" -payload = '''local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = {''' -match_indent = true - -# G.FUNCS.your_collections_joker_page -[[patches]] -[patches.pattern] -target = "functions/button_callbacks.lua" -pattern = '''for i = 1, 5 do''' -position = "before" -payload = ''' -local joker_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Joker) -''' -match_indent = true - -# G.FUNCS.your_collection_joker_page -[[patches]] -[patches.pattern] -target = "functions/button_callbacks.lua" -pattern = '''local center = G.P_CENTER_POOLS["Joker"][i+(j-1)*5 + (5*#G.your_collection*(args.cycle_config.current_option - 1))]''' -position = "at" -payload = '''local center = joker_pool[i+(j-1)*5 + (5*#G.your_collection*(args.cycle_config.current_option - 1))]''' -match_indent = true - -## Decks tab -# create_UIBox_your_collection_decks() -[[patches]] -[patches.pattern] -target = "functions/UI_definitions.lua" -pattern = '''G.GAME.viewed_back = Back(G.P_CENTERS.b_red)''' -position = "at" -payload = ''' -local deck_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Back) -G.GAME.viewed_back = Back(G.ACTIVE_MOD_UI and deck_pool[1] or G.P_CENTERS.b_red)''' -match_indent = true - -# create_UIBox_your_collection_decks() -[[patches]] -[patches.regex] -target = 'functions/UI_definitions.lua' -pattern = '''(?[\t ]*)for k, v in ipairs\(G\.P_CENTER_POOLS\.Back\) do\n[\s\S]{4}ordered_names\[#ordered_names\+1\] = v\.name\n[\s\S]{2}end''' -position = 'at' -payload = ''' -for k, v in ipairs(deck_pool) do - ordered_names[#ordered_names+1] = v.key -end''' -line_prepend = '$indent' - -## Note: This covers Decks, Boosters, and Tags -# create_UIBox_your_collection_decks() and create_UIBox_your_collection_boosters() and create_UIBox_your_collection_tags() -[[patches]] -[patches.pattern] -target = "functions/UI_definitions.lua" -pattern = '''local t = create_UIBox_generic_options({ back_func = 'your_collection', contents = {''' -position = "at" -payload = '''local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = {''' -match_indent = true - -# G.FUNCS.your_collection_deck_page -[[patches]] -[patches.pattern] -target = "functions/button_callbacks.lua" -pattern = '''G.GAME.viewed_back:change_to(G.P_CENTER_POOLS.Back[args.to_key])''' -position = "at" -payload = ''' -local deck_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Back) -G.GAME.viewed_back:change_to(deck_pool[args.to_key])''' -match_indent = true - -## Boosters Page -# create_UIBox_your_collection_boosters() -[[patches]] -[patches.pattern] -target = "functions/UI_definitions.lua" -pattern = '''local booster_options = {}''' -position = "before" -payload = ''' -local booster_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Booster)''' -match_indent = true - -# create_UIBox_your_collection_boosters() -[[patches]] -[patches.regex] -target = 'functions/UI_definitions.lua' -pattern = '''(?[\t ]*)for i = 1, math\.ceil\(#G\.P_CENTER_POOLS\.Booster\/8\) do\n[\s\S]{4}table\.insert\(booster_options, localize\('k_page'\)..' '..tostring\(i\)..'\/'..tostring\(math\.ceil\(#G\.P_CENTER_POOLS\.Booster\/8\)\)\)''' -position = 'at' -payload = ''' -for i = 1, math.ceil(#booster_pool/8) do - table.insert(booster_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#booster_pool/8)))''' -line_prepend = '$indent' - -# create_UIBox_your_collection_boosters() -[[patches]] -[patches.pattern] -target = 'functions/UI_definitions.lua' -pattern = '''local center = G.P_CENTER_POOLS["Booster"][i+(j-1)*4]''' -position = 'at' -payload = ''' -local center = booster_pool[i+(j-1)*4] -if not center then break end''' -match_indent = true - -# G.FUNCS.your_collection_booster_page -[[patches]] -[patches.pattern] -target = "functions/button_callbacks.lua" -pattern = '''G.FUNCS.your_collection_booster_page = function(args)''' -position = "after" -payload = ''' -local booster_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Booster)''' -match_indent = true - -# G.FUNCS.your_collection_booster_page -[[patches]] -[patches.pattern] -target = "functions/button_callbacks.lua" -pattern = '''local center = G.P_CENTER_POOLS["Booster"][i+(j-1)*4 + (8*(args.cycle_config.current_option - 1))]''' -position = "at" -payload = '''local center = booster_pool[i+(j-1)*4 + (8*(args.cycle_config.current_option - 1))]''' -match_indent = true - -## Voucher Tabs -# create_UIBox_your_collection_vouchers() -[[patches]] -[patches.pattern] -target = "functions/UI_definitions.lua" -pattern = '''local voucher_options = {}''' -position = "before" -payload = ''' -local voucher_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Voucher)''' -match_indent = true - -# create_UIBox_your_collection_vouchers() -[[patches]] -[patches.regex] -target = 'functions/UI_definitions.lua' -pattern = '''(?[\t ]*)for i = 1, math\.ceil\(#G\.P_CENTER_POOLS\.Voucher\/\(4\*#G\.your_collection\)\) do\n[\s\S]{4}table\.insert\(voucher_options, localize\('k_page'\)..' '..tostring\(i\)..'\/'..tostring\(math\.ceil\(#G\.P_CENTER_POOLS\.Voucher\/\(4\*#G\.your_collection\)\)\)\)''' -position = 'at' -payload = ''' - for i = 1, math.ceil(#voucher_pool/(4*#G.your_collection)) do - table.insert(voucher_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#voucher_pool/(4*#G.your_collection))))''' -line_prepend = '$indent' - -# create_UIBox_your_collection_boosters() -[[patches]] -[patches.pattern] -target = 'functions/UI_definitions.lua' -pattern = '''local center = G.P_CENTER_POOLS["Voucher"][i+(j-1)*4]''' -position = 'at' -payload = ''' -local center = voucher_pool[i+(j-1)*4] -if not center then break end''' -match_indent = true - -## Note: This covers Blinds and Vouchers -# create_UIBox_your_collection_vouchers() and create_UIBox_your_collection_blinds() -[[patches]] -[patches.pattern] -target = "functions/UI_definitions.lua" -pattern = '''local t = create_UIBox_generic_options({ back_func = exit or 'your_collection', contents = {''' -position = "at" -payload = '''local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or exit or 'your_collection', contents = {''' -match_indent = true - -# G.FUNCS.your_collection_voucher_page -[[patches]] -[patches.pattern] -target = "functions/button_callbacks.lua" -pattern = '''G.FUNCS.your_collection_voucher_page = function(args)''' -position = "after" -payload = ''' -local voucher_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Voucher)''' -match_indent = true - -# G.FUNCS.your_collection_voucher_page -[[patches]] -[patches.pattern] -target = "functions/button_callbacks.lua" -pattern = '''local center = G.P_CENTER_POOLS["Voucher"][i+(j-1)*4 + (8*(args.cycle_config.current_option - 1))]''' -position = "at" -payload = '''local center = voucher_pool[i+(j-1)*4 + (8*(args.cycle_config.current_option - 1))]''' -match_indent = true - -# create_UIBox_your_collection() -[[patches]] -[patches.regex] -target = 'functions/UI_definitions.lua' -pattern = '''(?[\t ]*)UIBox_button\(\{button = 'your_collection_blinds', label = \{localize\('b_blinds'\)\}, count = G\.DISCOVER_TALLIES\.blinds, minw = 5, minh = 2.0, id = 'your_collection_blinds', focus_args = \{snap_to = true\}\}\),''' -position = 'after' -payload = '''UIBox_button({button = 'your_collection_other_gameobjects', label = {localize('k_other')}, minw = 5, id = 'your_collection_other_gameobjects', focus_args = {snap_to = true}}),''' - -# Fix UIElement.config.chosen being overriden if choice=true is set -# UIElement:click() -[[patches]] -[patches.pattern] -target = "engine/ui.lua" -match_indent = true -position = "after" -pattern = "if self.config.choice then" -payload = " local chosen_temp = self.config.chosen" - -[[patches]] -[patches.pattern] -target = "engine/ui.lua" -match_indent = true -position = "at" -pattern = "self.config.chosen = true" -payload = "self.config.chosen = chosen_temp or true" - -# Escape from mod menu saves config -# Needs to be before all checks -[[patches]] -[patches.pattern] -target = 'engine/controller.lua' -pattern = "function Controller:key_press_update(key, dt)" -position = "after" -payload = ''' - if key == "escape" and G.ACTIVE_MOD_UI then - G.FUNCS.exit_mods() - end -''' -match_indent = true - -[[patches]] -[patches.regex] -target = 'functions/UI_definitions.lua' -position = 'before' -line_prepend = '$indent' -pattern = ''' -(?[\t ]*)return \{n=G\.UIT\.ROOT, config = \{align = 'cm', colour = G\.C\.CLEAR\}, nodes=\{ -[\t ]*\{n=G\.UIT\.C,''' -payload = ''' -local cols -if #info_boxes <= 3 then - cols = 1 -elseif #info_boxes <= 10 then - cols = 2 -elseif #info_boxes <= 24 then - cols = 3 -else - cols = 4 -end -local nodes_per_col = math.ceil(#info_boxes/cols) -local info_cols = {} -for i = 0, cols-1 do - local col = {} - for j = 1, nodes_per_col do - local info_box = info_boxes[i*nodes_per_col+j] - if info_box then - table.insert(col, info_box) - else break end - end - table.insert(info_cols, {n=G.UIT.C, config = {align="cm"}, nodes = col}) -end -info_boxes = {{n=G.UIT.R, config = {align="cm", padding = 0.05, card_pos = card.T.x }, nodes = info_cols}} -''' - -[[patches]] -[patches.pattern] -target = 'functions/button_callbacks.lua' -match_indent = true -position = 'at' -pattern = "config = {offset = {x=-0.03,y=0}, align = 'cl', parent = e}" -payload = """config = (not e.config.ref_table or not e.config.ref_table[1].config.card_pos or e.config.ref_table[1].config.card_pos > G.ROOM.T.w*0.4) and - {offset = {x=-0.03,y=0}, align = 'cl', parent = e} or - {offset = {x=0.03,y=0}, align = 'cr', parent = e}""" - -[[patches]] -[patches.pattern] -target = 'tag.lua' -match_indent = true -position = 'at' -pattern = "_self.config.h_popup_config ={align = 'cl', offset = {x=-0.1,y=0},parent = _self}" -payload = """_self.config.h_popup_config = (_self.T.x > G.ROOM.T.w*0.4) and - {align = 'cl', offset = {x=-0.1,y=0},parent = _self} or - {align = 'cr', offset = {x=0.1,y=0},parent = _self}""" - -# desc_from_rows -[[patches]] -[patches.regex] -target = 'functions/UI_definitions.lua' -position = 'at' -pattern = 'colour = empty and G\.C\.CLEAR or G\.C\.UI\.BACKGROUND_WHITE' -payload = 'colour = desc_nodes.background_colour or empty and G.C.CLEAR or G.C.UI.BACKGROUND_WHITE' - -# info_tip_from_rows -[[patches]] -[patches.regex] -target = 'functions/UI_definitions.lua' -position = 'at' -pattern = 'padding = 0\.05, colour = G\.C\.WHITE\}' -payload = 'padding = 0.05, colour = desc_nodes.background_colour or G.C.WHITE}' - -# localize -[[patches]] -[patches.regex] -target = 'functions/misc_functions.lua' -position = 'after' -pattern = '\(part\.control\.C and loc_colour\(part\.control\.C\)\)' -payload = ' or args.text_colour' - -[[patches]] -[patches.regex] -target = 'functions/misc_functions.lua' -position = 'at' -pattern = 'loc_colour\(part\.control\.C or nil, args\.default_col\)' -payload = 'not part.control.C and args.text_colour or loc_colour(part.control.C or nil, args.default_col)' - -[[patches]] -[patches.regex] -target = 'functions/misc_functions.lua' -position = 'after' -pattern = 'part\.control\.s and tonumber\(part\.control\.s\)' -payload = ' or args.scale ' \ No newline at end of file diff --git a/Steamodded/src/index.lua b/Steamodded/src/index.lua deleted file mode 100644 index c4a82c3..0000000 --- a/Steamodded/src/index.lua +++ /dev/null @@ -1,32 +0,0 @@ -SMODS.fetch_index = function() - SMODS.index = {} - local https = require"https" - local status, contents = https.request("https://github.com/Aurelius7309/Steamodded.index/archive/refs/heads/main.zip") - if status ~= 200 then return false end - love.filesystem.write('index.zip', contents) - if not love.filesystem.mount('index.zip', 'index') then return false end - local path = 'index/Steamodded.index-main/mods/' - for _, filename in ipairs(love.filesystem.getDirectoryItems(path)) do - local key, ext = filename:sub(1, -6), filename:sub(-5) - if ext:lower() == '.json' then - local success, data = pcall(function() return JSON.decode(love.filesystem.read(path..filename)) end) - if success and data.id == key then SMODS.index[key] = data end - end - end - love.filesystem.unmount('index.zip') - return true -end - -SMODS.update_mod_files = function(id) - local mod = SMODS.Mods[id] - if not mod then return false end - local use_git = os.execute('git -v') == 0 - if false and use_git and os.execute(('cd %s & git pull'):format(mod.path)) == 0 then - return true - end - local https = require"https" - local url = mod.github or (SMODS.index[id] or {}).github - local status, contents = https.request(url) -- TODO account for branches - local hash = contents:match('"currentOid":"([^"]*)"') - sendWarnMessage(hash, "Index") -end diff --git a/Steamodded/src/ui.lua b/Steamodded/src/ui.lua deleted file mode 100644 index 8fc6d82..0000000 --- a/Steamodded/src/ui.lua +++ /dev/null @@ -1,1797 +0,0 @@ -SMODS.GUI = {} -SMODS.GUI.DynamicUIManager = {} - -function STR_UNPACK(str) - local chunk, err = loadstring(str) - if chunk then - setfenv(chunk, {}) -- Use an empty environment to prevent access to potentially harmful functions - local success, result = pcall(chunk) - if success then - return result - else - print("Error unpacking string: " .. result) - return nil - end - else - print("Error loading string: " .. err) - return nil - end -end - - -local gameMainMenuRef = Game.main_menu -function Game:main_menu(change_context) - gameMainMenuRef(self, change_context) - UIBox({ - definition = { - n = G.UIT.ROOT, - config = { - align = "cm", - colour = G.C.UI.TRANSPARENT_DARK - }, - nodes = { - { - n = G.UIT.T, - config = { - scale = 0.3, - text = MODDED_VERSION, - colour = G.C.UI.TEXT_LIGHT - } - } - } - }, - config = { - align = "tri", - bond = "Weak", - offset = { - x = 0, - y = 0.3 - }, - major = G.ROOM_ATTACH - } - }) -end - -local gameUpdateRef = Game.update -function Game:update(dt) - if G.STATE ~= G.STATES.SPLASH and G.MAIN_MENU_UI then - local node = G.MAIN_MENU_UI:get_UIE_by_ID("main_menu_play") - - if node and not node.children.alert then - node.children.alert = UIBox({ - definition = create_UIBox_card_alert({ - text = localize('b_modded_version'), - no_bg = true, - scale = 0.4, - text_rot = -0.2 - }), - config = { - align = "tli", - offset = { - x = -0.1, - y = 0 - }, - major = node, - parent = node - } - }) - node.children.alert.states.collide.can = false - end - end - gameUpdateRef(self, dt) -end - -local function wrapText(text, maxChars) - local wrappedText = "" - local currentLineLength = 0 - - for word in text:gmatch("%S+") do - if currentLineLength + #word <= maxChars then - wrappedText = wrappedText .. word .. ' ' - currentLineLength = currentLineLength + #word + 1 - else - wrappedText = wrappedText .. '\n' .. word .. ' ' - currentLineLength = #word + 1 - end - end - - return wrappedText -end - --- Helper function to concatenate author names -local function concatAuthors(authors) - if type(authors) == "table" then - return table.concat(authors, ", ") - end - return authors or localize('b_unknown') -end - - -SMODS.LAST_SELECTED_MOD_TAB = "mod_desc" -function create_UIBox_mods(args) - local mod = G.ACTIVE_MOD_UI - if not SMODS.LAST_SELECTED_MOD_TAB then SMODS.LAST_SELECTED_MOD_TAB = "mod_desc" end - - local mod_tabs = {} - table.insert(mod_tabs, buildModDescTab(mod)) - local additions_tab = buildAdditionsTab(mod) - if additions_tab then table.insert(mod_tabs, additions_tab) end - local credits_func = mod.credits_tab - if credits_func and type(credits_func) == 'function' then - table.insert(mod_tabs, { - label = localize("b_credits"), - chosen = SMODS.LAST_SELECTED_MOD_TAB == "credits" or false, - tab_definition_function = function(...) - SMODS.LAST_SELECTED_MOD_TAB = "credits" - return credits_func(...) - end - }) - end - local config_func = mod.config_tab - if config_func and type(config_func) == 'function' then - table.insert(mod_tabs, { - label = localize("b_config"), - chosen = SMODS.LAST_SELECTED_MOD_TAB == "config" or false, - tab_definition_function = function(...) - SMODS.LAST_SELECTED_MOD_TAB = "config" - return config_func(...) - end - }) - end - - local mod_has_achievement - for _, v in pairs(SMODS.Achievements) do - if v.mod.id == mod.id then mod_has_achievement = true end - end - if mod_has_achievement then table.insert(mod_tabs, - { - label = localize("b_achievements"), - chosen = SMODS.LAST_SELECTED_MOD_TAB == "achievements" or false, - tab_definition_function = function() - SMODS.LAST_SELECTED_MOD_TAB = "achievements" - return buildAchievementsTab(mod) - end - }) - end - - local custom_ui_func = mod.extra_tabs - if custom_ui_func and type(custom_ui_func) == 'function' then - local custom_tabs = custom_ui_func() - if next(custom_tabs) and #custom_tabs == 0 then custom_tabs = { custom_tabs } end - for i, v in ipairs(custom_tabs) do - local id = mod.id..'_'..i - v.chosen = (SMODS.LAST_SELECTED_MOD_TAB == id) or false - v.label = v.label or '' - local def = v.tab_definition_function - assert(def, ('Custom defined mod tab with label "%s" from mod with id %s is missing definition function'):format(v.label, mod.id)) - v.tab_definition_function = function(...) - SMODS.LAST_SELECTED_MOD_TAB = id - return def(...) - end - table.insert(mod_tabs, v) - end - end - - return (create_UIBox_generic_options({ - back_func = "mods_button", - contents = { - { - n = G.UIT.R, - config = { - padding = 0, - align = "tm" - }, - nodes = { - create_tabs({ - snap_to_nav = true, - colour = G.C.BOOSTER, - tabs = mod_tabs - }) - } - } - } - })) -end - -function buildModDescTab(mod) - G.E_MANAGER:add_event(Event({ - blockable = false, - func = function() - G.REFRESH_ALERTS = nil - return true - end - })) - local label = mod.name - if (G.localization.descriptions.Mod or {})[mod.id] then - label = localize { type = 'name_text', set = 'Mod', key = mod.id } - end - return { - label = label, - chosen = SMODS.LAST_SELECTED_MOD_TAB == "mod_desc" or false, - tab_definition_function = function() - local modNodes = {} - local scale = 0.75 -- Scale factor for text - local maxCharsPerLine = 50 - - local wrappedDescription = wrapText(mod.description or '', maxCharsPerLine) - - local authors = localize('b_author' .. (#mod.author > 1 and 's' or '')) .. ': ' .. concatAuthors(mod.author) - - -- Authors names in blue - table.insert(modNodes, { - n = G.UIT.R, - config = { - padding = 0, - align = "cm", - r = 0.1, - emboss = 0.1, - outline = 1, - padding = 0.07 - }, - nodes = { - { - n = G.UIT.T, - config = { - text = authors, - shadow = true, - scale = scale * 0.65, - colour = G.C.BLUE, - } - } - } - }) - - -- Mod description - if (G.localization.descriptions.Mod or {})[mod.id] then - modNodes[#modNodes + 1] = {} - local loc_vars = mod.description_loc_vars and mod:description_loc_vars() or {} - localize { type = 'descriptions', key = loc_vars.key or mod.id, set = 'Mod', nodes = modNodes[#modNodes], vars = loc_vars.vars, scale = loc_vars.scale, text_colour = loc_vars.text_colour } - modNodes[#modNodes] = desc_from_rows(modNodes[#modNodes]) - modNodes[#modNodes].config.colour = loc_vars.background_colour or modNodes[#modNodes].config.colour - else - table.insert(modNodes, { - n = G.UIT.R, - config = { - padding = 0.2, - align = "cm" - }, - nodes = { - { - n = G.UIT.T, - config = { - text = wrappedDescription, - shadow = true, - scale = scale * 0.5, - colour = G.C.UI.TEXT_LIGHT - } - } - } - }) - end - - local custom_ui_func = mod.custom_ui - if custom_ui_func and type(custom_ui_func) == 'function' then - custom_ui_func(modNodes) - end - - return { - n = G.UIT.ROOT, - config = { - emboss = 0.05, - minh = 6, - r = 0.1, - minw = 6, - align = "tm", - padding = 0.2, - colour = G.C.BLACK - }, - nodes = modNodes - } - end - } -end - -function buildAdditionsTab(mod) - local consumable_nodes = {} - for _, key in ipairs(SMODS.ConsumableType.ctype_buffer) do - local id = 'your_collection_'..key:lower()..'s' - local tally = modsCollectionTally(G.P_CENTER_POOLS[key]) - if tally.of > 0 then - consumable_nodes[#consumable_nodes+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = tally, minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) - end - end - if #consumable_nodes > 3 then - consumable_nodes = { UIBox_button({ button = 'your_collection_consumables', label = {localize('b_stat_consumables'), localize{ type = 'variable', key = 'c_types', vars = {#consumable_nodes} } }, count = modsCollectionTally(G.P_CENTER_POOLS.Consumeables), minw = 4, minh = 4, id = 'your_collection_consumables', colour = G.C.FILTER }) } - end - - local leftside_nodes = {} - for _, v in ipairs { { k = 'Joker', minh = 1.7, scale = 0.6 }, { k = 'Back', b = 'decks' }, { k = 'Voucher' } } do - v.b = v.b or v.k:lower()..'s' - v.l = v.l or v.b - local tally = modsCollectionTally(G.P_CENTER_POOLS[v.k]) - if tally.of > 0 then - leftside_nodes[#leftside_nodes+1] = UIBox_button({button = 'your_collection_'..v.b, label = {localize('b_'..v.l)}, count = modsCollectionTally(G.P_CENTER_POOLS[v.k]), minw = 5, minh = v.minh, scale = v.scale, id = 'your_collection_'..v.b}) - end - end - if #consumable_nodes > 0 then - leftside_nodes[#leftside_nodes + 1] = { - n = G.UIT.R, - config = { align = "cm", padding = 0.1, r = 0.2, colour = G.C.BLACK }, - nodes = { - { - n = G.UIT.C, - config = { align = "cm", maxh = 2.9 }, - nodes = { - { n = G.UIT.T, config = { text = localize('k_cap_consumables'), scale = 0.45, colour = G.C.L_BLACK, vert = true, maxh = 2.2 } }, - } - }, - { n = G.UIT.C, config = { align = "cm", padding = 0.15 }, nodes = consumable_nodes } - } - } - end - - local rightside_nodes = {} - for _, v in ipairs { { k = 'Enhanced', b = 'enhancements', l = 'enhanced_cards'}, { k = 'Seal' }, { k = 'Edition' }, { k = 'Booster', l = 'booster_packs' }, { b = 'tags', p = G.P_TAGS }, { b = 'blinds', p = G.P_BLINDS, minh = 2.0 }, } do - v.b = v.b or v.k:lower()..'s' - v.l = v.l or v.b - v.p = v.p or G.P_CENTER_POOLS[v.k] - local tally = modsCollectionTally(v.p) - if tally.of > 0 then - rightside_nodes[#rightside_nodes+1] = UIBox_button({button = 'your_collection_'..v.b, label = {localize('b_'..v.l)}, count = modsCollectionTally(v.p), minw = 5, minh = v.minh, id = 'your_collection_'..v.b}) - end - end - local has_other_gameobjects = create_UIBox_Other_GameObjects() - if has_other_gameobjects then - rightside_nodes[#rightside_nodes+1] = UIBox_button({button = 'your_collection_other_gameobjects', label = {localize('k_other')}, minw = 5, id = 'your_collection_other_gameobjects', focus_args = {snap_to = true}}) - end - - local t = {n=G.UIT.R, config={align = "cm",padding = 0.2, minw = 7}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes = leftside_nodes }, - {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes = rightside_nodes } - }} - - local modNodes = {} - table.insert(modNodes, t) - return (#leftside_nodes > 0 or #rightside_nodes > 0 ) and { - label = localize("b_additions"), - chosen = SMODS.LAST_SELECTED_MOD_TAB == "additions" or false, - tab_definition_function = function() - SMODS.LAST_SELECTED_MOD_TAB = "additions" - return { - n = G.UIT.ROOT, - config = { - emboss = 0.05, - minh = 6, - r = 0.1, - minw = 6, - align = "tm", - padding = 0.2, - colour = G.C.BLACK - }, - nodes = modNodes - } - end - } or nil -end - --- Disable alerts when in Additions tab -local set_alerts_ref = set_alerts -function set_alerts() - if G.ACTIVE_MOD_UI then - else - set_alerts_ref() - end -end - -G.FUNCS.your_collection_other_gameobjects = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_Other_GameObjects(), - } -end - -function create_UIBox_Other_GameObjects() - local custom_gameobject_tabs = {{}} - local curr_height = 0 - local curr_col = 1 - local other_collections_tabs = {} - local smods_uibox_buttons = { - { - count = G.ACTIVE_MOD_UI and modsCollectionTally(SMODS.Stickers), --Returns nil outside of G.ACTIVE_MOD_UI but we don't use it anyways - button = UIBox_button({button = 'your_collection_stickers', label = {localize('b_stickers')}, count = G.ACTIVE_MOD_UI and modsCollectionTally(SMODS.Stickers), minw = 5, id = 'your_collection_stickers'}) - } - } - - if G.ACTIVE_MOD_UI then - for _, tab in pairs(smods_uibox_buttons) do - if tab.count.of > 0 then other_collections_tabs[#other_collections_tabs+1] = tab.button end - end - if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.custom_collection_tabs then - object_tabs = G.ACTIVE_MOD_UI.custom_collection_tabs() - for _, tab in ipairs(object_tabs) do - other_collections_tabs[#other_collections_tabs+1] = tab - end - end - else - for _, tab in pairs(smods_uibox_buttons) do - other_collections_tabs[#other_collections_tabs+1] = tab.button - end - for _, mod in pairs(SMODS.Mods) do - if mod.custom_collection_tabs and type(mod.custom_collection_tabs) == "function" then - object_tabs = mod.custom_collection_tabs() - for _, tab in ipairs(object_tabs) do - other_collections_tabs[#other_collections_tabs+1] = tab - end - end - end - end - - local custom_gameobject_rows = {} - if #other_collections_tabs > 0 then - for _, gameobject_tabs in ipairs(other_collections_tabs) do - table.insert(custom_gameobject_tabs[curr_col], gameobject_tabs) - curr_height = curr_height + gameobject_tabs.nodes[1].config.minh - if curr_height > 6 then --TODO: Verify that this is the ideal number - curr_height = 0 - curr_col = curr_col + 1 - custom_gameobject_tabs[curr_col] = {} - end - end - for _, v in ipairs(custom_gameobject_tabs) do - table.insert(custom_gameobject_rows, {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes = v}) - end - - local t = {n=G.UIT.C, config={align = "cm", r = 0.1, colour = G.C.BLACK, padding = 0.1, emboss = 0.05, minw = 7}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.15}, nodes = custom_gameobject_rows} - }} - - return create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = {t}}) - else - return nil - end -end - -G.FUNCS.your_collection_consumables = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_consumables(), - } -end - -function create_UIBox_your_collection_consumables() - local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = { - { n = G.UIT.C, config = { align = 'cm', minw = 11.5, minh = 6 }, nodes = { - { n = G.UIT.O, config = { id = 'consumable_collection', object = Moveable() },} - }}, - }}) - G.E_MANAGER:add_event(Event({func = function() - G.FUNCS.your_collection_consumables_page({ cycle_config = { current_option = 1 }}) - return true - end})) - return t -end - -G.FUNCS.your_collection_consumables_page = function(args) - if not args or not args.cycle_config then return end - if G.OVERLAY_MENU then - local uie = G.OVERLAY_MENU:get_UIE_by_ID('consumable_collection') - if uie then - if uie.config.object then - uie.config.object:remove() - end - uie.config.object = UIBox{ - definition = G.UIDEF.consumable_collection_page(args.cycle_config.current_option), - config = { align = 'cm', parent = uie} - } - end - end -end - -G.UIDEF.consumable_collection_page = function(page) - local nodes_per_page = 10 - local page_offset = nodes_per_page * ((page or 1) - 1) - local type_buf = {} - if G.ACTIVE_MOD_UI then - for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do - if modsCollectionTally(G.P_CENTER_POOLS[v]).of > 0 then type_buf[#type_buf + 1] = v end - end - else - type_buf = SMODS.ConsumableType.ctype_buffer - end - local center_options = {} - for i = 1, math.ceil(#type_buf / nodes_per_page) do - table.insert(center_options, - localize('k_page') .. - ' ' .. tostring(i) .. '/' .. tostring(math.ceil(#type_buf / nodes_per_page))) - end - local option_nodes = { create_option_cycle({ - options = center_options, - w = 4.5, - cycle_shoulders = true, - opt_callback = 'your_collection_consumables_page', - focus_args = { snap_to = true, nav = 'wide' }, - current_option = page or 1, - colour = G.C.RED, - no_pips = true - }) } - local function create_consumable_nodes(_start, _end) - local t = {} - for i = _start, _end do - local key = type_buf[i] - if not key then - if i == _start then break end - t[#t+1] = { n = G.UIT.R, config = { align ='cm', minh = 0.81 }, nodes = {}} - else - local id = 'your_collection_'..key:lower()..'s' - t[#t+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = G.ACTIVE_MOD_UI and modsCollectionTally(G.P_CENTER_POOLS[key]) or G.DISCOVER_TALLIES[key:lower()..'s'], minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) - end - end - return t - end - - local t = { n = G.UIT.C, config = { align = 'cm' }, nodes = { - {n=G.UIT.R, config = {align="cm"}, nodes = { - {n=G.UIT.C, config={align = "tm", padding = 0.15}, nodes= create_consumable_nodes(page_offset + 1, page_offset + math.ceil(nodes_per_page/2))}, - {n=G.UIT.C, config={align = "tm", padding = 0.15}, nodes= create_consumable_nodes(page_offset+1+math.ceil(nodes_per_page/2), page_offset + nodes_per_page)}, - }}, - {n=G.UIT.R, config = {align="cm"}, nodes = option_nodes}, - }} - return t -end - -G.FUNCS.your_collection_stickers = function(e) - G.SETTINGS.paused = true - G.FUNCS.overlay_menu{ - definition = create_UIBox_your_collection_stickers(), - } -end - -function create_UIBox_your_collection_stickers(exit) - local deck_tables = {} - local sticker_pool = SMODS.collection_pool(SMODS.Stickers) - local rows, cols = (#sticker_pool > 5 and 2 or 1), 5 - local page = 0 - - G.your_collection = {} - for j = 1, rows do - G.your_collection[j] = CardArea(G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2, G.ROOM.T.h, 5.3 * G.CARD_W, 1.03 * G.CARD_H, - { - card_limit = cols, - type = 'title', - highlight_limit = 0, - collection = true - }) - table.insert(deck_tables, - {n = G.UIT.R, config = {align = "cm", padding = 0, no_fill = true}, nodes = { - {n = G.UIT.O, config = {object = G.your_collection[j]}}}} - ) - end - - local count = math.min(cols * rows, #sticker_pool) - local index = 1 + (rows * cols * page) - for j = 1, rows do - for i = 1, cols do - local center = sticker_pool[index] - - if not center then - break - end - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w / 2, G.your_collection[j].T.y, - G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS["c_base"]) - card.ignore_pinned = true -- Scuffed solution to ignoring the effect of pinned, I'll figure out something better later - center:apply(card, true) - G.your_collection[j]:emplace(card) - index = index + 1 - end - if index > count then - break - end - end - - local edition_options = {} - - local t = create_UIBox_generic_options({ - back_func = "your_collection_other_gameobjects", - snap_back = true, - contents = { - {n = G.UIT.R, config = {align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = - deck_tables}} - }) - - if #sticker_pool > rows * cols then - for i = 1, math.ceil(#sticker_pool / (rows * cols)) do - table.insert(edition_options, localize('k_page') .. ' ' .. tostring(i) .. '/' .. - tostring(math.ceil(#sticker_pool / (rows * cols)))) - end - t = create_UIBox_generic_options({ - back_func = "your_collection_other_gameobjects", - snap_back = true, - contents = { - {n = G.UIT.R, config = {align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = - deck_tables}, - {n = G.UIT.R, config = {align = "cm"}, nodes = { - create_option_cycle({ - options = edition_options, - w = 4.5, - cycle_shoulders = true, - opt_callback = 'your_collection_stickers_page', - focus_args = { snap_to = true, nav = 'wide' }, - current_option = 1, - r = rows, - c = cols, - colour = G.C.RED, - no_pips = true - })}} - } - }) - end - return t -end - -G.FUNCS.your_collection_stickers_page = function(args) - if not args or not args.cycle_config then - return - end - local sticker_pool = SMODS.collection_pool(SMODS.Stickers) - local rows = (#sticker_pool > 5 and 2 or 1) - local cols = 5 - local page = args.cycle_config.current_option - if page > math.ceil(#sticker_pool / (rows * cols)) then - page = page - math.ceil(#sticker_pool / (rows * cols)) - end - local count = rows * cols - local offset = (rows * cols) * (page - 1) - - for j = 1, #G.your_collection do - for i = #G.your_collection[j].cards, 1, -1 do - if G.your_collection[j] ~= nil then - local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) - c:remove() - c = nil - end - end - end - - for j = 1, rows do - for i = 1, cols do - if count % rows > 0 and i <= count % rows and j == cols then - offset = offset - 1 - break - end - local idx = i + (j - 1) * cols + offset - if idx > #sticker_pool then return end - local center = sticker_pool[idx] - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w / 2, G.your_collection[j].T.y, - G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS["c_base"]) - card.ignore_pinned = true -- Scuffed solution to ignoring the effect of pinned, I'll figure out something better later - center:apply(card, true) - G.your_collection[j]:emplace(card) - end - end -end - -function buildAchievementsTab(mod, current_page) - current_page = current_page or 1 - fetch_achievements() - local achievement_matrix = {{},{}} - local achievements_per_row = 3 - local achievements_pool = {} - for k, v in pairs(G.ACHIEVEMENTS) do - if v.mod and v.mod.id == mod.id then achievements_pool[#achievements_pool+1] = v end - end - - local achievement_tab = {} - for k, v in pairs(achievements_pool) do - achievement_tab[#achievement_tab+1] = v - end - - table.sort(achievement_tab, function(a, b) return (a.order or 1) < (b.order or 1) end) - - local row = 1 - local max_lines = 2 - for i = 1, achievements_per_row*2 do - local v = achievement_tab[i+((achievements_per_row*2)*(current_page-1))] - if not v then break end - local temp_achievement = Sprite(0,0,1.1,1.1,G.ASSET_ATLAS[v.atlas or "achievements"], v.earned and v.pos or {x=0, y=0}) - temp_achievement:define_draw_steps({ - {shader = 'dissolve', shadow_height = 0.05}, - {shader = 'dissolve'} - }) - if i == 1 then - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = (function() - G.CONTROLLER:snap_to{node = temp_achievement} - return true - end) - })) - end - temp_achievement.float = true - temp_achievement.states.hover.can = true - temp_achievement.states.drag.can = false - temp_achievement.states.collide.can = true - --temp_achievement.config = {blind = v, force_focus = true} - temp_achievement.hover = function() - if not G.CONTROLLER.dragging.target or G.CONTROLLER.using_touch then - if not temp_achievement.hovering and temp_achievement.states.visible then - temp_achievement.hovering = true - temp_achievement.hover_tilt = 3 - temp_achievement:juice_up(0.05, 0.02) - play_sound('chips1', math.random()*0.1 + 0.55, 0.12) - Node.hover(temp_achievement) - if temp_achievement.children.alert then - temp_achievement.children.alert:remove() - temp_achievement.children.alert = nil - v.alerted = true - G:save_progress() - end - end - end - temp_achievement.stop_hover = function() temp_achievement.hovering = false; Node.stop_hover(temp_achievement); temp_achievement.hover_tilt = 0 end - end - - -- Description - local achievement_text = {} - local maxCharsPerLine = 30 - local function wrapText(text, maxChars) - local wrappedText = {""} - local curr_line = 1 - local currentLineLength = 0 - - for word in text:gmatch("%S+") do - if currentLineLength + #word <= maxChars then - wrappedText[curr_line] = wrappedText[curr_line] .. word .. ' ' - currentLineLength = currentLineLength + #word + 1 - else - wrappedText[curr_line] = string.sub(wrappedText[curr_line], 0, -2) - curr_line = curr_line + 1 - wrappedText[curr_line] = "" - wrappedText[curr_line] = wrappedText[curr_line] .. word .. ' ' - currentLineLength = #word + 1 - end - end - - wrappedText[curr_line] = string.sub(wrappedText[curr_line], 0, -2) - return wrappedText - end - - local loc_target = (v.hidden_text and not v.earned) and {localize("hidden_achievement", 'achievement_descriptions')} or wrapText(localize(v.key, 'achievement_descriptions'), maxCharsPerLine) - local loc_name = (v.hidden_name and not v.earned) and localize("hidden_achievement", 'achievement_names') or localize(v.key, 'achievement_names') - - local ability_text = {} - if loc_target then - for k, v in ipairs(loc_target) do - ability_text[#ability_text + 1] = {n=G.UIT.R, config={align = "cm"}, nodes={{n=G.UIT.T, config={text = v, scale = 0.35, shadow = true, colour = G.C.WHITE}}}} - end - end - max_lines = math.max(max_lines, #ability_text) - achievement_text[#achievement_text + 1] = - {n=G.UIT.R, config={align = "cm", emboss = 0.05, r = 0.1, minw = 4, maxw = 4, padding = 0.05, colour = G.C.WHITE, minh = 0.4*max_lines+0.1}, nodes={ - ability_text[1] and {n=G.UIT.R, config={align = "cm", padding = 0.08, colour = G.C.GREY, r = 0.1, emboss = 0.05, minw = 3.9, maxw = 3.9, minh = 0.4*max_lines}, nodes=ability_text} or nil - }} - - table.insert(achievement_matrix[row], { - n = G.UIT.C, - config = { align = "cm", padding = 0.1 }, - nodes = { - {n=G.UIT.R, config = {align = "cm"}, nodes = { - {n=G.UIT.R, config = {align = "cm", padding = 0.1}, nodes = {{ n = G.UIT.O, config = { object = temp_achievement, focus_with_object = true }}}}, - { - n=G.UIT.R, config = {align = "cm", minw = 4, maxw = 4, padding = 0.05}, nodes = { - {n=G.UIT.R, config={align = "cm", emboss = 0.05, r = 0.1, padding = 0.1, minh = 0.6, colour = G.C.GREY}, nodes={ - {n=G.UIT.O, config={align = "cm", maxw = 3.8, object = DynaText({string = loc_name, maxw = 3.8, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, spacing = 1, bump = true, scale = 0.4})}}, - }}, - {n=G.UIT.R, config={align = "cm"}, nodes=achievement_text}, - }, - }, - }}, - }, - }) - if #achievement_matrix[row] == achievements_per_row then - row = row + 1 - achievement_matrix[row] = {} - max_lines = 2 - end - end - - local achievements_options = {} - for i = 1, math.ceil(#achievements_pool/(2*achievements_per_row)) do - table.insert(achievements_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#achievements_pool/(2*achievements_per_row)))) - end - - local t = { - {n=G.UIT.C, config={}, nodes={ - {n=G.UIT.C, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm", padding = 0.1 }, nodes=achievement_matrix[1]}, - {n=G.UIT.R, config={align = "cm", padding = 0.1 }, nodes=achievement_matrix[2]}, - create_option_cycle({options = achievements_options, w = 4.5, cycle_shoulders = true, opt_callback = 'achievments_tab_page', focus_args = {snap_to = true, nav = 'wide'},current_option = current_page, colour = G.C.RED, no_pips = true}) - }} - }} - }}} - return { - n = G.UIT.ROOT, - config = { - emboss = 0.05, - minh = 6, - r = 0.1, - minw = 6, - align = "tm", - padding = 0.2, - colour = G.C.BLACK - }, - nodes = t - } -end - -G.FUNCS.achievments_tab_page = function(args) - if not args or not args.cycle_config then return end - achievement_matrix = {{},{}} - - local tab_contents = G.OVERLAY_MENU:get_UIE_by_ID('tab_contents') - tab_contents.config.object:remove() - tab_contents.config.object = UIBox{ - definition = buildAchievementsTab(G.ACTIVE_MOD_UI, args.cycle_config.current_option), - config = {offset = {x=0,y=0}, parent = tab_contents, type = 'cm'} - } - tab_contents.UIBox:recalculate() -end - --- TODO: Optimize this. -function modsCollectionTally(pool, set) - local set = set or nil - local obj_tally = {tally = 0, of = 0} - - for _, v in pairs(pool) do - if v.mod and G.ACTIVE_MOD_UI.id == v.mod.id then - if set then - if v.set and v.set == set then - obj_tally.of = obj_tally.of+1 - if v.discovered then - obj_tally.tally = obj_tally.tally+1 - end - end - else - obj_tally.of = obj_tally.of+1 - if v.discovered then - obj_tally.tally = obj_tally.tally+1 - end - end - end - end - - return obj_tally -end - --- TODO: Make better solution -local UIBox_button_ref = UIBox_button -function UIBox_button(args) - local button = UIBox_button_ref(args) - button.nodes[1].config.count = args.count - return button -end - -function buildModtag(mod) - local tag_pos, tag_message, tag_atlas = { x = 0, y = 0 }, "load_success", mod.prefix and mod.prefix .. '_modicon' or 'modicon' - local specific_vars = {} - - if not mod.can_load then - tag_message = "load_failure" - tag_atlas = "mod_tags" - specific_vars = {} - if next(mod.load_issues.dependencies) then - tag_message = tag_message..'_d' - table.insert(specific_vars, concatAuthors(mod.load_issues.dependencies)) - end - if next(mod.load_issues.conflicts) then - tag_message = tag_message .. '_c' - table.insert(specific_vars, concatAuthors(mod.load_issues.conflicts)) - end - if mod.load_issues.outdated then tag_message = 'load_failure_o' end - if mod.load_issues.version_mismatch then - tag_message = 'load_failure_i' - specific_vars = {mod.load_issues.version_mismatch, MODDED_VERSION:gsub('-STEAMODDED', '')} - end - if mod.load_issues.main_file_not_found then - tag_message = 'load_failure_m' - specific_vars = {mod.main_file} - end - if mod.load_issues.prefix_conflict then - tag_message = 'load_failure_p' - local name = mod.load_issues.prefix_conflict - for _, m in ipairs(SMODS.mod_list) do - if m.id == mod.load_issues.prefix_conflict then - name = m.name or name - end - end - specific_vars = {name} - end - if mod.disabled then - tag_pos = {x = 1, y = 0} - tag_message = 'load_disabled' - end - end - - - local tag_sprite_tab = nil - - local tag_sprite = Sprite(0, 0, 0.8*1, 0.8*1, G.ASSET_ATLAS[tag_atlas] or G.ASSET_ATLAS['tags'], tag_pos) - tag_sprite.T.scale = 1 - tag_sprite_tab = {n= G.UIT.C, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={w=0.8*1, h=0.8*1, colour = G.C.BLUE, object = tag_sprite, focus_with_object = true}}, - }} - tag_sprite:define_draw_steps({ - {shader = 'dissolve', shadow_height = 0.05}, - {shader = 'dissolve'}, - }) - tag_sprite.float = true - tag_sprite.states.hover.can = true - tag_sprite.states.drag.can = false - tag_sprite.states.collide.can = true - - tag_sprite.hover = function(_self) - if not G.CONTROLLER.dragging.target or G.CONTROLLER.using_touch then - if not _self.hovering and _self.states.visible then - _self.hovering = true - if _self == tag_sprite then - _self.hover_tilt = 3 - _self:juice_up(0.05, 0.02) - play_sound('paper1', math.random()*0.1 + 0.55, 0.42) - play_sound('tarot2', math.random()*0.1 + 0.55, 0.09) - end - tag_sprite.ability_UIBox_table = generate_card_ui({set = "Other", discovered = false, key = tag_message}, nil, specific_vars, 'Other', nil, false) - _self.config.h_popup = G.UIDEF.card_h_popup(_self) - _self.config.h_popup_config ={align = 'cl', offset = {x=-0.1,y=0},parent = _self} - Node.hover(_self) - if _self.children.alert then - _self.children.alert:remove() - _self.children.alert = nil - G:save_progress() - end - end - end - end - tag_sprite.stop_hover = function(_self) _self.hovering = false; Node.stop_hover(_self); _self.hover_tilt = 0 end - - tag_sprite:juice_up() - - return tag_sprite_tab -end - --- Helper function to create a clickable mod box -local function createClickableModBox(modInfo, scale) - local function invert(c) - return {1-c[1], 1-c[2], 1-c[3], c[4]} - end - local col, text_col - if modInfo.should_enable == nil then - modInfo.should_enable = not modInfo.disabled - end - if SMODS.full_restart == nil then - SMODS.full_restart = 0 - end - if modInfo.can_load then - col = G.C.BOOSTER - elseif modInfo.disabled then - col = G.C.UI.BACKGROUND_INACTIVE - else - col = mix_colours(G.C.RED, G.C.UI.BACKGROUND_INACTIVE, 0.7) - text_col = G.C.TEXT_DARK - end - local label = { " " .. modInfo.name .. " " } - if modInfo.lovely_only then - label[2] = localize('b_lovely_mod') - else - label[2] = localize('b_by') .. concatAuthors(modInfo.author) .. " " - end - local but = UIBox_button { - label = label, - shadow = true, - scale = scale, - colour = col, - text_colour = text_col, - button = "openModUI_" .. modInfo.id, - minh = 0.8, - minw = 7 - } - if modInfo.lovely_only then - local config = but.nodes[1].nodes[2].nodes[1].config - config.colour = mix_colours(invert(col), G.C.UI.TEXT_INACTIVE, 0.8) - config.scale = scale * .8 - end - if modInfo.version ~= '0.0.0' then - table.insert(but.nodes[1].nodes[1].nodes, { - n = G.UIT.T, - config = { - text = ('(%s)'):format(modInfo.version), - scale = scale*0.8, - colour = mix_colours(invert(col), G.C.UI.TEXT_INACTIVE, 0.8), - shadow = true, - }, - }) - end - return { - n = G.UIT.R, - config = { padding = 0, align = "cm" }, - nodes = { - { - n = G.UIT.C, - config = { align = "cm" }, - nodes = { - buildModtag(modInfo) - } - }, - { - n = G.UIT.C, - config = { align = "cm", padding = 0.1 }, - nodes = {}, - }, - { n = G.UIT.C, config = { padding = 0, align = "cm" }, nodes = { but } }, - create_toggle({ - label = '', - ref_table = modInfo, - ref_value = 'should_enable', - col = true, - w = 0, - h = 0.5, - callback = ( - function(_set_toggle) - if not modInfo.should_enable then - NFS.write(modInfo.path .. '.lovelyignore', '') - else - NFS.remove(modInfo.path .. '.lovelyignore') - end - local toChange = 1 - if modInfo.should_enable == not modInfo.disabled then - toChange = -1 - end - SMODS.full_restart = SMODS.full_restart + toChange - end - ) - }), - }} - -end - -function G.FUNCS.openModsDirectory(options) - if not love.filesystem.exists("Mods") then - love.filesystem.createDirectory("Mods") - end - - love.system.openURL("file://"..love.filesystem.getSaveDirectory().."/Mods") -end - -function G.FUNCS.mods_buttons_page(options) - if not options or not options.cycle_config then - return - end -end - -function SMODS.load_mod_config(mod) - local s1, config = pcall(function() - return load(NFS.read(('config/%s.jkr'):format(mod.id)), ('=[SMODS %s "config"]'):format(mod.id))() - end) - local s2, default_config = pcall(function() - return load(NFS.read(('%sconfig.lua'):format(mod.path)), ('=[SMODS %s "default_config"]'):format(mod.id))() - end) - if not s1 or type(config) ~= 'table' then config = {} end - if not s2 or type(default_config) ~= 'table' then default_config = {} end - mod.config = {} - for k, v in pairs(default_config) do mod.config[k] = v end - for k, v in pairs(config) do mod.config[k] = v end - return mod.config -end -SMODS:load_mod_config() -function SMODS.save_mod_config(mod) - local success = pcall(function() - NFS.createDirectory('config') - assert(mod.config and next(mod.config)) - local serialized = 'return '..serialize(mod.config) - NFS.write(('config/%s.jkr'):format(mod.id), serialized) - end) - return success -end -function SMODS.save_all_config() - SMODS:save_mod_config() - for _, v in ipairs(SMODS.mod_list) do - if v.can_load then - local save_func = type(v.save_mod_config) == 'function' and v.save_mod_config or SMODS.save_mod_config - save_func(v) - end - end -end - -function G.FUNCS.exit_mods(e) - G.ACTIVE_MOD_UI = nil - SMODS.save_all_config() - if SMODS.full_restart and SMODS.full_restart ~= 0 then - -- launch a new instance of the game and quit the current one - SMODS.restart_game() - end - SMODS.IN_MODS_TAB = nil - if e then - -- This is only needed when back button is pressed - G.FUNCS.exit_overlay_menu(e) - end -end - -function create_UIBox_mods_button() - local scale = 0.75 - SMODS.browse_search = SMODS.browse_search or '' - return (create_UIBox_generic_options({ - back_func = 'exit_mods', - contents = { - { - n = G.UIT.R, - config = { - padding = 0, - align = "cm" - }, - nodes = { - create_tabs({ - snap_to_nav = true, - colour = G.C.BOOSTER, - tabs = { - { - label = localize('b_mods'), - chosen = true, - tab_definition_function = function() - return SMODS.GUI.DynamicUIManager.initTab({ - updateFunctions = { - modsList = G.FUNCS.update_mod_list, - }, - staticPageDefinition = SMODS.GUI.staticModListContent() - }) - end - }, - -- { - -- label = localize('b_browse'), - -- tab_definition_function = function() - -- return { - -- n = G.UIT.ROOT, - -- config = { - -- align = "cm", - -- padding = 0.05, - -- colour = G.C.CLEAR, - -- }, - -- nodes = { - -- { - -- n = G.UIT.C, - -- config = { align = 'cm' }, - -- nodes = { - -- { - -- n = G.UIT.R, - -- config = { align = 'cl' }, - -- nodes = { - -- create_text_input{ - -- prompt_text = localize('b_search_prompt'), - -- max_length = 50, - -- text_scale = 0.6, - -- w = 6, - -- h = 1, - -- ref_table = SMODS, - -- ref_value = "browse_search", - -- extended_corpus = true, - -- }, - -- UIBox_button{ - -- button = 'browse_search', - -- label = {localize('b_search_button')}, - -- minw = 3, - -- colour = G.C.RED - -- } - -- } - -- }, - -- { - -- n = G.UIT.R, - -- config = { align = 'cm', emboss = 0.05, colour = G.C.BLACK, minh=5, minw=10.5}, - -- nodes = { - -- { - -- n = G.UIT.O, - -- config = { align = 'cm', object = Moveable(), id = 'browse_mods'} - -- } - -- } - -- } - -- } - -- } - -- } - -- } - -- end, - -- }, - { - - label = localize('b_credits'), - tab_definition_function = function() - return { - n = G.UIT.ROOT, - config = { - emboss = 0.05, - minh = 6, - r = 0.1, - minw = 6, - align = "cm", - padding = 0.2, - colour = G.C.BLACK - }, - nodes = { - { - n = G.UIT.R, - config = { - padding = 0, - align = "cm" - }, - nodes = { - { - n = G.UIT.T, - config = { - text = localize('b_mod_loader'), - shadow = true, - scale = scale * 0.8, - colour = G.C.UI.TEXT_LIGHT - } - } - } - }, - { - n = G.UIT.R, - config = { - padding = 0, - align = "cm" - }, - nodes = { - { - n = G.UIT.T, - config = { - text = localize('b_developed_by'), - shadow = true, - scale = scale * 0.8, - colour = G.C.UI.TEXT_LIGHT - } - }, - { - n = G.UIT.T, - config = { - text = "Steamo", - shadow = true, - scale = scale * 0.8, - colour = G.C.BLUE - } - } - } - }, - { - n = G.UIT.R, - config = { - padding = 0, - align = "cm" - }, - nodes = { - { - n = G.UIT.T, - config = { - text = localize('b_rewrite_by'), - shadow = true, - scale = scale * 0.8, - colour = G.C.UI.TEXT_LIGHT - } - }, - { - n = G.UIT.T, - config = { - text = "Aure", - shadow = true, - scale = scale * 0.8, - colour = G.C.BLUE - } - } - } - }, - { - n = G.UIT.R, - config = { - padding = 0.2, - align = "cm", - }, - nodes = { - UIBox_button({ - minw = 3.85, - button = "steamodded_github", - label = {localize('b_github_project')} - }) - } - }, - { - n = G.UIT.R, - config = { - padding = 0.2, - align = "cm" - }, - nodes = { - { - n = G.UIT.T, - config = { - text = localize('b_github_bugs_1')..'\n'..localize('b_github_bugs_2'), - shadow = true, - scale = scale * 0.5, - colour = G.C.UI.TEXT_LIGHT - } - }, - - } - }, - } - } - end - }, - { - label = localize('b_config'), - tab_definition_function = function() - return { - n = G.UIT.ROOT, - config = { - align = "cm", - padding = 0.05, - colour = G.C.CLEAR, - }, - nodes = { - create_toggle { - label = localize('b_disable_mod_badges'), - ref_table = SMODS.config, - ref_value = 'no_mod_badges', - }, - create_toggle { - label = localize('b_seeded_unlocks'), - info = {localize('b_seeded_unlocks_info')}, - ref_table = SMODS.config, - ref_value = 'seeded_unlocks', - }, - create_option_cycle { - w = 4.5, - scale = 0.8, - label = localize('b_achievements'), - options = localize('ml_achievement_settings'), - opt_callback = 'update_achievement_settings', - current_option = SMODS.config.achievements, - cycle_shoulders = true, - } - } - } - end - } - } - }) - } - } - } - })) -end - -G.FUNCS.update_achievement_settings = function(e) - local opt = (e.cycle_config or {}).current_option or 1 - SMODS.config.achievements = opt - G.F_NO_ACHIEVEMENTS = opt == 1 -end - -G.FUNCS.browse_search = function(e) - SMODS.fetch_index() - -end - -G.FUNCS.browse_mods_page = function(args) - local page = args.cycle_config and args.cycle_config.current_option or 1 -end - -function G.FUNCS.steamodded_github(e) - love.system.openURL("https://github.com/Steamopollys/Steamodded") -end - -function G.FUNCS.mods_button(e) - G.SETTINGS.paused = true - SMODS.LAST_SELECTED_MOD_TAB = nil - SMODS.IN_MODS_TAB = true - - G.FUNCS.overlay_menu({ - definition = create_UIBox_mods_button() - }) -end - -local create_UIBox_main_menu_buttonsRef = create_UIBox_main_menu_buttons -function create_UIBox_main_menu_buttons() - local modsButton = UIBox_button({ - id = "mods_button", - minh = 1.55, - minw = 1.85, - col = true, - button = "mods_button", - colour = G.C.BOOSTER, - label = {localize('b_mods_cap')}, - scale = 0.45 * 1.2 - }) - local menu = create_UIBox_main_menu_buttonsRef() - table.insert(menu.nodes[1].nodes[1].nodes, modsButton) - menu.nodes[1].nodes[1].config = {align = "cm", padding = 0.15, r = 0.1, emboss = 0.1, colour = G.C.L_BLACK, mid = true} - if SMODS.mod_button_alert then - G.E_MANAGER:add_event(Event({ - func = function() - if G.MAIN_MENU_UI then -- Wait until the ui is rendered before spawning the alert - UIBox{definition = create_UIBox_card_alert(), config = {align="tri", offset = {x = 0.05, y = -0.05}, major = G.MAIN_MENU_UI:get_UIE_by_ID('mods_button'), can_collide = false}} - return true - end - end, - blocking = false, - blockable = false - })) - end - return menu -end - -local create_UIBox_profile_buttonRef = create_UIBox_profile_button -function create_UIBox_profile_button() - local profile_menu = create_UIBox_profile_buttonRef() - profile_menu.nodes[1].config = {align = "cm", padding = 0.11, r = 0.1, emboss = 0.1, colour = G.C.L_BLACK} - return(profile_menu) -end - --- Disable achievments and crash report upload -function initGlobals() - G.F_NO_ACHIEVEMENTS = SMODS.config.achievements == 1 - G.F_CRASH_REPORTS = false -end - -function G.FUNCS.update_mod_list(args) - if not args or not args.cycle_config then return end - SMODS.GUI.DynamicUIManager.updateDynamicAreas({ - ["modsList"] = SMODS.GUI.dynamicModListContent(args.cycle_config.current_option) - }) -end - --- Same as Balatro base game code, but accepts a value to match against (rather than the index in the option list) --- e.g. create_option_cycle({ current_option = 1 }) vs. SMODS.GUID.createOptionSelector({ current_option = "Page 1/2" }) -function SMODS.GUI.createOptionSelector(args) - args = args or {} - args.colour = args.colour or G.C.RED - args.options = args.options or { - 'Option 1', - 'Option 2' - } - - local current_option_index = 1 - for i, option in ipairs(args.options) do - if option == args.current_option then - current_option_index = i - break - end - end - args.current_option_val = args.options[current_option_index] - args.current_option = current_option_index - args.opt_callback = args.opt_callback or nil - args.scale = args.scale or 1 - args.ref_table = args.ref_table or nil - args.ref_value = args.ref_value or nil - args.w = (args.w or 2.5)*args.scale - args.h = (args.h or 0.8)*args.scale - args.text_scale = (args.text_scale or 0.5)*args.scale - args.l = '<' - args.r = '>' - args.focus_args = args.focus_args or {} - args.focus_args.type = 'cycle' - - local info = nil - if args.info then - info = {} - for k, v in ipairs(args.info) do - table.insert(info, {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ - {n=G.UIT.T, config={text = v, scale = 0.3*args.scale, colour = G.C.UI.TEXT_LIGHT}} - }}) - end - info = {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes=info} - end - - local disabled = #args.options < 2 - local pips = {} - for i = 1, #args.options do - pips[#pips+1] = {n=G.UIT.B, config={w = 0.1*args.scale, h = 0.1*args.scale, r = 0.05, id = 'pip_'..i, colour = args.current_option == i and G.C.WHITE or G.C.BLACK}} - end - - local choice_pips = not args.no_pips and {n=G.UIT.R, config={align = "cm", padding = (0.05 - (#args.options > 15 and 0.03 or 0))*args.scale}, nodes=pips} or nil - - local t = - {n=G.UIT.C, config={align = "cm", padding = 0.1, r = 0.1, colour = G.C.CLEAR, id = args.id and (not args.label and args.id or nil) or nil, focus_args = args.focus_args}, nodes={ - {n=G.UIT.C, config={align = "cm",r = 0.1, minw = 0.6*args.scale, hover = not disabled, colour = not disabled and args.colour or G.C.BLACK,shadow = not disabled, button = not disabled and 'option_cycle' or nil, ref_table = args, ref_value = 'l', focus_args = {type = 'none'}}, nodes={ - {n=G.UIT.T, config={ref_table = args, ref_value = 'l', scale = args.text_scale, colour = not disabled and G.C.UI.TEXT_LIGHT or G.C.UI.TEXT_INACTIVE}} - }}, - args.mid and - {n=G.UIT.C, config={id = 'cycle_main'}, nodes={ - {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ - args.mid - }}, - not disabled and choice_pips or nil - }} - or {n=G.UIT.C, config={id = 'cycle_main', align = "cm", minw = args.w, minh = args.h, r = 0.1, padding = 0.05, colour = args.colour,emboss = 0.1, hover = true, can_collide = true, on_demand_tooltip = args.on_demand_tooltip}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = args, ref_value = "current_option_val"}}, colours = {G.C.UI.TEXT_LIGHT},pop_in = 0, pop_in_rate = 8, reset_pop_in = true,shadow = true, float = true, silent = true, bump = true, scale = args.text_scale, non_recalc = true})}}, - }}, - {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ - }}, - not disabled and choice_pips or nil - }} - }}, - {n=G.UIT.C, config={align = "cm",r = 0.1, minw = 0.6*args.scale, hover = not disabled, colour = not disabled and args.colour or G.C.BLACK,shadow = not disabled, button = not disabled and 'option_cycle' or nil, ref_table = args, ref_value = 'r', focus_args = {type = 'none'}}, nodes={ - {n=G.UIT.T, config={ref_table = args, ref_value = 'r', scale = args.text_scale, colour = not disabled and G.C.UI.TEXT_LIGHT or G.C.UI.TEXT_INACTIVE}} - }}, - }} - - if args.cycle_shoulders then - t = - {n=G.UIT.R, config={align = "cm", colour = G.C.CLEAR}, nodes = { - {n=G.UIT.C, config={minw = 0.7,align = "cm", colour = G.C.CLEAR,func = 'set_button_pip', focus_args = {button = 'leftshoulder', type = 'none', orientation = 'cm', scale = 0.7, offset = {x = -0.1, y = 0}}}, nodes = {}}, - {n=G.UIT.C, config={id = 'cycle_shoulders', padding = 0.1}, nodes={t}}, - {n=G.UIT.C, config={minw = 0.7,align = "cm", colour = G.C.CLEAR,func = 'set_button_pip', focus_args = {button = 'rightshoulder', type = 'none', orientation = 'cm', scale = 0.7, offset = {x = 0.1, y = 0}}}, nodes = {}}, - }} - else - t = - {n=G.UIT.R, config={align = "cm", colour = G.C.CLEAR, padding = 0.0}, nodes = { - t - }} - end - if args.label or args.info then - t = {n=G.UIT.R, config={align = "cm", padding = 0.05, id = args.id or nil}, nodes={ - args.label and {n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.T, config={text = args.label, scale = 0.5*args.scale, colour = G.C.UI.TEXT_LIGHT}} - }} or nil, - t, - info, - }} - end - return t -end - -local function generateBaseNode(staticPageDefinition) - return { - n = G.UIT.ROOT, - config = { - emboss = 0.05, - minh = 6, - r = 0.1, - minw = 8, - align = "cm", - padding = 0.2, - colour = G.C.BLACK - }, - nodes = { - staticPageDefinition - } - } -end - --- Initialize a tab with sections that can be updated dynamically (e.g. modifying text labels, showing additional UI elements after toggling buttons, etc.) -function SMODS.GUI.DynamicUIManager.initTab(args) - local updateFunctions = args.updateFunctions - local staticPageDefinition = args.staticPageDefinition - - for _, updateFunction in pairs(updateFunctions) do - G.E_MANAGER:add_event(Event({func = function() - updateFunction{cycle_config = {}} - return true - end})) - end - return generateBaseNode(staticPageDefinition) -end - --- Call this to trigger an update for a list of dynamic content areas -function SMODS.GUI.DynamicUIManager.updateDynamicAreas(uiDefinitions) - for id, uiDefinition in pairs(uiDefinitions) do - local dynamicArea = G.OVERLAY_MENU:get_UIE_by_ID(id) - if dynamicArea and dynamicArea.config.object then - dynamicArea.config.object:remove() - dynamicArea.config.object = UIBox{ - definition = uiDefinition, - config = {offset = {x=0, y=0}, align = 'cm', parent = dynamicArea} - } - end - end -end - -local function recalculateModsList(page) - page = page or SMODS.LAST_VIEWED_MODS_PAGE or 1 - SMODS.LAST_VIEWED_MODS_PAGE = page - local modsPerPage = 4 - local startIndex = (page - 1) * modsPerPage + 1 - local endIndex = startIndex + modsPerPage - 1 - local totalPages = math.ceil(#SMODS.mod_list / modsPerPage) - local currentPage = localize('k_page') .. ' ' .. page .. "/" .. totalPages - local pageOptions = {} - for i = 1, totalPages do - table.insert(pageOptions, (localize('k_page') .. ' ' .. tostring(i) .. "/" .. totalPages)) - end - local showingList = #SMODS.mod_list > 0 - - return currentPage, pageOptions, showingList, startIndex, endIndex, modsPerPage -end - --- Define the content in the pane that does not need to update --- Should include OBJECT nodes that indicate where the dynamic content sections will be populated --- EX: in this pane the 'modsList' node will contain the dynamic content which is defined in the function below -function SMODS.GUI.staticModListContent() - local scale = 0.75 - local currentPage, pageOptions, showingList = recalculateModsList() - return { - n = G.UIT.ROOT, - config = { - minh = 6, - r = 0.1, - minw = 10, - align = "tm", - padding = 0.2, - colour = G.C.BLACK - }, - nodes = { - -- row container - { - n = G.UIT.R, - config = { align = "cm", padding = 0.05 }, - nodes = { - -- column container - { - n = G.UIT.C, - config = { align = "cm", minw = 3, padding = 0.2, r = 0.1, colour = G.C.CLEAR }, - nodes = { - -- title row - { - n = G.UIT.R, - config = { - padding = 0.05, - align = "cm" - }, - nodes = { - { - n = G.UIT.T, - config = { - text = localize('b_mod_list'), - shadow = true, - scale = scale * 0.6, - colour = G.C.UI.TEXT_LIGHT - } - } - } - }, - - -- add some empty rows for spacing - { - n = G.UIT.R, - config = { align = "cm", padding = 0.05 }, - nodes = {} - }, - { - n = G.UIT.R, - config = { align = "cm", padding = 0.05 }, - nodes = {} - }, - { - n = G.UIT.R, - config = { align = "cm", padding = 0.05 }, - nodes = {} - }, - { - n = G.UIT.R, - config = { align = "cm", padding = 0.05 }, - nodes = {} - }, - - -- dynamic content rendered in this row container - -- list of 4 mods on the current page - { - n = G.UIT.R, - config = { - padding = 0.05, - align = "cm", - minh = 2, - minw = 4 - }, - nodes = { - {n=G.UIT.O, config={id = 'modsList', object = Moveable()}}, - } - }, - - -- another empty row for spacing - { - n = G.UIT.R, - config = { align = "cm", padding = 0.3 }, - nodes = {} - }, - - -- page selector - -- does not appear when list of mods is empty - showingList and SMODS.GUI.createOptionSelector({label = "", scale = 0.8, options = pageOptions, opt_callback = 'update_mod_list', no_pips = true, current_option = ( - currentPage - )}) or nil - } - }, - } - }, - } - } -end - -function SMODS.GUI.dynamicModListContent(page) - local scale = 0.75 - local _, __, showingList, startIndex, endIndex, modsPerPage = recalculateModsList(page) - - local modNodes = {} - - -- If no mods are loaded, show a default message - if showingList == false then - table.insert(modNodes, { - n = G.UIT.R, - config = { - padding = 0, - align = "cm" - }, - nodes = { - { - n = G.UIT.T, - config = { - text = localize('b_no_mods'), - shadow = true, - scale = scale * 0.5, - colour = G.C.UI.TEXT_DARK - } - } - } - }) - table.insert(modNodes, { - n = G.UIT.R, - config = { - padding = 0, - align = "cm", - }, - nodes = { - UIBox_button({ - label = { localize('b_open_mods_dir') }, - shadow = true, - scale = scale, - colour = G.C.BOOSTER, - button = "openModsDirectory", - minh = 0.8, - minw = 8 - }) - } - }) - else - local modCount = 0 - local id = 0 - - for _, condition in ipairs({ - function(m) return not m.can_load and not m.disabled end, - function(m) return m.can_load end, - function(m) return m.disabled end, - }) do - for _, modInfo in ipairs(SMODS.mod_list) do - if modCount >= modsPerPage then break end - if condition(modInfo) then - id = id + 1 - if id >= startIndex and id <= endIndex then - table.insert(modNodes, createClickableModBox(modInfo, scale * 0.5)) - modCount = modCount + 1 - end - end - end - end - end - - return { - n = G.UIT.C, - config = { - r = 0.1, - align = "cm", - padding = 0.2, - }, - nodes = modNodes - } -end - -G.FUNCS.SMODS_change_mipmap = function(args) - SMODS.config.graphics_mipmap_level = args.to_key - G:set_render_settings() - SMODS:save_mod_config() -end diff --git a/Steamodded/version.lua b/Steamodded/version.lua deleted file mode 100644 index 7d05e2f..0000000 --- a/Steamodded/version.lua +++ /dev/null @@ -1 +0,0 @@ -return "1.0.0~ALPHA-1220a-STEAMODDED" diff --git a/Talisman/config.lua b/Talisman/config.lua index 0f706ea..5cdb68f 100644 --- a/Talisman/config.lua +++ b/Talisman/config.lua @@ -1 +1 @@ -return {["disable_anims"]=false,["score_opt_id"]=3,["break_infinity"]="omeganum",} \ No newline at end of file +return {["disable_anims"]=true,["score_opt_id"]=3,["break_infinity"]="omeganum",} \ No newline at end of file diff --git a/lovely/dump/blind.lua b/lovely/dump/blind.lua index 3559228..1a7d1ae 100644 --- a/lovely/dump/blind.lua +++ b/lovely/dump/blind.lua @@ -1,4 +1,4 @@ -LOVELY_INTEGRITY = 'ceaf7d365cb8eac62c7dcf3be1ef07cc6b0dac3977bde52960496d7f844a668d' +LOVELY_INTEGRITY = '2c00c26e55b0f21d108e0353b98757a950fc433f1f9951ac8a454c589450b12c' --class Blind = Moveable:extend() @@ -606,7 +606,7 @@ function Blind:debuff_hand(cards, hand, handname, check) end if self.name == 'The Arm' then self.triggered = false - if G.GAME.hands[handname].level > 1 then + if to_big(G.GAME.hands[handname].level) > to_big(1) then self.triggered = true if not check then level_up_hand(self.children.animatedSprite, handname, nil, -1) diff --git a/lovely/dump/card.lua b/lovely/dump/card.lua index 2799ded..4cc4096 100644 --- a/lovely/dump/card.lua +++ b/lovely/dump/card.lua @@ -1,4 +1,4 @@ -LOVELY_INTEGRITY = 'af84d6c3467720a23ecaec33b0418eba5566291929fca3634893138f120ee811' +LOVELY_INTEGRITY = 'b7b1bb9e3088ca71ed96c4b7bdaf1ec1c67106c37ba37b8f4aef385f8743a60b' --class Card = Moveable:extend() @@ -4171,7 +4171,7 @@ function Card:calculate_joker(context) } end if self.ability.name == 'Vagabond' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then - if G.GAME.dollars <= self.ability.extra then + if to_big(G.GAME.dollars) <= to_big(self.ability.extra) then G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 G.E_MANAGER:add_event(Event({ trigger = 'before', @@ -4363,7 +4363,7 @@ function Card:calculate_joker(context) colour = G.C.MULT } end - if self.ability.name == 'Bull' and (G.GAME.dollars + (G.GAME.dollar_buffer or 0)) > 0 then + if self.ability.name == 'Bull' and to_big(G.GAME.dollars + (G.GAME.dollar_buffer or 0)) > to_big(0) then return { message = localize{type='variable',key='a_chips',vars={self.ability.extra*math.max(0,(G.GAME.dollars + (G.GAME.dollar_buffer or 0))) }}, chip_mod = self.ability.extra*math.max(0,(G.GAME.dollars + (G.GAME.dollar_buffer or 0))), @@ -4473,7 +4473,7 @@ function Card:calculate_joker(context) Xmult_mod = self.ability.extra.Xmult, } end - if self.ability.name == 'Bootstraps' and math.floor((G.GAME.dollars + (G.GAME.dollar_buffer or 0))/self.ability.extra.dollars) >= 1 then + if self.ability.name == 'Bootstraps' and to_big(math.floor((G.GAME.dollars + (G.GAME.dollar_buffer or 0))/self.ability.extra.dollars)) >= to_big(1) then return { message = localize{type='variable',key='a_mult',vars={self.ability.extra.mult*math.floor((G.GAME.dollars + (G.GAME.dollar_buffer or 0))/self.ability.extra.dollars)}}, mult_mod = self.ability.extra.mult*math.floor((G.GAME.dollars + (G.GAME.dollar_buffer or 0))/self.ability.extra.dollars) @@ -4795,7 +4795,6 @@ function Card:draw(layer) self.hover_tilt = 1 if not self.states.visible then return end - if self.VT.x < -3 or self.VT.x > G.TILE_W + 2.5 then return end if (layer == 'shadow' or layer == 'both') then self.ARGS.send_to_shader = self.ARGS.send_to_shader or {} diff --git a/lovely/dump/cardarea.lua b/lovely/dump/cardarea.lua index 343cc8d..06918dc 100644 --- a/lovely/dump/cardarea.lua +++ b/lovely/dump/cardarea.lua @@ -1,4 +1,4 @@ -LOVELY_INTEGRITY = 'e8693aca875516bf9cb3c84fcb6f392131135da095f221f2ef0e6ac727b926df' +LOVELY_INTEGRITY = '0825b896143c8e8c22c2c18adfc937960d407b986f1c18addc68bedde1768967' --Class CardArea = Moveable:extend() @@ -32,9 +32,6 @@ function CardArea:init(X, Y, W, H, config) end function CardArea:emplace(card, location, stay_flipped) -if self == G.jokers then - Cartomancer.handle_joker_added(card) -end if card.edition and card.edition.card_limit and (self == G.hand) then self.config.real_card_limit = (self.config.real_card_limit or self.config.card_limit) + card.edition.card_limit self.config.card_limit = math.max(0, self.config.real_card_limit) @@ -326,9 +323,6 @@ function CardArea:draw() } end self.children.area_uibox:draw() - if self == G.jokers then - Cartomancer.add_visibility_controls() - end end self:draw_boundingrect() @@ -431,39 +425,15 @@ function CardArea:align_cards() end if (self == G.hand or self == G.deck or self == G.discard or self == G.play) and G.view_deck and G.view_deck[1] and G.view_deck[1].cards then return end if self.config.type == 'deck' then - local display_limit - if not Cartomancer.SETTINGS.compact_deck_enabled then - display_limit = 999999 - else - display_limit = Cartomancer.SETTINGS.compact_deck_visible_cards - end - local deck_height = (self.config.deck_height or 0.15)/52 - local total_cards = #self.cards <= display_limit and #self.cards or display_limit -- limit height - local fixedX, fixedY, fixedR = nil, nil, nil - for k, card in ipairs(self.cards) do if card.facing == 'front' then card:flip() end - + if not card.states.drag.is then - if fixedX then - card.T.x = fixedX - card.T.y = fixedY - card.T.r = fixedR -- rotation - card.states.visible = false - else - card.T.x = self.T.x + 0.5*(self.T.w - card.T.w) + self.shadow_parrallax.x*deck_height*(total_cards/(self == G.deck and 1 or 2) - k) + 0.9*self.shuffle_amt*(1 - k*0.01)*(k%2 == 1 and 1 or -0) - card.T.y = self.T.y + 0.5*(self.T.h - card.T.h) + self.shadow_parrallax.y*deck_height*(total_cards/(self == G.deck and 1 or 2) - k) - card.T.r = 0 + 0.3*self.shuffle_amt*(1 + k*0.05)*(k%2 == 1 and 1 or -0) - card.T.x = card.T.x + card.shadow_parrallax.x/30 - card.states.visible = true - - if k >= display_limit then - fixedX = card.T.x - fixedY = card.T.y - fixedR = card.T.r - end - end + card.T.x = self.T.x + 0.5*(self.T.w - card.T.w) + self.shadow_parrallax.x*deck_height*(#self.cards/(self == G.deck and 1 or 2) - k) + 0.9*self.shuffle_amt*(1 - k*0.01)*(k%2 == 1 and 1 or -0) + card.T.y = self.T.y + 0.5*(self.T.h - card.T.h) + self.shadow_parrallax.y*deck_height*(#self.cards/(self == G.deck and 1 or 2) - k) + card.T.r = 0 + 0.3*self.shuffle_amt*(1 + k*0.05)*(k%2 == 1 and 1 or -0) + card.T.x = card.T.x + card.shadow_parrallax.x/30 end end end @@ -551,18 +521,7 @@ function CardArea:align_cards() end table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end) end - if self == G.jokers and G.jokers.cart_jokers_expanded then - local align_cards = Cartomancer.expand_G_jokers() - - -- This should work fine without cryptid. But because cryptid's patch is priority=0, it has to be this way - if not G.GAME.modifiers.cry_conveyor then - table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end) - end - - if align_cards then - G.jokers:hard_set_cards() - end - elseif self.config.type == 'joker' or self.config.type == 'title_2' then + if self.config.type == 'joker' or self.config.type == 'title_2' then for k, card in ipairs(self.cards) do if not card.states.drag.is then card.T.r = 0.1*(-#self.cards/2 - 0.5 + k)/(#self.cards)+ (G.SETTINGS.reduced_motion and 0 or 1)*0.02*math.sin(2*G.TIMERS.REAL+card.T.x) @@ -653,9 +612,6 @@ function CardArea:draw_card_from(area, stay_flipped, discarded_only) if area == G.discard then card.T.r = 0 end - if self == G.hand and not card.states.visible then - card.states.visible = true - end local stay_flipped = G.GAME and G.GAME.blind and G.GAME.blind:stay_flipped(self, card) if (self == G.hand) and G.GAME.modifiers.flipped_cards then if pseudorandom(pseudoseed('flipped_card')) < 1/G.GAME.modifiers.flipped_cards then diff --git a/lovely/dump/conf.lua b/lovely/dump/conf.lua deleted file mode 100644 index b3c8854..0000000 --- a/lovely/dump/conf.lua +++ /dev/null @@ -1,13 +0,0 @@ -LOVELY_INTEGRITY = 'cd11f803e89c48e476527cbfeec15ed491f002735c8b21fdbb0b2939cfd96518' - -_RELEASE_MODE = false -_DEMO = false - -function love.conf(t) - t.console = not _RELEASE_MODE - t.title = 'Balatro' - t.window.width = 0 - t.window.height = 0 - t.window.minwidth = 100 - t.window.minheight = 100 -end diff --git a/lovely/dump/engine/controller.lua b/lovely/dump/engine/controller.lua index 3af61ba..51aa67c 100644 --- a/lovely/dump/engine/controller.lua +++ b/lovely/dump/engine/controller.lua @@ -1,4 +1,4 @@ -LOVELY_INTEGRITY = 'd36e3953c2739cd4ea15794fb5e4031a2dac09fc33baadd0a2820e4726891304' +LOVELY_INTEGRITY = 'd9e5d51702216f37d8d0de3c89deb8d1a47bcad6430594945df872f263a14c04' ---@class Controller Controller = Object:extend() @@ -768,12 +768,6 @@ function Controller:button_release_update(button, dt) end function Controller:key_press_update(key, dt) - if key == "escape" and Cartomancer.INTERNAL_in_config then - Cartomancer.INTERNAL_in_config = false - if not Cartomancer.use_smods() then - Cartomancer.save_config() - end - end if key == "escape" and G.ACTIVE_MOD_UI then G.FUNCS.exit_mods() end @@ -828,7 +822,7 @@ function Controller:key_press_update(key, dt) end end end - if not _RELEASE_MODE and require("debugplus.core").isOkayToHandleDebugForKey(key) then + if not _RELEASE_MODE then if key == 'tab' and not G.debug_tools then G.debug_tools = UIBox{ definition = create_UIBox_debug_tools(), @@ -859,8 +853,6 @@ function Controller:key_press_update(key, dt) add_joker(_card.config.center.key) _card:set_sprites(_card.config.center) end - local debugplus = require("debugplus.core") - debugplus.handleSpawn(self, _card) if _card.ability.consumeable and G.consumeables and #G.consumeables.cards < G.consumeables.config.card_limit then add_joker(_card.config.center.key) _card:set_sprites(_card.config.center) @@ -912,17 +904,13 @@ function Controller:key_press_update(key, dt) if key == "space" then live_test() end - local debugplus = require("debugplus.core") - debugplus.handleKeys(self, key, dt) if key == 'v' then if not G.prof then G.prof = require "engine/profile"; G.prof.start() else G.prof:stop(); print(G.prof.report()); G.prof = nil end - debugplus.profileMessage() end if key == "p" then G.SETTINGS.perf_mode = not G.SETTINGS.perf_mode - debugplus.togglePerfUI() end end end diff --git a/lovely/dump/engine/save_manager.lua b/lovely/dump/engine/save_manager.lua new file mode 100644 index 0000000..693b4b2 --- /dev/null +++ b/lovely/dump/engine/save_manager.lua @@ -0,0 +1,102 @@ +LOVELY_INTEGRITY = 'a0a6222d417538f9ac51e6de9e5324e3e68a85bbdc35ead9c5c98bc11cb475e4' + +require "love.system" + +if (love.system.getOS() == 'OS X' ) and (jit.arch == 'arm64' or jit.arch == 'arm') then jit.off() end + +require "love.timer" +require "love.thread" +require 'love.filesystem' +require "engine/object" +require "engine/string_packer" + +--vars needed for sound manager thread +CHANNEL = love.thread.getChannel("save_request") +function tal_compress_and_save(_file, _data, talisman) + local save_string = type(_data) == 'table' and STR_PACK(_data) or _data + local fallback_save = STR_PACK({GAME = {won = true}}) --just bare minimum to not crash, maybe eventually display some info? + if talisman == 'bignumber' then + fallback_save = "if not BigMeta then " .. fallback_save + elseif talisman == 'omeganum' then + fallback_save = "if not OmegaMeta then " .. fallback_save + else + fallback_save = "if BigMeta or OmegaMeta then " .. fallback_save + end + fallback_save = fallback_save .. " end" + save_string = fallback_save .. " " .. save_string + save_string = love.data.compress('string', 'deflate', save_string, 1) + love.filesystem.write(_file,save_string) +end + + while true do + --Monitor the channel for any new requests + local request = CHANNEL:demand() -- Value from channel + if request then + if request.type == 'kill' then return end + --Saves progress for settings, unlocks, alerts and discoveries + if request.type == 'save_progress' then + local prefix_profile = (request.save_progress.SETTINGS.profile or 1)..'' + if not love.filesystem.getInfo(prefix_profile) then love.filesystem.createDirectory( prefix_profile ) end + prefix_profile = prefix_profile..'/' + + if not love.filesystem.getInfo(prefix_profile..'meta.jkr') then + love.filesystem.append( prefix_profile..'meta.jkr', 'return {}' ) + end + + local meta = STR_UNPACK(get_compressed(prefix_profile..'meta.jkr') or 'return {}') + meta.unlocked = meta.unlocked or {} + meta.discovered = meta.discovered or {} + meta.alerted = meta.alerted or {} + + local _append = false + + for k, v in pairs(request.save_progress.UDA) do + if string.find(v, 'u') and not meta.unlocked[k] then + meta.unlocked[k] = true + _append = true + end + if string.find(v, 'd') and not meta.discovered[k] then + meta.discovered[k] = true + _append = true + end + if string.find(v, 'a') and not meta.alerted[k] then + meta.alerted[k] = true + _append = true + end + end + if _append then compress_and_save( prefix_profile..'meta.jkr', STR_PACK(meta)) end + + compress_and_save('settings.jkr', request.save_progress.SETTINGS) + compress_and_save(prefix_profile..'profile.jkr', request.save_progress.PROFILE) + + CHANNEL:push('done') + --Saves the settings file + elseif request.type == 'save_settings' then + compress_and_save('settings.jkr', request.save_settings) + compress_and_save(request.profile_num..'/profile.jkr', request.save_profile) + --Saves the metrics file + elseif request.type == 'save_metrics' then + compress_and_save('metrics.jkr', request.save_metrics) + --Saves any notifications + elseif request.type == 'save_notify' then + local prefix_profile = (request.profile_num or 1)..'' + if not love.filesystem.getInfo(prefix_profile) then love.filesystem.createDirectory( prefix_profile ) end + prefix_profile = prefix_profile..'/' + + if not love.filesystem.getInfo(prefix_profile..'unlock_notify.jkr') then love.filesystem.append( prefix_profile..'unlock_notify.jkr', '') end + local unlock_notify = get_compressed(prefix_profile..'unlock_notify.jkr') or '' + + if request.save_notify and not string.find(unlock_notify, request.save_notify) then + compress_and_save( prefix_profile..'unlock_notify.jkr', unlock_notify..request.save_notify..'\n') + end + + --Saves the run + elseif request.type == 'save_run' then + local prefix_profile = (request.profile_num or 1)..'' + if not love.filesystem.getInfo(prefix_profile) then love.filesystem.createDirectory( prefix_profile ) end + prefix_profile = prefix_profile..'/' + + tal_compress_and_save(prefix_profile..'save.jkr', request.save_table, request.talisman) + end + end +end diff --git a/lovely/dump/engine/ui.lua b/lovely/dump/engine/ui.lua index fa684a8..2821d3a 100644 --- a/lovely/dump/engine/ui.lua +++ b/lovely/dump/engine/ui.lua @@ -1,4 +1,4 @@ -LOVELY_INTEGRITY = '435a9e8ef1b3d548ef4488606196332b7d61c0a33e2dd2225ca6c7f97e3ec32b' +LOVELY_INTEGRITY = 'ed73ce7b68b17bbbc04af6cf80e1577d8c38357ce87c6952cf5f2319cb9a578d' --Class UIBox = Moveable:extend() @@ -990,7 +990,6 @@ function UIElement:click() G.NO_MOD_CURSOR_STACK = nil if self.config.choice then - local chosen_temp = self.config.chosen local chosen_temp = self.config.chosen local choices = self.UIBox:get_group(nil, self.config.group) for k, v in pairs(choices) do diff --git a/lovely/dump/functions/UI_definitions.lua b/lovely/dump/functions/UI_definitions.lua index 4c8c8bc..0014d7b 100644 --- a/lovely/dump/functions/UI_definitions.lua +++ b/lovely/dump/functions/UI_definitions.lua @@ -1,12 +1,10 @@ -LOVELY_INTEGRITY = '6732b4a403b7b8feb5e2decf7325ea96cac23686fd99e992f1aa1c26a7881bbe' +LOVELY_INTEGRITY = 'c4606c194e720d427e9e0e1b2181bd1cd60d72f540c2377514fa195a2271958b' --Create a global UIDEF that contains all UI definition functions\ --As a rule, these contain functions that return a table T representing the definition for a UIBox G.UIDEF = {} function create_UIBox_debug_tools() -local debugplus = require("debugplus.core") -debugplus.registerButtons() G.debug_tool_config = G.debug_tool_config or {} G.FUNCS.DT_add_money = function() if G.STAGE == G.STAGES.RUN then ease_dollars(10) end end G.FUNCS.DT_add_round = function() if G.STAGE == G.STAGES.RUN then ease_round(1) end end @@ -96,40 +94,7 @@ debugplus.registerButtons() {n=G.UIT.T, config={text = "Hover over any Joker/Playing card", scale = 0.25, colour = G.C.WHITE, shadow = true}} }}, {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "hold [" .. require("debugplus.util").ctrlText .. "] (togglable in config)", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "and press [Q] to cycle Edition", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [W] to cycle Enhancement", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [E] to cycle Seal", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [A/S/D] to toggle Eternal/Perishable/Rental", scale = 0.2, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [F] to toggle Coupon (make free)", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [R/C] to destroy/copy card", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [M] to reload atlases", scale = 0.25, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [UP/DOWN] to cycle rank", scale = 0.2, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.00}, nodes={ - {n=G.UIT.T, config={text = "press [RIGHT/LEFT] to cycle suit", scale = 0.2, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ - {n=G.UIT.T, config={text = "press [z] plus [1-3] to save a save state", scale = 0.2, colour = G.C.WHITE, shadow = true}} - }}, - {n=G.UIT.R, config={align = "cm", padding = 0.00}, nodes={ - {n=G.UIT.T, config={text = "press [x] plus [1-3] to load a save state", scale = 0.2, colour = G.C.WHITE, shadow = true}} + {n=G.UIT.T, config={text = "and press [Q] to cycle Edition", scale = 0.25, colour = G.C.WHITE, shadow = true}} }}, }}, {n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={ @@ -161,8 +126,6 @@ debugplus.registerButtons() UIBox_button{ label = {"+1 Discard"}, button = "DT_add_discard", minw = 1.7, minh = 0.4, scale = 0.35}, UIBox_button{ label = {"Boss Reroll"}, button = "DT_reroll_boss", minw = 1.7, minh = 0.4, scale = 0.35}, UIBox_button{ label = {"Background"}, button = "DT_toggle_background", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"Win Blind"}, button = "DT_win_blind", minw = 1.7, minh = 0.4, scale = 0.35}, - UIBox_button{ label = {"Double Tag"}, button = "DT_double_tag", minw = 1.7, minh = 0.4, scale = 0.35}, }}, {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes={ UIBox_button{ label = {"+10 chips"}, button = "DT_add_chips", minw = 1.7, minh = 0.4, scale = 0.35}, @@ -556,7 +519,6 @@ function G.UIDEF.deck_preview(args) end local suit_map = {'Spades', 'Hearts', 'Clubs', 'Diamonds'} - local SUITS_SORTED = Cartomancer.tablecopy(SUITS) local stones = nil local rank_name_mapping = {'A','K','Q','J','10',9,8,7,6,5,4,3,2} @@ -1048,7 +1010,6 @@ end end function create_UIBox_buttons() - if G.hand and G.hand.cart_sorting == nil then G.hand.cart_sorting = true end local text_scale = 0.45 local button_height = 1.3 local play_button = {n=G.UIT.C, config={id = 'play_button', align = "tm", minw = 2.5, padding = 0.3, r = 0.1, hover = true, colour = G.C.BLUE, button = "play_cards_from_highlighted", one_press = true, shadow = true, func = 'can_play'}, nodes={ @@ -1070,9 +1031,6 @@ end {n=G.UIT.C, config={align = "cm", padding = 0.1, r = 0.1, colour =G.C.UI.TRANSPARENT_DARK, outline = 1.5, outline_colour = mix_colours(G.C.WHITE,G.C.JOKER_GREY, 0.7), line_emboss = 1}, nodes={ {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ - Cartomancer.SETTINGS.improved_hand_sorting and - create_toggle{ col = true, label = localize('b_sort_hand'), label_scale = text_scale*0.8, scale = 0.30, w = 0, shadow = true, ref_table = G.hand, ref_value = 'cart_sorting', callback = function () G.FUNCS.cartomancer_sort_hand_off() end } - or {n=G.UIT.T, config={text = localize('b_sort_hand'), scale = text_scale*0.8, colour = G.C.UI.TEXT_LIGHT}} }}, {n=G.UIT.R, config={align = "cm", padding = 0.1}, nodes={ @@ -2027,11 +1985,11 @@ function create_slider(args) local t = {n=G.UIT.C, config={align = "cm", minw = args.w, min_h = args.h, padding = 0.1, r = 0.1, colour = G.C.CLEAR, focus_args = {type = 'slider'}}, nodes={ {n=G.UIT.C, config={align = "cl", minw = args.w, r = 0.1,min_h = args.h,collideable = true, hover = true, colour = G.C.BLACK,emboss = 0.05,func = 'slider', refresh_movement = true}, nodes={ - {n=G.UIT.B, config={id = args.id, w=startval,h=args.h, r = 0.1, colour = args.colour, ref_table = args, refresh_movement = true}}, + {n=G.UIT.B, config={w=startval,h=args.h, r = 0.1, colour = args.colour, ref_table = args, refresh_movement = true}}, }}, - not args.hide_val and {n=G.UIT.C, config={align = "cm", minh = args.h,r = 0.1, minw = 0.8, colour = args.colour,shadow = true}, nodes={ + {n=G.UIT.C, config={align = "cm", minh = args.h,r = 0.1, minw = 0.8, colour = args.colour,shadow = true}, nodes={ {n=G.UIT.T, config={ref_table = args, ref_value = 'text', scale = args.text_scale, colour = G.C.UI.TEXT_LIGHT, decimal_places = args.decimal_places}} - }} or nil + }}, }} if args.label then t = {n=G.UIT.R, config={align = "cm", minh = 1, minw = 1, padding = 0.1*args.label_scale, colour = G.C.CLEAR}, nodes={ @@ -2437,21 +2395,6 @@ function create_UIBox_settings() tab_definition_function_args = 'Audio' } - if not require("debugplus.config").SMODSLoaded then - tabs[#tabs+1] = { - label = "DebugPlus", - tab_definition_function = require("debugplus.config").fakeConfigTab, - } - end - local settings_icon = Cartomancer.add_settings_icon() - if settings_icon then - tabs[#tabs+1] = { - colour = G.C.MONEY, - custom_button = {settings_icon}, - tab_definition_function = Cartomancer.config_tab, - tab_definition_function_args = '' - } - end local t = create_UIBox_generic_options({back_func = 'options',contents = {create_tabs( {tabs = tabs, tab_h = 7.05, @@ -3252,8 +3195,8 @@ function create_UIBox_current_hand_row(handname, simple) (not simple and {n=G.UIT.R, config={align = "cm", padding = 0.05, r = 0.1, colour = darken(G.C.JOKER_GREY, 0.1), emboss = 0.05, hover = true, force_focus = true, on_demand_tooltip = {text = localize(handname, 'poker_hand_descriptions'), filler = {func = create_UIBox_hand_tip, args = handname}}}, nodes={ {n=G.UIT.C, config={align = "cl", padding = 0, minw = 5}, nodes={ - {n=G.UIT.C, config={align = "cm", padding = 0.01, r = 0.1, colour = G.C.HAND_LEVELS[math.min(7, G.GAME.hands[handname].level)], minw = 1.5, outline = 0.8, outline_colour = G.C.WHITE}, nodes={ - {n=G.UIT.T, config={text = localize('k_level_prefix')..G.GAME.hands[handname].level, scale = 0.5, colour = G.C.UI.TEXT_DARK}} + {n=G.UIT.C, config={align = "cm", padding = 0.01, r = 0.1, colour = G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands[handname].level)):to_number()], minw = 1.5, outline = 0.8, outline_colour = G.C.WHITE}, nodes={ + {n=G.UIT.T, config={text = localize('k_level_prefix')..number_format(G.GAME.hands[handname].level), scale = 0.5, colour = G.C.UI.TEXT_DARK}} }}, {n=G.UIT.C, config={align = "cm", minw = 4.5, maxw = 4.5}, nodes={ {n=G.UIT.T, config={text = ' '..localize(handname,'poker_hands'), scale = 0.45, colour = G.C.UI.TEXT_LIGHT, shadow = true}} @@ -3452,59 +3395,37 @@ function G.UIDEF.view_deck(unplayed_only) Diamonds = {}, } local suit_map = {'Spades', 'Hearts', 'Clubs', 'Diamonds'} - local SUITS_SORTED = Cartomancer.tablecopy(SUITS) for k, v in ipairs(G.playing_cards) do - local greyed - if unplayed_only and not ((v.area and v.area == G.deck) or v.ability.wheel_flipped) then - greyed = true - end - local card_string = v:cart_to_string() - if greyed then - card_string = card_string .. "Greyed" - end - if greyed and Cartomancer.SETTINGS.deck_view_hide_drawn_cards then - -- Ignore this card. - elseif not SUITS[v.base.suit][card_string] then - table.insert(SUITS_SORTED[v.base.suit], card_string) - - local _scale = 0.7 - local copy = copy_card(v, nil, _scale) - - copy.greyed = greyed - copy.stacked_quantity = 1 - - SUITS[v.base.suit][card_string] = copy - else - local stacked_card = SUITS[v.base.suit][card_string] - stacked_card.stacked_quantity = stacked_card.stacked_quantity + 1 - end + table.insert(SUITS[v.base.suit], v) end for j = 1, 4 do - if SUITS_SORTED[suit_map[j]][1] then + if SUITS[suit_map[j]][1] then local view_deck = CardArea( G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, 6.5*G.CARD_W, 0.6*G.CARD_H, - {card_limit = #SUITS_SORTED[suit_map[j]], type = 'title', view_deck = true, highlight_limit = 0, card_w = G.CARD_W*0.7, draw_layers = {'card'}}) + {card_limit = #SUITS[suit_map[j]], type = 'title', view_deck = true, highlight_limit = 0, card_w = G.CARD_W*0.7, draw_layers = {'card'}}) table.insert(deck_tables, {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ {n=G.UIT.O, config={object = view_deck}} }} ) - for i = 1, #SUITS_SORTED[suit_map[j]] do - local card_string = SUITS_SORTED[suit_map[j]][i] - local card = SUITS[suit_map[j]][card_string] - - card.T.x = view_deck.T.x + view_deck.T.w/2 - card.T.y = view_deck.T.y - card:create_quantity_display() - - card:hard_set_T() - view_deck:emplace(card) - - end + for i = 1, #SUITS[suit_map[j]] do + if SUITS[suit_map[j]][i] then + local greyed, _scale = nil, 0.7 + if unplayed_only and not ((SUITS[suit_map[j]][i].area and SUITS[suit_map[j]][i].area == G.deck) or SUITS[suit_map[j]][i].ability.wheel_flipped) then + greyed = true + end + local copy = copy_card(SUITS[suit_map[j]][i],nil, _scale) + copy.greyed = greyed + copy.T.x = view_deck.T.x + view_deck.T.w/2 + copy.T.y = view_deck.T.y + copy:hard_set_T() + view_deck:emplace(copy) + end + end end end @@ -3618,7 +3539,6 @@ function G.UIDEF.view_deck(unplayed_only) {n=G.UIT.C, config={align = "cm", padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables} }}, {n=G.UIT.R, config={align = "cm", minh = 0.8, padding = 0.05}, nodes={ - not unplayed_only and Cartomancer.add_unique_count() or nil, modded and {n=G.UIT.R, config={align = "cm"}, nodes={ {n=G.UIT.C, config={padding = 0.3, r = 0.1, colour = mix_colours(G.C.BLUE, G.C.WHITE,0.7)}, nodes = {}}, {n=G.UIT.T, config={text =' '..localize('ph_deck_preview_effective'),colour = G.C.WHITE, scale =0.3}}, @@ -4337,20 +4257,9 @@ function create_UIBox_your_collection_blinds(exit) end) })) - local min_ante = 1 - local max_ante = 16 - local spacing = 1 - 15*0.06 - if G.GAME and G.GAME.round_resets and G.GAME.round_resets.ante then - local current_ante = G.GAME.round_resets.ante - - if current_ante > 8 then - min_ante = current_ante - 8 + 1 - max_ante = current_ante + 8 - end - end local ante_amounts = {} - for i = min_ante, max_ante do - -- :3 + for i = 1, math.min(16, math.max(16, G.PROFILES[G.SETTINGS.profile].high_scores.furthest_ante.amt)) do + local spacing = 1 - math.min(20, math.max(15, G.PROFILES[G.SETTINGS.profile].high_scores.furthest_ante.amt))*0.06 if spacing > 0 and i > 1 then ante_amounts[#ante_amounts+1] = {n=G.UIT.R, config={minh = spacing}, nodes={}} end @@ -6455,13 +6364,6 @@ function UIBox_button(args) local but_UI_label = {} local button_pip = nil - if args.dynamic_label then - but_UI_label = {} - - table.insert(but_UI_label, {n=G.UIT.R, config={align = "cm", padding = 0, minw = args.minw, maxw = args.maxw}, nodes={ - {n=G.UIT.T, config={ref_table = args.dynamic_label, ref_value = 'text', scale = args.scale, colour = args.text_colour, shadow = args.shadow, focus_args = button_pip and args.focus_args or nil, func = button_pip,}} - }}) - end for k, v in ipairs(args.label) do if k == #args.label and args.focus_args and args.focus_args.set_button_pip then button_pip ='set_button_pip' @@ -6486,7 +6388,7 @@ function UIBox_button(args) padding = args.padding or 0, r = 0.1, hover = true, - colour = args.ref_table and args.ref_table.colour or args.colour, -- Cartomancer + colour = args.colour, one_press = args.one_press, button = (args.button ~= 'nil') and args.button or nil, choice = args.choice, @@ -6500,6 +6402,6 @@ function UIBox_button(args) ref_table = args.ref_table, mid = args.mid }, nodes= - args.ref_table and args.ref_table.custom_button or but_UI_label -- Cartomancer + but_UI_label }}} end diff --git a/lovely/dump/functions/button_callbacks.lua b/lovely/dump/functions/button_callbacks.lua index bb48dfb..ecaa550 100644 --- a/lovely/dump/functions/button_callbacks.lua +++ b/lovely/dump/functions/button_callbacks.lua @@ -1,4 +1,4 @@ -LOVELY_INTEGRITY = 'd7f48a66f05694a22b7aae4c15c27e443dc398089f32ae2891b595f051091e07' +LOVELY_INTEGRITY = 'e36471bd79b456102440b1c69061665aed2f0a92e67cfd840d15eafe4e55be17' --Moves the tutorial to the next step in queue -- @@ -55,7 +55,7 @@ end ---@param e {} --**e** Is the UIE that called this function G.FUNCS.can_buy = function(e) - if (e.config.ref_table.cost > G.GAME.dollars - G.GAME.bankrupt_at) and (e.config.ref_table.cost > 0) then + if (to_big(e.config.ref_table.cost) > to_big(G.GAME.dollars) - to_big(G.GAME.bankrupt_at)) and (e.config.ref_table.cost > 0) then e.config.colour = G.C.UI.BACKGROUND_INACTIVE e.config.button = nil else @@ -77,7 +77,7 @@ end ---@param e {} --**e** Is the UIE that called this function G.FUNCS.can_buy_and_use = function(e) - if (((e.config.ref_table.cost > G.GAME.dollars - G.GAME.bankrupt_at) and (e.config.ref_table.cost > 0)) or (not e.config.ref_table:can_use_consumeable())) then + if (((to_big(e.config.ref_table.cost) > to_big(G.GAME.dollars) - to_big(G.GAME.bankrupt_at)) and (e.config.ref_table.cost > 0)) or (not e.config.ref_table:can_use_consumeable())) then e.UIBox.states.visible = false e.config.colour = G.C.UI.BACKGROUND_INACTIVE e.config.button = nil @@ -96,7 +96,7 @@ end ---@param e {} --**e** Is the UIE that called this function G.FUNCS.can_redeem = function(e) - if e.config.ref_table.cost > G.GAME.dollars - G.GAME.bankrupt_at then + if to_big(e.config.ref_table.cost) > to_big(G.GAME.dollars) - to_big(G.GAME.bankrupt_at) then e.config.colour = G.C.UI.BACKGROUND_INACTIVE e.config.button = nil else @@ -111,7 +111,7 @@ end ---@param e {} --**e** Is the UIE that called this function G.FUNCS.can_open = function(e) - if (e.config.ref_table.cost) > 0 and (e.config.ref_table.cost > G.GAME.dollars - G.GAME.bankrupt_at) then + if (e.config.ref_table.cost) > 0 and (to_big(e.config.ref_table.cost) > to_big(G.GAME.dollars) - to_big(G.GAME.bankrupt_at)) then e.config.colour = G.C.UI.BACKGROUND_INACTIVE e.config.button = nil else @@ -2020,12 +2020,12 @@ G.FUNCS.flame_handler = function(e) local exptime = math.exp(-0.4*G.real_dt) if to_big(G.ARGS.score_intensity.earned_score) >= to_big(G.ARGS.score_intensity.required_score) and to_big(G.ARGS.score_intensity.required_score) > to_big(0) then - _F.intensity = ((G.pack_cards and not G.pack_cards.REMOVED) or (G.TAROT_INTERRUPT)) and 0 or Cartomancer.get_flames_intensity() + _F.intensity = ((G.pack_cards and not G.pack_cards.REMOVED) or (G.TAROT_INTERRUPT)) and 0 or math.max(0., math.log(G.ARGS.score_intensity.earned_score, 5)-2) else _F.intensity = 0 end - _F.timer = Cartomancer.handle_flames_timer(_F.timer, _F.intensity) + _F.timer = _F.timer + G.real_dt*(1 + _F.intensity*0.2) if _F.intensity_vel < 0 then _F.intensity_vel = _F.intensity_vel*(1 - 10*G.real_dt) end _F.intensity_vel = (1-exptime)*(_F.intensity - _F.real_intensity)*G.real_dt*25 + exptime*_F.intensity_vel _F.real_intensity = math.max(0, _F.real_intensity + _F.intensity_vel) @@ -2078,7 +2078,7 @@ end end G.FUNCS.can_reroll = function(e) - if ((G.GAME.dollars-G.GAME.bankrupt_at) - G.GAME.current_round.reroll_cost < 0) and G.GAME.current_round.reroll_cost ~= 0 then + if ((to_big(G.GAME.dollars)-to_big(G.GAME.bankrupt_at)) - to_big(G.GAME.current_round.reroll_cost) < to_big(0)) and G.GAME.current_round.reroll_cost ~= 0 then e.config.colour = G.C.UI.BACKGROUND_INACTIVE e.config.button = nil --e.children[1].children[1].config.shadow = false diff --git a/lovely/dump/functions/common_events.lua b/lovely/dump/functions/common_events.lua index 6c6400a..f6fee75 100644 --- a/lovely/dump/functions/common_events.lua +++ b/lovely/dump/functions/common_events.lua @@ -1,4 +1,4 @@ -LOVELY_INTEGRITY = '2c8ce4c0bac30f3323a4c474be97cee2bdcdd76ecf06cecea0a240c944640f67' +LOVELY_INTEGRITY = 'ab00e08d711a2c3f72976a640fd09ce67bc5a2fbcc3a1d480a50325ec883c75e' function set_screen_positions() if G.STAGE == G.STAGES.RUN then @@ -75,7 +75,7 @@ function ease_dollars(mod, instant) mod = mod or 0 local text = '+'..localize('$') local col = G.C.MONEY - if mod < 0 then + if to_big(mod) < to_big(0) then text = '-'..localize('$') col = G.C.RED else @@ -120,7 +120,7 @@ function ease_discard(mod, instant, silent) mod = math.max(-G.GAME.current_round.discards_left, mod) local text = '+' local col = G.C.GREEN - if mod < 0 then + if to_big(mod) < to_big(0) then text = '' col = G.C.RED end @@ -159,7 +159,7 @@ function ease_hands_played(mod, instant) mod = mod or 0 local text = '+' local col = G.C.GREEN - if mod < 0 then + if to_big(mod) < to_big(0) then text = '' col = G.C.RED end @@ -200,7 +200,7 @@ function ease_ante(mod) mod = mod or 0 local text = '+' local col = G.C.IMPORTANT - if mod < 0 then + if to_big(mod) < to_big(0) then text = '-' col = G.C.RED end @@ -235,7 +235,7 @@ function ease_round(mod) mod = mod or 0 local text = '+' local col = G.C.IMPORTANT - if mod < 0 then + if to_big(mod) < to_big(0) then text = '' col = G.C.RED end @@ -405,9 +405,6 @@ function draw_card(from, to, percent, dir, sort, card, delay, mute, stay_flipped if card then if from then card = from:remove_card(card) end if card then drawn = true end - if card and to == G.hand and not card.states.visible then - card.states.visible = true - end local stay_flipped = G.GAME and G.GAME.blind and G.GAME.blind:stay_flipped(to, card) if G.GAME.modifiers.flipped_cards and to == G.hand then if pseudorandom(pseudoseed('flipped_card')) < 1/G.GAME.modifiers.flipped_cards then @@ -487,7 +484,7 @@ function level_up_hand(card, hand, instant, amount) G.GAME.hands[hand].mult = math.max(G.GAME.hands[hand].mult * (universum_mod)^amount, 1) G.GAME.hands[hand].chips = math.max(G.GAME.hands[hand].chips * (universum_mod)^amount, 1) end - if not instant then + if not instant and not Talisman.config_file.disable_anims then G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function() play_sound('tarot1') if card and card.juice_up then card:juice_up(0.8, 0.5) end @@ -577,8 +574,8 @@ function update_hand_text(config, vals) G.GAME.current_round.current_hand.hand_level = vals.level else G.GAME.current_round.current_hand.hand_level = ' '..localize('k_lvl')..tostring(vals.level) - if type(vals.level) == 'number' then - G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[math.min(vals.level, 7)] + if is_number(vals.level) then + G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[to_big(math.min(vals.level, 7)):to_number()] else G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[1] end @@ -954,12 +951,12 @@ function card_eval_status_text(card, eval_type, amt, percent, dir, extra) sound = 'chips1' amt = amt colour = G.C.CHIPS - text = localize{type='variable',key='a_chips'..(amt<0 and '_minus' or ''),vars={math.abs(amt)}} + text = localize{type='variable',key='a_chips'..(to_big(amt) 60 or num_dollars < -60 then + num_dollars = to_number(num_dollars); if math.abs(to_number(num_dollars)) > 60 then if num_dollars < 0 then --if negative G.E_MANAGER:add_event(Event({ trigger = 'before',delay = 0.38, @@ -1345,7 +1342,7 @@ function change_shop_size(mod) if not G.GAME.shop then return end G.GAME.shop.joker_max = G.GAME.shop.joker_max + mod if G.shop_jokers and G.shop_jokers.cards then - if mod < 0 then + if to_big(mod) < to_big(0) then --Remove jokers in shop for i = #G.shop_jokers.cards, G.GAME.shop.joker_max+1, -1 do if G.shop_jokers.cards[i] then @@ -1477,7 +1474,7 @@ function check_for_unlock(args) end end if args.type == 'money' then - if G.GAME.dollars >= 400 then + if to_big(G.GAME.dollars) >= to_big(400) then unlock_achievement('nest_egg') end end @@ -1514,7 +1511,7 @@ function check_for_unlock(args) end end if args.type == 'upgrade_hand' then - if args.level >= 10 then + if to_big(args.level) >= to_big(10) then unlock_achievement('retrograde') end end @@ -1751,7 +1748,7 @@ function check_for_unlock(args) end end if args.type == 'money' then - if card.unlock_condition.extra <= G.GAME.dollars then + if to_big(card.unlock_condition.extra) <= to_big(G.GAME.dollars) then ret = true unlock_card(card) end @@ -3123,7 +3120,7 @@ function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, h elseif _c.set == 'Planet' then loc_vars = { G.GAME.hands[cfg.hand_type].level,localize(cfg.hand_type, 'poker_hands'), G.GAME.hands[cfg.hand_type].l_mult, G.GAME.hands[cfg.hand_type].l_chips, - colours = {(G.GAME.hands[cfg.hand_type].level==1 and G.C.UI.TEXT_DARK or G.C.HAND_LEVELS[math.min(7, G.GAME.hands[cfg.hand_type].level)])} + colours = {(to_big(G.GAME.hands[cfg.hand_type].level)==to_big(1) and G.C.UI.TEXT_DARK or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands[cfg.hand_type].level)):to_number()])} } localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = _c.vars or loc_vars} elseif _c.set == 'Tarot' then diff --git a/lovely/dump/functions/misc_functions.lua b/lovely/dump/functions/misc_functions.lua index d4bb369..8c30e57 100644 --- a/lovely/dump/functions/misc_functions.lua +++ b/lovely/dump/functions/misc_functions.lua @@ -1,4 +1,4 @@ -LOVELY_INTEGRITY = '7af2e0e0690a3e982bc378e0f2810cf02634e614841ab27a2036b576c0fdc825' +LOVELY_INTEGRITY = '947c501831366deb5e5f19e43dac710ed1309c3fcf0da962c8524122a4e9a142' --Updates all display information for all displays for a given screenmode. Returns the key for the resolution option cycle -- @@ -818,7 +818,7 @@ function modulate_sound(dt) for k, v in pairs(G.ARGS.ambient_sounds) do AC[k] = AC[k] or {} AC[k].per = (k == 'ambientOrgan1') and 0.7 or (k == 'ambientFire1' and 1.1) or (k == 'ambientFire2' and 1.05) or 1 - AC[k].vol = Cartomancer.handle_flames_volume((not G.video_organ and G.STATE == G.STATES.SPLASH) and 0 or AC[k].vol and v.volfunc(AC[k].vol) or 0) + AC[k].vol = (not G.video_organ and G.STATE == G.STATES.SPLASH) and 0 or AC[k].vol and v.volfunc(AC[k].vol) or 0 end G.ARGS.push = G.ARGS.push or {} diff --git a/lovely/dump/functions/state_events.lua b/lovely/dump/functions/state_events.lua index cbb1e7e..acc06e7 100644 --- a/lovely/dump/functions/state_events.lua +++ b/lovely/dump/functions/state_events.lua @@ -1,4 +1,4 @@ -LOVELY_INTEGRITY = '4e744c84a896d13965c350778ddd9bc20dc5aeec8b4dd69951b460db6f5383cb' +LOVELY_INTEGRITY = '444830d91f018dc97aacd41f468f575ea3ad4eea5095b8d83a79bd7e8a40c1ff' function win_game() if (not G.GAME.seeded and not G.GAME.challenge) or SMODS.config.seeded_unlocks then @@ -1090,7 +1090,7 @@ G.FUNCS.evaluate_round = function() dollars = dollars + ret.dollars end end - if G.GAME.dollars >= 5 and not G.GAME.modifiers.no_interest and G.GAME.cry_payload then + if to_big(G.GAME.dollars) >= to_big(5) and not G.GAME.modifiers.no_interest and G.GAME.cry_payload then add_round_eval_row({bonus = true, payload = G.GAME.cry_payload, name='interest_payload', pitch = pitch, dollars = G.GAME.interest_amount*G.GAME.cry_payload*math.min(math.floor(G.GAME.dollars/5), G.GAME.interest_cap/5)}) pitch = pitch + 0.06 if not G.GAME.seeded and not G.GAME.challenge then @@ -1103,7 +1103,7 @@ G.FUNCS.evaluate_round = function() check_for_unlock({type = 'interest_streak'}) dollars = dollars + G.GAME.interest_amount*G.GAME.cry_payload*math.min(math.floor(G.GAME.dollars/5), G.GAME.interest_cap/5) G.GAME.cry_payload = nil - elseif G.GAME.dollars >= 5 and not G.GAME.modifiers.no_interest then + elseif to_big(G.GAME.dollars) >= to_big(5) and not G.GAME.modifiers.no_interest then add_round_eval_row({bonus = true, name='interest', pitch = pitch, dollars = G.GAME.interest_amount*math.min(math.floor(G.GAME.dollars/5), G.GAME.interest_cap/5)}) pitch = pitch + 0.06 if (not G.GAME.seeded and not G.GAME.challenge) or SMODS.config.seeded_unlocks then diff --git a/lovely/dump/game.lua b/lovely/dump/game.lua index 3c0b2d8..0582f02 100644 --- a/lovely/dump/game.lua +++ b/lovely/dump/game.lua @@ -1,4 +1,4 @@ -LOVELY_INTEGRITY = '4af0a05e5998e1bbb1bd6610b6f3d87c6fea5c42d526b7d7d6bd3d6bf983044e' +LOVELY_INTEGRITY = 'fff73090942942422c5293599c9a5f94fd18419e9275888a510770e6688dd01c' --Class Game = Object:extend() @@ -109,109 +109,7 @@ function Game:start_up() boot_timer('window init', 'savemanager') --call the save manager to wait for any save requests G.SAVE_MANAGER = { - thread = love.thread.newThread([[require "love.system" - - if (love.system.getOS() == 'OS X' ) and (jit.arch == 'arm64' or jit.arch == 'arm') then jit.off() end - - require "love.timer" - require "love.thread" - require 'love.filesystem' - require "engine/object" - require "engine/string_packer" - - --vars needed for sound manager thread - CHANNEL = love.thread.getChannel("save_request") - - talisman = "]] .. Talisman.config_file.break_infinity .. [[" - - --untested - function tal_compress_and_save(_file, _data) - local save_string = type(_data) == 'table' and STR_PACK(_data) or _data - local fallback_save = STR_PACK({GAME = {won = true}}) --just bare minimum to not crash, maybe eventually display some info? - if talisman == 'bignumber' then - fallback_save = "if not BigMeta then " .. fallback_save - elseif talisman == 'omeganum' then - fallback_save = "if not OmegaMeta then " .. fallback_save - else - fallback_save = "if BigMeta or OmegaMeta then " .. fallback_save - end - fallback_save = fallback_save .. " end" - save_string = fallback_save .. " " .. save_string - save_string = love.data.compress('string', 'deflate', save_string, 1) - love.filesystem.write(_file,save_string) - end - - while true do - --Monitor the channel for any new requests - local request = CHANNEL:demand() -- Value from channel - if request then - --Saves progress for settings, unlocks, alerts and discoveries - if request.type == 'save_progress' then - local prefix_profile = (request.save_progress.SETTINGS.profile or 1)..'' - if not love.filesystem.getInfo(prefix_profile) then love.filesystem.createDirectory( prefix_profile ) end - prefix_profile = prefix_profile..'/' - - if not love.filesystem.getInfo(prefix_profile..'meta.jkr') then - love.filesystem.append( prefix_profile..'meta.jkr', 'return {}' ) - end - - local meta = STR_UNPACK(get_compressed(prefix_profile..'meta.jkr') or 'return {}') - meta.unlocked = meta.unlocked or {} - meta.discovered = meta.discovered or {} - meta.alerted = meta.alerted or {} - - local _append = false - - for k, v in pairs(request.save_progress.UDA) do - if string.find(v, 'u') and not meta.unlocked[k] then - meta.unlocked[k] = true - _append = true - end - if string.find(v, 'd') and not meta.discovered[k] then - meta.discovered[k] = true - _append = true - end - if string.find(v, 'a') and not meta.alerted[k] then - meta.alerted[k] = true - _append = true - end - end - if _append then compress_and_save( prefix_profile..'meta.jkr', STR_PACK(meta)) end - - compress_and_save('settings.jkr', request.save_progress.SETTINGS) - compress_and_save(prefix_profile..'profile.jkr', request.save_progress.PROFILE) - - CHANNEL:push('done') - --Saves the settings file - elseif request.type == 'save_settings' then - compress_and_save('settings.jkr', request.save_settings) - compress_and_save(request.profile_num..'/profile.jkr', request.save_profile) - --Saves the metrics file - elseif request.type == 'save_metrics' then - compress_and_save('metrics.jkr', request.save_metrics) - --Saves any notifications - elseif request.type == 'save_notify' then - local prefix_profile = (request.profile_num or 1)..'' - if not love.filesystem.getInfo(prefix_profile) then love.filesystem.createDirectory( prefix_profile ) end - prefix_profile = prefix_profile..'/' - - if not love.filesystem.getInfo(prefix_profile..'unlock_notify.jkr') then love.filesystem.append( prefix_profile..'unlock_notify.jkr', '') end - local unlock_notify = get_compressed(prefix_profile..'unlock_notify.jkr') or '' - - if request.save_notify and not string.find(unlock_notify, request.save_notify) then - compress_and_save( prefix_profile..'unlock_notify.jkr', unlock_notify..request.save_notify..'\n') - end - - --Saves the run - elseif request.type == 'save_run' then - local prefix_profile = (request.profile_num or 1)..'' - if not love.filesystem.getInfo(prefix_profile) then love.filesystem.createDirectory( prefix_profile ) end - prefix_profile = prefix_profile..'/' - - tal_compress_and_save(prefix_profile..'save.jkr', request.save_table) - end - end - end]]), + thread = love.thread.newThread('engine/save_manager.lua'), channel = love.thread.getChannel('save_request') } G.SAVE_MANAGER.thread:start(2) @@ -322,7 +220,6 @@ function Game:start_up() end end set_profile_progress() - Cartomancer.load_mod_file('internal/localization.lua', 'localization') boot_timer('prep stage', 'splash prep',1) self:splash_screen() boot_timer('splash prep', 'end',1) @@ -1355,7 +1252,7 @@ function Game:prep_stage(new_stage, new_state, new_game_obj) self.CONTROLLER.locks[k] = nil end if new_game_obj then self.GAME = self:init_game_object() end - if new_game_obj and Talisman and Talisman.igo then self.GAME = Talisman.igo(self.GAME) end + if Talisman and Talisman.igo then self.GAME = Talisman.igo(self.GAME) end self.STAGE = new_stage or self.STAGES.MAIN_MENU self.STATE = new_state or self.STATES.MENU self.STATE_COMPLETE = false @@ -2193,7 +2090,7 @@ function Game:start_run(args) local selected_back = saveTable and saveTable.BACK.name or (args.challenge and args.challenge.deck and args.challenge.deck.type) or (self.GAME.viewed_back and self.GAME.viewed_back.name) or self.GAME.selected_back and self.GAME.selected_back.name or 'Red Deck' selected_back = get_deck_from_name(selected_back) self.GAME = saveTable and saveTable.GAME or self:init_game_object() - if (not saveTable or not saveTable.GAME) and Talisman and Talisman.igo then self.GAME = Talisman.igo(self.GAME) end + if Talisman and Talisman.igo then self.GAME = Talisman.igo(self.GAME) end Handy.UI.init() self.GAME.modifiers = self.GAME.modifiers or {} self.GAME.stake = args.stake or self.GAME.stake or 1 @@ -2656,7 +2553,6 @@ function Game:start_run(args) reset_blinds() end - Cartomancer.update_tags_visibility() G.FUNCS.blind_chip_UI_scale(G.hand_text_area.blind_chips) self.HUD:recalculate() @@ -2693,7 +2589,7 @@ function Game:update(dt) self.TIMERS.BACKGROUND = self.TIMERS.BACKGROUND + dt*(G.ARGS.spin and G.ARGS.spin.amount or 0) self.real_dt = dt - if require('debugplus.config').getValue('enableLongDT') and self.real_dt > 0.05 then print('LONG DT @ '..math.floor(G.TIMERS.REAL)..': '..self.real_dt) end + if self.real_dt > 0.05 then print('LONG DT @ '..math.floor(G.TIMERS.REAL)..': '..self.real_dt) end if not G.fbf or G.new_frame then G.new_frame = false @@ -2711,7 +2607,7 @@ function Game:update(dt) if G.STATE ~= G.ACC_state then G.ACC = 0 end G.ACC_state = G.STATE - if (G.STATE == G.STATES.HAND_PLAYED) or (G.STATE == G.STATES.NEW_ROUND) or Incantation and Incantation.accelerate then + if (G.STATE == G.STATES.HAND_PLAYED) or (G.STATE == G.STATES.NEW_ROUND) then G.ACC = math.min((G.ACC or 0) + dt*0.2*self.SETTINGS.GAMESPEED, 16) elseif Handy.insta_cash_out.is_skipped then G.ACC = 999 else @@ -2955,6 +2851,7 @@ function Game:update(dt) if G.FILE_HANDLER.run then G.SAVE_MANAGER.channel:push({ type = 'save_run', + talisman = Talisman.config_file.break_infinity, save_table = G.ARGS.save_run, profile_num = G.SETTINGS.profile}) G.SAVED_GAME = nil @@ -3210,23 +3107,11 @@ love.graphics.pop() timer_checkpoint('canvas', 'draw') - if require("debugplus.config").getValue("showHUD") and not G.video_control and G.F_VERBOSE then + if not _RELEASE_MODE and G.DEBUG and not G.video_control and G.F_VERBOSE then love.graphics.push() love.graphics.setColor(0, 1, 1,1) local fps = love.timer.getFPS( ) - do - local otherSize = 0 - for k,v in pairs(G.E_MANAGER.queues or {}) do - if k ~= 'base' then - otherSize = otherSize + #v - end - end - if otherSize ~= 0 then - love.graphics.print(string.format("Current FPS: %d\nBase event queue: %d\nOther event queues: %d", fps, #(G.E_MANAGER.queues and G.E_MANAGER.queues.base or {}), otherSize), 10, 10) - else - love.graphics.print(string.format("Current FPS: %d\nBase event queue: %d", fps, #(G.E_MANAGER.queues and G.E_MANAGER.queues.base or {})), 10, 10) - end - end + love.graphics.print("Current FPS: "..fps, 10, 10) if G.check and G.SETTINGS.perf_mode then local section_h = 30 @@ -3245,10 +3130,6 @@ love.graphics.pop() end love.graphics.rectangle('fill', 10+poll_w*kk, 20 + v_off, 5*poll_w, -(vv)*resolution) end - v_off = v_off + section_h - end - local v_off = v_off - section_h * #b.checkpoint_list - for k, v in ipairs(b.checkpoint_list) do love.graphics.setColor(a == 2 and 0.5 or 1, a == 2 and 1 or 0.5, 1,1) love.graphics.print(v.label..': '..(string.format("%.2f",1000*(v.average or 0)))..'\n', 10, -section_h + 30 + v_off) v_off = v_off + section_h diff --git a/lovely/dump/main.lua b/lovely/dump/main.lua index 9ca8190..d827f38 100644 --- a/lovely/dump/main.lua +++ b/lovely/dump/main.lua @@ -1,148 +1,4 @@ -LOVELY_INTEGRITY = 'bb0f108ed0f5fea2a65f1d93362d3d1e1561e17a19a8c7e0d07c0cc4747d3696' - - -local Cartomancer_replacements = { - { - find = [[ - for k, v in ipairs%(G%.playing_cards%) do - if v%.base%.suit then table%.insert%(SUITS%[v%.base%.suit%], v%) end]], - -- Steamodded<0917b - find_alt = [[ - for k, v in ipairs%(G%.playing_cards%) do - table%.insert%(SUITS%[v%.base%.suit%], v%)]], - place = [[ -local SUITS_SORTED = Cartomancer.tablecopy(SUITS) -for k, v in ipairs(G.playing_cards) do - if v.base.suit then - local greyed - if unplayed_only and not ((v.area and v.area == G.deck) or v.ability.wheel_flipped) then - greyed = true - end - local card_string = v:cart_to_string() - if greyed then - card_string = card_string .. "Greyed" -- for some reason format doesn't work and final string is `sGreyed` - end - if greyed and Cartomancer.SETTINGS.deck_view_hide_drawn_cards then - -- Ignore this card. - elseif not Cartomancer.SETTINGS.deck_view_stack_enabled then - -- Don't stack cards - local _scale = 0.7 - local copy = copy_card(v, nil, _scale) - - copy.greyed = greyed - copy.stacked_quantity = 1 - table.insert(SUITS_SORTED[v.base.suit], copy) - - elseif not SUITS[v.base.suit][card_string] then - -- Initiate stack - table.insert(SUITS_SORTED[v.base.suit], card_string) - - local _scale = 0.7 - local copy = copy_card(v, nil, _scale) - - copy.greyed = greyed - copy.stacked_quantity = 1 - - SUITS[v.base.suit][card_string] = copy - else - -- Stack cards - local stacked_card = SUITS[v.base.suit][card_string] - stacked_card.stacked_quantity = stacked_card.stacked_quantity + 1 - end - end]] - }, - - { - find = "card_limit = #SUITS%[suit_map%[j%]%],", - place = "card_limit = #SUITS_SORTED[suit_map[j]]," - }, - - { - find = [[ -for i = 1%, %#SUITS%[suit_map%[j%]%] do - if SUITS%[suit_map%[j%]%]%[i%] then - local greyed%, _scale = nil%, 0%.7 - if unplayed_only and not %(%(SUITS%[suit_map%[j%]%]%[i%]%.area and SUITS%[suit_map%[j%]%]%[i%]%.area == G%.deck%) or SUITS%[suit_map%[j%]%]%[i%]%.ability%.wheel_flipped%) then - greyed = true - end - local copy = copy_card%(SUITS%[suit_map%[j%]%]%[i%]%, nil%, _scale%) - copy%.greyed = greyed - copy%.T%.x = view_deck%.T%.x %+ view_deck%.T%.w %/ 2 - copy%.T%.y = view_deck%.T%.y - - copy:hard_set_T%(%) - view_deck:emplace%(copy%) - end - end]], - place = [[ -for i = 1%, %#SUITS_SORTED%[suit_map%[j%]%] do - local card - if not Cartomancer.SETTINGS.deck_view_stack_enabled then - card = SUITS_SORTED%[suit_map%[j%]%]%[i%] - else - local card_string = SUITS_SORTED%[suit_map%[j%]%]%[i%] - card = SUITS%[suit_map%[j%]%]%[card_string%] - end - - card%.T%.x = view_deck%.T%.x %+ view_deck%.T%.w%/2 - card%.T%.y = view_deck%.T%.y - card:create_quantity_display%(%) - - card:hard_set_T%(%) - view_deck:emplace%(card%) -end]] - }, - - { - find = ' modded and {n = G.UIT.R, config = {align = "cm"}, nodes = {', - place = [=[ - not unplayed_only and Cartomancer.add_unique_count() or nil, - modded and {n = G.UIT.R, config = {align = "cm"}, nodes = {]=] - }, - -} - - --- Mom, can we have lovely patches for overrides.lua? --- No, we have lovely patches at home - --- Lovely patches at home: - -local Cartomancer_nfs_read -local Cartomancer_nfs_read_override = function (containerOrName, nameOrSize, sizeOrNil) - local data, size = Cartomancer_nfs_read(containerOrName, nameOrSize, sizeOrNil) - - if type(containerOrName) ~= "string" then - return data, size - end - local overrides = '/overrides.lua' - if containerOrName:sub(-#overrides) ~= overrides then - return data, size - end - - local replaced = 0 - local total_replaced = 0 - for _, v in ipairs(Cartomancer_replacements) do - data, replaced = string.gsub(data, v.find, v.place) - - if replaced == 0 and v.find_alt then - data, replaced = string.gsub(data, v.find_alt, v.place) - end - - if replaced == 0 then - print("Failed to replace " .. v.find .. " for overrides.lua") - else - total_replaced = total_replaced + 1 - end - end - - print("Totally applied " .. total_replaced .. " replacements to overrides.lua") - - -- We no longer need this override - NFS.read = Cartomancer_nfs_read - - return data, size -end +LOVELY_INTEGRITY = '7a80102588959caa0bf8986947ac508ff87fd856221043d85aeb54a472571ab0' --- STEAMODDED CORE --- MODULE STACKTRACE @@ -1001,10 +857,6 @@ injectStackTrace() -- --------MOD CORE API STACKTRACE END----------- if (love.system.getOS() == 'OS X' ) and (jit.arch == 'arm64' or jit.arch == 'arm') then jit.off() end -do - local logger = require("debugplus.logger") - logger.registerLogHandler() -end require "engine/object" require "bit" require "engine/string_packer" @@ -1150,17 +1002,10 @@ function love.draw() --Perf monitoring checkpoint timer_checkpoint(nil, 'draw', true) G:draw() - do - local console = require("debugplus.console") - console.doConsoleRender() - timer_checkpoint('DebugPlus Console', 'draw') - end end function love.keypressed(key) if Handy.controller.process_key(key, false) then return end -local console = require("debugplus.console") -if not console.consoleHandleKey(key) then return end if not _RELEASE_MODE and G.keybind_mapping[key] then love.gamepadpressed(G.CONTROLLER.keyboard_controller, G.keybind_mapping[key]) else G.CONTROLLER:set_HID_flags('mouse') @@ -1480,10 +1325,6 @@ end SMODS.path = find_self(SMODS.MODS_DIR, 'core.lua', '--- STEAMODDED CORE') -Cartomancer_nfs_read = NFS.read -NFS.read = Cartomancer_nfs_read_override - - for _, path in ipairs { "src/ui.lua", "src/index.lua", @@ -3771,7 +3612,9 @@ if Talisman.config_file.break_infinity then v.s_mult = to_big(v.s_mult) v.l_chips = to_big(v.l_chips) v.l_mult = to_big(v.l_mult) + v.level = to_big(v.level) end + obj.starting_params.dollars = to_big(obj.starting_params.dollars) return obj end @@ -3793,6 +3636,11 @@ if Talisman.config_file.break_infinity then if type(x) == 'table' then return x:floor() end return mf(x) end + local mc = math.ceil + function math.ceil(x) + if type(x) == 'table' then return x:ceil() end + return mc(x) + end local l10 = math.log10 function math.log10(x) @@ -3908,6 +3756,25 @@ if Talisman.config_file.break_infinity then end--]] --going to hold off on modifying this until proper save loading exists end + local ics = inc_career_stat + -- This is used often for unlocks, so we can't just prevent big money from being added + -- Also, I'm completely overriding this, since I don't think any mods would want to change it + function inc_career_stat(stat, mod) + if G.GAME.seeded or G.GAME.challenge then return end + if not G.PROFILES[G.SETTINGS.profile].career_stats[stat] then G.PROFILES[G.SETTINGS.profile].career_stats[stat] = 0 end + G.PROFILES[G.SETTINGS.profile].career_stats[stat] = G.PROFILES[G.SETTINGS.profile].career_stats[stat] + (mod or 0) + -- Make sure this isn't ever a talisman number + if type(G.PROFILES[G.SETTINGS.profile].career_stats[stat]) == 'table' then + if G.PROFILES[G.SETTINGS.profile].career_stats[stat] > to_big(1e300) then + G.PROFILES[G.SETTINGS.profile].career_stats[stat] = to_big(1e300) + elseif G.PROFILES[G.SETTINGS.profile].career_stats[stat] < to_big(-1e300) then + G.PROFILES[G.SETTINGS.profile].career_stats[stat] = to_big(-1e300) + end + G.PROFILES[G.SETTINGS.profile].career_stats[stat] = G.PROFILES[G.SETTINGS.profile].career_stats[stat]:to_number() + end + G:save_settings() + end + local sn = scale_number function scale_number(number, scale, max, e_switch_point) if not Big then return sn(number, scale, max, e_switch_point) end @@ -4067,8 +3934,8 @@ function tal_uht(config, vals) G.GAME.current_round.current_hand.hand_level = vals.level else G.GAME.current_round.current_hand.hand_level = ' '..localize('k_lvl')..tostring(vals.level) - if type(vals.level) == 'number' then - G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[math.min(vals.level, 7)] + if is_number(vals.level) then + G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[to_big(math.min(vals.level, 7)):to_number()] else G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[1] end @@ -4102,135 +3969,145 @@ function Game:update(dt) Talisman.dollar_update = false end end ---scoring coroutine -local oldplay = G.FUNCS.evaluate_play - -function G.FUNCS.evaluate_play() - G.SCORING_COROUTINE = coroutine.create(oldplay) - G.LAST_SCORING_YIELD = love.timer.getTime() - G.CARD_CALC_COUNTS = {} -- keys = cards, values = table containing numbers - local success, err = coroutine.resume(G.SCORING_COROUTINE) - if not success then - error(err) - end -end - - -local oldupd = love.update -function love.update(dt, ...) - oldupd(dt, ...) - if G.SCORING_COROUTINE then - if collectgarbage("count") > 1024*1024 then - collectgarbage("collect") - end - if coroutine.status(G.SCORING_COROUTINE) == "dead" then - G.SCORING_COROUTINE = nil - G.FUNCS.exit_overlay_menu() - local totalCalcs = 0 - for i, v in pairs(G.CARD_CALC_COUNTS) do - totalCalcs = totalCalcs + v[1] - end - G.GAME.LAST_CALCS = totalCalcs - else - G.SCORING_TEXT = nil - if not G.OVERLAY_MENU then - G.scoring_text = {"Calculating...", "", "", ""} - G.SCORING_TEXT = { - {n = G.UIT.C, nodes = { - {n = G.UIT.R, config = {padding = 0.1, align = "cm"}, nodes = { - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.scoring_text, ref_value = 1}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 1, silent = true})}}, - }},{n = G.UIT.R, nodes = { - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.scoring_text, ref_value = 2}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4, silent = true})}}, - }},{n = G.UIT.R, nodes = { - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.scoring_text, ref_value = 3}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4, silent = true})}}, - }},{n = G.UIT.R, nodes = { - {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.scoring_text, ref_value = 4}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4, silent = true})}}, - }}}}} - G.FUNCS.overlay_menu({ - definition = - {n=G.UIT.ROOT, minw = G.ROOM.T.w*5, minh = G.ROOM.T.h*5, config={align = "cm", padding = 9999, offset = {x = 0, y = -3}, r = 0.1, colour = {G.C.GREY[1], G.C.GREY[2], G.C.GREY[3],0.7}}, nodes= G.SCORING_TEXT}, - config = {align="cm", offset = {x=0,y=0}, major = G.ROOM_ATTACH, bond = 'Weak'} - }) - else - - if G.OVERLAY_MENU and G.scoring_text then - local totalCalcs = 0 - for i, v in pairs(G.CARD_CALC_COUNTS) do - totalCalcs = totalCalcs + v[1] - end - local jokersYetToScore = #G.jokers.cards + #G.play.cards - #G.CARD_CALC_COUNTS - G.scoring_text[1] = "Calculating..." - G.scoring_text[2] = "Elapsed calculations: "..tostring(totalCalcs) - G.scoring_text[3] = "Cards yet to score: "..tostring(jokersYetToScore) - G.scoring_text[4] = "Calculations last played hand: " .. tostring(G.GAME.LAST_CALCS or "Unknown") - end - - end - --this coroutine allows us to stagger GC cycles through - --the main source of waste in terms of memory (especially w joker retriggers) is through local variables that become garbage - --this practically eliminates the memory overhead of scoring - --event queue overhead seems to not exist if Talismans Disable Scoring Animations is off. - --event manager has to wait for scoring to finish until it can keep processing events anyways. - - - G.LAST_SCORING_YIELD = love.timer.getTime() - - local success, msg = coroutine.resume(G.SCORING_COROUTINE) - if not success then - error(msg) - end - end - end -end - - - -TIME_BETWEEN_SCORING_FRAMES = 0.03 -- 30 fps during scoring --- we dont want overhead from updates making scoring much slower --- originally 10 fps, I think 30 fps is a good way to balance it while making it look smooth, too ---wrap everything in calculating contexts so we can do more things with it -Talisman.calculating_joker = false -Talisman.calculating_score = false -Talisman.calculating_card = false -Talisman.dollar_update = false -local ccj = Card.calculate_joker -function Card:calculate_joker(context) +Talisman.F_NO_COROUTINE = false --easy disabling for bugfixing, since the coroutine can make it hard to see where errors are +if not Talisman.F_NO_COROUTINE then --scoring coroutine - G.CURRENT_SCORING_CARD = self - G.CARD_CALC_COUNTS = G.CARD_CALC_COUNTS or {} - if G.CARD_CALC_COUNTS[self] then - G.CARD_CALC_COUNTS[self][1] = G.CARD_CALC_COUNTS[self][1] + 1 - else - G.CARD_CALC_COUNTS[self] = {1, 1} + local oldplay = G.FUNCS.evaluate_play + + function G.FUNCS.evaluate_play() + G.SCORING_COROUTINE = coroutine.create(oldplay) + G.LAST_SCORING_YIELD = love.timer.getTime() + G.CARD_CALC_COUNTS = {} -- keys = cards, values = table containing numbers + local success, err = coroutine.resume(G.SCORING_COROUTINE) + if not success then + error(err) + end end - if G.LAST_SCORING_YIELD and ((love.timer.getTime() - G.LAST_SCORING_YIELD) > TIME_BETWEEN_SCORING_FRAMES) and coroutine.running() then - coroutine.yield() - end - Talisman.calculating_joker = true - local ret = ccj(self, context) + local oldupd = love.update + function love.update(dt, ...) + oldupd(dt, ...) + if G.SCORING_COROUTINE then + if collectgarbage("count") > 1024*1024 then + collectgarbage("collect") + end + if coroutine.status(G.SCORING_COROUTINE) == "dead" then + G.SCORING_COROUTINE = nil + G.FUNCS.exit_overlay_menu() + local totalCalcs = 0 + for i, v in pairs(G.CARD_CALC_COUNTS) do + totalCalcs = totalCalcs + v[1] + end + G.GAME.LAST_CALCS = totalCalcs + G.GAME.LAST_CALC_TIME = G.CURRENT_CALC_TIME + else + G.SCORING_TEXT = nil + if not G.OVERLAY_MENU then + G.scoring_text = {"Calculating...", "", "", ""} + G.SCORING_TEXT = { + {n = G.UIT.C, nodes = { + {n = G.UIT.R, config = {padding = 0.1, align = "cm"}, nodes = { + {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.scoring_text, ref_value = 1}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 1, silent = true})}}, + }},{n = G.UIT.R, nodes = { + {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.scoring_text, ref_value = 2}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4, silent = true})}}, + }},{n = G.UIT.R, nodes = { + {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.scoring_text, ref_value = 3}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4, silent = true})}}, + }},{n = G.UIT.R, nodes = { + {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.scoring_text, ref_value = 4}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4, silent = true})}}, + }}}}} + G.FUNCS.overlay_menu({ + definition = + {n=G.UIT.ROOT, minw = G.ROOM.T.w*5, minh = G.ROOM.T.h*5, config={align = "cm", padding = 9999, offset = {x = 0, y = -3}, r = 0.1, colour = {G.C.GREY[1], G.C.GREY[2], G.C.GREY[3],0.7}}, nodes= G.SCORING_TEXT}, + config = {align="cm", offset = {x=0,y=0}, major = G.ROOM_ATTACH, bond = 'Weak'} + }) + else - if ret and type(ret) == "table" and ret.repetitions then - G.CARD_CALC_COUNTS[ret.card] = G.CARD_CALC_COUNTS[ret.card] or {1,1} - G.CARD_CALC_COUNTS[ret.card][2] = G.CARD_CALC_COUNTS[ret.card][2] + ret.repetitions + if G.OVERLAY_MENU and G.scoring_text then + local totalCalcs = 0 + for i, v in pairs(G.CARD_CALC_COUNTS) do + totalCalcs = totalCalcs + v[1] + end + local jokersYetToScore = #G.jokers.cards + #G.play.cards - #G.CARD_CALC_COUNTS + G.CURRENT_CALC_TIME = (G.CURRENT_CALC_TIME or 0) + dt + G.scoring_text[1] = "Calculating..." + G.scoring_text[2] = "Elapsed calculations: "..tostring(totalCalcs).." ("..tostring(number_format(G.CURRENT_CALC_TIME)).."s)" + G.scoring_text[3] = "Cards yet to score: "..tostring(jokersYetToScore) + G.scoring_text[4] = "Calculations last played hand: " .. tostring(G.GAME.LAST_CALCS or "Unknown") .." ("..tostring(G.GAME.LAST_CALC_TIME and number_format(G.GAME.LAST_CALC_TIME) or "???").."s)" + end + + end + --this coroutine allows us to stagger GC cycles through + --the main source of waste in terms of memory (especially w joker retriggers) is through local variables that become garbage + --this practically eliminates the memory overhead of scoring + --event queue overhead seems to not exist if Talismans Disable Scoring Animations is off. + --event manager has to wait for scoring to finish until it can keep processing events anyways. + + + G.LAST_SCORING_YIELD = love.timer.getTime() + + local success, msg = coroutine.resume(G.SCORING_COROUTINE) + if not success then + error(msg) + end + end + end end + + + + TIME_BETWEEN_SCORING_FRAMES = 0.03 -- 30 fps during scoring + -- we dont want overhead from updates making scoring much slower + -- originally 10 fps, I think 30 fps is a good way to balance it while making it look smooth, too + --wrap everything in calculating contexts so we can do more things with it Talisman.calculating_joker = false - return ret -end -local cuc = Card.use_consumable -function Card:use_consumable(x,y) - Talisman.calculating_score = true - local ret = cuc(self, x,y) Talisman.calculating_score = false - return ret -end -local gfep = G.FUNCS.evaluate_play -G.FUNCS.evaluate_play = function(e) - Talisman.calculating_score = true - local ret = gfep(e) - Talisman.calculating_score = false - return ret + Talisman.calculating_card = false + Talisman.dollar_update = false + local ccj = Card.calculate_joker + function Card:calculate_joker(context) + --scoring coroutine + G.CURRENT_SCORING_CARD = self + G.CARD_CALC_COUNTS = G.CARD_CALC_COUNTS or {} + if G.CARD_CALC_COUNTS[self] then + G.CARD_CALC_COUNTS[self][1] = G.CARD_CALC_COUNTS[self][1] + 1 + else + G.CARD_CALC_COUNTS[self] = {1, 1} + end + + + if G.LAST_SCORING_YIELD and ((love.timer.getTime() - G.LAST_SCORING_YIELD) > TIME_BETWEEN_SCORING_FRAMES) and coroutine.running() then + coroutine.yield() + end + Talisman.calculating_joker = true + local ret, trig = ccj(self, context) + + if ret and type(ret) == "table" and ret.repetitions then + if not ret.card then + G.CARD_CALC_COUNTS.other = G.CARD_CALC_COUNTS.other or {1,1} + G.CARD_CALC_COUNTS.other[2] = G.CARD_CALC_COUNTS.other[2] + ret.repetitions + else + G.CARD_CALC_COUNTS[ret.card] = G.CARD_CALC_COUNTS[ret.card] or {1,1} + G.CARD_CALC_COUNTS[ret.card][2] = G.CARD_CALC_COUNTS[ret.card][2] + ret.repetitions + end + end + Talisman.calculating_joker = false + return ret, trig + end + local cuc = Card.use_consumable + function Card:use_consumable(x,y) + Talisman.calculating_score = true + local ret = cuc(self, x,y) + Talisman.calculating_score = false + return ret + end + local gfep = G.FUNCS.evaluate_play + G.FUNCS.evaluate_play = function(e) + Talisman.calculating_score = true + local ret = gfep(e) + Talisman.calculating_score = false + return ret + end end --[[local ec = eval_card function eval_card() @@ -4325,7 +4202,7 @@ local edo = ease_dollars function ease_dollars(mod, instant) if Talisman.config_file.disable_anims then--and (Talisman.calculating_joker or Talisman.calculating_score or Talisman.calculating_card) then mod = mod or 0 - if mod < 0 then inc_career_stat('c_dollars_earned', mod) end + if to_big(mod) < to_big(0) then inc_career_stat('c_dollars_earned', mod) end G.GAME.dollars = G.GAME.dollars + mod Talisman.dollar_update = true else return edo(mod, instant) end @@ -4340,11 +4217,13 @@ function safe_str_unpack(str) if success then return result else - print("Error unpacking string: " .. result) + print("[Talisman] Error unpacking string: " .. result) + print(tostring(str)) return nil end else - print("Error loading string: " .. err) + print("[Talisman] Error loading string: " .. err) + print(tostring(str)) return nil end end @@ -4373,6 +4252,207 @@ function G.FUNCS.evaluate_round() end end +local g_start_run = Game.start_run +function Game:start_run(args) + local ret = g_start_run(self, args) + self.GAME.round_resets.ante_disp = self.GAME.round_resets.ante_disp or number_format(self.GAME.round_resets.ante) + return ret +end + +-- Steamodded calculation API: add extra operations +if SMODS and SMODS.calculate_individual_effect then + local smods_xchips = false + for _, v in pairs(SMODS.calculation_keys) do + if v == 'x_chips' then + smods_xchips = true + break + end + end + local scie = SMODS.calculate_individual_effect + function SMODS.calculate_individual_effect(effect, scored_card, key, amount, from_edition) + -- For some reason, some keys' animations are completely removed + -- I think this is caused by a lovely patch conflict + --if key == 'chip_mod' then key = 'chips' end + --if key == 'mult_mod' then key = 'mult' end + --if key == 'Xmult_mod' then key = 'x_mult' end + local ret = scie(effect, scored_card, key, amount, from_edition) + if ret then + return ret + end + if not smods_xchips and (key == 'x_chips' or key == 'xchips' or key == 'Xchip_mod') and amount ~= 1 then + if effect.card then juice_card(effect.card) end + hand_chips = mod_chips(hand_chips * amount) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "X"..amount, colour = G.C.EDITION, edition = true}) + elseif key ~= 'Xchip_mod' then + if effect.xchip_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.xchip_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'x_chips', amount, percent) + end + end + end + return true + end + + if (key == 'e_chips' or key == 'echips' or key == 'Echip_mod') and amount ~= 1 then + if effect.card then juice_card(effect.card) end + hand_chips = mod_chips(hand_chips ^ amount) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^"..amount, colour = G.C.EDITION, edition = true}) + elseif key ~= 'Echip_mod' then + if effect.echip_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.echip_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'e_chips', amount, percent) + end + end + end + return true + end + + if (key == 'ee_chips' or key == 'eechips' or key == 'EEchip_mod') and amount ~= 1 then + if effect.card then juice_card(effect.card) end + hand_chips = mod_chips(hand_chips:arrow(2, amount)) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^^"..amount, colour = G.C.EDITION, edition = true}) + elseif key ~= 'EEchip_mod' then + if effect.eechip_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.eechip_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'ee_chips', amount, percent) + end + end + end + return true + end + + if (key == 'eee_chips' or key == 'eeechips' or key == 'EEEchip_mod') and amount ~= 1 then + if effect.card then juice_card(effect.card) end + hand_chips = mod_chips(hand_chips:arrow(3, amount)) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^^^"..amount, colour = G.C.EDITION, edition = true}) + elseif key ~= 'EEEchip_mod' then + if effect.eeechip_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.eeechip_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'eee_chips', amount, percent) + end + end + end + return true + end + + if (key == 'hyper_chips' or key == 'hyperchips' or key == 'hyperchip_mod') and type(amount) == 'table' then + if effect.card then juice_card(effect.card) end + hand_chips = mod_chips(hand_chips:arrow(amount[1], amount[2])) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = (amount[1] > 5 and ('{' .. amount[1] .. '}') or string.rep('^', amount[1])) .. amount[2], colour = G.C.EDITION, edition = true}) + elseif key ~= 'hyperchip_mod' then + if effect.hyperchip_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.hyperchip_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'hyper_chips', amount, percent) + end + end + end + return true + end + + if (key == 'e_mult' or key == 'emult' or key == 'Emult_mod') and amount ~= 1 then + if effect.card then juice_card(effect.card) end + mult = mod_chips(mult ^ amount) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^"..amount.." Mult", colour = G.C.EDITION, edition = true}) + elseif key ~= 'Emult_mod' then + if effect.emult_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.emult_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'e_mult', amount, percent) + end + end + end + return true + end + + if (key == 'ee_mult' or key == 'eemult' or key == 'EEmult_mod') and amount ~= 1 then + if effect.card then juice_card(effect.card) end + mult = mod_chips(mult:arrow(2, amount)) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^^"..amount.." Mult", colour = G.C.EDITION, edition = true}) + elseif key ~= 'EEmult_mod' then + if effect.eemult_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.eemult_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'ee_mult', amount, percent) + end + end + end + return true + end + + if (key == 'eee_mult' or key == 'eeemult' or key == 'EEEmult_mod') and amount ~= 1 then + if effect.card then juice_card(effect.card) end + mult = mod_chips(mult:arrow(3, amount)) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^^^"..amount.." Mult", colour = G.C.EDITION, edition = true}) + elseif key ~= 'EEEmult_mod' then + if effect.eeemult_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.eeemult_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'eee_mult', amount, percent) + end + end + end + return true + end + + if (key == 'hyper_mult' or key == 'hypermult' or key == 'hypermult_mod') and type(amount) == 'table' then + if effect.card then juice_card(effect.card) end + mult = mod_chips(mult:arrow(amount[1], amount[2])) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = ((amount[1] > 5 and ('{' .. amount[1] .. '}') or string.rep('^', amount[1])) .. amount[2]).." Mult", colour = G.C.EDITION, edition = true}) + elseif key ~= 'hypermult_mod' then + if effect.hypermult_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.hypermult_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'hyper_mult', amount, percent) + end + end + end + return true + end + end + for _, v in ipairs({'e_mult', 'e_chips', 'ee_mult', 'ee_chips', 'eee_mult', 'eee_chips', 'hyper_mult', 'hyper_chips', + 'emult', 'echips', 'eemult', 'eechips', 'eeemult', 'eeechips', 'hypermult', 'hyperchips', + 'Emult_mod', 'Echip_mod', 'EEmult_mod', 'EEchip_mod', 'EEEmult_mod', 'EEEchip_mod', 'hypermult_mod', 'hyperchip_mod'}) do + table.insert(SMODS.calculation_keys, v) + end + if not smods_xchips then + for _, v in ipairs({'x_chips', 'xchips', 'Xchip_mod'}) do + table.insert(SMODS.calculation_keys, v) + end + end +end + --some debugging functions --[[local callstep=0 function printCallerInfo() @@ -4390,79 +4470,3 @@ function EventManager:add_event(x,y,z) printCallerInfo() return emae(self,x,y,z) end--]] - -require 'cartomancer.init' - -Cartomancer.path = assert( - Cartomancer.find_self('cartomancer.lua'), - "Failed to find mod folder. Make sure that `Cartomancer` folder has `cartomancer.lua` file!" -) - -Cartomancer.load_mod_file('internal/config.lua', 'internal.config') -Cartomancer.load_mod_file('internal/atlas.lua', 'internal.atlas') -Cartomancer.load_mod_file('internal/ui.lua', 'internal.ui') -Cartomancer.load_mod_file('internal/keybinds.lua', 'internal.keybinds') - -Cartomancer.load_mod_file('core/view-deck.lua', 'core.view-deck') -Cartomancer.load_mod_file('core/flames.lua', 'core.flames') -Cartomancer.load_mod_file('core/optimizations.lua', 'core.optimizations') -Cartomancer.load_mod_file('core/jokers.lua', 'core.jokers') -Cartomancer.load_mod_file('core/hand.lua', 'core.hand') - -Cartomancer.load_config() - -Cartomancer.INTERNAL_jokers_menu = false - --- TODO dedicated keybinds file? keybinds need to load after config -Cartomancer.register_keybind { - name = 'hide_joker', - func = function (controller) - Cartomancer.hide_hovered_joker(controller) - end -} - -Cartomancer.register_keybind { - name = 'toggle_tags', - func = function (controller) - Cartomancer.SETTINGS.hide_tags = not Cartomancer.SETTINGS.hide_tags - Cartomancer.update_tags_visibility() - end -} - -Cartomancer.register_keybind { - name = 'toggle_consumables', - func = function (controller) - Cartomancer.SETTINGS.hide_consumables = not Cartomancer.SETTINGS.hide_consumables - end -} - -Cartomancer.register_keybind { - name = 'toggle_deck', - func = function (controller) - Cartomancer.SETTINGS.hide_deck = not Cartomancer.SETTINGS.hide_deck - end -} - -Cartomancer.register_keybind { - name = 'toggle_jokers', - func = function (controller) - if not (G and G.jokers) then - return - end - G.jokers.cart_hide_all = not G.jokers.cart_hide_all - - if G.jokers.cart_hide_all then - Cartomancer.hide_all_jokers() - else - Cartomancer.show_all_jokers() - end - Cartomancer.align_G_jokers() - end -} - -Cartomancer.register_keybind { - name = 'toggle_jokers_buttons', - func = function (controller) - Cartomancer.SETTINGS.jokers_controls_buttons = not Cartomancer.SETTINGS.jokers_controls_buttons - end -} diff --git a/lovely/log/lovely-2025.01.06-16.24.29.log b/lovely/log/lovely-2025.01.06-16.24.29.log deleted file mode 100644 index 9d660e6..0000000 --- a/lovely/log/lovely-2025.01.06-16.24.29.log +++ /dev/null @@ -1,115 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Initialization complete in 127ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 10 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 72 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 121 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 47 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 203 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-06 16:24:30 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-06 16:24:31 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-06 16:24:31 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-06 16:24:31 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-06 16:24:31 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-06 16:24:31 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-06 16:24:31 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-06 16:24:31 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.747 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0030] Injected Atlas in 795.883 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0025] Injected Sound in 20.008 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0032] Injected Stake in 0.804 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0008] Injected Rarity in 0.031 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.073 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0391] Injected Center in 1.877 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.010 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0027] Injected Blind in 0.116 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0002] Injected Seal in 0.064 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0004] Injected Suit in 0.761 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0013] Injected Rank in 0.216 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.039 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.129 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0031] Injected Challenge in 0.033 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0028] Injected Tag in 0.116 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0009] Injected Sticker in 0.398 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0009] Injected Shader in 161.469 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0020] Injected Achievement in 0.157 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.633 ms -INFO - [G] 2025-01-06 16:24:32 :: INFO :: TIMER :: [0011] Injected Event in 0.105 ms -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.08058204 -INFO - [G] LONG DT @ 14: 0.064967672 -INFO - [G] LONG DT @ 14: 0.0525077976 diff --git a/lovely/log/lovely-2025.01.06-16.24.54.log b/lovely/log/lovely-2025.01.06-16.24.54.log deleted file mode 100644 index 23da833..0000000 --- a/lovely/log/lovely-2025.01.06-16.24.54.log +++ /dev/null @@ -1,364 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 124ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 10 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 72 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 121 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 47 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 203 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-06 16:24:55 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-06 16:24:56 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-06 16:24:56 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-06 16:24:56 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-06 16:24:56 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-06 16:24:56 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-06 16:24:56 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-06 16:24:56 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.728 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0030] Injected Atlas in 776.599 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0025] Injected Sound in 21.525 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0032] Injected Stake in 2.105 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0008] Injected Rarity in 0.062 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.083 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0391] Injected Center in 2.357 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.009 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0027] Injected Blind in 0.096 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0002] Injected Seal in 0.119 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0004] Injected Suit in 0.295 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0013] Injected Rank in 0.214 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.037 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.182 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0031] Injected Challenge in 0.034 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0028] Injected Tag in 0.255 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0009] Injected Sticker in 0.737 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0009] Injected Shader in 53.803 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0000] Injected Keybind in 0.002 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0020] Injected Achievement in 0.052 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.209 ms -INFO - [G] 2025-01-06 16:24:57 :: INFO :: TIMER :: [0011] Injected Event in 0.012 ms -INFO - [G] LONG DT @ 3: 0.1 -INFO - [G] LONG DT @ 3: 0.08331644 -INFO - [G] LONG DT @ 3: 0.069972552 -INFO - [G] LONG DT @ 3: 0.0592162216 -INFO - [G] LONG DT @ 3: 0.05065199728 -INFO - [G] LONG DT @ 50: 0.1 -INFO - [G] LONG DT @ 50: 0.1 -INFO - [G] LONG DT @ 50: 0.1 -INFO - [G] LONG DT @ 50: 0.1 -INFO - [G] LONG DT @ 50: 0.08123894 -INFO - [G] LONG DT @ 50: 0.065959192 -INFO - [G] LONG DT @ 50: 0.053649213600001 -INFO - [G] LONG DT @ 51: 0.1 -INFO - [G] LONG DT @ 51: 0.1 -INFO - [G] LONG DT @ 51: 0.1 -INFO - [G] LONG DT @ 51: 0.1 -INFO - [G] LONG DT @ 51: 0.1 -INFO - [G] LONG DT @ 52: 0.1 -INFO - [G] LONG DT @ 52: 0.1 -INFO - [G] LONG DT @ 52: 0.1 -INFO - [G] LONG DT @ 52: 0.1 -INFO - [G] LONG DT @ 52: 0.1 -INFO - [G] LONG DT @ 52: 0.1 -INFO - [G] LONG DT @ 52: 0.1 -INFO - [G] LONG DT @ 52: 0.1 -INFO - [G] LONG DT @ 52: 0.1 -INFO - [G] LONG DT @ 52: 0.1 -INFO - [G] LONG DT @ 53: 0.1 -INFO - [G] LONG DT @ 53: 0.1 -INFO - [G] LONG DT @ 53: 0.1 -INFO - [G] LONG DT @ 53: 0.081268919999998 -INFO - [G] LONG DT @ 53: 0.066091736 -INFO - [G] LONG DT @ 53: 0.0538612688 -INFO - [G] LONG DT @ 55: 0.1 -INFO - [G] LONG DT @ 55: 0.1 -INFO - [G] LONG DT @ 55: 0.1 -INFO - [G] LONG DT @ 55: 0.1 -INFO - [G] LONG DT @ 55: 0.1 -INFO - [G] LONG DT @ 55: 0.1 -INFO - [G] LONG DT @ 55: 0.1 -INFO - [G] LONG DT @ 55: 0.1 -INFO - [G] LONG DT @ 56: 0.1 -INFO - [G] LONG DT @ 56: 0.1 -INFO - [G] LONG DT @ 56: 0.081317280000001 -INFO - [G] LONG DT @ 56: 0.066314163999999 -INFO - [G] LONG DT @ 56: 0.054187291200002 -INFO - [G] LONG DT @ 210: 0.1 -INFO - [G] LONG DT @ 210: 0.1 -INFO - [G] LONG DT @ 210: 0.1 -INFO - [G] LONG DT @ 210: 0.1 -INFO - [G] LONG DT @ 210: 0.1 -INFO - [G] LONG DT @ 210: 0.1 -INFO - [G] LONG DT @ 210: 0.1 -INFO - [G] LONG DT @ 211: 0.1 -INFO - [G] LONG DT @ 211: 0.1 -INFO - [G] LONG DT @ 211: 0.1 -INFO - [G] LONG DT @ 211: 0.1 -INFO - [G] LONG DT @ 211: 0.1 -INFO - [G] LONG DT @ 211: 0.1 -INFO - [G] LONG DT @ 211: 0.1 -INFO - [G] LONG DT @ 211: 0.1 -INFO - [G] LONG DT @ 211: 0.1 -INFO - [G] LONG DT @ 211: 0.1 -INFO - [G] LONG DT @ 212: 0.1 -INFO - [G] LONG DT @ 212: 0.1 -INFO - [G] LONG DT @ 212: 0.1 -INFO - [G] LONG DT @ 212: 0.1 -INFO - [G] LONG DT @ 212: 0.1 -INFO - [G] LONG DT @ 212: 0.1 -INFO - [G] LONG DT @ 212: 0.1 -INFO - [G] LONG DT @ 212: 0.1 -INFO - [G] LONG DT @ 212: 0.1 -INFO - [G] LONG DT @ 212: 0.1 -INFO - [G] LONG DT @ 213: 0.1 -INFO - [G] LONG DT @ 213: 0.1 -INFO - [G] LONG DT @ 213: 0.1 -INFO - [G] LONG DT @ 213: 0.1 -INFO - [G] LONG DT @ 213: 0.1 -INFO - [G] LONG DT @ 213: 0.1 -INFO - [G] LONG DT @ 213: 0.1 -INFO - [G] LONG DT @ 213: 0.1 -INFO - [G] LONG DT @ 213: 0.1 -INFO - [G] LONG DT @ 213: 0.1 -INFO - [G] LONG DT @ 214: 0.1 -INFO - [G] LONG DT @ 214: 0.1 -INFO - [G] LONG DT @ 214: 0.1 -INFO - [G] LONG DT @ 214: 0.1 -INFO - [G] LONG DT @ 214: 0.1 -INFO - [G] LONG DT @ 214: 0.1 -INFO - [G] LONG DT @ 214: 0.1 -INFO - [G] LONG DT @ 214: 0.1 -INFO - [G] LONG DT @ 214: 0.1 -INFO - [G] LONG DT @ 214: 0.1 -INFO - [G] LONG DT @ 215: 0.1 -INFO - [G] LONG DT @ 215: 0.1 -INFO - [G] LONG DT @ 215: 0.1 -INFO - [G] LONG DT @ 215: 0.1 -INFO - [G] LONG DT @ 215: 0.1 -INFO - [G] LONG DT @ 215: 0.1 -INFO - [G] LONG DT @ 215: 0.1 -INFO - [G] LONG DT @ 215: 0.1 -INFO - [G] LONG DT @ 215: 0.1 -INFO - [G] LONG DT @ 215: 0.1 -INFO - [G] LONG DT @ 216: 0.1 -INFO - [G] LONG DT @ 216: 0.1 -INFO - [G] LONG DT @ 216: 0.1 -INFO - [G] LONG DT @ 216: 0.1 -INFO - [G] LONG DT @ 216: 0.1 -INFO - [G] LONG DT @ 216: 0.1 -INFO - [G] LONG DT @ 216: 0.1 -INFO - [G] LONG DT @ 216: 0.1 -INFO - [G] LONG DT @ 216: 0.1 -INFO - [G] LONG DT @ 216: 0.1 -INFO - [G] LONG DT @ 217: 0.1 -INFO - [G] LONG DT @ 217: 0.1 -INFO - [G] LONG DT @ 217: 0.1 -INFO - [G] LONG DT @ 217: 0.1 -INFO - [G] LONG DT @ 217: 0.1 -INFO - [G] LONG DT @ 217: 0.1 -INFO - [G] LONG DT @ 217: 0.1 -INFO - [G] LONG DT @ 217: 0.1 -INFO - [G] LONG DT @ 217: 0.1 -INFO - [G] LONG DT @ 217: 0.1 -INFO - [G] LONG DT @ 218: 0.1 -INFO - [G] LONG DT @ 218: 0.1 -INFO - [G] LONG DT @ 218: 0.1 -INFO - [G] LONG DT @ 218: 0.1 -INFO - [G] LONG DT @ 218: 0.1 -INFO - [G] LONG DT @ 218: 0.1 -INFO - [G] LONG DT @ 218: 0.1 -INFO - [G] LONG DT @ 218: 0.1 -INFO - [G] LONG DT @ 218: 0.1 -INFO - [G] LONG DT @ 218: 0.1 -INFO - [G] LONG DT @ 219: 0.1 -INFO - [G] LONG DT @ 219: 0.1 -INFO - [G] LONG DT @ 219: 0.1 -INFO - [G] LONG DT @ 219: 0.1 -INFO - [G] LONG DT @ 219: 0.1 -INFO - [G] LONG DT @ 219: 0.1 -INFO - [G] LONG DT @ 219: 0.1 -INFO - [G] LONG DT @ 219: 0.1 -INFO - [G] LONG DT @ 219: 0.1 -INFO - [G] LONG DT @ 219: 0.1 -INFO - [G] LONG DT @ 220: 0.1 -INFO - [G] LONG DT @ 220: 0.1 -INFO - [G] LONG DT @ 220: 0.1 -INFO - [G] LONG DT @ 220: 0.1 -INFO - [G] LONG DT @ 220: 0.1 -INFO - [G] LONG DT @ 220: 0.1 -INFO - [G] LONG DT @ 220: 0.1 -INFO - [G] LONG DT @ 220: 0.1 -INFO - [G] LONG DT @ 220: 0.1 -INFO - [G] LONG DT @ 220: 0.1 -INFO - [G] LONG DT @ 221: 0.1 -INFO - [G] LONG DT @ 221: 0.1 -INFO - [G] LONG DT @ 221: 0.1 -INFO - [G] LONG DT @ 221: 0.1 -INFO - [G] LONG DT @ 221: 0.1 -INFO - [G] LONG DT @ 221: 0.1 -INFO - [G] LONG DT @ 221: 0.1 -INFO - [G] LONG DT @ 221: 0.1 -INFO - [G] LONG DT @ 221: 0.1 -INFO - [G] LONG DT @ 221: 0.1 -INFO - [G] LONG DT @ 222: 0.1 -INFO - [G] LONG DT @ 222: 0.1 -INFO - [G] LONG DT @ 222: 0.1 -INFO - [G] LONG DT @ 222: 0.1 -INFO - [G] LONG DT @ 222: 0.1 -INFO - [G] LONG DT @ 222: 0.1 -INFO - [G] LONG DT @ 222: 0.1 -INFO - [G] LONG DT @ 222: 0.1 -INFO - [G] LONG DT @ 222: 0.1 -INFO - [G] LONG DT @ 222: 0.1 -INFO - [G] LONG DT @ 223: 0.1 -INFO - [G] LONG DT @ 223: 0.1 -INFO - [G] LONG DT @ 223: 0.1 -INFO - [G] LONG DT @ 223: 0.1 -INFO - [G] LONG DT @ 223: 0.1 -INFO - [G] LONG DT @ 223: 0.1 -INFO - [G] LONG DT @ 223: 0.1 -INFO - [G] LONG DT @ 223: 0.1 -INFO - [G] LONG DT @ 223: 0.1 -INFO - [G] LONG DT @ 223: 0.1 -INFO - [G] LONG DT @ 224: 0.1 -INFO - [G] LONG DT @ 224: 0.1 -INFO - [G] LONG DT @ 224: 0.1 -INFO - [G] LONG DT @ 224: 0.1 -INFO - [G] LONG DT @ 224: 0.1 -INFO - [G] LONG DT @ 224: 0.1 -INFO - [G] LONG DT @ 224: 0.1 -INFO - [G] LONG DT @ 224: 0.1 -INFO - [G] LONG DT @ 224: 0.1 -INFO - [G] LONG DT @ 224: 0.1 -INFO - [G] LONG DT @ 225: 0.1 -INFO - [G] LONG DT @ 225: 0.1 -INFO - [G] LONG DT @ 225: 0.1 -INFO - [G] LONG DT @ 225: 0.1 -INFO - [G] LONG DT @ 225: 0.1 -INFO - [G] LONG DT @ 225: 0.1 -INFO - [G] LONG DT @ 225: 0.1 -INFO - [G] LONG DT @ 225: 0.1 -INFO - [G] LONG DT @ 225: 0.1 -INFO - [G] LONG DT @ 225: 0.1 -INFO - [G] LONG DT @ 226: 0.1 -INFO - [G] LONG DT @ 226: 0.1 -INFO - [G] LONG DT @ 226: 0.1 -INFO - [G] LONG DT @ 226: 0.1 -INFO - [G] LONG DT @ 226: 0.1 -INFO - [G] LONG DT @ 226: 0.1 -INFO - [G] LONG DT @ 226: 0.081283380000007 -INFO - [G] LONG DT @ 226: 0.066030723999999 -INFO - [G] LONG DT @ 226: 0.053615339200006 -INFO - [G] LONG DT @ 326: 0.1 -INFO - [G] LONG DT @ 326: 0.1 -INFO - [G] LONG DT @ 326: 0.1 -INFO - [G] LONG DT @ 326: 0.1 -INFO - [G] LONG DT @ 326: 0.1 -INFO - [G] LONG DT @ 326: 0.1 -INFO - [G] LONG DT @ 326: 0.1 -INFO - [G] LONG DT @ 326: 0.1 -INFO - [G] LONG DT @ 327: 0.1 -INFO - [G] LONG DT @ 327: 0.1 -INFO - [G] LONG DT @ 327: 0.1 -INFO - [G] LONG DT @ 327: 0.1 -INFO - [G] LONG DT @ 327: 0.1 -INFO - [G] LONG DT @ 327: 0.1 -INFO - [G] LONG DT @ 327: 0.1 -INFO - [G] LONG DT @ 327: 0.081428220000003 -INFO - [G] LONG DT @ 327: 0.066303576000004 -INFO - [G] LONG DT @ 327: 0.054125840800004 -INFO - [G] LONG DT @ 360: 0.1 -INFO - [G] LONG DT @ 360: 0.1 -INFO - [G] LONG DT @ 361: 0.1 -INFO - [G] LONG DT @ 361: 0.1 -INFO - [G] LONG DT @ 361: 0.1 -INFO - [G] LONG DT @ 361: 0.1 -INFO - [G] LONG DT @ 361: 0.1 -INFO - [G] LONG DT @ 361: 0.1 -INFO - [G] LONG DT @ 361: 0.1 -INFO - [G] LONG DT @ 361: 0.1 -INFO - [G] LONG DT @ 361: 0.1 -INFO - [G] LONG DT @ 361: 0.1 -INFO - [G] LONG DT @ 362: 0.1 -INFO - [G] LONG DT @ 362: 0.1 -INFO - [G] LONG DT @ 362: 0.1 -INFO - [G] LONG DT @ 362: 0.1 -INFO - [G] LONG DT @ 362: 0.1 -INFO - [G] LONG DT @ 362: 0.1 -INFO - [G] LONG DT @ 362: 0.1 -INFO - [G] LONG DT @ 362: 0.081710219999995 -INFO - [G] LONG DT @ 362: 0.066695916000007 -INFO - [G] LONG DT @ 362: 0.054951152799998 diff --git a/lovely/log/lovely-2025.01.06-17.54.40.log b/lovely/log/lovely-2025.01.06-17.54.40.log deleted file mode 100644 index ae1fa73..0000000 --- a/lovely/log/lovely-2025.01.06-17.54.40.log +++ /dev/null @@ -1,370 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 142ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 10 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 72 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 121 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 47 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 203 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-06 17:54:41 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-06 17:54:42 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-06 17:54:42 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-06 17:54:42 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-06 17:54:42 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-06 17:54:42 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-06 17:54:42 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-06 17:54:42 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.853 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0030] Injected Atlas in 787.588 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0025] Injected Sound in 19.834 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0032] Injected Stake in 1.880 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0008] Injected Rarity in 0.067 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.112 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0391] Injected Center in 2.593 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.012 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0027] Injected Blind in 0.072 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0002] Injected Seal in 0.064 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0004] Injected Suit in 0.095 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0013] Injected Rank in 0.177 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.032 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.087 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0031] Injected Challenge in 0.035 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0028] Injected Tag in 0.095 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0009] Injected Sticker in 0.089 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0009] Injected Shader in 54.228 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0020] Injected Achievement in 0.053 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.124 ms -INFO - [G] 2025-01-06 17:54:43 :: INFO :: TIMER :: [0011] Injected Event in 0.018 ms -INFO - [G] LONG DT @ 1401: 0.1 -INFO - [G] LONG DT @ 1401: 0.1 -INFO - [G] LONG DT @ 1402: 0.1 -INFO - [G] LONG DT @ 1402: 0.1 -INFO - [G] LONG DT @ 1402: 0.1 -INFO - [G] LONG DT @ 1402: 0.1 -INFO - [G] LONG DT @ 1402: 0.1 -INFO - [G] LONG DT @ 1402: 0.1 -INFO - [G] LONG DT @ 1402: 0.1 -INFO - [G] LONG DT @ 1402: 0.1 -INFO - [G] LONG DT @ 1402: 0.1 -INFO - [G] LONG DT @ 1402: 0.1 -INFO - [G] LONG DT @ 1403: 0.1 -INFO - [G] LONG DT @ 1403: 0.1 -INFO - [G] LONG DT @ 1403: 0.1 -INFO - [G] LONG DT @ 1403: 0.1 -INFO - [G] LONG DT @ 1403: 0.1 -INFO - [G] LONG DT @ 1403: 0.1 -INFO - [G] LONG DT @ 1403: 0.1 -INFO - [G] LONG DT @ 1403: 0.1 -INFO - [G] LONG DT @ 1403: 0.1 -INFO - [G] LONG DT @ 1403: 0.1 -INFO - [G] LONG DT @ 1404: 0.1 -INFO - [G] LONG DT @ 1404: 0.081285999999982 -INFO - [G] LONG DT @ 1404: 0.066031859999979 -INFO - [G] LONG DT @ 1404: 0.053697567999983 -INFO - [G] LONG DT @ 1411: 0.1 -INFO - [G] LONG DT @ 1411: 0.081767680000012 -INFO - [G] LONG DT @ 1411: 0.066567164000002 -INFO - [G] LONG DT @ 1411: 0.1 -INFO - [G] LONG DT @ 1411: 0.1 -INFO - [G] LONG DT @ 1411: 0.081600499999995 -INFO - [G] LONG DT @ 1411: 0.066364679999982 -INFO - [G] LONG DT @ 1412: 0.1 -INFO - [G] LONG DT @ 1412: 0.081730199999975 -INFO - [G] LONG DT @ 1412: 0.066622379999984 -INFO - [G] LONG DT @ 1412: 0.1 -INFO - [G] LONG DT @ 1412: 0.1 -INFO - [G] LONG DT @ 1412: 0.1 -INFO - [G] LONG DT @ 1412: 0.1 -INFO - [G] LONG DT @ 1412: 0.081709560000018 -INFO - [G] LONG DT @ 1412: 0.1 -INFO - [G] LONG DT @ 1412: 0.081940880000029 -INFO - [G] LONG DT @ 1412: 0.066753623999997 -INFO - [G] LONG DT @ 1413: 0.1 -INFO - [G] LONG DT @ 1413: 0.081713160000008 -INFO - [G] LONG DT @ 1413: 0.066586568000015 -INFO - [G] LONG DT @ 1413: 0.1 -INFO - [G] LONG DT @ 1413: 0.081658380000026 -INFO - [G] LONG DT @ 1413: 0.066325323999994 -INFO - [G] LONG DT @ 1413: 0.053997039200024 -INFO - [G] LONG DT @ 1446: 0.1 -INFO - [G] LONG DT @ 1446: 0.1 -INFO - [G] LONG DT @ 1446: 0.081840320000019 -INFO - [G] LONG DT @ 1446: 0.1 -INFO - [G] LONG DT @ 1446: 0.1 -INFO - [G] LONG DT @ 1446: 0.1 -INFO - [G] LONG DT @ 1446: 0.1 -INFO - [G] LONG DT @ 1446: 0.1 -INFO - [G] LONG DT @ 1447: 0.1 -INFO - [G] LONG DT @ 1447: 0.1 -INFO - [G] LONG DT @ 1447: 0.1 -INFO - [G] LONG DT @ 1447: 0.082028060000021 -INFO - [G] LONG DT @ 1447: 0.067336968000012 -INFO - [G] LONG DT @ 1447: 0.055066294400017 -INFO - [G] LONG DT @ 1554: 0.1 -INFO - [G] LONG DT @ 1554: 0.1 -INFO - [G] LONG DT @ 1554: 0.081597339999989 -INFO - [G] LONG DT @ 1554: 0.066234331999989 -INFO - [G] LONG DT @ 1554: 0.053803365599989 -INFO - [G] LONG DT @ 1605: 0.1 -INFO - [G] LONG DT @ 1605: 0.1 -INFO - [G] LONG DT @ 1605: 0.1 -INFO - [G] LONG DT @ 1605: 0.1 -INFO - [G] LONG DT @ 1605: 0.1 -INFO - [G] LONG DT @ 1605: 0.1 -INFO - [G] LONG DT @ 1606: 0.1 -INFO - [G] LONG DT @ 1606: 0.081722380000001 -INFO - [G] LONG DT @ 1606: 0.066607564000036 -INFO - [G] LONG DT @ 1606: 0.054445931200006 -INFO - [G] LONG DT @ 1667: 0.1 -INFO - [G] LONG DT @ 1667: 0.1 -INFO - [G] LONG DT @ 1667: 0.1 -INFO - [G] LONG DT @ 1667: 0.1 -INFO - [G] LONG DT @ 1668: 0.1 -INFO - [G] LONG DT @ 1668: 0.1 -INFO - [G] LONG DT @ 1668: 0.1 -INFO - [G] LONG DT @ 1668: 0.1 -INFO - [G] LONG DT @ 1668: 0.1 -INFO - [G] LONG DT @ 1668: 0.1 -INFO - [G] LONG DT @ 1668: 0.1 -INFO - [G] LONG DT @ 1668: 0.1 -INFO - [G] LONG DT @ 1668: 0.1 -INFO - [G] LONG DT @ 1668: 0.081780099999996 -INFO - [G] LONG DT @ 1669: 0.06657709999999 -INFO - [G] LONG DT @ 1669: 0.054286639999987 -INFO - [G] 2025-01-06 18:24:01 :: INFO :: TIMER :: [0000] Injected Language in 0.002 ms -INFO - [G] 2025-01-06 18:24:01 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.939 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0030] Injected Atlas in 772.983 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0025] Injected Sound in 18.565 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0032] Injected Stake in 0.111 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0008] Injected Rarity in 0.019 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.062 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0391] Injected Center in 1.430 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.010 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0027] Injected Blind in 0.034 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0002] Injected Seal in 0.042 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0004] Injected Suit in 0.049 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0013] Injected Rank in 0.023 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.021 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.055 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0031] Injected Challenge in 0.106 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0028] Injected Tag in 0.221 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0009] Injected Sticker in 0.068 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0009] Injected Shader in 21.968 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0020] Injected Achievement in 0.054 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.055 ms -INFO - [G] 2025-01-06 18:24:02 :: INFO :: TIMER :: [0011] Injected Event in 0.010 ms -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 12: 0.080777819999985 -INFO - [G] LONG DT @ 12: 0.064926176000021 -INFO - [G] LONG DT @ 12: 0.052253900799991 -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0000] Injected Language in 0.002 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.767 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0030] Injected Atlas in 750.861 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0025] Injected Sound in 18.431 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0032] Injected Stake in 0.143 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0008] Injected Rarity in 0.017 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.032 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0391] Injected Center in 1.187 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.008 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0027] Injected Blind in 0.084 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0002] Injected Seal in 0.036 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0004] Injected Suit in 0.049 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0013] Injected Rank in 0.023 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.043 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.075 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0031] Injected Challenge in 0.055 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0028] Injected Tag in 0.079 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0009] Injected Sticker in 0.063 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0009] Injected Shader in 76.396 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0020] Injected Achievement in 0.071 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.298 ms -INFO - [G] 2025-01-06 18:24:12 :: INFO :: TIMER :: [0011] Injected Event in 0.013 ms -INFO - [G] LONG DT @ 21: 0.1 -INFO - [G] LONG DT @ 12: 0.080835899999993 -INFO - [G] LONG DT @ 12: 0.064991679999988 -INFO - [G] LONG DT @ 12: 0.052397784000002 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 18: 0.080871459999962 -INFO - [G] LONG DT @ 18: 0.065903347999978 -INFO - [G] LONG DT @ 18: 0.053924178400007 -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] LONG DT @ 135: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 137: 0.1 -INFO - [G] LONG DT @ 137: 0.1 -INFO - [G] LONG DT @ 137: 0.1 -INFO - [G] LONG DT @ 137: 0.1 -INFO - [G] LONG DT @ 137: 0.1 -INFO - [G] LONG DT @ 137: 0.1 -INFO - [G] LONG DT @ 137: 0.1 -INFO - [G] LONG DT @ 137: 0.1 -INFO - [G] LONG DT @ 137: 0.1 -INFO - [G] LONG DT @ 137: 0.1 -INFO - [G] LONG DT @ 138: 0.1 -INFO - [G] LONG DT @ 138: 0.081146120000067 -INFO - [G] LONG DT @ 138: 0.065857816000047 -INFO - [G] LONG DT @ 138: 0.05390055280003 -INFO - [G] 2025-01-06 18:41:18 :: INFO :: TIMER :: [0000] Injected Language in 0.002 ms -INFO - [G] 2025-01-06 18:41:18 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.747 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0030] Injected Atlas in 762.820 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0025] Injected Sound in 18.082 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0032] Injected Stake in 0.378 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0008] Injected Rarity in 0.021 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.034 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0391] Injected Center in 0.985 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.008 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0027] Injected Blind in 0.027 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0002] Injected Seal in 0.038 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0004] Injected Suit in 0.049 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0013] Injected Rank in 0.022 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.022 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.039 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0031] Injected Challenge in 0.023 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0028] Injected Tag in 0.036 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0009] Injected Sticker in 0.082 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0009] Injected Shader in 54.513 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0020] Injected Achievement in 0.059 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.200 ms -INFO - [G] 2025-01-06 18:41:19 :: INFO :: TIMER :: [0011] Injected Event in 0.011 ms -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 12: 0.081048679999985 -INFO - [G] LONG DT @ 12: 0.065136364000049 -INFO - [G] LONG DT @ 12: 0.052441751200043 diff --git a/lovely/log/lovely-2025.01.06-23.32.17.log b/lovely/log/lovely-2025.01.06-23.32.17.log deleted file mode 100644 index c5aa866..0000000 --- a/lovely/log/lovely-2025.01.06-23.32.17.log +++ /dev/null @@ -1,408 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 136ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 10 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 72 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 121 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 47 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 203 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-06 23:32:19 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-06 23:32:19 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-06 23:32:19 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-06 23:32:19 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-06 23:32:19 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-06 23:32:19 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-06 23:32:19 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-06 23:32:19 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.890 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0030] Injected Atlas in 788.181 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0025] Injected Sound in 21.314 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0032] Injected Stake in 1.667 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0008] Injected Rarity in 0.074 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.126 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0391] Injected Center in 2.374 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.012 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0027] Injected Blind in 0.188 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0002] Injected Seal in 0.058 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0004] Injected Suit in 0.115 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0013] Injected Rank in 0.212 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.031 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.202 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0031] Injected Challenge in 0.078 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0028] Injected Tag in 0.091 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0009] Injected Sticker in 0.209 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0009] Injected Shader in 53.804 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0020] Injected Achievement in 0.092 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.056 ms -INFO - [G] 2025-01-06 23:32:20 :: INFO :: TIMER :: [0011] Injected Event in 0.014 ms -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 69: 0.1 -INFO - [G] LONG DT @ 69: 0.1 -INFO - [G] LONG DT @ 69: 0.1 -INFO - [G] LONG DT @ 69: 0.1 -INFO - [G] LONG DT @ 69: 0.1 -INFO - [G] LONG DT @ 69: 0.1 -INFO - [G] LONG DT @ 69: 0.1 -INFO - [G] LONG DT @ 69: 0.1 -INFO - [G] LONG DT @ 69: 0.1 -INFO - [G] LONG DT @ 69: 0.1 -INFO - [G] LONG DT @ 70: 0.1 -INFO - [G] LONG DT @ 70: 0.1 -INFO - [G] LONG DT @ 70: 0.1 -INFO - [G] LONG DT @ 70: 0.1 -INFO - [G] LONG DT @ 70: 0.1 -INFO - [G] LONG DT @ 70: 0.1 -INFO - [G] LONG DT @ 70: 0.1 -INFO - [G] LONG DT @ 70: 0.1 -INFO - [G] LONG DT @ 70: 0.1 -INFO - [G] LONG DT @ 70: 0.1 -INFO - [G] LONG DT @ 71: 0.1 -INFO - [G] LONG DT @ 71: 0.1 -INFO - [G] LONG DT @ 71: 0.1 -INFO - [G] LONG DT @ 71: 0.1 -INFO - [G] LONG DT @ 71: 0.1 -INFO - [G] LONG DT @ 71: 0.1 -INFO - [G] LONG DT @ 71: 0.1 -INFO - [G] LONG DT @ 71: 0.1 -INFO - [G] LONG DT @ 71: 0.1 -INFO - [G] LONG DT @ 71: 0.1 -INFO - [G] LONG DT @ 72: 0.1 -INFO - [G] LONG DT @ 72: 0.1 -INFO - [G] LONG DT @ 72: 0.1 -INFO - [G] LONG DT @ 72: 0.1 -INFO - [G] LONG DT @ 72: 0.1 -INFO - [G] LONG DT @ 72: 0.1 -INFO - [G] LONG DT @ 72: 0.1 -INFO - [G] LONG DT @ 72: 0.1 -INFO - [G] LONG DT @ 72: 0.1 -INFO - [G] LONG DT @ 72: 0.1 -INFO - [G] LONG DT @ 73: 0.1 -INFO - [G] LONG DT @ 73: 0.1 -INFO - [G] LONG DT @ 73: 0.1 -INFO - [G] LONG DT @ 73: 0.1 -INFO - [G] LONG DT @ 73: 0.1 -INFO - [G] LONG DT @ 73: 0.1 -INFO - [G] LONG DT @ 73: 0.1 -INFO - [G] LONG DT @ 73: 0.1 -INFO - [G] LONG DT @ 73: 0.1 -INFO - [G] LONG DT @ 73: 0.1 -INFO - [G] LONG DT @ 74: 0.1 -INFO - [G] LONG DT @ 74: 0.1 -INFO - [G] LONG DT @ 74: 0.1 -INFO - [G] LONG DT @ 74: 0.1 -INFO - [G] LONG DT @ 74: 0.1 -INFO - [G] LONG DT @ 74: 0.1 -INFO - [G] LONG DT @ 74: 0.1 -INFO - [G] LONG DT @ 74: 0.081261959999999 -INFO - [G] LONG DT @ 74: 0.066264627999999 -INFO - [G] LONG DT @ 74: 0.054103482400001 -INFO - [G] LONG DT @ 80: 0.1 -INFO - [G] LONG DT @ 80: 0.1 -INFO - [G] LONG DT @ 80: 0.1 -INFO - [G] LONG DT @ 80: 0.1 -INFO - [G] LONG DT @ 81: 0.1 -INFO - [G] LONG DT @ 81: 0.1 -INFO - [G] LONG DT @ 81: 0.1 -INFO - [G] LONG DT @ 81: 0.1 -INFO - [G] LONG DT @ 81: 0.1 -INFO - [G] LONG DT @ 81: 0.1 -INFO - [G] LONG DT @ 81: 0.1 -INFO - [G] LONG DT @ 81: 0.1 -INFO - [G] LONG DT @ 81: 0.1 -INFO - [G] LONG DT @ 81: 0.1 -INFO - [G] LONG DT @ 82: 0.1 -INFO - [G] LONG DT @ 82: 0.1 -INFO - [G] LONG DT @ 82: 0.1 -INFO - [G] LONG DT @ 82: 0.1 -INFO - [G] LONG DT @ 82: 0.1 -INFO - [G] LONG DT @ 82: 0.1 -INFO - [G] LONG DT @ 82: 0.1 -INFO - [G] LONG DT @ 82: 0.1 -INFO - [G] LONG DT @ 82: 0.1 -INFO - [G] LONG DT @ 82: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 87: 0.1 -INFO - [G] LONG DT @ 87: 0.1 -INFO - [G] LONG DT @ 87: 0.081094640000002 -INFO - [G] LONG DT @ 87: 0.065771371999999 -INFO - [G] LONG DT @ 87: 0.053828057600003 -INFO - [G] LONG DT @ 131: 0.1 -INFO - [G] LONG DT @ 131: 0.1 -INFO - [G] LONG DT @ 132: 0.1 -INFO - [G] LONG DT @ 132: 0.1 -INFO - [G] LONG DT @ 132: 0.1 -INFO - [G] LONG DT @ 132: 0.1 -INFO - [G] LONG DT @ 132: 0.1 -INFO - [G] LONG DT @ 132: 0.1 -INFO - [G] LONG DT @ 132: 0.1 -INFO - [G] LONG DT @ 132: 0.1 -INFO - [G] LONG DT @ 132: 0.1 -INFO - [G] LONG DT @ 132: 0.1 -INFO - [G] LONG DT @ 133: 0.1 -INFO - [G] LONG DT @ 133: 0.1 -INFO - [G] LONG DT @ 133: 0.1 -INFO - [G] LONG DT @ 133: 0.1 -INFO - [G] LONG DT @ 133: 0.1 -INFO - [G] LONG DT @ 133: 0.1 -INFO - [G] LONG DT @ 133: 0.1 -INFO - [G] LONG DT @ 133: 0.1 -INFO - [G] LONG DT @ 133: 0.1 -INFO - [G] LONG DT @ 133: 0.1 -INFO - [G] LONG DT @ 134: 0.1 -INFO - [G] LONG DT @ 134: 0.1 -INFO - [G] LONG DT @ 134: 0.1 -INFO - [G] LONG DT @ 134: 0.1 -INFO - [G] LONG DT @ 134: 0.1 -INFO - [G] LONG DT @ 134: 0.1 -INFO - [G] LONG DT @ 134: 0.1 -INFO - [G] LONG DT @ 134: 0.1 -INFO - [G] LONG DT @ 134: 0.1 -INFO - [G] LONG DT @ 134: 0.1 -INFO - [G] LONG DT @ 135: 0.1 -INFO - [G] LONG DT @ 135: 0.1 -INFO - [G] LONG DT @ 135: 0.1 -INFO - [G] LONG DT @ 135: 0.1 -INFO - [G] LONG DT @ 135: 0.1 -INFO - [G] LONG DT @ 135: 0.1 -INFO - [G] LONG DT @ 135: 0.1 -INFO - [G] LONG DT @ 135: 0.1 -INFO - [G] LONG DT @ 135: 0.1 -INFO - [G] LONG DT @ 135: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.1 -INFO - [G] LONG DT @ 136: 0.081191100000005 -INFO - [G] LONG DT @ 136: 0.066190239999998 -INFO - [G] LONG DT @ 136: 0.054027572000007 -INFO - [G] LONG DT @ 138: 0.1 -INFO - [G] LONG DT @ 139: 0.1 -INFO - [G] LONG DT @ 139: 0.1 -INFO - [G] LONG DT @ 139: 0.1 -INFO - [G] LONG DT @ 139: 0.1 -INFO - [G] LONG DT @ 139: 0.1 -INFO - [G] LONG DT @ 139: 0.1 -INFO - [G] LONG DT @ 139: 0.1 -INFO - [G] LONG DT @ 139: 0.1 -INFO - [G] LONG DT @ 139: 0.1 -INFO - [G] LONG DT @ 139: 0.1 -INFO - [G] LONG DT @ 140: 0.1 -INFO - [G] LONG DT @ 140: 0.1 -INFO - [G] LONG DT @ 140: 0.1 -INFO - [G] LONG DT @ 140: 0.1 -INFO - [G] LONG DT @ 140: 0.1 -INFO - [G] LONG DT @ 140: 0.1 -INFO - [G] LONG DT @ 140: 0.1 -INFO - [G] LONG DT @ 140: 0.1 -INFO - [G] LONG DT @ 140: 0.1 -INFO - [G] LONG DT @ 140: 0.1 -INFO - [G] LONG DT @ 141: 0.1 -INFO - [G] LONG DT @ 141: 0.1 -INFO - [G] LONG DT @ 141: 0.1 -INFO - [G] LONG DT @ 141: 0.1 -INFO - [G] LONG DT @ 141: 0.1 -INFO - [G] LONG DT @ 141: 0.1 -INFO - [G] LONG DT @ 141: 0.1 -INFO - [G] LONG DT @ 141: 0.1 -INFO - [G] LONG DT @ 141: 0.1 -INFO - [G] LONG DT @ 141: 0.1 -INFO - [G] LONG DT @ 142: 0.1 -INFO - [G] LONG DT @ 142: 0.1 -INFO - [G] LONG DT @ 142: 0.1 -INFO - [G] LONG DT @ 142: 0.1 -INFO - [G] LONG DT @ 142: 0.1 -INFO - [G] LONG DT @ 142: 0.1 -INFO - [G] LONG DT @ 142: 0.1 -INFO - [G] LONG DT @ 142: 0.1 -INFO - [G] LONG DT @ 142: 0.1 -INFO - [G] LONG DT @ 142: 0.1 -INFO - [G] LONG DT @ 143: 0.1 -INFO - [G] LONG DT @ 143: 0.1 -INFO - [G] LONG DT @ 143: 0.1 -INFO - [G] LONG DT @ 143: 0.1 -INFO - [G] LONG DT @ 143: 0.1 -INFO - [G] LONG DT @ 143: 0.1 -INFO - [G] LONG DT @ 143: 0.1 -INFO - [G] LONG DT @ 143: 0.1 -INFO - [G] LONG DT @ 143: 0.1 -INFO - [G] LONG DT @ 143: 0.1 -INFO - [G] LONG DT @ 144: 0.1 -INFO - [G] LONG DT @ 144: 0.1 -INFO - [G] LONG DT @ 144: 0.1 -INFO - [G] LONG DT @ 144: 0.1 -INFO - [G] LONG DT @ 144: 0.1 -INFO - [G] LONG DT @ 144: 0.1 -INFO - [G] LONG DT @ 144: 0.1 -INFO - [G] LONG DT @ 144: 0.1 -INFO - [G] LONG DT @ 144: 0.1 -INFO - [G] LONG DT @ 144: 0.1 -INFO - [G] LONG DT @ 145: 0.1 -INFO - [G] LONG DT @ 145: 0.1 -INFO - [G] LONG DT @ 145: 0.1 -INFO - [G] LONG DT @ 145: 0.1 -INFO - [G] LONG DT @ 145: 0.1 -INFO - [G] LONG DT @ 145: 0.1 -INFO - [G] LONG DT @ 145: 0.1 -INFO - [G] LONG DT @ 145: 0.1 -INFO - [G] LONG DT @ 145: 0.1 -INFO - [G] LONG DT @ 145: 0.1 -INFO - [G] LONG DT @ 146: 0.1 -INFO - [G] LONG DT @ 146: 0.1 -INFO - [G] LONG DT @ 146: 0.1 -INFO - [G] LONG DT @ 146: 0.1 -INFO - [G] LONG DT @ 146: 0.1 -INFO - [G] LONG DT @ 146: 0.1 -INFO - [G] LONG DT @ 146: 0.1 -INFO - [G] LONG DT @ 146: 0.1 -INFO - [G] LONG DT @ 146: 0.1 -INFO - [G] LONG DT @ 146: 0.1 -INFO - [G] LONG DT @ 147: 0.1 -INFO - [G] LONG DT @ 147: 0.1 -INFO - [G] LONG DT @ 147: 0.1 -INFO - [G] LONG DT @ 147: 0.1 -INFO - [G] LONG DT @ 147: 0.1 -INFO - [G] LONG DT @ 147: 0.1 -INFO - [G] LONG DT @ 147: 0.1 -INFO - [G] LONG DT @ 147: 0.1 -INFO - [G] LONG DT @ 147: 0.1 -INFO - [G] LONG DT @ 147: 0.1 -INFO - [G] LONG DT @ 148: 0.1 -INFO - [G] LONG DT @ 148: 0.1 -INFO - [G] LONG DT @ 148: 0.1 -INFO - [G] LONG DT @ 148: 0.1 -INFO - [G] LONG DT @ 148: 0.1 -INFO - [G] LONG DT @ 148: 0.1 -INFO - [G] LONG DT @ 148: 0.1 -INFO - [G] LONG DT @ 148: 0.1 -INFO - [G] LONG DT @ 148: 0.1 -INFO - [G] LONG DT @ 148: 0.1 -INFO - [G] LONG DT @ 149: 0.1 -INFO - [G] LONG DT @ 149: 0.1 -INFO - [G] LONG DT @ 149: 0.1 -INFO - [G] LONG DT @ 149: 0.0812112 -INFO - [G] LONG DT @ 149: 0.066017799999999 -INFO - [G] LONG DT @ 149: 0.053712919999999 diff --git a/lovely/log/lovely-2025.01.07-02.04.03.log b/lovely/log/lovely-2025.01.07-02.04.03.log deleted file mode 100644 index 1c47e77..0000000 --- a/lovely/log/lovely-2025.01.07-02.04.03.log +++ /dev/null @@ -1,118 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 131ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 10 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 72 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 121 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 47 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 203 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-07 02:04:05 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-07 02:04:06 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-07 02:04:06 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-07 02:04:06 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-07 02:04:06 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-07 02:04:06 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-07 02:04:06 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-07 02:04:06 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.883 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0030] Injected Atlas in 785.442 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0025] Injected Sound in 21.318 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0032] Injected Stake in 1.772 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0008] Injected Rarity in 0.099 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.094 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0391] Injected Center in 2.605 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.010 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0027] Injected Blind in 0.434 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0002] Injected Seal in 0.055 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0004] Injected Suit in 0.066 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0013] Injected Rank in 0.081 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.028 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.083 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0031] Injected Challenge in 0.039 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0028] Injected Tag in 0.777 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0009] Injected Sticker in 0.498 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0009] Injected Shader in 57.738 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0020] Injected Achievement in 0.056 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.307 ms -INFO - [G] 2025-01-07 02:04:07 :: INFO :: TIMER :: [0011] Injected Event in 0.015 ms -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.08386144 -INFO - [G] LONG DT @ 22: 0.070841552 -INFO - [G] LONG DT @ 22: 0.0602701216 -INFO - [G] LONG DT @ 22: 0.05176605728 diff --git a/lovely/log/lovely-2025.01.08-01.06.04.log b/lovely/log/lovely-2025.01.08-01.06.04.log deleted file mode 100644 index 274f7c3..0000000 --- a/lovely/log/lovely-2025.01.08-01.06.04.log +++ /dev/null @@ -1,120 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 140ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 10 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 72 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 121 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 47 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 203 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-08 01:06:06 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-08 01:06:07 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-08 01:06:07 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-08 01:06:07 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-08 01:06:07 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-08 01:06:07 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-08 01:06:07 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-08 01:06:07 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 1.066 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0030] Injected Atlas in 778.382 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0025] Injected Sound in 19.657 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0032] Injected Stake in 1.566 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0008] Injected Rarity in 0.043 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.077 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0391] Injected Center in 2.198 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.011 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0027] Injected Blind in 0.059 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0002] Injected Seal in 0.049 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0004] Injected Suit in 0.069 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0013] Injected Rank in 0.050 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.064 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.085 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0031] Injected Challenge in 0.036 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0028] Injected Tag in 0.091 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0009] Injected Sticker in 0.107 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0009] Injected Shader in 50.960 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0020] Injected Achievement in 0.067 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.045 ms -INFO - [G] 2025-01-08 01:06:08 :: INFO :: TIMER :: [0011] Injected Event in 0.017 ms -INFO - [G] LONG DT @ 6: 0.050069491898674 -INFO - [G] LONG DT @ 12: 0.1 -INFO - [G] LONG DT @ 12: 0.08280844 -INFO - [G] LONG DT @ 12: 0.068812992 -INFO - [G] LONG DT @ 12: 0.0575500936 -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load diff --git a/lovely/log/lovely-2025.01.08-01.08.26.log b/lovely/log/lovely-2025.01.08-01.08.26.log deleted file mode 100644 index 5270611..0000000 --- a/lovely/log/lovely-2025.01.08-01.08.26.log +++ /dev/null @@ -1,220 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 136ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 10 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 72 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 121 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 47 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 203 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-08 01:08:28 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-08 01:08:28 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-08 01:08:28 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-08 01:08:28 :: TRACE :: Loader :: Processing Mod file (Legacy header): MoreSpeeds.lua -INFO - [G] 2025-01-08 01:08:28 :: TRACE :: Loader :: Saving Mod Info: MoreSpeed -INFO - [G] 2025-01-08 01:08:28 :: ERROR :: Loader :: Found invalid metadata JSON file at C:\users\steamuser\AppData\Roaming\Balatro\Mods/Steamopollys-MoreSpeed-0.8.2/manifest.json, ignoring: [SMODS _ "src/loader.lua"]:212: id -INFO - [G] 2025-01-08 01:08:28 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-08 01:08:28 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-08 01:08:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-08 01:08:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-08 01:08:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-08 01:08:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-08 01:08:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-08 01:08:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-08 01:08:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-08 01:08:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-08 01:08:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-08 01:08:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-08 01:08:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-08 01:08:29 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-08 01:08:29 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-08 01:08:29 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-08 01:08:29 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 1.050 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0030] Injected Atlas in 767.423 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0025] Injected Sound in 20.446 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0032] Injected Stake in 1.084 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0008] Injected Rarity in 0.025 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.063 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0391] Injected Center in 2.572 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.009 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0027] Injected Blind in 0.092 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0002] Injected Seal in 0.071 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0004] Injected Suit in 0.071 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0013] Injected Rank in 0.110 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.032 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.113 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0031] Injected Challenge in 0.036 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0028] Injected Tag in 0.751 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0009] Injected Sticker in 0.531 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0009] Injected Shader in 56.041 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0000] Injected Keybind in 0.002 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0020] Injected Achievement in 0.056 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.440 ms -INFO - [G] 2025-01-08 01:08:29 :: INFO :: TIMER :: [0011] Injected Event in 0.015 ms -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] LONG DT @ 757: 0.1 -INFO - [G] LONG DT @ 757: 0.1 -INFO - [G] LONG DT @ 757: 0.1 -INFO - [G] LONG DT @ 757: 0.1 -INFO - [G] LONG DT @ 757: 0.1 -INFO - [G] LONG DT @ 758: 0.1 -INFO - [G] LONG DT @ 758: 0.1 -INFO - [G] LONG DT @ 758: 0.1 -INFO - [G] LONG DT @ 758: 0.1 -INFO - [G] LONG DT @ 758: 0.1 -INFO - [G] LONG DT @ 758: 0.1 -INFO - [G] LONG DT @ 758: 0.1 -INFO - [G] LONG DT @ 758: 0.1 -INFO - [G] LONG DT @ 758: 0.1 -INFO - [G] LONG DT @ 758: 0.1 -INFO - [G] LONG DT @ 759: 0.1 -INFO - [G] LONG DT @ 759: 0.1 -INFO - [G] LONG DT @ 759: 0.1 -INFO - [G] LONG DT @ 759: 0.1 -INFO - [G] LONG DT @ 759: 0.1 -INFO - [G] LONG DT @ 759: 0.1 -INFO - [G] LONG DT @ 759: 0.1 -INFO - [G] LONG DT @ 759: 0.1 -INFO - [G] LONG DT @ 759: 0.1 -INFO - [G] LONG DT @ 759: 0.1 -INFO - [G] LONG DT @ 760: 0.1 -INFO - [G] LONG DT @ 760: 0.1 -INFO - [G] LONG DT @ 760: 0.1 -INFO - [G] LONG DT @ 760: 0.1 -INFO - [G] LONG DT @ 760: 0.1 -INFO - [G] LONG DT @ 760: 0.1 -INFO - [G] LONG DT @ 760: 0.1 -INFO - [G] LONG DT @ 760: 0.1 -INFO - [G] LONG DT @ 760: 0.1 -INFO - [G] LONG DT @ 760: 0.081941880000004 -INFO - [G] LONG DT @ 760: 0.067397723999979 -INFO - [G] LONG DT @ 761: 0.055312819199972 -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] LONG DT @ 568: 0.1 -INFO - [G] LONG DT @ 568: 0.1 -INFO - [G] LONG DT @ 568: 0.1 -INFO - [G] LONG DT @ 568: 0.1 -INFO - [G] LONG DT @ 568: 0.1 -INFO - [G] LONG DT @ 568: 0.1 -INFO - [G] LONG DT @ 568: 0.1 -INFO - [G] LONG DT @ 568: 0.1 -INFO - [G] LONG DT @ 568: 0.1 -INFO - [G] LONG DT @ 568: 0.1 -INFO - [G] LONG DT @ 569: 0.1 -INFO - [G] LONG DT @ 569: 0.1 -INFO - [G] LONG DT @ 569: 0.082049099999977 -INFO - [G] LONG DT @ 569: 0.067290059999981 -INFO - [G] LONG DT @ 569: 0.055326167999992 -INFO - [G] LONG DT @ 571: 0.066332079068852 -INFO - [G] LONG DT @ 571: 0.056924363255082 -INFO - [G] LONG DT @ 657: 0.1 -INFO - [G] LONG DT @ 657: 0.1 -INFO - [G] LONG DT @ 657: 0.1 -INFO - [G] LONG DT @ 657: 0.1 -INFO - [G] LONG DT @ 657: 0.1 -INFO - [G] LONG DT @ 657: 0.1 -INFO - [G] LONG DT @ 657: 0.1 -INFO - [G] LONG DT @ 657: 0.1 -INFO - [G] LONG DT @ 657: 0.1 -INFO - [G] LONG DT @ 657: 0.1 -INFO - [G] LONG DT @ 658: 0.1 -INFO - [G] LONG DT @ 658: 0.1 -INFO - [G] LONG DT @ 658: 0.1 -INFO - [G] LONG DT @ 658: 0.1 -INFO - [G] LONG DT @ 658: 0.1 -INFO - [G] LONG DT @ 658: 0.1 -INFO - [G] LONG DT @ 658: 0.1 -INFO - [G] LONG DT @ 658: 0.1 -INFO - [G] LONG DT @ 658: 0.1 -INFO - [G] LONG DT @ 658: 0.1 -INFO - [G] LONG DT @ 659: 0.1 -INFO - [G] LONG DT @ 659: 0.1 -INFO - [G] LONG DT @ 659: 0.1 -INFO - [G] LONG DT @ 659: 0.1 -INFO - [G] LONG DT @ 659: 0.1 -INFO - [G] LONG DT @ 659: 0.1 -INFO - [G] LONG DT @ 659: 0.1 -INFO - [G] LONG DT @ 659: 0.1 -INFO - [G] LONG DT @ 659: 0.1 -INFO - [G] LONG DT @ 659: 0.1 -INFO - [G] LONG DT @ 660: 0.1 -INFO - [G] LONG DT @ 660: 0.1 -INFO - [G] LONG DT @ 660: 0.1 -INFO - [G] LONG DT @ 660: 0.1 -INFO - [G] LONG DT @ 660: 0.1 -INFO - [G] LONG DT @ 660: 0.1 -INFO - [G] LONG DT @ 660: 0.1 -INFO - [G] LONG DT @ 660: 0.1 -INFO - [G] LONG DT @ 660: 0.1 -INFO - [G] LONG DT @ 660: 0.08137937999998 -INFO - [G] LONG DT @ 660: 0.066217124000008 -INFO - [G] LONG DT @ 661: 0.05408547919998 diff --git a/lovely/log/lovely-2025.01.08-02.05.16.log b/lovely/log/lovely-2025.01.08-02.05.16.log deleted file mode 100644 index 2451455..0000000 --- a/lovely/log/lovely-2025.01.08-02.05.16.log +++ /dev/null @@ -1,814 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 135ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 12 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 19 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 77 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 121 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 47 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 203 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-08 02:05:18 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] { - [1] = table: 0x046f3a10 { - [1] = 0.99607843137255, - [2] = 0.37254901960784, - [3] = 0.33333333333333, - [4] = 1, - }, - [2] = table: 0x046f3a60 { - [1] = 0, - [2] = 0.6156862745098, - [3] = 1, - [4] = 1, - }, -} -INFO - [G] 2025-01-08 02:05:19 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-08 02:05:19 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-08 02:05:19 :: TRACE :: Loader :: Processing Mod file (Legacy header): MoreSpeeds.lua -INFO - [G] 2025-01-08 02:05:19 :: TRACE :: Loader :: Saving Mod Info: MoreSpeed -INFO - [G] 2025-01-08 02:05:19 :: ERROR :: Loader :: Found invalid metadata JSON file at C:\users\steamuser\AppData\Roaming\Balatro\Mods/Steamopollys-MoreSpeed-0.8.2/manifest.json, ignoring: [SMODS _ "src/loader.lua"]:212: id -INFO - [G] 2025-01-08 02:05:19 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-08 02:05:19 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-08 02:05:19 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-08 02:05:19 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-08 02:05:19 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.697 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0030] Injected Atlas in 777.868 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0025] Injected Sound in 28.353 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0032] Injected Stake in 2.176 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0008] Injected Rarity in 0.069 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.107 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0391] Injected Center in 1.860 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.007 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0027] Injected Blind in 0.039 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0002] Injected Seal in 0.106 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0004] Injected Suit in 0.282 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0013] Injected Rank in 0.241 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.071 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0016] Injected PokerHand in 1.828 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0031] Injected Challenge in 0.093 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0028] Injected Tag in 0.047 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0009] Injected Sticker in 3.352 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0009] Injected Shader in 49.105 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0020] Injected Achievement in 0.081 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.582 ms -INFO - [G] 2025-01-08 02:05:20 :: INFO :: TIMER :: [0011] Injected Event in 0.013 ms -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] LONG DT @ 1195: 0.065513680611866 -INFO - [G] LONG DT @ 1195: 0.059834684489461 -INFO - [G] LONG DT @ 1195: 0.055208227591607 -INFO - [G] LONG DT @ 2138: 0.067980991829622 -INFO - [G] LONG DT @ 2138: 0.061686373463664 -INFO - [G] LONG DT @ 2138: 0.056641658770973 -INFO - [G] LONG DT @ 2138: 0.052576427016779 -INFO - [G] LONG DT @ 2614: 0.1 -INFO - [G] LONG DT @ 2614: 0.1 -INFO - [G] LONG DT @ 2614: 0.1 -INFO - [G] LONG DT @ 2614: 0.1 -INFO - [G] LONG DT @ 2614: 0.1 -INFO - [G] LONG DT @ 2614: 0.1 -INFO - [G] LONG DT @ 2614: 0.1 -INFO - [G] LONG DT @ 2614: 0.1 -INFO - [G] LONG DT @ 2614: 0.1 -INFO - [G] LONG DT @ 2615: 0.1 -INFO - [G] LONG DT @ 2615: 0.1 -INFO - [G] LONG DT @ 2615: 0.1 -INFO - [G] LONG DT @ 2615: 0.1 -INFO - [G] LONG DT @ 2615: 0.1 -INFO - [G] LONG DT @ 2615: 0.1 -INFO - [G] LONG DT @ 2615: 0.1 -INFO - [G] LONG DT @ 2615: 0.1 -INFO - [G] LONG DT @ 2615: 0.1 -INFO - [G] LONG DT @ 2615: 0.1 -INFO - [G] LONG DT @ 2616: 0.1 -INFO - [G] LONG DT @ 2616: 0.1 -INFO - [G] LONG DT @ 2616: 0.1 -INFO - [G] LONG DT @ 2616: 0.1 -INFO - [G] LONG DT @ 2616: 0.1 -INFO - [G] LONG DT @ 2616: 0.1 -INFO - [G] LONG DT @ 2616: 0.081539159999993 -INFO - [G] LONG DT @ 2616: 0.06645142800004 -INFO - [G] LONG DT @ 2616: 0.05440646240003 -INFO - [G] LONG DT @ 2617: 0.1 -INFO - [G] LONG DT @ 2617: 0.1 -INFO - [G] LONG DT @ 2618: 0.1 -INFO - [G] LONG DT @ 2618: 0.081775039999939 -INFO - [G] LONG DT @ 2618: 0.066723771999954 -INFO - [G] LONG DT @ 2618: 0.054492697599944 -INFO - [G] LONG DT @ 2619: 0.1 -INFO - [G] LONG DT @ 2619: 0.1 -INFO - [G] LONG DT @ 2620: 0.1 -INFO - [G] LONG DT @ 2620: 0.1 -INFO - [G] LONG DT @ 2620: 0.1 -INFO - [G] LONG DT @ 2620: 0.1 -INFO - [G] LONG DT @ 2620: 0.1 -INFO - [G] LONG DT @ 2620: 0.1 -INFO - [G] LONG DT @ 2620: 0.1 -INFO - [G] LONG DT @ 2620: 0.1 -INFO - [G] LONG DT @ 2620: 0.1 -INFO - [G] LONG DT @ 2620: 0.1 -INFO - [G] LONG DT @ 2621: 0.1 -INFO - [G] LONG DT @ 2621: 0.1 -INFO - [G] LONG DT @ 2621: 0.1 -INFO - [G] LONG DT @ 2621: 0.1 -INFO - [G] LONG DT @ 2621: 0.1 -INFO - [G] LONG DT @ 2621: 0.1 -INFO - [G] LONG DT @ 2621: 0.1 -INFO - [G] LONG DT @ 2621: 0.1 -INFO - [G] LONG DT @ 2621: 0.1 -INFO - [G] LONG DT @ 2621: 0.1 -INFO - [G] LONG DT @ 2622: 0.1 -INFO - [G] LONG DT @ 2622: 0.1 -INFO - [G] LONG DT @ 2622: 0.1 -INFO - [G] LONG DT @ 2622: 0.1 -INFO - [G] LONG DT @ 2622: 0.1 -INFO - [G] LONG DT @ 2622: 0.1 -INFO - [G] LONG DT @ 2622: 0.1 -INFO - [G] LONG DT @ 2622: 0.1 -INFO - [G] LONG DT @ 2622: 0.1 -INFO - [G] LONG DT @ 2622: 0.1 -INFO - [G] LONG DT @ 2623: 0.1 -INFO - [G] LONG DT @ 2623: 0.1 -INFO - [G] LONG DT @ 2623: 0.1 -INFO - [G] LONG DT @ 2623: 0.1 -INFO - [G] LONG DT @ 2623: 0.1 -INFO - [G] LONG DT @ 2623: 0.1 -INFO - [G] LONG DT @ 2623: 0.1 -INFO - [G] LONG DT @ 2623: 0.1 -INFO - [G] LONG DT @ 2623: 0.1 -INFO - [G] LONG DT @ 2623: 0.1 -INFO - [G] LONG DT @ 2624: 0.1 -INFO - [G] LONG DT @ 2624: 0.1 -INFO - [G] LONG DT @ 2624: 0.1 -INFO - [G] LONG DT @ 2624: 0.1 -INFO - [G] LONG DT @ 2624: 0.1 -INFO - [G] LONG DT @ 2624: 0.1 -INFO - [G] LONG DT @ 2624: 0.1 -INFO - [G] LONG DT @ 2624: 0.1 -INFO - [G] LONG DT @ 2624: 0.1 -INFO - [G] LONG DT @ 2624: 0.1 -INFO - [G] LONG DT @ 2625: 0.1 -INFO - [G] LONG DT @ 2625: 0.1 -INFO - [G] LONG DT @ 2625: 0.1 -INFO - [G] LONG DT @ 2625: 0.1 -INFO - [G] LONG DT @ 2625: 0.1 -INFO - [G] LONG DT @ 2625: 0.1 -INFO - [G] LONG DT @ 2625: 0.1 -INFO - [G] LONG DT @ 2625: 0.1 -INFO - [G] LONG DT @ 2625: 0.1 -INFO - [G] LONG DT @ 2625: 0.1 -INFO - [G] LONG DT @ 2626: 0.1 -INFO - [G] LONG DT @ 2626: 0.1 -INFO - [G] LONG DT @ 2626: 0.1 -INFO - [G] LONG DT @ 2626: 0.1 -INFO - [G] LONG DT @ 2626: 0.1 -INFO - [G] LONG DT @ 2626: 0.1 -INFO - [G] LONG DT @ 2626: 0.1 -INFO - [G] LONG DT @ 2626: 0.1 -INFO - [G] LONG DT @ 2626: 0.1 -INFO - [G] LONG DT @ 2626: 0.1 -INFO - [G] LONG DT @ 2627: 0.1 -INFO - [G] LONG DT @ 2627: 0.1 -INFO - [G] LONG DT @ 2627: 0.1 -INFO - [G] LONG DT @ 2627: 0.1 -INFO - [G] LONG DT @ 2627: 0.1 -INFO - [G] LONG DT @ 2627: 0.1 -INFO - [G] LONG DT @ 2627: 0.1 -INFO - [G] LONG DT @ 2627: 0.1 -INFO - [G] LONG DT @ 2627: 0.1 -INFO - [G] LONG DT @ 2627: 0.1 -INFO - [G] LONG DT @ 2628: 0.1 -INFO - [G] LONG DT @ 2628: 0.1 -INFO - [G] LONG DT @ 2628: 0.1 -INFO - [G] LONG DT @ 2628: 0.1 -INFO - [G] LONG DT @ 2628: 0.1 -INFO - [G] LONG DT @ 2628: 0.1 -INFO - [G] LONG DT @ 2628: 0.1 -INFO - [G] LONG DT @ 2628: 0.1 -INFO - [G] LONG DT @ 2628: 0.1 -INFO - [G] LONG DT @ 2628: 0.1 -INFO - [G] LONG DT @ 2629: 0.1 -INFO - [G] LONG DT @ 2629: 0.1 -INFO - [G] LONG DT @ 2629: 0.1 -INFO - [G] LONG DT @ 2629: 0.1 -INFO - [G] LONG DT @ 2629: 0.1 -INFO - [G] LONG DT @ 2629: 0.1 -INFO - [G] LONG DT @ 2629: 0.1 -INFO - [G] LONG DT @ 2629: 0.1 -INFO - [G] LONG DT @ 2629: 0.1 -INFO - [G] LONG DT @ 2629: 0.1 -INFO - [G] LONG DT @ 2630: 0.1 -INFO - [G] LONG DT @ 2630: 0.1 -INFO - [G] LONG DT @ 2630: 0.1 -INFO - [G] LONG DT @ 2630: 0.1 -INFO - [G] LONG DT @ 2630: 0.1 -INFO - [G] LONG DT @ 2630: 0.1 -INFO - [G] LONG DT @ 2630: 0.1 -INFO - [G] LONG DT @ 2630: 0.1 -INFO - [G] LONG DT @ 2630: 0.1 -INFO - [G] LONG DT @ 2630: 0.1 -INFO - [G] LONG DT @ 2631: 0.1 -INFO - [G] LONG DT @ 2631: 0.1 -INFO - [G] LONG DT @ 2631: 0.1 -INFO - [G] LONG DT @ 2631: 0.1 -INFO - [G] LONG DT @ 2631: 0.1 -INFO - [G] LONG DT @ 2631: 0.1 -INFO - [G] LONG DT @ 2631: 0.1 -INFO - [G] LONG DT @ 2631: 0.1 -INFO - [G] LONG DT @ 2631: 0.1 -INFO - [G] LONG DT @ 2631: 0.1 -INFO - [G] LONG DT @ 2632: 0.1 -INFO - [G] LONG DT @ 2632: 0.1 -INFO - [G] LONG DT @ 2632: 0.1 -INFO - [G] LONG DT @ 2632: 0.1 -INFO - [G] LONG DT @ 2632: 0.1 -INFO - [G] LONG DT @ 2632: 0.1 -INFO - [G] LONG DT @ 2632: 0.1 -INFO - [G] LONG DT @ 2632: 0.1 -INFO - [G] LONG DT @ 2632: 0.1 -INFO - [G] LONG DT @ 2632: 0.1 -INFO - [G] LONG DT @ 2633: 0.1 -INFO - [G] LONG DT @ 2633: 0.1 -INFO - [G] LONG DT @ 2633: 0.1 -INFO - [G] LONG DT @ 2633: 0.1 -INFO - [G] LONG DT @ 2633: 0.1 -INFO - [G] LONG DT @ 2633: 0.1 -INFO - [G] LONG DT @ 2633: 0.1 -INFO - [G] LONG DT @ 2633: 0.1 -INFO - [G] LONG DT @ 2633: 0.1 -INFO - [G] LONG DT @ 2633: 0.1 -INFO - [G] LONG DT @ 2634: 0.1 -INFO - [G] LONG DT @ 2634: 0.1 -INFO - [G] LONG DT @ 2634: 0.1 -INFO - [G] LONG DT @ 2634: 0.1 -INFO - [G] LONG DT @ 2634: 0.1 -INFO - [G] LONG DT @ 2634: 0.1 -INFO - [G] LONG DT @ 2634: 0.1 -INFO - [G] LONG DT @ 2634: 0.1 -INFO - [G] LONG DT @ 2634: 0.1 -INFO - [G] LONG DT @ 2634: 0.1 -INFO - [G] LONG DT @ 2635: 0.1 -INFO - [G] LONG DT @ 2635: 0.1 -INFO - [G] LONG DT @ 2635: 0.1 -INFO - [G] LONG DT @ 2635: 0.1 -INFO - [G] LONG DT @ 2635: 0.1 -INFO - [G] LONG DT @ 2635: 0.1 -INFO - [G] LONG DT @ 2635: 0.1 -INFO - [G] LONG DT @ 2635: 0.1 -INFO - [G] LONG DT @ 2635: 0.1 -INFO - [G] LONG DT @ 2635: 0.1 -INFO - [G] LONG DT @ 2636: 0.1 -INFO - [G] LONG DT @ 2636: 0.1 -INFO - [G] LONG DT @ 2636: 0.1 -INFO - [G] LONG DT @ 2636: 0.1 -INFO - [G] LONG DT @ 2636: 0.1 -INFO - [G] LONG DT @ 2636: 0.1 -INFO - [G] LONG DT @ 2636: 0.1 -INFO - [G] LONG DT @ 2636: 0.1 -INFO - [G] LONG DT @ 2636: 0.1 -INFO - [G] LONG DT @ 2636: 0.1 -INFO - [G] LONG DT @ 2637: 0.1 -INFO - [G] LONG DT @ 2637: 0.1 -INFO - [G] LONG DT @ 2637: 0.1 -INFO - [G] LONG DT @ 2637: 0.1 -INFO - [G] LONG DT @ 2637: 0.1 -INFO - [G] LONG DT @ 2637: 0.1 -INFO - [G] LONG DT @ 2637: 0.1 -INFO - [G] LONG DT @ 2637: 0.1 -INFO - [G] LONG DT @ 2637: 0.1 -INFO - [G] LONG DT @ 2637: 0.1 -INFO - [G] LONG DT @ 2638: 0.1 -INFO - [G] LONG DT @ 2638: 0.1 -INFO - [G] LONG DT @ 2638: 0.1 -INFO - [G] LONG DT @ 2638: 0.1 -INFO - [G] LONG DT @ 2638: 0.1 -INFO - [G] LONG DT @ 2638: 0.1 -INFO - [G] LONG DT @ 2638: 0.1 -INFO - [G] LONG DT @ 2638: 0.1 -INFO - [G] LONG DT @ 2638: 0.1 -INFO - [G] LONG DT @ 2638: 0.1 -INFO - [G] LONG DT @ 2639: 0.1 -INFO - [G] LONG DT @ 2639: 0.1 -INFO - [G] LONG DT @ 2639: 0.1 -INFO - [G] LONG DT @ 2639: 0.1 -INFO - [G] LONG DT @ 2639: 0.1 -INFO - [G] LONG DT @ 2639: 0.1 -INFO - [G] LONG DT @ 2639: 0.1 -INFO - [G] LONG DT @ 2639: 0.1 -INFO - [G] LONG DT @ 2639: 0.1 -INFO - [G] LONG DT @ 2639: 0.1 -INFO - [G] LONG DT @ 2640: 0.1 -INFO - [G] LONG DT @ 2640: 0.1 -INFO - [G] LONG DT @ 2640: 0.1 -INFO - [G] LONG DT @ 2640: 0.1 -INFO - [G] LONG DT @ 2640: 0.1 -INFO - [G] LONG DT @ 2640: 0.1 -INFO - [G] LONG DT @ 2640: 0.1 -INFO - [G] LONG DT @ 2640: 0.1 -INFO - [G] LONG DT @ 2640: 0.1 -INFO - [G] LONG DT @ 2640: 0.1 -INFO - [G] LONG DT @ 2641: 0.1 -INFO - [G] LONG DT @ 2641: 0.1 -INFO - [G] LONG DT @ 2641: 0.1 -INFO - [G] LONG DT @ 2641: 0.1 -INFO - [G] LONG DT @ 2641: 0.1 -INFO - [G] LONG DT @ 2641: 0.1 -INFO - [G] LONG DT @ 2641: 0.1 -INFO - [G] LONG DT @ 2641: 0.1 -INFO - [G] LONG DT @ 2641: 0.1 -INFO - [G] LONG DT @ 2641: 0.1 -INFO - [G] LONG DT @ 2642: 0.1 -INFO - [G] LONG DT @ 2642: 0.1 -INFO - [G] LONG DT @ 2642: 0.1 -INFO - [G] LONG DT @ 2642: 0.1 -INFO - [G] LONG DT @ 2642: 0.081699619999999 -INFO - [G] LONG DT @ 2642: 0.066955996000073 -INFO - [G] LONG DT @ 2642: 0.05506961680005 -INFO - [G] LONG DT @ 2819: 0.078233621775879 -INFO - [G] LONG DT @ 2819: 0.069938437420648 -INFO - [G] LONG DT @ 2819: 0.06331674993652 -INFO - [G] LONG DT @ 2819: 0.057957119949289 -INFO - [G] LONG DT @ 2819: 0.053641975959382 -INFO - [G] LONG DT @ 2819: 0.050245880767558 -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] LONG DT @ 194: 0.071740551129342 -INFO - [G] LONG DT @ 194: 0.065649660903379 -INFO - [G] LONG DT @ 194: 0.060814248722684 -INFO - [G] LONG DT @ 194: 0.056813078978159 -INFO - [G] LONG DT @ 194: 0.053617323182511 -INFO - [G] LONG DT @ 194: 0.051086578546088 -INFO - [G] LONG DT @ 196: 0.091272774803762 -INFO - [G] LONG DT @ 196: 0.083941239842983 -INFO - [G] LONG DT @ 196: 0.076216871874417 -INFO - [G] LONG DT @ 196: 0.070000177499522 -INFO - [G] LONG DT @ 197: 0.065033461999598 -INFO - [G] LONG DT @ 197: 0.061090349599607 -INFO - [G] LONG DT @ 197: 0.057885019679757 -INFO - [G] LONG DT @ 197: 0.055433015743755 -INFO - [G] LONG DT @ 197: 0.053460112594947 -INFO - [G] LONG DT @ 197: 0.051912350075951 -INFO - [G] LONG DT @ 197: 0.050586360060833 -INFO - [G] LONG DT @ 199: 0.097694309481017 -INFO - [G] LONG DT @ 199: 0.088001087584726 -INFO - [G] LONG DT @ 199: 0.080328370067829 -INFO - [G] LONG DT @ 199: 0.074060296054356 -INFO - [G] LONG DT @ 199: 0.0691370568435 -INFO - [G] LONG DT @ 199: 0.065180025474647 -INFO - [G] LONG DT @ 199: 0.062111960379742 -INFO - [G] LONG DT @ 199: 0.059300948303817 -INFO - [G] LONG DT @ 199: 0.057272998643159 -INFO - [G] LONG DT @ 199: 0.055614338914531 -INFO - [G] LONG DT @ 199: 0.054506611131621 -INFO - [G] LONG DT @ 199: 0.053565028905273 -INFO - [G] LONG DT @ 200: 0.052918123124077 -INFO - [G] LONG DT @ 200: 0.052277278499426 -INFO - [G] LONG DT @ 200: 0.051922182799429 -INFO - [G] LONG DT @ 200: 0.051481306239644 -INFO - [G] LONG DT @ 200: 0.051265364991622 -INFO - [G] LONG DT @ 200: 0.050990871993395 -INFO - [G] LONG DT @ 200: 0.050951137594657 -INFO - [G] LONG DT @ 200: 0.05074659007568 -INFO - [G] LONG DT @ 200: 0.050694912060638 -INFO - [G] LONG DT @ 200: 0.050578969648453 -INFO - [G] LONG DT @ 200: 0.050643875718672 -INFO - [G] LONG DT @ 200: 0.050578220575024 -INFO - [G] LONG DT @ 200: 0.050874116459969 -INFO - [G] LONG DT @ 200: 0.051354713167942 -INFO - [G] LONG DT @ 200: 0.051427710534519 -INFO - [G] LONG DT @ 200: 0.051501748427547 -INFO - [G] LONG DT @ 200: 0.051663718742116 -INFO - [G] LONG DT @ 200: 0.05174329499358 -INFO - [G] LONG DT @ 200: 0.051846075994861 -INFO - [G] LONG DT @ 200: 0.051824380795848 -INFO - [G] LONG DT @ 201: 0.051907244636696 -INFO - [G] LONG DT @ 201: 0.051908795709359 -INFO - [G] LONG DT @ 201: 0.052026296567447 -INFO - [G] LONG DT @ 201: 0.052128777254097 -INFO - [G] LONG DT @ 201: 0.052242481803205 -INFO - [G] LONG DT @ 201: 0.052358945442574 -INFO - [G] LONG DT @ 201: 0.052447236354019 -INFO - [G] LONG DT @ 201: 0.052506329083342 -INFO - [G] LONG DT @ 201: 0.052631863266628 -INFO - [G] LONG DT @ 201: 0.052666870613338 -INFO - [G] LONG DT @ 201: 0.052716056490637 -INFO - [G] LONG DT @ 201: 0.052785585192543 -INFO - [G] LONG DT @ 201: 0.1 -INFO - [G] LONG DT @ 201: 0.090691880000013 -INFO - [G] LONG DT @ 201: 0.083268543999933 -INFO - [G] LONG DT @ 201: 0.077285855199919 -INFO - [G] LONG DT @ 202: 0.072541424159989 -INFO - [G] LONG DT @ 202: 0.068734379327971 -INFO - [G] LONG DT @ 202: 0.065741463462343 -INFO - [G] LONG DT @ 202: 0.063424070769984 -INFO - [G] LONG DT @ 202: 0.061578436615844 -INFO - [G] LONG DT @ 202: 0.060105169292829 -INFO - [G] LONG DT @ 202: 0.058898875434105 -INFO - [G] LONG DT @ 202: 0.057740500347411 -INFO - [G] LONG DT @ 202: 0.056856160277918 -INFO - [G] LONG DT @ 202: 0.056334868222269 -INFO - [G] LONG DT @ 202: 0.056264014577837 -INFO - [G] LONG DT @ 202: 0.054580111662246 -INFO - [G] LONG DT @ 275: 0.1 -INFO - [G] LONG DT @ 275: 0.1 -INFO - [G] LONG DT @ 275: 0.1 -INFO - [G] LONG DT @ 276: 0.1 -INFO - [G] LONG DT @ 276: 0.1 -INFO - [G] LONG DT @ 276: 0.1 -INFO - [G] LONG DT @ 276: 0.1 -INFO - [G] LONG DT @ 276: 0.1 -INFO - [G] LONG DT @ 276: 0.1 -INFO - [G] LONG DT @ 276: 0.1 -INFO - [G] LONG DT @ 276: 0.1 -INFO - [G] LONG DT @ 276: 0.1 -INFO - [G] LONG DT @ 276: 0.085295939999996 -INFO - [G] LONG DT @ 276: 0.072963631999904 -INFO - [G] LONG DT @ 277: 0.062996905600022 -INFO - [G] LONG DT @ 277: 0.054947484479912 -INFO - [G] LONG DT @ 773: 0.1 -INFO - [G] LONG DT @ 773: 0.1 -INFO - [G] LONG DT @ 773: 0.1 -INFO - [G] LONG DT @ 773: 0.1 -INFO - [G] LONG DT @ 773: 0.1 -INFO - [G] LONG DT @ 773: 0.1 -INFO - [G] LONG DT @ 773: 0.1 -INFO - [G] LONG DT @ 773: 0.1 -INFO - [G] LONG DT @ 773: 0.1 -INFO - [G] LONG DT @ 774: 0.1 -INFO - [G] LONG DT @ 774: 0.1 -INFO - [G] LONG DT @ 774: 0.1 -INFO - [G] LONG DT @ 774: 0.1 -INFO - [G] LONG DT @ 774: 0.1 -INFO - [G] LONG DT @ 774: 0.1 -INFO - [G] LONG DT @ 774: 0.1 -INFO - [G] LONG DT @ 774: 0.1 -INFO - [G] LONG DT @ 774: 0.1 -INFO - [G] LONG DT @ 774: 0.1 -INFO - [G] LONG DT @ 775: 0.1 -INFO - [G] LONG DT @ 775: 0.1 -INFO - [G] LONG DT @ 775: 0.1 -INFO - [G] LONG DT @ 775: 0.1 -INFO - [G] LONG DT @ 775: 0.1 -INFO - [G] LONG DT @ 775: 0.1 -INFO - [G] LONG DT @ 775: 0.1 -INFO - [G] LONG DT @ 775: 0.1 -INFO - [G] LONG DT @ 775: 0.1 -INFO - [G] LONG DT @ 775: 0.1 -INFO - [G] LONG DT @ 776: 0.1 -INFO - [G] LONG DT @ 776: 0.1 -INFO - [G] LONG DT @ 776: 0.1 -INFO - [G] LONG DT @ 776: 0.1 -INFO - [G] LONG DT @ 776: 0.1 -INFO - [G] LONG DT @ 776: 0.1 -INFO - [G] LONG DT @ 776: 0.1 -INFO - [G] LONG DT @ 776: 0.1 -INFO - [G] LONG DT @ 776: 0.1 -INFO - [G] LONG DT @ 776: 0.1 -INFO - [G] LONG DT @ 777: 0.1 -INFO - [G] LONG DT @ 777: 0.1 -INFO - [G] LONG DT @ 777: 0.1 -INFO - [G] LONG DT @ 777: 0.1 -INFO - [G] LONG DT @ 777: 0.1 -INFO - [G] LONG DT @ 777: 0.1 -INFO - [G] LONG DT @ 777: 0.1 -INFO - [G] LONG DT @ 777: 0.1 -INFO - [G] LONG DT @ 777: 0.1 -INFO - [G] LONG DT @ 777: 0.1 -INFO - [G] LONG DT @ 778: 0.1 -INFO - [G] LONG DT @ 778: 0.1 -INFO - [G] LONG DT @ 778: 0.1 -INFO - [G] LONG DT @ 778: 0.1 -INFO - [G] LONG DT @ 778: 0.1 -INFO - [G] LONG DT @ 778: 0.1 -INFO - [G] LONG DT @ 778: 0.1 -INFO - [G] LONG DT @ 778: 0.1 -INFO - [G] LONG DT @ 778: 0.1 -INFO - [G] LONG DT @ 778: 0.1 -INFO - [G] LONG DT @ 779: 0.1 -INFO - [G] LONG DT @ 779: 0.1 -INFO - [G] LONG DT @ 779: 0.1 -INFO - [G] LONG DT @ 779: 0.1 -INFO - [G] LONG DT @ 779: 0.1 -INFO - [G] LONG DT @ 779: 0.1 -INFO - [G] LONG DT @ 779: 0.1 -INFO - [G] LONG DT @ 779: 0.1 -INFO - [G] LONG DT @ 779: 0.1 -INFO - [G] LONG DT @ 779: 0.1 -INFO - [G] LONG DT @ 780: 0.1 -INFO - [G] LONG DT @ 780: 0.1 -INFO - [G] LONG DT @ 780: 0.1 -INFO - [G] LONG DT @ 780: 0.1 -INFO - [G] LONG DT @ 780: 0.1 -INFO - [G] LONG DT @ 780: 0.1 -INFO - [G] LONG DT @ 780: 0.1 -INFO - [G] LONG DT @ 780: 0.1 -INFO - [G] LONG DT @ 780: 0.1 -INFO - [G] LONG DT @ 780: 0.1 -INFO - [G] LONG DT @ 781: 0.1 -INFO - [G] LONG DT @ 781: 0.1 -INFO - [G] LONG DT @ 781: 0.1 -INFO - [G] LONG DT @ 781: 0.1 -INFO - [G] LONG DT @ 781: 0.1 -INFO - [G] LONG DT @ 781: 0.1 -INFO - [G] LONG DT @ 781: 0.1 -INFO - [G] LONG DT @ 781: 0.1 -INFO - [G] LONG DT @ 781: 0.1 -INFO - [G] LONG DT @ 781: 0.1 -INFO - [G] LONG DT @ 782: 0.1 -INFO - [G] LONG DT @ 782: 0.1 -INFO - [G] LONG DT @ 782: 0.1 -INFO - [G] LONG DT @ 782: 0.1 -INFO - [G] LONG DT @ 782: 0.1 -INFO - [G] LONG DT @ 782: 0.1 -INFO - [G] LONG DT @ 782: 0.1 -INFO - [G] LONG DT @ 782: 0.1 -INFO - [G] LONG DT @ 782: 0.1 -INFO - [G] LONG DT @ 782: 0.1 -INFO - [G] LONG DT @ 783: 0.1 -INFO - [G] LONG DT @ 783: 0.1 -INFO - [G] LONG DT @ 783: 0.1 -INFO - [G] LONG DT @ 783: 0.1 -INFO - [G] LONG DT @ 783: 0.1 -INFO - [G] LONG DT @ 783: 0.1 -INFO - [G] LONG DT @ 783: 0.1 -INFO - [G] LONG DT @ 783: 0.1 -INFO - [G] LONG DT @ 783: 0.1 -INFO - [G] LONG DT @ 783: 0.1 -INFO - [G] LONG DT @ 784: 0.1 -INFO - [G] LONG DT @ 784: 0.1 -INFO - [G] LONG DT @ 784: 0.1 -INFO - [G] LONG DT @ 784: 0.1 -INFO - [G] LONG DT @ 784: 0.1 -INFO - [G] LONG DT @ 784: 0.1 -INFO - [G] LONG DT @ 784: 0.1 -INFO - [G] LONG DT @ 784: 0.1 -INFO - [G] LONG DT @ 784: 0.1 -INFO - [G] LONG DT @ 784: 0.1 -INFO - [G] LONG DT @ 785: 0.1 -INFO - [G] LONG DT @ 785: 0.1 -INFO - [G] LONG DT @ 785: 0.1 -INFO - [G] LONG DT @ 785: 0.1 -INFO - [G] LONG DT @ 785: 0.1 -INFO - [G] LONG DT @ 785: 0.1 -INFO - [G] LONG DT @ 785: 0.1 -INFO - [G] LONG DT @ 785: 0.1 -INFO - [G] LONG DT @ 785: 0.1 -INFO - [G] LONG DT @ 785: 0.1 -INFO - [G] LONG DT @ 786: 0.1 -INFO - [G] LONG DT @ 786: 0.1 -INFO - [G] LONG DT @ 786: 0.1 -INFO - [G] LONG DT @ 786: 0.1 -INFO - [G] LONG DT @ 786: 0.1 -INFO - [G] LONG DT @ 786: 0.1 -INFO - [G] LONG DT @ 786: 0.1 -INFO - [G] LONG DT @ 786: 0.1 -INFO - [G] LONG DT @ 786: 0.1 -INFO - [G] LONG DT @ 786: 0.1 -INFO - [G] LONG DT @ 787: 0.1 -INFO - [G] LONG DT @ 787: 0.1 -INFO - [G] LONG DT @ 787: 0.1 -INFO - [G] LONG DT @ 787: 0.1 -INFO - [G] LONG DT @ 787: 0.1 -INFO - [G] LONG DT @ 787: 0.1 -INFO - [G] LONG DT @ 787: 0.1 -INFO - [G] LONG DT @ 787: 0.1 -INFO - [G] LONG DT @ 787: 0.1 -INFO - [G] LONG DT @ 787: 0.1 -INFO - [G] LONG DT @ 788: 0.1 -INFO - [G] LONG DT @ 788: 0.1 -INFO - [G] LONG DT @ 788: 0.1 -INFO - [G] LONG DT @ 788: 0.1 -INFO - [G] LONG DT @ 788: 0.1 -INFO - [G] LONG DT @ 788: 0.1 -INFO - [G] LONG DT @ 788: 0.1 -INFO - [G] LONG DT @ 788: 0.1 -INFO - [G] LONG DT @ 788: 0.1 -INFO - [G] LONG DT @ 788: 0.1 -INFO - [G] LONG DT @ 789: 0.1 -INFO - [G] LONG DT @ 789: 0.1 -INFO - [G] LONG DT @ 789: 0.1 -INFO - [G] LONG DT @ 789: 0.1 -INFO - [G] LONG DT @ 789: 0.1 -INFO - [G] LONG DT @ 789: 0.1 -INFO - [G] LONG DT @ 789: 0.1 -INFO - [G] LONG DT @ 789: 0.1 -INFO - [G] LONG DT @ 789: 0.1 -INFO - [G] LONG DT @ 789: 0.1 -INFO - [G] LONG DT @ 790: 0.1 -INFO - [G] LONG DT @ 790: 0.1 -INFO - [G] LONG DT @ 790: 0.1 -INFO - [G] LONG DT @ 790: 0.1 -INFO - [G] LONG DT @ 790: 0.1 -INFO - [G] LONG DT @ 790: 0.1 -INFO - [G] LONG DT @ 790: 0.1 -INFO - [G] LONG DT @ 790: 0.1 -INFO - [G] LONG DT @ 790: 0.1 -INFO - [G] LONG DT @ 790: 0.1 -INFO - [G] LONG DT @ 791: 0.1 -INFO - [G] LONG DT @ 791: 0.1 -INFO - [G] LONG DT @ 791: 0.1 -INFO - [G] LONG DT @ 791: 0.1 -INFO - [G] LONG DT @ 791: 0.1 -INFO - [G] LONG DT @ 791: 0.1 -INFO - [G] LONG DT @ 791: 0.1 -INFO - [G] LONG DT @ 791: 0.1 -INFO - [G] LONG DT @ 791: 0.1 -INFO - [G] LONG DT @ 791: 0.1 -INFO - [G] LONG DT @ 792: 0.1 -INFO - [G] LONG DT @ 792: 0.1 -INFO - [G] LONG DT @ 792: 0.1 -INFO - [G] LONG DT @ 792: 0.1 -INFO - [G] LONG DT @ 792: 0.1 -INFO - [G] LONG DT @ 792: 0.1 -INFO - [G] LONG DT @ 792: 0.1 -INFO - [G] LONG DT @ 792: 0.1 -INFO - [G] LONG DT @ 792: 0.1 -INFO - [G] LONG DT @ 792: 0.1 -INFO - [G] LONG DT @ 793: 0.1 -INFO - [G] LONG DT @ 793: 0.1 -INFO - [G] LONG DT @ 793: 0.1 -INFO - [G] LONG DT @ 793: 0.1 -INFO - [G] LONG DT @ 793: 0.1 -INFO - [G] LONG DT @ 793: 0.1 -INFO - [G] LONG DT @ 793: 0.1 -INFO - [G] LONG DT @ 793: 0.1 -INFO - [G] LONG DT @ 793: 0.1 -INFO - [G] LONG DT @ 793: 0.1 -INFO - [G] LONG DT @ 794: 0.1 -INFO - [G] LONG DT @ 794: 0.1 -INFO - [G] LONG DT @ 794: 0.1 -INFO - [G] LONG DT @ 794: 0.1 -INFO - [G] LONG DT @ 794: 0.1 -INFO - [G] LONG DT @ 794: 0.1 -INFO - [G] LONG DT @ 794: 0.1 -INFO - [G] LONG DT @ 794: 0.1 -INFO - [G] LONG DT @ 794: 0.1 -INFO - [G] LONG DT @ 794: 0.1 -INFO - [G] LONG DT @ 795: 0.1 -INFO - [G] LONG DT @ 795: 0.1 -INFO - [G] LONG DT @ 795: 0.1 -INFO - [G] LONG DT @ 795: 0.1 -INFO - [G] LONG DT @ 795: 0.1 -INFO - [G] LONG DT @ 795: 0.1 -INFO - [G] LONG DT @ 795: 0.1 -INFO - [G] LONG DT @ 795: 0.084980339999929 -INFO - [G] LONG DT @ 795: 0.072510191999958 -INFO - [G] LONG DT @ 795: 0.062349313599934 -INFO - [G] LONG DT @ 795: 0.053827370880011 -INFO - [G] LONG DT @ 798: 0.1 -INFO - [G] LONG DT @ 799: 0.1 -INFO - [G] LONG DT @ 799: 0.1 -INFO - [G] LONG DT @ 799: 0.1 -INFO - [G] LONG DT @ 799: 0.1 -INFO - [G] LONG DT @ 799: 0.1 -INFO - [G] LONG DT @ 799: 0.1 -INFO - [G] LONG DT @ 799: 0.1 -INFO - [G] LONG DT @ 799: 0.1 -INFO - [G] LONG DT @ 799: 0.1 -INFO - [G] LONG DT @ 799: 0.1 -INFO - [G] LONG DT @ 800: 0.1 -INFO - [G] LONG DT @ 800: 0.1 -INFO - [G] LONG DT @ 800: 0.1 -INFO - [G] LONG DT @ 800: 0.1 -INFO - [G] LONG DT @ 800: 0.1 -INFO - [G] LONG DT @ 800: 0.1 -INFO - [G] LONG DT @ 800: 0.1 -INFO - [G] LONG DT @ 800: 0.1 -INFO - [G] LONG DT @ 800: 0.1 -INFO - [G] LONG DT @ 800: 0.1 -INFO - [G] LONG DT @ 801: 0.1 -INFO - [G] LONG DT @ 801: 0.1 -INFO - [G] LONG DT @ 801: 0.1 -INFO - [G] LONG DT @ 801: 0.1 -INFO - [G] LONG DT @ 801: 0.1 -INFO - [G] LONG DT @ 801: 0.1 -INFO - [G] LONG DT @ 801: 0.084517260000102 -INFO - [G] LONG DT @ 801: 0.071884148000121 -INFO - [G] LONG DT @ 801: 0.061747078400115 -INFO - [G] LONG DT @ 801: 0.053707842720085 -INFO - [G] LONG DT @ 2165: 0.1 -INFO - [G] LONG DT @ 2165: 0.1 -INFO - [G] LONG DT @ 2165: 0.1 -INFO - [G] LONG DT @ 2166: 0.1 -INFO - [G] LONG DT @ 2166: 0.1 -INFO - [G] LONG DT @ 2166: 0.1 -INFO - [G] LONG DT @ 2166: 0.1 -INFO - [G] LONG DT @ 2166: 0.1 -INFO - [G] LONG DT @ 2166: 0.1 -INFO - [G] LONG DT @ 2166: 0.1 -INFO - [G] LONG DT @ 2166: 0.1 -INFO - [G] LONG DT @ 2166: 0.1 -INFO - [G] LONG DT @ 2166: 0.1 -INFO - [G] LONG DT @ 2167: 0.1 -INFO - [G] LONG DT @ 2167: 0.1 -INFO - [G] LONG DT @ 2167: 0.1 -INFO - [G] LONG DT @ 2167: 0.1 -INFO - [G] LONG DT @ 2167: 0.1 -INFO - [G] LONG DT @ 2167: 0.1 -INFO - [G] LONG DT @ 2167: 0.1 -INFO - [G] LONG DT @ 2167: 0.1 -INFO - [G] LONG DT @ 2167: 0.1 -INFO - [G] LONG DT @ 2167: 0.1 -INFO - [G] LONG DT @ 2168: 0.1 -INFO - [G] LONG DT @ 2168: 0.1 -INFO - [G] LONG DT @ 2168: 0.1 -INFO - [G] LONG DT @ 2168: 0.1 -INFO - [G] LONG DT @ 2168: 0.1 -INFO - [G] LONG DT @ 2168: 0.082458560000014 -INFO - [G] LONG DT @ 2168: 0.068404507999861 -INFO - [G] LONG DT @ 2168: 0.056868526400026 -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load diff --git a/lovely/log/lovely-2025.01.08-17.38.33.log b/lovely/log/lovely-2025.01.08-17.38.33.log deleted file mode 100644 index 598c3d7..0000000 --- a/lovely/log/lovely-2025.01.08-17.38.33.log +++ /dev/null @@ -1,301 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 127ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-08 17:38:36 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-08 17:38:36 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-08 17:38:36 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-08 17:38:37 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-08 17:38:37 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-08 17:38:37 :: TRACE :: Loader :: Processing Mod file (Legacy header): MoreSpeeds.lua -INFO - [G] 2025-01-08 17:38:37 :: TRACE :: Loader :: Saving Mod Info: MoreSpeed -INFO - [G] 2025-01-08 17:38:37 :: ERROR :: Loader :: Found invalid metadata JSON file at C:\users\steamuser\AppData\Roaming\Balatro\Mods/Steamopollys-MoreSpeed-0.8.2/manifest.json, ignoring: [SMODS _ "src/loader.lua"]:212: id -INFO - [G] 2025-01-08 17:38:37 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-08 17:38:37 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-08 17:38:37 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.657 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0031] Injected Atlas in 785.420 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0025] Injected Sound in 20.950 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0032] Injected Stake in 0.846 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0008] Injected Rarity in 0.022 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.046 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0391] Injected Center in 1.724 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.010 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0027] Injected Blind in 0.046 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0002] Injected Seal in 0.236 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0004] Injected Suit in 0.076 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0013] Injected Rank in 0.083 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.030 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.080 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0031] Injected Challenge in 0.052 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0028] Injected Tag in 0.166 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0009] Injected Sticker in 0.836 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0009] Injected Shader in 52.758 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0020] Injected Achievement in 0.060 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.535 ms -INFO - [G] 2025-01-08 17:38:37 :: INFO :: TIMER :: [0011] Injected Event in 0.014 ms -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] LONG DT @ 39: 0.065712979523191 -INFO - [G] LONG DT @ 39: 0.060389583618553 -INFO - [G] LONG DT @ 39: 0.056165686894845 -INFO - [G] LONG DT @ 39: 0.052731249515871 -INFO - [G] LONG DT @ 40: 0.050146759612697 -INFO - [G] LONG DT @ 111: 0.095699457251497 -INFO - [G] LONG DT @ 111: 0.080804165801191 -INFO - [G] LONG DT @ 111: 0.068675732640958 -INFO - [G] LONG DT @ 111: 0.058927466112769 -INFO - [G] LONG DT @ 111: 0.051127652890209 -INFO - [G] LONG DT @ 112: 0.096535065488646 -INFO - [G] LONG DT @ 112: 0.081490312390913 -INFO - [G] LONG DT @ 113: 0.069177289912728 -INFO - [G] LONG DT @ 113: 0.059315731930188 -INFO - [G] LONG DT @ 113: 0.051432785544151 -INFO - [G] LONG DT @ 116: 0.094952365049208 -INFO - [G] LONG DT @ 116: 0.080242152039362 -INFO - [G] LONG DT @ 116: 0.068324881631487 -INFO - [G] LONG DT @ 116: 0.058683005305196 -INFO - [G] LONG DT @ 116: 0.050930144244158 -INFO - [G] LONG DT @ 117: 0.097258736826162 -INFO - [G] LONG DT @ 117: 0.082028629460933 -INFO - [G] LONG DT @ 117: 0.069546203568743 -INFO - [G] LONG DT @ 117: 0.059564662854991 -INFO - [G] LONG DT @ 117: 0.051638010283997 -INFO - [G] LONG DT @ 118: 0.098028523224237 -INFO - [G] LONG DT @ 118: 0.082668138579396 -INFO - [G] LONG DT @ 118: 0.07006381086351 -INFO - [G] LONG DT @ 118: 0.059985808690812 -INFO - [G] LONG DT @ 118: 0.052064346952648 -INFO - [G] LONG DT @ 122: 0.09540292718411 -INFO - [G] LONG DT @ 122: 0.080490081747291 -INFO - [G] LONG DT @ 122: 0.06832148539783 -INFO - [G] LONG DT @ 122: 0.058542668318261 -INFO - [G] LONG DT @ 122: 0.050775934654615 -INFO - [G] LONG DT @ 122: 0.096532873421755 -INFO - [G] LONG DT @ 123: 0.081521458737407 -INFO - [G] LONG DT @ 123: 0.06927398698992 -INFO - [G] LONG DT @ 123: 0.05948656959194 -INFO - [G] LONG DT @ 123: 0.051520375673556 -INFO - [G] LONG DT @ 123: 0.097209348797013 -INFO - [G] LONG DT @ 123: 0.081988359037613 -INFO - [G] LONG DT @ 124: 0.069696227230091 -INFO - [G] LONG DT @ 124: 0.059829721784076 -INFO - [G] LONG DT @ 124: 0.052009517427251 -INFO - [G] LONG DT @ 124: 0.097376561111689 -INFO - [G] LONG DT @ 124: 0.082168188889353 -INFO - [G] LONG DT @ 124: 0.069937571111482 -INFO - [G] LONG DT @ 124: 0.060007256889186 -INFO - [G] LONG DT @ 124: 0.052020225511347 -INFO - [G] LONG DT @ 125: 0.1 -INFO - [G] LONG DT @ 125: 0.08424352 -INFO - [G] LONG DT @ 125: 0.071398515999998 -INFO - [G] LONG DT @ 125: 0.061317012800006 -INFO - [G] LONG DT @ 125: 0.053182570239996 -INFO - [G] LONG DT @ 166: 0.1 -INFO - [G] LONG DT @ 166: 0.1 -INFO - [G] LONG DT @ 166: 0.1 -INFO - [G] LONG DT @ 166: 0.1 -INFO - [G] LONG DT @ 166: 0.1 -INFO - [G] LONG DT @ 166: 0.1 -INFO - [G] LONG DT @ 166: 0.1 -INFO - [G] LONG DT @ 166: 0.1 -INFO - [G] LONG DT @ 166: 0.1 -INFO - [G] LONG DT @ 166: 0.1 -INFO - [G] LONG DT @ 167: 0.1 -INFO - [G] LONG DT @ 167: 0.1 -INFO - [G] LONG DT @ 167: 0.1 -INFO - [G] LONG DT @ 167: 0.1 -INFO - [G] LONG DT @ 167: 0.1 -INFO - [G] LONG DT @ 167: 0.1 -INFO - [G] LONG DT @ 167: 0.1 -INFO - [G] LONG DT @ 167: 0.1 -INFO - [G] LONG DT @ 167: 0.1 -INFO - [G] LONG DT @ 167: 0.1 -INFO - [G] LONG DT @ 168: 0.1 -INFO - [G] LONG DT @ 168: 0.1 -INFO - [G] LONG DT @ 168: 0.1 -INFO - [G] LONG DT @ 168: 0.1 -INFO - [G] LONG DT @ 168: 0.1 -INFO - [G] LONG DT @ 168: 0.1 -INFO - [G] LONG DT @ 168: 0.1 -INFO - [G] LONG DT @ 168: 0.1 -INFO - [G] LONG DT @ 168: 0.1 -INFO - [G] LONG DT @ 168: 0.082439040000002 -INFO - [G] LONG DT @ 169: 0.068138351999998 -INFO - [G] LONG DT @ 169: 0.056457401599999 -INFO - [G] LONG DT @ 178: 0.1 -INFO - [G] LONG DT @ 178: 0.1 -INFO - [G] LONG DT @ 178: 0.1 -INFO - [G] LONG DT @ 178: 0.1 -INFO - [G] LONG DT @ 178: 0.1 -INFO - [G] LONG DT @ 179: 0.1 -INFO - [G] LONG DT @ 179: 0.1 -INFO - [G] LONG DT @ 179: 0.1 -INFO - [G] LONG DT @ 179: 0.1 -INFO - [G] LONG DT @ 179: 0.1 -INFO - [G] LONG DT @ 179: 0.1 -INFO - [G] LONG DT @ 179: 0.1 -INFO - [G] LONG DT @ 179: 0.1 -INFO - [G] LONG DT @ 179: 0.1 -INFO - [G] LONG DT @ 179: 0.1 -INFO - [G] LONG DT @ 180: 0.1 -INFO - [G] LONG DT @ 180: 0.1 -INFO - [G] LONG DT @ 180: 0.1 -INFO - [G] LONG DT @ 180: 0.1 -INFO - [G] LONG DT @ 180: 0.1 -INFO - [G] LONG DT @ 180: 0.1 -INFO - [G] LONG DT @ 180: 0.1 -INFO - [G] LONG DT @ 180: 0.1 -INFO - [G] LONG DT @ 180: 0.1 -INFO - [G] LONG DT @ 180: 0.1 -INFO - [G] LONG DT @ 181: 0.1 -INFO - [G] LONG DT @ 181: 0.1 -INFO - [G] LONG DT @ 181: 0.1 -INFO - [G] LONG DT @ 181: 0.1 -INFO - [G] LONG DT @ 181: 0.1 -INFO - [G] LONG DT @ 181: 0.1 -INFO - [G] LONG DT @ 181: 0.1 -INFO - [G] LONG DT @ 181: 0.1 -INFO - [G] LONG DT @ 181: 0.1 -INFO - [G] LONG DT @ 181: 0.1 -INFO - [G] LONG DT @ 182: 0.1 -INFO - [G] LONG DT @ 182: 0.1 -INFO - [G] LONG DT @ 182: 0.082272540000001 -INFO - [G] LONG DT @ 182: 0.067807391999994 -INFO - [G] LONG DT @ 182: 0.056140173600001 -INFO - [G] LONG DT @ 12: 0.1 -INFO - [G] LONG DT @ 12: 0.1 -INFO - [G] LONG DT @ 13: 0.08107439999997 -INFO - [G] LONG DT @ 13: 0.066038119999979 -INFO - [G] LONG DT @ 13: 0.05402949599998 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 14: 0.08114552 -INFO - [G] LONG DT @ 14: 0.06609379599999 -INFO - [G] LONG DT @ 14: 0.054067856799998 -INFO - [G] LONG DT @ 14: 0.081042646327903 -INFO - [G] LONG DT @ 14: 0.067260957062321 -INFO - [G] LONG DT @ 15: 0.056172265649858 -INFO - [G] LONG DT @ 16: 0.087443327538586 -INFO - [G] LONG DT @ 16: 0.072506082030878 -INFO - [G] LONG DT @ 16: 0.060509325624702 -INFO - [G] LONG DT @ 16: 0.050798180499756 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.08268916 -INFO - [G] LONG DT @ 17: 0.068605627999999 -INFO - [G] LONG DT @ 17: 0.057244302400021 -INFO - [G] LONG DT @ 43: 0.1 -INFO - [G] LONG DT @ 43: 0.1 -INFO - [G] LONG DT @ 43: 0.1 -INFO - [G] LONG DT @ 43: 0.1 -INFO - [G] LONG DT @ 43: 0.1 -INFO - [G] LONG DT @ 43: 0.1 -INFO - [G] LONG DT @ 43: 0.1 -INFO - [G] LONG DT @ 43: 0.1 -INFO - [G] LONG DT @ 43: 0.1 -INFO - [G] LONG DT @ 44: 0.1 -INFO - [G] LONG DT @ 44: 0.1 -INFO - [G] LONG DT @ 44: 0.1 -INFO - [G] LONG DT @ 44: 0.1 -INFO - [G] LONG DT @ 44: 0.1 -INFO - [G] LONG DT @ 44: 0.1 -INFO - [G] LONG DT @ 44: 0.1 -INFO - [G] LONG DT @ 44: 0.1 -INFO - [G] LONG DT @ 44: 0.1 -INFO - [G] LONG DT @ 44: 0.1 -INFO - [G] LONG DT @ 45: 0.1 -INFO - [G] LONG DT @ 45: 0.1 -INFO - [G] LONG DT @ 45: 0.1 -INFO - [G] LONG DT @ 45: 0.1 -INFO - [G] LONG DT @ 45: 0.1 -INFO - [G] LONG DT @ 45: 0.1 -INFO - [G] LONG DT @ 45: 0.1 -INFO - [G] LONG DT @ 45: 0.1 -INFO - [G] LONG DT @ 45: 0.1 -INFO - [G] LONG DT @ 45: 0.1 -INFO - [G] LONG DT @ 46: 0.1 -INFO - [G] LONG DT @ 46: 0.1 -INFO - [G] LONG DT @ 46: 0.1 -INFO - [G] LONG DT @ 46: 0.1 -INFO - [G] LONG DT @ 46: 0.1 diff --git a/lovely/log/lovely-2025.01.08-18.19.46.log b/lovely/log/lovely-2025.01.08-18.19.46.log deleted file mode 100644 index dea18c7..0000000 --- a/lovely/log/lovely-2025.01.08-18.19.46.log +++ /dev/null @@ -1,132 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 139ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-08 18:19:49 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-08 18:19:49 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-08 18:19:49 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-08 18:19:49 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-08 18:19:49 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-08 18:19:49 :: TRACE :: Loader :: Processing Mod file (Legacy header): MoreSpeeds.lua -INFO - [G] 2025-01-08 18:19:49 :: TRACE :: Loader :: Saving Mod Info: MoreSpeed -INFO - [G] 2025-01-08 18:19:49 :: ERROR :: Loader :: Found invalid metadata JSON file at C:\users\steamuser\AppData\Roaming\Balatro\Mods/Steamopollys-MoreSpeed-0.8.2/manifest.json, ignoring: [SMODS _ "src/loader.lua"]:212: id -INFO - [G] 2025-01-08 18:19:49 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-08 18:19:49 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-08 18:19:49 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-08 18:19:49 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-08 18:19:49 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.667 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0031] Injected Atlas in 781.149 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0025] Injected Sound in 21.225 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0032] Injected Stake in 0.755 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0008] Injected Rarity in 0.022 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.057 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0391] Injected Center in 1.728 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.010 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0027] Injected Blind in 0.047 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0002] Injected Seal in 0.435 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0004] Injected Suit in 0.096 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0013] Injected Rank in 0.085 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.033 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.069 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0031] Injected Challenge in 0.041 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0028] Injected Tag in 0.058 ms -INFO - [G] 2025-01-08 18:19:50 :: INFO :: TIMER :: [0009] Injected Sticker in 0.087 ms -INFO - [G] 2025-01-08 18:19:51 :: INFO :: TIMER :: [0009] Injected Shader in 883.524 ms -INFO - [G] 2025-01-08 18:19:51 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-08 18:19:51 :: INFO :: TIMER :: [0020] Injected Achievement in 0.061 ms -INFO - [G] 2025-01-08 18:19:51 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.829 ms -INFO - [G] 2025-01-08 18:19:51 :: INFO :: TIMER :: [0011] Injected Event in 0.013 ms -INFO - [G] LONG DT @ 0: 0.1 -INFO - [G] LONG DT @ 0: 0.1 -INFO - [G] LONG DT @ 0: 0.08089688 -INFO - [G] LONG DT @ 0: 0.064980484 -INFO - [G] LONG DT @ 0: 0.0522670872 -INFO - [G] LONG DT @ 27: 0.088014122060336 -INFO - [G] LONG DT @ 27: 0.07460833764827 -INFO - [G] LONG DT @ 27: 0.063927730118615 -INFO - [G] LONG DT @ 28: 0.055742924094892 -INFO - [G] LONG DT @ 29: 0.1 -INFO - [G] LONG DT @ 29: 0.08403702 -INFO - [G] LONG DT @ 29: 0.071189556 -INFO - [G] LONG DT @ 29: 0.0608984248 -INFO - [G] LONG DT @ 29: 0.05286677984 diff --git a/lovely/log/lovely-2025.01.08-18.21.41.log b/lovely/log/lovely-2025.01.08-18.21.41.log deleted file mode 100644 index da870e6..0000000 --- a/lovely/log/lovely-2025.01.08-18.21.41.log +++ /dev/null @@ -1,275 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 134ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-08 18:21:44 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-08 18:21:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-08 18:21:45 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-08 18:21:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-08 18:21:45 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-08 18:21:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-08 18:21:45 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-08 18:21:45 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.689 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0031] Injected Atlas in 780.615 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0025] Injected Sound in 22.243 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0032] Injected Stake in 0.845 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0008] Injected Rarity in 0.026 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.076 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0391] Injected Center in 2.058 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.028 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0027] Injected Blind in 0.052 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0002] Injected Seal in 0.045 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0004] Injected Suit in 0.095 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0013] Injected Rank in 0.078 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.029 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.103 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0031] Injected Challenge in 0.057 ms -INFO - [G] 2025-01-08 18:21:45 :: INFO :: TIMER :: [0028] Injected Tag in 0.175 ms -INFO - [G] 2025-01-08 18:21:46 :: INFO :: TIMER :: [0009] Injected Sticker in 0.613 ms -INFO - [G] 2025-01-08 18:21:46 :: INFO :: TIMER :: [0009] Injected Shader in 52.614 ms -INFO - [G] 2025-01-08 18:21:46 :: INFO :: TIMER :: [0000] Injected Keybind in 0.019 ms -INFO - [G] 2025-01-08 18:21:46 :: INFO :: TIMER :: [0020] Injected Achievement in 0.053 ms -INFO - [G] 2025-01-08 18:21:47 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.421 ms -INFO - [G] 2025-01-08 18:21:47 :: INFO :: TIMER :: [0011] Injected Event in 0.031 ms -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.09256014 -INFO - [G] LONG DT @ 14: 0.074577492 -INFO - [G] LONG DT @ 14: 0.0607911936 -INFO - [G] LONG DT @ 60: 0.1 -INFO - [G] LONG DT @ 60: 0.1 -INFO - [G] LONG DT @ 60: 0.1 -INFO - [G] LONG DT @ 60: 0.1 -INFO - [G] LONG DT @ 60: 0.1 -INFO - [G] LONG DT @ 60: 0.1 -INFO - [G] LONG DT @ 60: 0.1 -INFO - [G] LONG DT @ 61: 0.1 -INFO - [G] LONG DT @ 61: 0.08106802 -INFO - [G] LONG DT @ 61: 0.065711856000001 -INFO - [G] LONG DT @ 61: 0.053207244800002 -INFO - [G] LONG DT @ 921: 0.1 -INFO - [G] LONG DT @ 921: 0.1 -INFO - [G] LONG DT @ 921: 0.1 -INFO - [G] LONG DT @ 921: 0.1 -INFO - [G] LONG DT @ 921: 0.1 -INFO - [G] LONG DT @ 921: 0.1 -INFO - [G] LONG DT @ 921: 0.086798800000001 -INFO - [G] LONG DT @ 921: 0.070583059999994 -INFO - [G] LONG DT @ 922: 0.05730684800001 -INFO - [G] LONG DT @ 1015: 0.1 -INFO - [G] LONG DT @ 1015: 0.1 -INFO - [G] LONG DT @ 1015: 0.1 -INFO - [G] LONG DT @ 1015: 0.1 -INFO - [G] LONG DT @ 1015: 0.1 -INFO - [G] LONG DT @ 1015: 0.1 -INFO - [G] LONG DT @ 1015: 0.1 -INFO - [G] LONG DT @ 1015: 0.1 -INFO - [G] LONG DT @ 1016: 0.1 -INFO - [G] LONG DT @ 1016: 0.1 -INFO - [G] LONG DT @ 1016: 0.1 -INFO - [G] LONG DT @ 1016: 0.1 -INFO - [G] LONG DT @ 1016: 0.1 -INFO - [G] LONG DT @ 1016: 0.1 -INFO - [G] LONG DT @ 1016: 0.1 -INFO - [G] LONG DT @ 1016: 0.1 -INFO - [G] LONG DT @ 1016: 0.1 -INFO - [G] LONG DT @ 1016: 0.1 -INFO - [G] LONG DT @ 1017: 0.1 -INFO - [G] LONG DT @ 1017: 0.1 -INFO - [G] LONG DT @ 1017: 0.1 -INFO - [G] LONG DT @ 1017: 0.1 -INFO - [G] LONG DT @ 1017: 0.1 -INFO - [G] LONG DT @ 1017: 0.1 -INFO - [G] LONG DT @ 1017: 0.1 -INFO - [G] LONG DT @ 1017: 0.1 -INFO - [G] LONG DT @ 1017: 0.1 -INFO - [G] LONG DT @ 1017: 0.1 -INFO - [G] LONG DT @ 1018: 0.1 -INFO - [G] LONG DT @ 1018: 0.1 -INFO - [G] LONG DT @ 1018: 0.1 -INFO - [G] LONG DT @ 1018: 0.1 -INFO - [G] LONG DT @ 1018: 0.1 -INFO - [G] LONG DT @ 1018: 0.1 -INFO - [G] LONG DT @ 1018: 0.1 -INFO - [G] LONG DT @ 1018: 0.1 -INFO - [G] LONG DT @ 1018: 0.1 -INFO - [G] LONG DT @ 1018: 0.081382860000012 -INFO - [G] LONG DT @ 1019: 0.066360148000007 -INFO - [G] LONG DT @ 1019: 0.054098598400019 -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] LONG DT @ 458: 0.061078604946058 -INFO - [G] LONG DT @ 458: 0.054626863956966 -INFO - [G] LONG DT @ 1165: 0.1 -INFO - [G] LONG DT @ 1165: 0.1 -INFO - [G] LONG DT @ 1165: 0.1 -INFO - [G] LONG DT @ 1165: 0.1 -INFO - [G] LONG DT @ 1165: 0.1 -INFO - [G] LONG DT @ 1165: 0.1 -INFO - [G] LONG DT @ 1165: 0.1 -INFO - [G] LONG DT @ 1165: 0.1 -INFO - [G] LONG DT @ 1165: 0.1 -INFO - [G] LONG DT @ 1166: 0.1 -INFO - [G] LONG DT @ 1166: 0.081653579999947 -INFO - [G] LONG DT @ 1166: 0.066631924000088 -INFO - [G] LONG DT @ 1166: 0.055204399199963 -INFO - [G] LONG DT @ 2309: 0.1 -INFO - [G] LONG DT @ 2310: 0.1 -INFO - [G] LONG DT @ 2310: 0.1 -INFO - [G] LONG DT @ 2310: 0.1 -INFO - [G] LONG DT @ 2310: 0.1 -INFO - [G] LONG DT @ 2310: 0.1 -INFO - [G] LONG DT @ 2310: 0.1 -INFO - [G] LONG DT @ 2310: 0.1 -INFO - [G] LONG DT @ 2310: 0.1 -INFO - [G] LONG DT @ 2310: 0.1 -INFO - [G] LONG DT @ 2310: 0.1 -INFO - [G] LONG DT @ 2311: 0.1 -INFO - [G] LONG DT @ 2311: 0.1 -INFO - [G] LONG DT @ 2311: 0.1 -INFO - [G] LONG DT @ 2311: 0.1 -INFO - [G] LONG DT @ 2311: 0.1 -INFO - [G] LONG DT @ 2311: 0.091925340000016 -INFO - [G] LONG DT @ 2311: 0.075753931999883 -INFO - [G] LONG DT @ 2311: 0.06252940559998 -INFO - [G] LONG DT @ 2311: 0.051754684480038 -INFO - [G] LONG DT @ 2313: 0.1 -INFO - [G] LONG DT @ 2313: 0.1 -INFO - [G] LONG DT @ 2313: 0.1 -INFO - [G] LONG DT @ 2313: 0.082357920000031 -INFO - [G] LONG DT @ 2313: 0.068063896000043 -INFO - [G] LONG DT @ 2313: 0.056773116799947 -INFO - [G] LONG DT @ 2325: 0.1 -INFO - [G] LONG DT @ 2325: 0.1 -INFO - [G] LONG DT @ 2325: 0.084979600000115 -INFO - [G] LONG DT @ 2326: 0.072676400000004 -INFO - [G] LONG DT @ 2326: 0.062823440000032 -INFO - [G] LONG DT @ 2326: 0.055019411999946 -INFO - [G] LONG DT @ 2443: 0.1 -INFO - [G] LONG DT @ 2443: 0.1 -INFO - [G] LONG DT @ 2443: 0.1 -INFO - [G] LONG DT @ 2443: 0.081888280000094 -INFO - [G] LONG DT @ 2443: 0.067131484000078 -INFO - [G] LONG DT @ 2443: 0.055165087200071 -INFO - [G] LONG DT @ 2538: 0.051000998776919 -INFO - [G] LONG DT @ 2716: 0.1 -INFO - [G] LONG DT @ 2716: 0.1 -INFO - [G] LONG DT @ 2716: 0.084713020000054 -INFO - [G] LONG DT @ 2716: 0.072307556 -INFO - [G] LONG DT @ 2716: 0.062347904799982 -INFO - [G] LONG DT @ 2716: 0.054740163839998 -INFO - [G] LONG DT @ 4107: 0.050062153510581 -INFO - [G] LONG DT @ 4206: 0.06230287349689 -INFO - [G] LONG DT @ 4206: 0.055591798797241 -INFO - [G] LONG DT @ 4208: 0.081529427191557 -INFO - [G] LONG DT @ 4208: 0.090117361753097 -INFO - [G] LONG DT @ 4208: 0.07642262940246 -INFO - [G] LONG DT @ 4208: 0.065446543521991 -INFO - [G] LONG DT @ 4208: 0.056319414817464 -INFO - [G] LONG DT @ 4443: 0.057108973628938 -INFO - [G] LONG DT @ 4560: 0.067182903383624 -INFO - [G] LONG DT @ 4560: 0.059166322706767 -INFO - [G] LONG DT @ 4560: 0.052543658165696 -INFO - [G] LONG DT @ 4592: 0.063660842852936 -INFO - [G] LONG DT @ 4592: 0.054208014282502 -INFO - [G] LONG DT @ 4633: 0.055609383440104 -INFO - [G] LONG DT @ 4633: 0.058235466751902 -INFO - [G] LONG DT @ 4678: 0.060809812721608 -INFO - [G] LONG DT @ 4678: 0.05218811017715 -INFO - [G] LONG DT @ 4678: 0.1 -INFO - [G] LONG DT @ 4678: 0.082854800000205 -INFO - [G] LONG DT @ 4678: 0.068664159999957 -INFO - [G] LONG DT @ 4678: 0.057290388000128 -INFO - [G] LONG DT @ 116: 0.1 -INFO - [G] LONG DT @ 116: 0.1 -INFO - [G] LONG DT @ 116: 0.1 -INFO - [G] LONG DT @ 116: 0.08920961999982 -INFO - [G] LONG DT @ 117: 0.07305883600004 -INFO - [G] LONG DT @ 117: 0.059714548800056 diff --git a/lovely/log/lovely-2025.01.08-21.02.39.log b/lovely/log/lovely-2025.01.08-21.02.39.log deleted file mode 100644 index f46c3fb..0000000 --- a/lovely/log/lovely-2025.01.08-21.02.39.log +++ /dev/null @@ -1,276 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 129ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-08 21:02:42 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-08 21:02:43 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-08 21:02:43 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-08 21:02:43 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-08 21:02:43 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-08 21:02:43 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-08 21:02:43 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-08 21:02:43 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-08 21:02:43 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-08 21:02:43 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.665 ms -INFO - [G] 2025-01-08 21:02:43 :: INFO :: TIMER :: [0031] Injected Atlas in 780.808 ms -INFO - [G] 2025-01-08 21:02:43 :: INFO :: TIMER :: [0025] Injected Sound in 20.034 ms -INFO - [G] 2025-01-08 21:02:43 :: INFO :: TIMER :: [0032] Injected Stake in 0.758 ms -INFO - [G] 2025-01-08 21:02:43 :: INFO :: TIMER :: [0008] Injected Rarity in 0.021 ms -INFO - [G] 2025-01-08 21:02:43 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.045 ms -INFO - [G] 2025-01-08 21:02:43 :: INFO :: TIMER :: [0391] Injected Center in 1.673 ms -INFO - [G] 2025-01-08 21:02:43 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.026 ms -INFO - [G] 2025-01-08 21:02:43 :: INFO :: TIMER :: [0027] Injected Blind in 0.065 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0002] Injected Seal in 0.042 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0004] Injected Suit in 0.086 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0013] Injected Rank in 0.087 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.057 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.071 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0031] Injected Challenge in 0.062 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0028] Injected Tag in 0.057 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0009] Injected Sticker in 0.084 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0009] Injected Shader in 166.273 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0020] Injected Achievement in 0.050 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.250 ms -INFO - [G] 2025-01-08 21:02:44 :: INFO :: TIMER :: [0011] Injected Event in 0.013 ms -INFO - [G] LONG DT @ 428: 0.1 -INFO - [G] LONG DT @ 428: 0.1 -INFO - [G] LONG DT @ 428: 0.1 -INFO - [G] LONG DT @ 428: 0.1 -INFO - [G] LONG DT @ 428: 0.1 -INFO - [G] LONG DT @ 428: 0.1 -INFO - [G] LONG DT @ 428: 0.1 -INFO - [G] LONG DT @ 428: 0.1 -INFO - [G] LONG DT @ 428: 0.1 -INFO - [G] LONG DT @ 429: 0.1 -INFO - [G] LONG DT @ 429: 0.1 -INFO - [G] LONG DT @ 429: 0.1 -INFO - [G] LONG DT @ 429: 0.081563339999996 -INFO - [G] LONG DT @ 429: 0.066743972000001 -INFO - [G] LONG DT @ 429: 0.054993957599995 -INFO - [G] LONG DT @ 531: 0.1 -INFO - [G] LONG DT @ 531: 0.1 -INFO - [G] LONG DT @ 531: 0.1 -INFO - [G] LONG DT @ 531: 0.1 -INFO - [G] LONG DT @ 531: 0.1 -INFO - [G] LONG DT @ 531: 0.1 -INFO - [G] LONG DT @ 531: 0.1 -INFO - [G] LONG DT @ 532: 0.1 -INFO - [G] LONG DT @ 532: 0.1 -INFO - [G] LONG DT @ 532: 0.1 -INFO - [G] LONG DT @ 532: 0.1 -INFO - [G] LONG DT @ 532: 0.1 -INFO - [G] LONG DT @ 532: 0.1 -INFO - [G] LONG DT @ 532: 0.1 -INFO - [G] LONG DT @ 532: 0.1 -INFO - [G] LONG DT @ 532: 0.1 -INFO - [G] LONG DT @ 532: 0.1 -INFO - [G] LONG DT @ 533: 0.1 -INFO - [G] LONG DT @ 533: 0.1 -INFO - [G] LONG DT @ 533: 0.1 -INFO - [G] LONG DT @ 533: 0.1 -INFO - [G] LONG DT @ 533: 0.1 -INFO - [G] LONG DT @ 533: 0.1 -INFO - [G] LONG DT @ 533: 0.1 -INFO - [G] LONG DT @ 533: 0.1 -INFO - [G] LONG DT @ 533: 0.1 -INFO - [G] LONG DT @ 533: 0.1 -INFO - [G] LONG DT @ 534: 0.1 -INFO - [G] LONG DT @ 534: 0.1 -INFO - [G] LONG DT @ 534: 0.1 -INFO - [G] LONG DT @ 534: 0.1 -INFO - [G] LONG DT @ 534: 0.1 -INFO - [G] LONG DT @ 534: 0.1 -INFO - [G] LONG DT @ 534: 0.1 -INFO - [G] LONG DT @ 534: 0.1 -INFO - [G] LONG DT @ 534: 0.1 -INFO - [G] LONG DT @ 534: 0.1 -INFO - [G] LONG DT @ 535: 0.1 -INFO - [G] LONG DT @ 535: 0.1 -INFO - [G] LONG DT @ 535: 0.1 -INFO - [G] LONG DT @ 535: 0.1 -INFO - [G] LONG DT @ 535: 0.1 -INFO - [G] LONG DT @ 535: 0.1 -INFO - [G] LONG DT @ 535: 0.1 -INFO - [G] LONG DT @ 535: 0.1 -INFO - [G] LONG DT @ 535: 0.1 -INFO - [G] LONG DT @ 535: 0.1 -INFO - [G] LONG DT @ 536: 0.1 -INFO - [G] LONG DT @ 536: 0.1 -INFO - [G] LONG DT @ 536: 0.1 -INFO - [G] LONG DT @ 536: 0.1 -INFO - [G] LONG DT @ 536: 0.1 -INFO - [G] LONG DT @ 536: 0.1 -INFO - [G] LONG DT @ 536: 0.1 -INFO - [G] LONG DT @ 536: 0.1 -INFO - [G] LONG DT @ 536: 0.1 -INFO - [G] LONG DT @ 536: 0.1 -INFO - [G] LONG DT @ 537: 0.1 -INFO - [G] LONG DT @ 537: 0.1 -INFO - [G] LONG DT @ 537: 0.1 -INFO - [G] LONG DT @ 537: 0.1 -INFO - [G] LONG DT @ 537: 0.1 -INFO - [G] LONG DT @ 537: 0.1 -INFO - [G] LONG DT @ 537: 0.1 -INFO - [G] LONG DT @ 537: 0.1 -INFO - [G] LONG DT @ 537: 0.1 -INFO - [G] LONG DT @ 537: 0.1 -INFO - [G] LONG DT @ 538: 0.1 -INFO - [G] LONG DT @ 538: 0.1 -INFO - [G] LONG DT @ 538: 0.1 -INFO - [G] LONG DT @ 538: 0.1 -INFO - [G] LONG DT @ 538: 0.1 -INFO - [G] LONG DT @ 538: 0.1 -INFO - [G] LONG DT @ 538: 0.0816887 -INFO - [G] LONG DT @ 538: 0.066798879999987 -INFO - [G] LONG DT @ 538: 0.05471962399999 -INFO - [G] LONG DT @ 804: 0.1 -INFO - [G] LONG DT @ 804: 0.1 -INFO - [G] LONG DT @ 804: 0.1 -INFO - [G] LONG DT @ 805: 0.1 -INFO - [G] LONG DT @ 805: 0.1 -INFO - [G] LONG DT @ 805: 0.1 -INFO - [G] LONG DT @ 805: 0.1 -INFO - [G] LONG DT @ 805: 0.1 -INFO - [G] LONG DT @ 805: 0.1 -INFO - [G] LONG DT @ 805: 0.1 -INFO - [G] LONG DT @ 805: 0.1 -INFO - [G] LONG DT @ 805: 0.1 -INFO - [G] LONG DT @ 805: 0.1 -INFO - [G] LONG DT @ 806: 0.1 -INFO - [G] LONG DT @ 806: 0.1 -INFO - [G] LONG DT @ 806: 0.1 -INFO - [G] LONG DT @ 806: 0.1 -INFO - [G] LONG DT @ 806: 0.1 -INFO - [G] LONG DT @ 806: 0.1 -INFO - [G] LONG DT @ 806: 0.1 -INFO - [G] LONG DT @ 806: 0.1 -INFO - [G] LONG DT @ 806: 0.1 -INFO - [G] LONG DT @ 806: 0.1 -INFO - [G] LONG DT @ 807: 0.1 -INFO - [G] LONG DT @ 807: 0.1 -INFO - [G] LONG DT @ 807: 0.1 -INFO - [G] LONG DT @ 807: 0.1 -INFO - [G] LONG DT @ 807: 0.1 -INFO - [G] LONG DT @ 807: 0.1 -INFO - [G] LONG DT @ 807: 0.08180848 -INFO - [G] LONG DT @ 807: 0.066933044000001 -INFO - [G] LONG DT @ 807: 0.054882335200005 -INFO - [G] LONG DT @ 823: 0.1 -INFO - [G] LONG DT @ 823: 0.1 -INFO - [G] LONG DT @ 823: 0.1 -INFO - [G] LONG DT @ 823: 0.1 -INFO - [G] LONG DT @ 823: 0.1 -INFO - [G] LONG DT @ 823: 0.1 -INFO - [G] LONG DT @ 823: 0.1 -INFO - [G] LONG DT @ 823: 0.1 -INFO - [G] LONG DT @ 824: 0.1 -INFO - [G] LONG DT @ 824: 0.1 -INFO - [G] LONG DT @ 824: 0.1 -INFO - [G] LONG DT @ 824: 0.1 -INFO - [G] LONG DT @ 824: 0.1 -INFO - [G] LONG DT @ 824: 0.1 -INFO - [G] LONG DT @ 824: 0.1 -INFO - [G] LONG DT @ 824: 0.1 -INFO - [G] LONG DT @ 824: 0.1 -INFO - [G] LONG DT @ 824: 0.1 -INFO - [G] LONG DT @ 825: 0.1 -INFO - [G] LONG DT @ 825: 0.1 -INFO - [G] LONG DT @ 825: 0.1 -INFO - [G] LONG DT @ 825: 0.1 -INFO - [G] LONG DT @ 825: 0.1 -INFO - [G] LONG DT @ 825: 0.1 -INFO - [G] LONG DT @ 825: 0.1 -INFO - [G] LONG DT @ 825: 0.081634119999994 -INFO - [G] LONG DT @ 825: 0.066672395999994 -INFO - [G] LONG DT @ 825: 0.056100496800007 -INFO - [G] LONG DT @ 830: 0.1 -INFO - [G] LONG DT @ 830: 0.1 -INFO - [G] LONG DT @ 831: 0.1 -INFO - [G] LONG DT @ 831: 0.1 -INFO - [G] LONG DT @ 831: 0.1 -INFO - [G] LONG DT @ 831: 0.1 -INFO - [G] LONG DT @ 831: 0.1 -INFO - [G] LONG DT @ 831: 0.084873039999984 -INFO - [G] LONG DT @ 831: 0.069626072 -INFO - [G] LONG DT @ 831: 0.057503137599993 diff --git a/lovely/log/lovely-2025.01.09-00.41.50.log b/lovely/log/lovely-2025.01.09-00.41.50.log deleted file mode 100644 index b8c5dff..0000000 --- a/lovely/log/lovely-2025.01.09-00.41.50.log +++ /dev/null @@ -1,279 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 149ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-09 00:41:53 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-09 00:41:54 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-09 00:41:54 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-09 00:41:54 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-09 00:41:54 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-09 00:41:54 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-09 00:41:54 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-09 00:41:54 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-09 00:41:54 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-09 00:41:54 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.647 ms -INFO - [G] 2025-01-09 00:41:55 :: INFO :: TIMER :: [0031] Injected Atlas in 815.097 ms -INFO - [G] 2025-01-09 00:41:55 :: INFO :: TIMER :: [0025] Injected Sound in 23.004 ms -INFO - [G] 2025-01-09 00:41:55 :: INFO :: TIMER :: [0032] Injected Stake in 1.041 ms -INFO - [G] 2025-01-09 00:41:55 :: INFO :: TIMER :: [0008] Injected Rarity in 0.022 ms -INFO - [G] 2025-01-09 00:41:56 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.121 ms -INFO - [G] 2025-01-09 00:41:57 :: INFO :: TIMER :: [0391] Injected Center in 2.134 ms -INFO - [G] 2025-01-09 00:41:58 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.044 ms -INFO - [G] 2025-01-09 00:41:59 :: INFO :: TIMER :: [0027] Injected Blind in 0.541 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0002] Injected Seal in 0.082 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0004] Injected Suit in 0.195 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0013] Injected Rank in 0.091 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.034 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.145 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0031] Injected Challenge in 0.076 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0028] Injected Tag in 0.672 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0009] Injected Sticker in 0.634 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0009] Injected Shader in 58.053 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0020] Injected Achievement in 0.147 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.512 ms -INFO - [G] 2025-01-09 00:42:00 :: INFO :: TIMER :: [0011] Injected Event in 0.128 ms -INFO - [G] LONG DT @ 242: 0.1 -INFO - [G] LONG DT @ 242: 0.1 -INFO - [G] LONG DT @ 242: 0.1 -INFO - [G] LONG DT @ 242: 0.1 -INFO - [G] LONG DT @ 242: 0.1 -INFO - [G] LONG DT @ 242: 0.1 -INFO - [G] LONG DT @ 242: 0.1 -INFO - [G] LONG DT @ 242: 0.1 -INFO - [G] LONG DT @ 242: 0.1 -INFO - [G] LONG DT @ 243: 0.1 -INFO - [G] LONG DT @ 243: 0.1 -INFO - [G] LONG DT @ 243: 0.1 -INFO - [G] LONG DT @ 243: 0.1 -INFO - [G] LONG DT @ 243: 0.1 -INFO - [G] LONG DT @ 243: 0.1 -INFO - [G] LONG DT @ 243: 0.1 -INFO - [G] LONG DT @ 243: 0.1 -INFO - [G] LONG DT @ 243: 0.1 -INFO - [G] LONG DT @ 243: 0.1 -INFO - [G] LONG DT @ 244: 0.082632259999996 -INFO - [G] LONG DT @ 244: 0.068562608000001 -INFO - [G] LONG DT @ 244: 0.056856906399998 -INFO - [G] LONG DT @ 245: 0.1 -INFO - [G] LONG DT @ 245: 0.085794560000004 -INFO - [G] LONG DT @ 245: 0.074059648000008 -INFO - [G] LONG DT @ 245: 0.064583038400001 -INFO - [G] LONG DT @ 245: 0.056899570719997 -INFO - [G] LONG DT @ 245: 0.050576436576004 -INFO - [G] LONG DT @ 2620: 0.083872598038467 -INFO - [G] LONG DT @ 2620: 0.071462498430776 -INFO - [G] LONG DT @ 2620: 0.06149121874464 -INFO - [G] LONG DT @ 2621: 0.053595214995748 -INFO - [G] LONG DT @ 2623: 0.065053737025595 -INFO - [G] LONG DT @ 2623: 0.053883289620479 -INFO - [G] LONG DT @ 2690: 0.050212301610195 -INFO - [G] LONG DT @ 2693: 0.060296654117329 -INFO - [G] LONG DT @ 2834: 0.091615562591627 -INFO - [G] LONG DT @ 2834: 0.077839310073238 -INFO - [G] LONG DT @ 2835: 0.066596148058642 -INFO - [G] LONG DT @ 2835: 0.061569958446904 -INFO - [G] LONG DT @ 2835: 0.057908826757507 -INFO - [G] LONG DT @ 2835: 0.051225401406005 -INFO - [G] LONG DT @ 2980: 0.1 -INFO - [G] LONG DT @ 2980: 0.090045579999951 -INFO - [G] LONG DT @ 2980: 0.077122443999928 -INFO - [G] LONG DT @ 2981: 0.06597911519997 -INFO - [G] LONG DT @ 2981: 0.057087452159968 -INFO - [G] LONG DT @ 2995: 0.091635811342222 -INFO - [G] LONG DT @ 2996: 0.077788569073772 -INFO - [G] LONG DT @ 2996: 0.066564055259036 -INFO - [G] LONG DT @ 2996: 0.057793044207199 -INFO - [G] LONG DT @ 2996: 0.050740935365784 -INFO - [G] LONG DT @ 3094: 0.051310382816534 -INFO - [G] LONG DT @ 3183: 0.052398811267431 -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 01:35:42 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] LONG DT @ 3217: 0.075648980118892 -INFO - [G] LONG DT @ 3217: 0.065100084095132 -INFO - [G] LONG DT @ 3218: 0.056437267276064 -INFO - [G] LONG DT @ 3218: 0.087668246337747 -INFO - [G] LONG DT @ 3218: 0.072008577070179 -INFO - [G] LONG DT @ 3218: 0.059283001656161 -INFO - [G] LONG DT @ 3226: 0.1 -INFO - [G] LONG DT @ 3226: 0.081910039999984 -INFO - [G] LONG DT @ 3226: 0.067285091999987 -INFO - [G] LONG DT @ 3226: 0.055555193600022 -INFO - [G] LONG DT @ 3266: 0.056312389973779 -INFO - [G] LONG DT @ 3266: 0.082847785583251 -INFO - [G] LONG DT @ 3266: 0.069255608466593 -INFO - [G] LONG DT @ 3266: 0.058611506773266 -INFO - [G] LONG DT @ 3273: 0.056317270673948 -INFO - [G] LONG DT @ 3313: 0.050398878949625 -INFO - [G] LONG DT @ 3313: 0.1 -INFO - [G] LONG DT @ 3313: 0.084667760000029 -INFO - [G] LONG DT @ 3313: 0.072256508000031 -INFO - [G] LONG DT @ 3313: 0.062049906400006 -INFO - [G] LONG DT @ 3313: 0.053923685120003 -INFO - [G] LONG DT @ 3335: 0.1 -INFO - [G] LONG DT @ 3335: 0.085362460000015 -INFO - [G] LONG DT @ 3335: 0.073826367999995 -INFO - [G] LONG DT @ 3335: 0.064719494399989 -INFO - [G] LONG DT @ 3335: 0.05712447552001 -INFO - [G] LONG DT @ 3335: 0.051197000416037 -INFO - [G] LONG DT @ 3341: 0.065757603206926 -INFO - [G] LONG DT @ 3341: 0.05724356256556 -INFO - [G] LONG DT @ 3341: 0.050297950052414 diff --git a/lovely/log/lovely-2025.01.09-01.39.41.log b/lovely/log/lovely-2025.01.09-01.39.41.log deleted file mode 100644 index 80f36d0..0000000 --- a/lovely/log/lovely-2025.01.09-01.39.41.log +++ /dev/null @@ -1,307 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 130ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-09 01:39:44 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-09 01:39:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-09 01:39:45 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-09 01:39:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-09 01:39:45 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-09 01:39:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-09 01:39:45 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-09 01:39:45 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-09 01:39:45 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-09 01:39:45 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.729 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0031] Injected Atlas in 800.171 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0025] Injected Sound in 21.776 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0032] Injected Stake in 0.729 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0008] Injected Rarity in 0.021 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.053 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0391] Injected Center in 2.165 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.025 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0027] Injected Blind in 0.470 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0002] Injected Seal in 0.042 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0004] Injected Suit in 0.103 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0013] Injected Rank in 0.086 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.032 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.110 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0031] Injected Challenge in 0.052 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0028] Injected Tag in 0.610 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0009] Injected Sticker in 0.559 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0009] Injected Shader in 54.651 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0020] Injected Achievement in 0.143 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.167 ms -INFO - [G] 2025-01-09 01:39:46 :: INFO :: TIMER :: [0011] Injected Event in 0.091 ms -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 13: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 14: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 15: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 16: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.080447499999999 -INFO - [G] LONG DT @ 19: 0.06554884 -INFO - [G] LONG DT @ 20: 0.053682532 -INFO - [G] LONG DT @ 1067: 0.1 -INFO - [G] LONG DT @ 1067: 0.1 -INFO - [G] LONG DT @ 1067: 0.1 -INFO - [G] LONG DT @ 1067: 0.1 -INFO - [G] LONG DT @ 1067: 0.1 -INFO - [G] LONG DT @ 1067: 0.1 -INFO - [G] LONG DT @ 1067: 0.1 -INFO - [G] LONG DT @ 1068: 0.1 -INFO - [G] LONG DT @ 1068: 0.1 -INFO - [G] LONG DT @ 1068: 0.1 -INFO - [G] LONG DT @ 1068: 0.1 -INFO - [G] LONG DT @ 1068: 0.1 -INFO - [G] LONG DT @ 1068: 0.1 -INFO - [G] LONG DT @ 1068: 0.1 -INFO - [G] LONG DT @ 1068: 0.1 -INFO - [G] LONG DT @ 1068: 0.1 -INFO - [G] LONG DT @ 1068: 0.1 -INFO - [G] LONG DT @ 1069: 0.1 -INFO - [G] LONG DT @ 1069: 0.1 -INFO - [G] LONG DT @ 1069: 0.1 -INFO - [G] LONG DT @ 1069: 0.1 -INFO - [G] LONG DT @ 1069: 0.1 -INFO - [G] LONG DT @ 1069: 0.1 -INFO - [G] LONG DT @ 1069: 0.1 -INFO - [G] LONG DT @ 1069: 0.1 -INFO - [G] LONG DT @ 1069: 0.1 -INFO - [G] LONG DT @ 1069: 0.1 -INFO - [G] LONG DT @ 1070: 0.1 -INFO - [G] LONG DT @ 1070: 0.1 -INFO - [G] LONG DT @ 1070: 0.1 -INFO - [G] LONG DT @ 1070: 0.1 -INFO - [G] LONG DT @ 1070: 0.1 -INFO - [G] LONG DT @ 1070: 0.1 -INFO - [G] LONG DT @ 1070: 0.1 -INFO - [G] LONG DT @ 1070: 0.1 -INFO - [G] LONG DT @ 1070: 0.1 -INFO - [G] LONG DT @ 1070: 0.1 -INFO - [G] LONG DT @ 1071: 0.1 -INFO - [G] LONG DT @ 1071: 0.1 -INFO - [G] LONG DT @ 1071: 0.1 -INFO - [G] LONG DT @ 1071: 0.1 -INFO - [G] LONG DT @ 1071: 0.1 -INFO - [G] LONG DT @ 1071: 0.1 -INFO - [G] LONG DT @ 1071: 0.1 -INFO - [G] LONG DT @ 1071: 0.1 -INFO - [G] LONG DT @ 1071: 0.1 -INFO - [G] LONG DT @ 1071: 0.1 -INFO - [G] LONG DT @ 1072: 0.1 -INFO - [G] LONG DT @ 1072: 0.1 -INFO - [G] LONG DT @ 1072: 0.1 -INFO - [G] LONG DT @ 1072: 0.1 -INFO - [G] LONG DT @ 1072: 0.1 -INFO - [G] LONG DT @ 1072: 0.1 -INFO - [G] LONG DT @ 1072: 0.1 -INFO - [G] LONG DT @ 1072: 0.1 -INFO - [G] LONG DT @ 1072: 0.08151194 -INFO - [G] LONG DT @ 1072: 0.066704631999995 -INFO - [G] LONG DT @ 1072: 0.054642965599997 -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] 2025-01-09 02:31:58 :: INFO :: TIMER :: [0000] Injected Language in 0.002 ms -INFO - [G] 2025-01-09 02:31:58 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 15.079 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0031] Injected Atlas in 811.704 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0025] Injected Sound in 20.201 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0032] Injected Stake in 0.317 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0008] Injected Rarity in 0.020 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.034 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0391] Injected Center in 0.822 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.021 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0027] Injected Blind in 0.026 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0002] Injected Seal in 0.041 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0004] Injected Suit in 0.046 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0013] Injected Rank in 0.025 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.020 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.060 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0031] Injected Challenge in 0.022 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0028] Injected Tag in 0.028 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0009] Injected Sticker in 0.121 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0009] Injected Shader in 36.829 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0000] Injected Keybind in 0.002 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0020] Injected Achievement in 0.121 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 9.214 ms -INFO - [G] 2025-01-09 02:31:59 :: INFO :: TIMER :: [0011] Injected Event in 0.012 ms -INFO - [G] LONG DT @ 45: 0.1 -INFO - [G] LONG DT @ 12: 0.084008939999949 -INFO - [G] LONG DT @ 12: 0.070627251999998 -INFO - [G] LONG DT @ 12: 0.059946401599965 -INFO - [G] LONG DT @ 12: 0.051411801280022 -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] 2025-01-09 02:34:59 :: INFO :: TIMER :: [0000] Injected Language in 0.002 ms -INFO - [G] 2025-01-09 02:34:59 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 12.776 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0031] Injected Atlas in 791.418 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0025] Injected Sound in 19.979 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0032] Injected Stake in 0.147 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0008] Injected Rarity in 0.017 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.057 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0391] Injected Center in 0.836 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.009 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0027] Injected Blind in 0.026 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0002] Injected Seal in 0.039 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0004] Injected Suit in 0.051 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0013] Injected Rank in 0.028 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.021 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.037 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0031] Injected Challenge in 0.025 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0028] Injected Tag in 0.029 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0009] Injected Sticker in 0.084 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0009] Injected Shader in 67.462 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0000] Injected Keybind in 0.002 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0020] Injected Achievement in 0.077 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 12.424 ms -INFO - [G] 2025-01-09 02:35:00 :: INFO :: TIMER :: [0011] Injected Event in 0.011 ms -INFO - [G] LONG DT @ 163: 0.1 -INFO - [G] LONG DT @ 12: 0.084497160000028 -INFO - [G] LONG DT @ 12: 0.071077967999976 -INFO - [G] LONG DT @ 12: 0.060296154399958 -INFO - [G] LONG DT @ 12: 0.051660703520015 diff --git a/lovely/log/lovely-2025.01.09-02.37.25.log b/lovely/log/lovely-2025.01.09-02.37.25.log deleted file mode 100644 index 1bd97d6..0000000 --- a/lovely/log/lovely-2025.01.09-02.37.25.log +++ /dev/null @@ -1,115 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 128ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-09 02:37:29 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-09 02:37:29 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-09 02:37:29 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-09 02:37:29 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-09 02:37:29 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-09 02:37:29 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-09 02:37:29 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-09 02:37:30 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.752 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0031] Injected Atlas in 790.632 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0025] Injected Sound in 21.453 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0032] Injected Stake in 0.859 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0008] Injected Rarity in 0.022 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.048 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0391] Injected Center in 1.995 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.028 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0027] Injected Blind in 0.290 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0002] Injected Seal in 0.214 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0004] Injected Suit in 0.077 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0013] Injected Rank in 0.195 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.031 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.075 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0031] Injected Challenge in 0.055 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0028] Injected Tag in 0.052 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0009] Injected Sticker in 0.075 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0009] Injected Shader in 53.570 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0020] Injected Achievement in 0.060 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.675 ms -INFO - [G] 2025-01-09 02:37:30 :: INFO :: TIMER :: [0011] Injected Event in 0.014 ms diff --git a/lovely/log/lovely-2025.01.09-17.52.43.log b/lovely/log/lovely-2025.01.09-17.52.43.log deleted file mode 100644 index 66767cd..0000000 --- a/lovely/log/lovely-2025.01.09-17.52.43.log +++ /dev/null @@ -1,214 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 137ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-09 17:52:47 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-09 17:52:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-09 17:52:48 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-09 17:52:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-09 17:52:48 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-09 17:52:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-09 17:52:48 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-09 17:52:48 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.987 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0031] Injected Atlas in 799.057 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0025] Injected Sound in 23.766 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0032] Injected Stake in 0.613 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0008] Injected Rarity in 0.022 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.046 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0391] Injected Center in 2.202 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.044 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0027] Injected Blind in 0.417 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0002] Injected Seal in 0.276 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0004] Injected Suit in 0.120 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0013] Injected Rank in 0.105 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.033 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.104 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0031] Injected Challenge in 0.063 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0028] Injected Tag in 0.782 ms -INFO - [G] 2025-01-09 17:52:48 :: INFO :: TIMER :: [0009] Injected Sticker in 0.459 ms -INFO - [G] 2025-01-09 17:52:49 :: INFO :: TIMER :: [0009] Injected Shader in 61.350 ms -INFO - [G] 2025-01-09 17:52:49 :: INFO :: TIMER :: [0000] Injected Keybind in 0.002 ms -INFO - [G] 2025-01-09 17:52:49 :: INFO :: TIMER :: [0020] Injected Achievement in 0.242 ms -INFO - [G] 2025-01-09 17:52:49 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.695 ms -INFO - [G] 2025-01-09 17:52:49 :: INFO :: TIMER :: [0011] Injected Event in 0.165 ms -INFO - [G] LONG DT @ 67: 0.1 -INFO - [G] LONG DT @ 67: 0.1 -INFO - [G] LONG DT @ 67: 0.1 -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 68: 0.1 -INFO - [G] LONG DT @ 68: 0.081165979999999 -INFO - [G] LONG DT @ 68: 0.065826343999999 -INFO - [G] LONG DT @ 68: 0.0538825152 -INFO - [G] LONG DT @ 74: 0.080170907077756 -INFO - [G] LONG DT @ 75: 0.067432685662204 -INFO - [G] LONG DT @ 75: 0.057214428529764 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 83: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 84: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 85: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 86: 0.1 -INFO - [G] LONG DT @ 87: 0.1 -INFO - [G] LONG DT @ 87: 0.1 -INFO - [G] LONG DT @ 87: 0.1 -INFO - [G] LONG DT @ 87: 0.1 -INFO - [G] LONG DT @ 87: 0.1 -INFO - [G] LONG DT @ 87: 0.1 -INFO - [G] LONG DT @ 87: 0.1 -INFO - [G] LONG DT @ 87: 0.1 -INFO - [G] LONG DT @ 87: 0.1 -INFO - [G] LONG DT @ 87: 0.1 -INFO - [G] LONG DT @ 88: 0.1 -INFO - [G] LONG DT @ 88: 0.1 -INFO - [G] LONG DT @ 88: 0.1 -INFO - [G] LONG DT @ 88: 0.1 -INFO - [G] LONG DT @ 88: 0.1 -INFO - [G] LONG DT @ 88: 0.1 -INFO - [G] LONG DT @ 88: 0.1 -INFO - [G] LONG DT @ 88: 0.1 -INFO - [G] LONG DT @ 88: 0.1 -INFO - [G] LONG DT @ 88: 0.1 -INFO - [G] LONG DT @ 89: 0.1 -INFO - [G] LONG DT @ 89: 0.1 -INFO - [G] LONG DT @ 89: 0.1 -INFO - [G] LONG DT @ 89: 0.1 -INFO - [G] LONG DT @ 89: 0.1 -INFO - [G] LONG DT @ 89: 0.1 -INFO - [G] LONG DT @ 89: 0.1 -INFO - [G] LONG DT @ 89: 0.1 -INFO - [G] LONG DT @ 89: 0.1 -INFO - [G] LONG DT @ 89: 0.1 -INFO - [G] LONG DT @ 90: 0.1 -INFO - [G] LONG DT @ 90: 0.1 -INFO - [G] LONG DT @ 90: 0.1 -INFO - [G] LONG DT @ 90: 0.1 -INFO - [G] LONG DT @ 90: 0.1 -INFO - [G] LONG DT @ 90: 0.1 -INFO - [G] LONG DT @ 90: 0.1 -INFO - [G] LONG DT @ 90: 0.1 -INFO - [G] LONG DT @ 90: 0.1 -INFO - [G] LONG DT @ 90: 0.1 -INFO - [G] LONG DT @ 91: 0.1 -INFO - [G] LONG DT @ 91: 0.1 -INFO - [G] LONG DT @ 91: 0.1 -INFO - [G] LONG DT @ 91: 0.1 -INFO - [G] LONG DT @ 91: 0.1 -INFO - [G] LONG DT @ 91: 0.081291100000003 -INFO - [G] LONG DT @ 91: 0.066132180000001 -INFO - [G] LONG DT @ 91: 0.053766764000003 diff --git a/lovely/log/lovely-2025.01.09-17.55.53.log b/lovely/log/lovely-2025.01.09-17.55.53.log deleted file mode 100644 index 60107dc..0000000 --- a/lovely/log/lovely-2025.01.09-17.55.53.log +++ /dev/null @@ -1,256 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 123ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-09 17:55:57 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-09 17:55:57 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-09 17:55:57 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-09 17:55:57 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-09 17:55:57 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-09 17:55:57 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-09 17:55:57 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-09 17:55:57 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-09 17:55:57 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-09 17:55:57 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-09 17:55:58 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0000] Injected Language in 0.002 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.805 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0031] Injected Atlas in 803.834 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0025] Injected Sound in 20.557 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0032] Injected Stake in 0.720 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0008] Injected Rarity in 0.028 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.063 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0391] Injected Center in 1.838 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.010 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0027] Injected Blind in 0.057 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0002] Injected Seal in 0.049 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0004] Injected Suit in 0.084 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0013] Injected Rank in 0.065 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.049 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.109 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0031] Injected Challenge in 0.145 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0028] Injected Tag in 0.237 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0009] Injected Sticker in 0.686 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0009] Injected Shader in 55.551 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0000] Injected Keybind in 0.002 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0020] Injected Achievement in 0.069 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 4.205 ms -INFO - [G] 2025-01-09 17:55:58 :: INFO :: TIMER :: [0011] Injected Event in 0.014 ms -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] LONG DT @ 1894: 0.05097178820817 -INFO - [G] LONG DT @ 1952: 0.057003341348129 -INFO - [G] LONG DT @ 1952: 0.053710233078511 -INFO - [G] LONG DT @ 1952: 0.051085246462804 -INFO - [G] LONG DT @ 2109: 0.053958635977822 -INFO - [G] LONG DT @ 2109: 0.051689768782252 -INFO - [G] LONG DT @ 2109: 0.051517575025819 -INFO - [G] LONG DT @ 2109: 0.070034700020704 -INFO - [G] LONG DT @ 2109: 0.064395700016535 -INFO - [G] LONG DT @ 2109: 0.059747920013218 -INFO - [G] LONG DT @ 2109: 0.055842956010539 -INFO - [G] LONG DT @ 2109: 0.052902364808485 -INFO - [G] LONG DT @ 2109: 0.050436091846788 -INFO - [G] LONG DT @ 2187: 0.052896893123253 -INFO - [G] LONG DT @ 2187: 0.050348194498558 -INFO - [G] LONG DT @ 2268: 0.1 -INFO - [G] LONG DT @ 2268: 0.088545119999962 -INFO - [G] LONG DT @ 2269: 0.079070815999989 -INFO - [G] LONG DT @ 2269: 0.071441232800025 -INFO - [G] LONG DT @ 2269: 0.065316486239975 -INFO - [G] LONG DT @ 2269: 0.060285708992031 -INFO - [G] LONG DT @ 2269: 0.056594347193611 -INFO - [G] LONG DT @ 2269: 0.053259517754862 -INFO - [G] LONG DT @ 2269: 0.050781854203861 -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'cry_runarea' not instantiated before load -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-01-09 18:36:51 :: ERROR :: StackTrace :: Oops! The game crashed -[SMODS Cryptid "Items/CodeCards.lua"]:4064: attempt to index field 'cry_runarea' (a nil value) -Stack Traceback -=============== -(1) Lua local 'handler' at file 'main.lua:612' - Local variables: - msg = string: "[SMODS Cryptid \"Items/CodeCards.lua\"]:4064: attempt to index field 'cry_runarea' (a nil value)" - (*temporary) = Lua function '?' (defined at line 31 of chunk [SMODS _ "src/logging.lua"]) - (*temporary) = string: "Oops! The game crashed\ -" -(2) LÖVE metamethod at file 'boot.lua:352' - Local variables: - errhand = Lua function '?' (defined at line 598 of chunk main.lua) - handler = Lua function '?' (defined at line 598 of chunk main.lua) -(3) Lua function '?' at file 'Items/CodeCards.lua:4064' (from mod with id Cryptid) (best guess) - Local variables: - e = table: 0x06184158 {pixellated_rect:table: 0x09410d98, click_offset:table: 0x065037c8, children:table: 0x06184220 (more...)} - (*temporary) = nil - (*temporary) = table: 0x08fdd358 {queue_last_processed:2451.7833333369, queues:table: 0x04d01170, queue_dt:0.016666666666667 (more...)} - (*temporary) = table: 0x09132048 {start_timer:false, timer:TOTAL, blockable:true, trigger:after, func:function: 0x09132028 (more...)} - (*temporary) = string: "base" - (*temporary) = nil - (*temporary) = table: 0x04d20d90 {1:table: 0x06ec6f10, 2:table: 0x0901c6a0, 3:table: 0x09763468, 4:table: 0x044ac940 (more...)} - (*temporary) = number: 47 - (*temporary) = table: 0x0427d3a8 {handle:function: 0x0427c440, __index:table: 0x0427d3a8, init:function: 0x0427c9a8 (more...)} - (*temporary) = table: 0x0427d3a8 {handle:function: 0x0427c440, __index:table: 0x0427d3a8, init:function: 0x0427c9a8 (more...)} - (*temporary) = boolean: true - (*temporary) = table: 0x09131f98 {func:function: 0x09132028, trigger:after, delay:0.5} - (*temporary) = string: "attempt to index field 'cry_runarea' (a nil value)" -(4) Lua method 'click' at file 'engine/ui.lua:988' - Local variables: - self = table: 0x06184158 {pixellated_rect:table: 0x09410d98, click_offset:table: 0x065037c8, children:table: 0x06184220 (more...)} -(5) Lua method 'update' at file 'engine/controller.lua:375' - Local variables: - self = table: 0x049db078 {held_button_times:table: 0x049db948, focus_cursor_stack_level:1, snap_cursor_to:table: 0x11496848 (more...)} - dt = number: 0.006097 -(6) Lua upvalue 'gameUpdateRef' at file 'game.lua:2866' - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0871ed68 (more...)} - dt = number: 0.006097 -(7) Lua upvalue 'upd' at Steamodded file 'src/ui.lua:81' - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0871ed68 (more...)} - dt = number: 0.006097 -(8) Lua upvalue 'upd' at file 'main.lua:3934' - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0871ed68 (more...)} - dt = number: 0.006097 -(9) Lua upvalue 'upd' at file 'Items/Blinds.lua:1310' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0871ed68 (more...)} - dt = number: 0.006097 -(10) Lua upvalue 'upd' at file 'Items/CodeCards.lua:4106' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0871ed68 (more...)} - dt = number: 0.006097 -(11) Lua upvalue 'upd' at file 'Items/Decks.lua:429' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0871ed68 (more...)} - dt = number: 0.006097 -(12) Lua upvalue 'upd' at file 'Items/MiscJokers.lua:6658' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0871ed68 (more...)} - dt = number: 0.006097 -(13) Lua method 'update' at file 'Cryptid.lua:2948' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0871ed68 (more...)} - dt = number: 0.006097 -(14) Lua upvalue 'love_update_ref' at file 'main.lua:993' - Local variables: - dt = number: 0.006097 -(15) Lua upvalue 'oldupd' at file 'main.lua:2796' - Local variables: - dt = number: 0.006097 -(16) Lua field 'update' at file 'main.lua:3961' - Local variables: - dt = number: 0.006097 -(17) Lua function '?' at file 'main.lua:931' (best guess) -(18) global C function 'xpcall' -(19) LÖVE function at file 'boot.lua:377' (best guess) - Local variables: - func = Lua function '?' (defined at line 902 of chunk main.lua) - inerror = boolean: true - deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"]) - earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"]) - -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-01-09 18:36:51 :: INFO :: StackTrace :: Additional Context: -Balatro Version: 1.0.1n-FULL -Modded Version: 1.0.0~ALPHA-1220a-STEAMODDED -LÖVE Version: 11.5.0 -Lovely Version: 0.6.0 -Steamodded Mods: - 1: J Cursor by Jie65535, MarioMak967 [ID: JCursor] - 2: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.2, Uses Lovely] - Break Infinity: omeganum - 3: Handy by SleepyG11 [ID: Handy, Version: 1.1.5, Uses Lovely] - 4: Cryptid by MathIsFun_, Cryptid and Balatro Discords [ID: Cryptid, Priority: 1e+299, Version: 0.5.3a, Uses Lovely] -Lovely Mods: diff --git a/lovely/log/lovely-2025.01.09-18.37.40.log b/lovely/log/lovely-2025.01.09-18.37.40.log deleted file mode 100644 index 2e60f88..0000000 --- a/lovely/log/lovely-2025.01.09-18.37.40.log +++ /dev/null @@ -1,229 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 130ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-09 18:37:44 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-09 18:37:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-09 18:37:45 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-09 18:37:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-09 18:37:45 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-09 18:37:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-09 18:37:45 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-09 18:37:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-09 18:37:45 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-09 18:37:45 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-09 18:37:45 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-09 18:37:45 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-09 18:37:45 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.666 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0031] Injected Atlas in 778.134 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0025] Injected Sound in 20.385 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0032] Injected Stake in 0.849 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0008] Injected Rarity in 0.027 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.052 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0391] Injected Center in 1.617 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.014 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0027] Injected Blind in 0.044 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0002] Injected Seal in 0.049 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0004] Injected Suit in 0.068 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0013] Injected Rank in 0.067 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.066 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.107 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0031] Injected Challenge in 0.036 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0028] Injected Tag in 0.317 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0009] Injected Sticker in 0.071 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0009] Injected Shader in 109.290 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0020] Injected Achievement in 0.056 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.450 ms -INFO - [G] 2025-01-09 18:37:46 :: INFO :: TIMER :: [0011] Injected Event in 0.014 ms -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'cry_runarea' not instantiated before load -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-01-09 18:37:57 :: ERROR :: StackTrace :: Oops! The game crashed -[SMODS Cryptid "Items/CodeCards.lua"]:4064: attempt to index field 'cry_runarea' (a nil value) -Stack Traceback -=============== -(1) Lua local 'handler' at file 'main.lua:612' - Local variables: - msg = string: "[SMODS Cryptid \"Items/CodeCards.lua\"]:4064: attempt to index field 'cry_runarea' (a nil value)" - (*temporary) = Lua function '?' (defined at line 31 of chunk [SMODS _ "src/logging.lua"]) - (*temporary) = string: "Oops! The game crashed\ -" -(2) LÖVE metamethod at file 'boot.lua:352' - Local variables: - errhand = Lua function '?' (defined at line 598 of chunk main.lua) - handler = Lua function '?' (defined at line 598 of chunk main.lua) -(3) Lua function '?' at file 'Items/CodeCards.lua:4064' (from mod with id Cryptid) (best guess) - Local variables: - e = table: 0x04c14ea8 {pixellated_rect:table: 0x08653338, click_offset:table: 0x084a64f0, children:table: 0x04c14ed0 (more...)} - (*temporary) = nil - (*temporary) = table: 0x04cdf9f8 {queue_last_processed:10.933333333333, queues:table: 0x04cdfa20, queue_dt:0.016666666666667 (more...)} - (*temporary) = table: 0x04bf79d0 {start_timer:false, timer:TOTAL, blockable:true, trigger:after, func:function: 0x08650280 (more...)} - (*temporary) = string: "base" - (*temporary) = nil - (*temporary) = table: 0x04d23008 {1:table: 0x1180b030, 2:table: 0x087ea7c0, 3:table: 0x044c9508, 4:table: 0x14224b90 (more...)} - (*temporary) = number: 47 - (*temporary) = table: 0x0427d3a8 {handle:function: 0x0427c440, __index:table: 0x0427d3a8, init:function: 0x0427c9a8 (more...)} - (*temporary) = table: 0x0427d3a8 {handle:function: 0x0427c440, __index:table: 0x0427d3a8, init:function: 0x0427c9a8 (more...)} - (*temporary) = boolean: true - (*temporary) = table: 0x04bf7940 {func:function: 0x08650280, trigger:after, delay:0.5} - (*temporary) = string: "attempt to index field 'cry_runarea' (a nil value)" -(4) Lua method 'click' at file 'engine/ui.lua:988' - Local variables: - self = table: 0x04c14ea8 {pixellated_rect:table: 0x08653338, click_offset:table: 0x084a64f0, children:table: 0x04c14ed0 (more...)} -(5) Lua method 'update' at file 'engine/controller.lua:375' - Local variables: - self = table: 0x049daff0 {held_button_times:table: 0x049db8c0, focus_cursor_stack_level:1, snap_cursor_to:table: 0x142e4858 (more...)} - dt = number: 0.00611024 -(6) Lua upvalue 'gameUpdateRef' at file 'game.lua:2866' - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06844500 (more...)} - dt = number: 0.00611024 -(7) Lua upvalue 'upd' at Steamodded file 'src/ui.lua:81' - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06844500 (more...)} - dt = number: 0.00611024 -(8) Lua upvalue 'upd' at file 'main.lua:3934' - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06844500 (more...)} - dt = number: 0.00611024 -(9) Lua upvalue 'upd' at file 'Items/Blinds.lua:1310' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06844500 (more...)} - dt = number: 0.00611024 -(10) Lua upvalue 'upd' at file 'Items/CodeCards.lua:4106' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06844500 (more...)} - dt = number: 0.00611024 -(11) Lua upvalue 'upd' at file 'Items/Decks.lua:429' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06844500 (more...)} - dt = number: 0.00611024 -(12) Lua upvalue 'upd' at file 'Items/MiscJokers.lua:6658' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06844500 (more...)} - dt = number: 0.00611024 -(13) Lua method 'update' at file 'Cryptid.lua:2948' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06844500 (more...)} - dt = number: 0.00611024 -(14) Lua upvalue 'love_update_ref' at file 'main.lua:993' - Local variables: - dt = number: 0.00611024 -(15) Lua upvalue 'oldupd' at file 'main.lua:2796' - Local variables: - dt = number: 0.00611024 -(16) Lua field 'update' at file 'main.lua:3961' - Local variables: - dt = number: 0.00611024 -(17) Lua function '?' at file 'main.lua:931' (best guess) -(18) global C function 'xpcall' -(19) LÖVE function at file 'boot.lua:377' (best guess) - Local variables: - func = Lua function '?' (defined at line 902 of chunk main.lua) - inerror = boolean: true - deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"]) - earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"]) - -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-01-09 18:37:57 :: INFO :: StackTrace :: Additional Context: -Balatro Version: 1.0.1n-FULL -Modded Version: 1.0.0~ALPHA-1220a-STEAMODDED -LÖVE Version: 11.5.0 -Lovely Version: 0.6.0 -Steamodded Mods: - 1: J Cursor by Jie65535, MarioMak967 [ID: JCursor] - 2: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.2, Uses Lovely] - Break Infinity: omeganum - 3: Handy by SleepyG11 [ID: Handy, Version: 1.1.5, Uses Lovely] - 4: Cryptid by MathIsFun_, Cryptid and Balatro Discords [ID: Cryptid, Priority: 1e+299, Version: 0.5.3a, Uses Lovely] -Lovely Mods: diff --git a/lovely/log/lovely-2025.01.09-18.38.18.log b/lovely/log/lovely-2025.01.09-18.38.18.log deleted file mode 100644 index a7454bc..0000000 --- a/lovely/log/lovely-2025.01.09-18.38.18.log +++ /dev/null @@ -1,229 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 129ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-09 18:38:28 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-09 18:38:29 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-09 18:38:29 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-09 18:38:29 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-09 18:38:29 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-09 18:38:29 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-09 18:38:29 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-09 18:38:29 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-09 18:38:29 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-09 18:38:29 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-09 18:38:29 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-09 18:38:29 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-09 18:38:29 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.646 ms -INFO - [G] 2025-01-09 18:38:29 :: INFO :: TIMER :: [0031] Injected Atlas in 784.712 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0025] Injected Sound in 20.795 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0032] Injected Stake in 0.679 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0008] Injected Rarity in 0.024 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.080 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0391] Injected Center in 1.784 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.012 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0027] Injected Blind in 0.044 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0002] Injected Seal in 0.066 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0004] Injected Suit in 0.065 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0013] Injected Rank in 0.067 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.035 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.104 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0031] Injected Challenge in 0.038 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0028] Injected Tag in 0.381 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0009] Injected Sticker in 0.541 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0009] Injected Shader in 55.214 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0020] Injected Achievement in 0.054 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.489 ms -INFO - [G] 2025-01-09 18:38:30 :: INFO :: TIMER :: [0011] Injected Event in 0.014 ms -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'cry_runarea' not instantiated before load -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-01-09 18:38:40 :: ERROR :: StackTrace :: Oops! The game crashed -[SMODS Cryptid "Items/CodeCards.lua"]:4064: attempt to index field 'cry_runarea' (a nil value) -Stack Traceback -=============== -(1) Lua local 'handler' at file 'main.lua:612' - Local variables: - msg = string: "[SMODS Cryptid \"Items/CodeCards.lua\"]:4064: attempt to index field 'cry_runarea' (a nil value)" - (*temporary) = Lua function '?' (defined at line 31 of chunk [SMODS _ "src/logging.lua"]) - (*temporary) = string: "Oops! The game crashed\ -" -(2) LÖVE metamethod at file 'boot.lua:352' - Local variables: - errhand = Lua function '?' (defined at line 598 of chunk main.lua) - handler = Lua function '?' (defined at line 598 of chunk main.lua) -(3) Lua function '?' at file 'Items/CodeCards.lua:4064' (from mod with id Cryptid) (best guess) - Local variables: - e = table: 0x04bcea98 {pixellated_rect:table: 0x045efce8, click_offset:table: 0x0612d750, children:table: 0x04bceb60 (more...)} - (*temporary) = nil - (*temporary) = table: 0x049dc418 {queue_last_processed:10.666666666667, queues:table: 0x049dc440, queue_dt:0.016666666666667 (more...)} - (*temporary) = table: 0x04d35ca8 {start_timer:false, timer:TOTAL, blockable:true, trigger:after, func:function: 0x042731f8 (more...)} - (*temporary) = string: "base" - (*temporary) = nil - (*temporary) = table: 0x04ce3290 {1:table: 0x13e0fa40, 2:table: 0x0f566dd0, 3:table: 0x0c12fc30, 4:table: 0x00c01ba8 (more...)} - (*temporary) = number: 26 - (*temporary) = table: 0x0427d3a8 {handle:function: 0x0427c440, __index:table: 0x0427d3a8, init:function: 0x0427c9a8 (more...)} - (*temporary) = table: 0x0427d3a8 {handle:function: 0x0427c440, __index:table: 0x0427d3a8, init:function: 0x0427c9a8 (more...)} - (*temporary) = boolean: true - (*temporary) = table: 0x04d35c18 {func:function: 0x042731f8, trigger:after, delay:0.5} - (*temporary) = string: "attempt to index field 'cry_runarea' (a nil value)" -(4) Lua method 'click' at file 'engine/ui.lua:988' - Local variables: - self = table: 0x04bcea98 {pixellated_rect:table: 0x045efce8, click_offset:table: 0x0612d750, children:table: 0x04bceb60 (more...)} -(5) Lua method 'update' at file 'engine/controller.lua:375' - Local variables: - self = table: 0x049db088 {held_button_times:table: 0x049db958, focus_cursor_stack_level:1, snap_cursor_to:table: 0x064d6e08 (more...)} - dt = number: 0.0061158 -(6) Lua upvalue 'gameUpdateRef' at file 'game.lua:2866' - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x060805e0 (more...)} - dt = number: 0.0061158 -(7) Lua upvalue 'upd' at Steamodded file 'src/ui.lua:81' - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x060805e0 (more...)} - dt = number: 0.0061158 -(8) Lua upvalue 'upd' at file 'main.lua:3934' - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x060805e0 (more...)} - dt = number: 0.0061158 -(9) Lua upvalue 'upd' at file 'Items/Blinds.lua:1310' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x060805e0 (more...)} - dt = number: 0.0061158 -(10) Lua upvalue 'upd' at file 'Items/CodeCards.lua:4106' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x060805e0 (more...)} - dt = number: 0.0061158 -(11) Lua upvalue 'upd' at file 'Items/Decks.lua:429' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x060805e0 (more...)} - dt = number: 0.0061158 -(12) Lua upvalue 'upd' at file 'Items/MiscJokers.lua:6658' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x060805e0 (more...)} - dt = number: 0.0061158 -(13) Lua method 'update' at file 'Cryptid.lua:2948' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x060805e0 (more...)} - dt = number: 0.0061158 -(14) Lua upvalue 'love_update_ref' at file 'main.lua:993' - Local variables: - dt = number: 0.0061158 -(15) Lua upvalue 'oldupd' at file 'main.lua:2796' - Local variables: - dt = number: 0.0061158 -(16) Lua field 'update' at file 'main.lua:3961' - Local variables: - dt = number: 0.0061158 -(17) Lua function '?' at file 'main.lua:931' (best guess) -(18) global C function 'xpcall' -(19) LÖVE function at file 'boot.lua:377' (best guess) - Local variables: - func = Lua function '?' (defined at line 902 of chunk main.lua) - inerror = boolean: true - deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"]) - earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"]) - -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-01-09 18:38:40 :: INFO :: StackTrace :: Additional Context: -Balatro Version: 1.0.1n-FULL -Modded Version: 1.0.0~ALPHA-1220a-STEAMODDED -LÖVE Version: 11.5.0 -Lovely Version: 0.6.0 -Steamodded Mods: - 1: J Cursor by Jie65535, MarioMak967 [ID: JCursor] - 2: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.2, Uses Lovely] - Break Infinity: omeganum - 3: Handy by SleepyG11 [ID: Handy, Version: 1.1.5, Uses Lovely] - 4: Cryptid by MathIsFun_, Cryptid and Balatro Discords [ID: Cryptid, Priority: 1e+299, Version: 0.5.3a, Uses Lovely] -Lovely Mods: diff --git a/lovely/log/lovely-2025.01.09-18.39.03.log b/lovely/log/lovely-2025.01.09-18.39.03.log deleted file mode 100644 index 585d698..0000000 --- a/lovely/log/lovely-2025.01.09-18.39.03.log +++ /dev/null @@ -1,229 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 154ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-09 18:39:07 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-09 18:39:08 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-09 18:39:08 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-09 18:39:08 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-09 18:39:08 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-09 18:39:08 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-09 18:39:08 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-09 18:39:08 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-09 18:39:08 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-09 18:39:08 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-09 18:39:08 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-09 18:39:08 :: INFO :: TIMER :: [0000] Injected Language in 0.002 ms -INFO - [G] 2025-01-09 18:39:08 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.721 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0031] Injected Atlas in 775.306 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0025] Injected Sound in 19.414 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0032] Injected Stake in 0.587 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0008] Injected Rarity in 0.023 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.041 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0391] Injected Center in 1.826 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.011 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0027] Injected Blind in 0.042 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0002] Injected Seal in 0.054 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0004] Injected Suit in 0.076 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0013] Injected Rank in 0.064 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.059 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.089 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0031] Injected Challenge in 0.162 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0028] Injected Tag in 0.252 ms -INFO - [G] 2025-01-09 18:39:09 :: INFO :: TIMER :: [0009] Injected Sticker in 0.549 ms -INFO - [G] 2025-01-09 18:39:10 :: INFO :: TIMER :: [0009] Injected Shader in 826.031 ms -INFO - [G] 2025-01-09 18:39:10 :: INFO :: TIMER :: [0000] Injected Keybind in 0.002 ms -INFO - [G] 2025-01-09 18:39:10 :: INFO :: TIMER :: [0020] Injected Achievement in 0.057 ms -INFO - [G] 2025-01-09 18:39:10 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.632 ms -INFO - [G] 2025-01-09 18:39:10 :: INFO :: TIMER :: [0011] Injected Event in 0.021 ms -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'cry_runarea' not instantiated before load -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-01-09 18:39:47 :: ERROR :: StackTrace :: Oops! The game crashed -[SMODS Cryptid "Items/CodeCards.lua"]:4064: attempt to index field 'cry_runarea' (a nil value) -Stack Traceback -=============== -(1) Lua local 'handler' at file 'main.lua:612' - Local variables: - msg = string: "[SMODS Cryptid \"Items/CodeCards.lua\"]:4064: attempt to index field 'cry_runarea' (a nil value)" - (*temporary) = Lua function '?' (defined at line 31 of chunk [SMODS _ "src/logging.lua"]) - (*temporary) = string: "Oops! The game crashed\ -" -(2) LÖVE metamethod at file 'boot.lua:352' - Local variables: - errhand = Lua function '?' (defined at line 598 of chunk main.lua) - handler = Lua function '?' (defined at line 598 of chunk main.lua) -(3) Lua function '?' at file 'Items/CodeCards.lua:4064' (from mod with id Cryptid) (best guess) - Local variables: - e = table: 0x0bb5a048 {pixellated_rect:table: 0x05ff8d90, click_offset:table: 0x086fee90, children:table: 0x0bb5a070 (more...)} - (*temporary) = nil - (*temporary) = table: 0x046d5af0 {queue_last_processed:37.833333333332, queues:table: 0x046d5b18, queue_dt:0.016666666666667 (more...)} - (*temporary) = table: 0x086092e8 {start_timer:false, timer:TOTAL, blockable:true, trigger:after, func:function: 0x086092c8 (more...)} - (*temporary) = string: "base" - (*temporary) = nil - (*temporary) = table: 0x046d5b68 {1:table: 0x0f8e4190, 2:table: 0x1428ec78, 3:table: 0x08608d60, 4:table: 0x08609088 (more...)} - (*temporary) = number: 5 - (*temporary) = table: 0x0427d3a8 {handle:function: 0x0427c440, __index:table: 0x0427d3a8, init:function: 0x0427c9a8 (more...)} - (*temporary) = table: 0x0427d3a8 {handle:function: 0x0427c440, __index:table: 0x0427d3a8, init:function: 0x0427c9a8 (more...)} - (*temporary) = boolean: true - (*temporary) = table: 0x08609238 {func:function: 0x086092c8, trigger:after, delay:0.5} - (*temporary) = string: "attempt to index field 'cry_runarea' (a nil value)" -(4) Lua method 'click' at file 'engine/ui.lua:988' - Local variables: - self = table: 0x0bb5a048 {pixellated_rect:table: 0x05ff8d90, click_offset:table: 0x086fee90, children:table: 0x0bb5a070 (more...)} -(5) Lua method 'update' at file 'engine/controller.lua:375' - Local variables: - self = table: 0x049cf9e0 {held_button_times:table: 0x049cf5b8, focus_cursor_stack_level:1, snap_cursor_to:table: 0x08a999e0 (more...)} - dt = number: 0.00612002 -(6) Lua upvalue 'gameUpdateRef' at file 'game.lua:2866' - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0bf67978 (more...)} - dt = number: 0.00612002 -(7) Lua upvalue 'upd' at Steamodded file 'src/ui.lua:81' - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0bf67978 (more...)} - dt = number: 0.00612002 -(8) Lua upvalue 'upd' at file 'main.lua:3934' - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0bf67978 (more...)} - dt = number: 0.00612002 -(9) Lua upvalue 'upd' at file 'Items/Blinds.lua:1310' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0bf67978 (more...)} - dt = number: 0.00612002 -(10) Lua upvalue 'upd' at file 'Items/CodeCards.lua:4106' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0bf67978 (more...)} - dt = number: 0.00612002 -(11) Lua upvalue 'upd' at file 'Items/Decks.lua:429' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0bf67978 (more...)} - dt = number: 0.00612002 -(12) Lua upvalue 'upd' at file 'Items/MiscJokers.lua:6658' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0bf67978 (more...)} - dt = number: 0.00612002 -(13) Lua method 'update' at file 'Cryptid.lua:2948' (from mod with id Cryptid) - Local variables: - self = table: 0x042f89c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0bf67978 (more...)} - dt = number: 0.00612002 -(14) Lua upvalue 'love_update_ref' at file 'main.lua:993' - Local variables: - dt = number: 0.00612002 -(15) Lua upvalue 'oldupd' at file 'main.lua:2796' - Local variables: - dt = number: 0.00612002 -(16) Lua field 'update' at file 'main.lua:3961' - Local variables: - dt = number: 0.00612002 -(17) Lua function '?' at file 'main.lua:931' (best guess) -(18) global C function 'xpcall' -(19) LÖVE function at file 'boot.lua:377' (best guess) - Local variables: - func = Lua function '?' (defined at line 902 of chunk main.lua) - inerror = boolean: true - deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"]) - earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"]) - -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-01-09 18:39:47 :: INFO :: StackTrace :: Additional Context: -Balatro Version: 1.0.1n-FULL -Modded Version: 1.0.0~ALPHA-1220a-STEAMODDED -LÖVE Version: 11.5.0 -Lovely Version: 0.6.0 -Steamodded Mods: - 1: J Cursor by Jie65535, MarioMak967 [ID: JCursor] - 2: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.2, Uses Lovely] - Break Infinity: omeganum - 3: Handy by SleepyG11 [ID: Handy, Version: 1.1.5, Uses Lovely] - 4: Cryptid by MathIsFun_, Cryptid and Balatro Discords [ID: Cryptid, Priority: 1e+299, Version: 0.5.3a, Uses Lovely] -Lovely Mods: diff --git a/lovely/log/lovely-2025.01.09-18.40.11.log b/lovely/log/lovely-2025.01.09-18.40.11.log deleted file mode 100644 index ff2f793..0000000 --- a/lovely/log/lovely-2025.01.09-18.40.11.log +++ /dev/null @@ -1,121 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 131ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-09 18:40:15 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-09 18:40:16 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-09 18:40:16 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-09 18:40:16 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-09 18:40:16 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-09 18:40:16 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-09 18:40:16 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-09 18:40:16 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-09 18:40:16 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-09 18:40:16 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-09 18:40:16 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-09 18:40:16 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-09 18:40:16 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.653 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0031] Injected Atlas in 777.138 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0025] Injected Sound in 20.617 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0032] Injected Stake in 1.267 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0008] Injected Rarity in 0.028 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.081 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0391] Injected Center in 2.667 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.012 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0027] Injected Blind in 0.059 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0002] Injected Seal in 0.054 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0004] Injected Suit in 0.079 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0013] Injected Rank in 0.059 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.030 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.104 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0031] Injected Challenge in 0.044 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0028] Injected Tag in 0.395 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0009] Injected Sticker in 0.066 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0009] Injected Shader in 53.614 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0020] Injected Achievement in 0.069 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.516 ms -INFO - [G] 2025-01-09 18:40:17 :: INFO :: TIMER :: [0011] Injected Event in 0.082 ms -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load diff --git a/lovely/log/lovely-2025.01.09-21.35.12.log b/lovely/log/lovely-2025.01.09-21.35.12.log deleted file mode 100644 index 8b2cb08..0000000 --- a/lovely/log/lovely-2025.01.09-21.35.12.log +++ /dev/null @@ -1,461 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 130ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-09 21:35:17 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-09 21:35:18 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-09 21:35:18 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-09 21:35:18 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-09 21:35:18 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-09 21:35:18 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-09 21:35:18 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-09 21:35:18 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-09 21:35:18 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-09 21:35:18 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-09 21:35:18 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.652 ms -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0031] Injected Atlas in 787.294 ms -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0025] Injected Sound in 22.890 ms -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0032] Injected Stake in 0.749 ms -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0008] Injected Rarity in 0.027 ms -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.125 ms -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0391] Injected Center in 2.057 ms -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.010 ms -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0027] Injected Blind in 0.054 ms -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0002] Injected Seal in 0.050 ms -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0004] Injected Suit in 0.081 ms -INFO - [G] 2025-01-09 21:35:18 :: INFO :: TIMER :: [0013] Injected Rank in 0.128 ms -INFO - [G] 2025-01-09 21:35:19 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.045 ms -INFO - [G] 2025-01-09 21:35:19 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.107 ms -INFO - [G] 2025-01-09 21:35:19 :: INFO :: TIMER :: [0031] Injected Challenge in 0.191 ms -INFO - [G] 2025-01-09 21:35:19 :: INFO :: TIMER :: [0028] Injected Tag in 0.373 ms -INFO - [G] 2025-01-09 21:35:19 :: INFO :: TIMER :: [0009] Injected Sticker in 0.717 ms -INFO - [G] 2025-01-09 21:35:19 :: INFO :: TIMER :: [0009] Injected Shader in 61.765 ms -INFO - [G] 2025-01-09 21:35:19 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-09 21:35:19 :: INFO :: TIMER :: [0020] Injected Achievement in 0.070 ms -INFO - [G] 2025-01-09 21:35:19 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 3.712 ms -INFO - [G] 2025-01-09 21:35:19 :: INFO :: TIMER :: [0011] Injected Event in 0.015 ms -INFO - [G] LONG DT @ 420: 0.1 -INFO - [G] LONG DT @ 420: 0.1 -INFO - [G] LONG DT @ 420: 0.1 -INFO - [G] LONG DT @ 420: 0.1 -INFO - [G] LONG DT @ 420: 0.1 -INFO - [G] LONG DT @ 420: 0.1 -INFO - [G] LONG DT @ 421: 0.1 -INFO - [G] LONG DT @ 421: 0.087805280000002 -INFO - [G] LONG DT @ 421: 0.072251723999992 -INFO - [G] LONG DT @ 421: 0.059350199199999 -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:11 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:51 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] 2025-01-09 21:58:53 :: WARN :: Blind :: Blind object bl_cry_obsidian_orb has debuff_card function, recalc_debuff is preferred -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 17: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 18: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 19: 0.1 -INFO - [G] LONG DT @ 20: 0.1 -INFO - [G] LONG DT @ 20: 0.1 -INFO - [G] LONG DT @ 20: 0.1 -INFO - [G] LONG DT @ 20: 0.1 -INFO - [G] LONG DT @ 20: 0.1 -INFO - [G] LONG DT @ 20: 0.1 -INFO - [G] LONG DT @ 20: 0.1 -INFO - [G] LONG DT @ 20: 0.1 -INFO - [G] LONG DT @ 20: 0.1 -INFO - [G] LONG DT @ 20: 0.1 -INFO - [G] LONG DT @ 21: 0.1 -INFO - [G] LONG DT @ 21: 0.1 -INFO - [G] LONG DT @ 21: 0.1 -INFO - [G] LONG DT @ 21: 0.1 -INFO - [G] LONG DT @ 21: 0.1 -INFO - [G] LONG DT @ 21: 0.1 -INFO - [G] LONG DT @ 21: 0.1 -INFO - [G] LONG DT @ 21: 0.1 -INFO - [G] LONG DT @ 21: 0.1 -INFO - [G] LONG DT @ 21: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 24: 0.081568279999992 -INFO - [G] LONG DT @ 24: 0.066641264000004 -INFO - [G] LONG DT @ 24: 0.054512091199972 diff --git a/lovely/log/lovely-2025.01.10-02.26.25.log b/lovely/log/lovely-2025.01.10-02.26.25.log deleted file mode 100644 index ba5dd26..0000000 --- a/lovely/log/lovely-2025.01.10-02.26.25.log +++ /dev/null @@ -1,257 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 170ms -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 16 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 4 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 45 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 75 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -INFO - [♥] Applied 6 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 97 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 123 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 51 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 205 patches to 'card.lua' -INFO - [♥] Applied 15 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-10 02:26:26 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-10 02:26:28 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-10 02:26:28 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-10 02:26:28 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-10 02:26:28 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-10 02:26:28 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-10 02:26:28 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-10 02:26:28 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-10 02:26:28 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-10 02:26:28 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-10 02:26:28 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-10 02:26:28 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-10 02:26:28 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 1.030 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0031] Injected Atlas in 784.296 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0025] Injected Sound in 262.659 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0032] Injected Stake in 0.639 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0008] Injected Rarity in 0.021 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.035 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0391] Injected Center in 1.662 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.008 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0027] Injected Blind in 0.043 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0002] Injected Seal in 0.033 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0004] Injected Suit in 0.075 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0013] Injected Rank in 0.039 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.033 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.091 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0031] Injected Challenge in 0.036 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0028] Injected Tag in 0.408 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0009] Injected Sticker in 0.273 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0009] Injected Shader in 61.561 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0020] Injected Achievement in 0.054 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 4.248 ms -INFO - [G] 2025-01-10 02:26:29 :: INFO :: TIMER :: [0011] Injected Event in 0.012 ms -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 22: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 23: 0.1 -INFO - [G] LONG DT @ 24: 0.1 -INFO - [G] LONG DT @ 24: 0.1 -INFO - [G] LONG DT @ 24: 0.1 -INFO - [G] LONG DT @ 24: 0.1 -INFO - [G] LONG DT @ 24: 0.1 -INFO - [G] LONG DT @ 24: 0.1 -INFO - [G] LONG DT @ 24: 0.1 -INFO - [G] LONG DT @ 24: 0.1 -INFO - [G] LONG DT @ 24: 0.1 -INFO - [G] LONG DT @ 24: 0.1 -INFO - [G] LONG DT @ 25: 0.1 -INFO - [G] LONG DT @ 25: 0.1 -INFO - [G] LONG DT @ 25: 0.1 -INFO - [G] LONG DT @ 25: 0.1 -INFO - [G] LONG DT @ 25: 0.1 -INFO - [G] LONG DT @ 25: 0.1 -INFO - [G] LONG DT @ 25: 0.1 -INFO - [G] LONG DT @ 25: 0.1 -INFO - [G] LONG DT @ 25: 0.1 -INFO - [G] LONG DT @ 25: 0.1 -INFO - [G] LONG DT @ 26: 0.1 -INFO - [G] LONG DT @ 26: 0.1 -INFO - [G] LONG DT @ 26: 0.1 -INFO - [G] LONG DT @ 26: 0.1 -INFO - [G] LONG DT @ 26: 0.1 -INFO - [G] LONG DT @ 26: 0.1 -INFO - [G] LONG DT @ 26: 0.1 -INFO - [G] LONG DT @ 26: 0.1 -INFO - [G] LONG DT @ 26: 0.1 -INFO - [G] LONG DT @ 26: 0.1 -INFO - [G] LONG DT @ 27: 0.1 -INFO - [G] LONG DT @ 27: 0.1 -INFO - [G] LONG DT @ 27: 0.1 -INFO - [G] LONG DT @ 27: 0.1 -INFO - [G] LONG DT @ 27: 0.1 -INFO - [G] LONG DT @ 27: 0.1 -INFO - [G] LONG DT @ 27: 0.1 -INFO - [G] LONG DT @ 27: 0.1 -INFO - [G] LONG DT @ 27: 0.1 -INFO - [G] LONG DT @ 27: 0.1 -INFO - [G] LONG DT @ 28: 0.1 -INFO - [G] LONG DT @ 28: 0.1 -INFO - [G] LONG DT @ 28: 0.1 -INFO - [G] LONG DT @ 28: 0.1 -INFO - [G] LONG DT @ 28: 0.1 -INFO - [G] LONG DT @ 28: 0.1 -INFO - [G] LONG DT @ 28: 0.1 -INFO - [G] LONG DT @ 28: 0.1 -INFO - [G] LONG DT @ 28: 0.1 -INFO - [G] LONG DT @ 28: 0.1 -INFO - [G] LONG DT @ 29: 0.1 -INFO - [G] LONG DT @ 29: 0.1 -INFO - [G] LONG DT @ 29: 0.1 -INFO - [G] LONG DT @ 29: 0.1 -INFO - [G] LONG DT @ 29: 0.1 -INFO - [G] LONG DT @ 29: 0.1 -INFO - [G] LONG DT @ 29: 0.1 -INFO - [G] LONG DT @ 29: 0.1 -INFO - [G] LONG DT @ 29: 0.1 -INFO - [G] LONG DT @ 29: 0.1 -INFO - [G] LONG DT @ 30: 0.1 -INFO - [G] LONG DT @ 30: 0.1 -INFO - [G] LONG DT @ 30: 0.1 -INFO - [G] LONG DT @ 30: 0.1 -INFO - [G] LONG DT @ 30: 0.1 -INFO - [G] LONG DT @ 30: 0.1 -INFO - [G] LONG DT @ 30: 0.1 -INFO - [G] LONG DT @ 30: 0.1 -INFO - [G] LONG DT @ 30: 0.1 -INFO - [G] LONG DT @ 30: 0.1 -INFO - [G] LONG DT @ 31: 0.1 -INFO - [G] LONG DT @ 31: 0.1 -INFO - [G] LONG DT @ 31: 0.1 -INFO - [G] LONG DT @ 31: 0.1 -INFO - [G] LONG DT @ 31: 0.1 -INFO - [G] LONG DT @ 31: 0.1 -INFO - [G] LONG DT @ 31: 0.1 -INFO - [G] LONG DT @ 31: 0.1 -INFO - [G] LONG DT @ 31: 0.1 -INFO - [G] LONG DT @ 31: 0.1 -INFO - [G] LONG DT @ 32: 0.1 -INFO - [G] LONG DT @ 32: 0.1 -INFO - [G] LONG DT @ 32: 0.1 -INFO - [G] LONG DT @ 32: 0.1 -INFO - [G] LONG DT @ 32: 0.1 -INFO - [G] LONG DT @ 32: 0.1 -INFO - [G] LONG DT @ 32: 0.1 -INFO - [G] LONG DT @ 32: 0.1 -INFO - [G] LONG DT @ 32: 0.1 -INFO - [G] LONG DT @ 32: 0.1 -INFO - [G] LONG DT @ 33: 0.1 -INFO - [G] LONG DT @ 33: 0.1 -INFO - [G] LONG DT @ 33: 0.1 -INFO - [G] LONG DT @ 33: 0.1 -INFO - [G] LONG DT @ 33: 0.1 -INFO - [G] LONG DT @ 33: 0.1 -INFO - [G] LONG DT @ 33: 0.1 -INFO - [G] LONG DT @ 33: 0.1 -INFO - [G] LONG DT @ 33: 0.1 -INFO - [G] LONG DT @ 33: 0.1 -INFO - [G] LONG DT @ 34: 0.1 -INFO - [G] LONG DT @ 34: 0.1 -INFO - [G] LONG DT @ 34: 0.1 -INFO - [G] LONG DT @ 34: 0.1 -INFO - [G] LONG DT @ 34: 0.1 -INFO - [G] LONG DT @ 34: 0.1 -INFO - [G] LONG DT @ 34: 0.1 -INFO - [G] LONG DT @ 34: 0.1 -INFO - [G] LONG DT @ 34: 0.1 -INFO - [G] LONG DT @ 34: 0.1 -INFO - [G] LONG DT @ 35: 0.1 -INFO - [G] LONG DT @ 35: 0.1 -INFO - [G] LONG DT @ 35: 0.1 -INFO - [G] LONG DT @ 35: 0.081521959999997 -INFO - [G] LONG DT @ 35: 0.066589188000001 -INFO - [G] LONG DT @ 35: 0.054426990399997 diff --git a/lovely/log/lovely-2025.01.10-14.30.56.log b/lovely/log/lovely-2025.01.10-14.30.56.log deleted file mode 100644 index 1c65396..0000000 --- a/lovely/log/lovely-2025.01.10-14.30.56.log +++ /dev/null @@ -1,227 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 212ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -WARN - [♥] Pattern 'if not _RELEASE_MODE then' on target 'engine/controller.lua' resulted in no matches -INFO - [♥] Applied 10 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-10 14:30:58 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-10 14:30:59 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-10 14:30:59 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-10 14:30:59 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-10 14:30:59 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-10 14:30:59 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-10 14:30:59 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-10 14:30:59 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-10 14:30:59 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-10 14:30:59 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-10 14:30:59 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-10 14:30:59 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-10 14:30:59 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-10 14:30:59 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-10 14:30:59 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-10 14:30:59 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-10 14:30:59 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-10 14:30:59 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 1.066 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0032] Injected Atlas in 856.949 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0025] Injected Sound in 283.071 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0032] Injected Stake in 0.753 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0008] Injected Rarity in 0.026 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.060 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0392] Injected Center in 1.683 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.009 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0027] Injected Blind in 0.041 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0002] Injected Seal in 0.040 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0004] Injected Suit in 0.070 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0013] Injected Rank in 0.036 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.027 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.051 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0031] Injected Challenge in 0.124 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0028] Injected Tag in 0.193 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0009] Injected Sticker in 0.577 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0009] Injected Shader in 53.226 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0020] Injected Achievement in 0.058 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.991 ms -INFO - [G] 2025-01-10 14:31:00 :: INFO :: TIMER :: [0011] Injected Event in 0.013 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] > help -INFO - [G] < Help: -Below is a list of commands. -echo: Repeat's what you say -help: Get command info -eval: Evaluate lua code -money: Set or add money -round: Set or add to your round -ante: Set or add to your ante -discards: Set or add to your hand -hands: Set or add to your hand -watch: Watch and execute a file when it changes. -tutorial: Modify the tutorial state. -resetshop: Reset the shop. -value: Get and modify highlighted card values - -For more information about a specific command, run 'help ' -INFO - [G] > help -INFO - [G] < Help: -Below is a list of commands. -echo: Repeat's what you say -help: Get command info -eval: Evaluate lua code -money: Set or add money -round: Set or add to your round -ante: Set or add to your ante -discards: Set or add to your hand -hands: Set or add to your hand -watch: Watch and execute a file when it changes. -tutorial: Modify the tutorial state. -resetshop: Reset the shop. -value: Get and modify highlighted card values - -For more information about a specific command, run 'help ' -INFO - [G] > echo your mother i -INFO - [G] < your mother i -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] 2025-01-10 14:35:55 :: INFO :: TIMER :: [0000] Injected Language in 0.002 ms -INFO - [G] 2025-01-10 14:35:55 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 11.872 ms -INFO - [G] 2025-01-10 14:35:55 :: INFO :: TIMER :: [0032] Injected Atlas in 753.511 ms -INFO - [G] 2025-01-10 14:35:55 :: INFO :: TIMER :: [0025] Injected Sound in 18.633 ms -INFO - [G] 2025-01-10 14:35:55 :: INFO :: TIMER :: [0032] Injected Stake in 0.188 ms -INFO - [G] 2025-01-10 14:35:55 :: INFO :: TIMER :: [0008] Injected Rarity in 0.022 ms -INFO - [G] 2025-01-10 14:35:55 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.036 ms -INFO - [G] 2025-01-10 14:35:55 :: INFO :: TIMER :: [0392] Injected Center in 1.311 ms -INFO - [G] 2025-01-10 14:35:55 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.007 ms -INFO - [G] 2025-01-10 14:35:55 :: INFO :: TIMER :: [0027] Injected Blind in 0.031 ms -INFO - [G] 2025-01-10 14:35:55 :: INFO :: TIMER :: [0002] Injected Seal in 0.038 ms -INFO - [G] 2025-01-10 14:35:55 :: INFO :: TIMER :: [0004] Injected Suit in 0.046 ms -INFO - [G] 2025-01-10 14:35:56 :: INFO :: TIMER :: [0013] Injected Rank in 0.123 ms -INFO - [G] 2025-01-10 14:35:56 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.019 ms -INFO - [G] 2025-01-10 14:35:56 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.037 ms -INFO - [G] 2025-01-10 14:35:56 :: INFO :: TIMER :: [0031] Injected Challenge in 0.066 ms -INFO - [G] 2025-01-10 14:35:56 :: INFO :: TIMER :: [0028] Injected Tag in 0.032 ms -INFO - [G] 2025-01-10 14:35:56 :: INFO :: TIMER :: [0009] Injected Sticker in 0.061 ms -INFO - [G] 2025-01-10 14:35:56 :: INFO :: TIMER :: [0009] Injected Shader in 84.833 ms -INFO - [G] 2025-01-10 14:35:56 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-10 14:35:56 :: INFO :: TIMER :: [0020] Injected Achievement in 0.067 ms -INFO - [G] 2025-01-10 14:35:56 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 28.154 ms -INFO - [G] 2025-01-10 14:35:56 :: INFO :: TIMER :: [0011] Injected Event in 0.011 ms -INFO - [G] > help -INFO - [G] < Help: -Below is a list of commands. -echo: Repeat's what you say -help: Get command info -eval: Evaluate lua code -money: Set or add money -round: Set or add to your round -ante: Set or add to your ante -discards: Set or add to your hand -hands: Set or add to your hand -watch: Watch and execute a file when it changes. -tutorial: Modify the tutorial state. -resetshop: Reset the shop. -value: Get and modify highlighted card values - -For more information about a specific command, run 'help ' -INFO - [G] > value -INFO - [G] < This command only works while hovering over a card. Rerun it while hovering over a card. -INFO - [G] > value -INFO - [G] < Invalid argument. Use 'get' or 'set' or 'set_center'. -INFO - [G] > value get -INFO - [G] < Values: -extra money 3 -hands_played_at_create 27 -INFO - [G] > value set -INFO - [G] < Please provide a key to set -INFO - [G] > value set extra money 100 -INFO - [G] < Value set successfully. -INFO - [G] > value get -INFO - [G] < This command only works while hovering over a card. Rerun it while hovering over a card. -INFO - [G] > value get -INFO - [G] < Values: -extra 25 -hands_played_at_create 27 diff --git a/lovely/log/lovely-2025.01.10-14.42.50.log b/lovely/log/lovely-2025.01.10-14.42.50.log deleted file mode 100644 index dd9b05e..0000000 --- a/lovely/log/lovely-2025.01.10-14.42.50.log +++ /dev/null @@ -1,154 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 139ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-10 14:42:52 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-10 14:42:53 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-10 14:42:53 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-10 14:42:53 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-10 14:42:53 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-10 14:42:53 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-10 14:42:53 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-10 14:42:53 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-10 14:42:53 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-10 14:42:53 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-10 14:42:53 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-10 14:42:53 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-10 14:42:53 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-10 14:42:53 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-10 14:42:53 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-10 14:42:53 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-10 14:42:53 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-10 14:42:53 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.691 ms -INFO - [G] 2025-01-10 14:42:53 :: INFO :: TIMER :: [0032] Injected Atlas in 752.222 ms -INFO - [G] 2025-01-10 14:42:53 :: INFO :: TIMER :: [0025] Injected Sound in 19.123 ms -INFO - [G] 2025-01-10 14:42:53 :: INFO :: TIMER :: [0032] Injected Stake in 0.529 ms -INFO - [G] 2025-01-10 14:42:53 :: INFO :: TIMER :: [0008] Injected Rarity in 0.022 ms -INFO - [G] 2025-01-10 14:42:53 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.052 ms -INFO - [G] 2025-01-10 14:42:53 :: INFO :: TIMER :: [0392] Injected Center in 1.952 ms -INFO - [G] 2025-01-10 14:42:53 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.011 ms -INFO - [G] 2025-01-10 14:42:53 :: INFO :: TIMER :: [0027] Injected Blind in 0.051 ms -INFO - [G] 2025-01-10 14:42:53 :: INFO :: TIMER :: [0002] Injected Seal in 0.107 ms -INFO - [G] 2025-01-10 14:42:53 :: INFO :: TIMER :: [0004] Injected Suit in 0.056 ms -INFO - [G] 2025-01-10 14:42:54 :: INFO :: TIMER :: [0013] Injected Rank in 0.055 ms -INFO - [G] 2025-01-10 14:42:54 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.038 ms -INFO - [G] 2025-01-10 14:42:54 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.077 ms -INFO - [G] 2025-01-10 14:42:54 :: INFO :: TIMER :: [0031] Injected Challenge in 0.152 ms -INFO - [G] 2025-01-10 14:42:54 :: INFO :: TIMER :: [0028] Injected Tag in 0.308 ms -INFO - [G] 2025-01-10 14:42:54 :: INFO :: TIMER :: [0009] Injected Sticker in 0.805 ms -INFO - [G] 2025-01-10 14:42:54 :: INFO :: TIMER :: [0009] Injected Shader in 57.027 ms -INFO - [G] 2025-01-10 14:42:54 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-10 14:42:54 :: INFO :: TIMER :: [0020] Injected Achievement in 0.126 ms -INFO - [G] 2025-01-10 14:42:54 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 7.196 ms -INFO - [G] 2025-01-10 14:42:54 :: INFO :: TIMER :: [0011] Injected Event in 0.033 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 9.458 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0032] Injected Atlas in 742.288 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0025] Injected Sound in 16.892 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0032] Injected Stake in 0.281 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0008] Injected Rarity in 0.016 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.034 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0392] Injected Center in 1.403 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.007 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0027] Injected Blind in 0.034 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0002] Injected Seal in 0.046 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0004] Injected Suit in 0.063 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0013] Injected Rank in 0.059 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.171 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.040 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0031] Injected Challenge in 0.053 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0028] Injected Tag in 0.108 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0009] Injected Sticker in 1.012 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0009] Injected Shader in 109.197 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0020] Injected Achievement in 0.104 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 37.331 ms -INFO - [G] 2025-01-10 15:00:39 :: INFO :: TIMER :: [0011] Injected Event in 0.011 ms diff --git a/lovely/log/lovely-2025.01.10-20.43.00.log b/lovely/log/lovely-2025.01.10-20.43.00.log deleted file mode 100644 index e2e0c07..0000000 --- a/lovely/log/lovely-2025.01.10-20.43.00.log +++ /dev/null @@ -1,128 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 138ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-10 20:43:02 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-10 20:43:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-10 20:43:03 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-10 20:43:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-10 20:43:03 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-10 20:43:03 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-10 20:43:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-10 20:43:03 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-10 20:43:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-10 20:43:03 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-10 20:43:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-10 20:43:03 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-10 20:43:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-10 20:43:03 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-10 20:43:03 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-10 20:43:03 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-10 20:43:03 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-10 20:43:03 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.782 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0032] Injected Atlas in 809.700 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0025] Injected Sound in 25.339 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0032] Injected Stake in 0.825 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0008] Injected Rarity in 0.026 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.060 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0392] Injected Center in 2.641 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.009 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0027] Injected Blind in 0.447 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0002] Injected Seal in 0.057 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0004] Injected Suit in 0.082 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0013] Injected Rank in 0.103 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.033 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.204 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0031] Injected Challenge in 0.139 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0028] Injected Tag in 0.614 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0009] Injected Sticker in 0.495 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0009] Injected Shader in 139.276 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0000] Injected Keybind in 0.002 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0020] Injected Achievement in 0.078 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.753 ms -INFO - [G] 2025-01-10 20:43:04 :: INFO :: TIMER :: [0011] Injected Event in 0.015 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews diff --git a/lovely/log/lovely-2025.01.10-21.28.54.log b/lovely/log/lovely-2025.01.10-21.28.54.log deleted file mode 100644 index 6c6e603..0000000 --- a/lovely/log/lovely-2025.01.10-21.28.54.log +++ /dev/null @@ -1,241 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 149ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-10 21:28:56 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-10 21:28:57 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-10 21:28:57 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-10 21:28:57 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-10 21:28:57 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-10 21:28:57 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-10 21:28:57 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-10 21:28:57 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-10 21:28:57 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-10 21:28:57 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-10 21:28:57 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-10 21:28:57 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-10 21:28:57 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-10 21:28:57 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-10 21:28:57 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-10 21:28:57 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-10 21:28:57 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-10 21:28:57 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.662 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0032] Injected Atlas in 774.183 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0025] Injected Sound in 19.506 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0032] Injected Stake in 0.551 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0008] Injected Rarity in 0.024 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.052 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0392] Injected Center in 1.775 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.010 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0027] Injected Blind in 0.061 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0002] Injected Seal in 0.048 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0004] Injected Suit in 0.057 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0013] Injected Rank in 0.063 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.035 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.088 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0031] Injected Challenge in 0.155 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0028] Injected Tag in 0.293 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0009] Injected Sticker in 0.608 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0009] Injected Shader in 54.808 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0020] Injected Achievement in 0.099 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.453 ms -INFO - [G] 2025-01-10 21:28:58 :: INFO :: TIMER :: [0011] Injected Event in 0.013 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] > help -INFO - [G] < Help: -Below is a list of commands. -echo: Repeat's what you say -help: Get command info -eval: Evaluate lua code -money: Set or add money -round: Set or add to your round -ante: Set or add to your ante -discards: Set or add to your hand -hands: Set or add to your hand -watch: Watch and execute a file when it changes. -tutorial: Modify the tutorial state. -resetshop: Reset the shop. -value: Get and modify highlighted card values - -For more information about a specific command, run 'help ' -INFO - [G] > value get -INFO - [G] < Values: -extra Emult 1 -extra Emult_mod 0.03 -INFO - [G] > value set 9999999 -INFO - [G] < Please provide a value to set -INFO - [G] > value set Emult 9 -INFO - [G] < Value set successfully. -INFO - [G] > value get -INFO - [G] < Values: -extra Emult 1 -extra Emult_mod 0.03 -Emult 9 -INFO - [G] > value set extra Emult 999999999999999 -INFO - [G] < Value set successfully. -INFO - [G] > value set emult 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 -INFO - [G] < Value set successfully. -INFO - [G] > value get -INFO - [G] < Values: -emult 1e+301 -extra Emult 1e+15 -extra Emult_mod 0.03 -Emult 9 -INFO - [G] > value set extra Emult 1e+999 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra Emult 1e+308 -INFO - [G] < This command only works while hovering over a card. Rerun it while hovering over a card. -INFO - [G] > value set extra Emult 1e+300 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra Emult 1e+301 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra Emult 1e+302 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra Emult 1e+307 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra Emult 1e+308 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra Emult 1e+3010 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra Emult 1e+300 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra Emult 1e+400 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra Emult 1e+308 -INFO - [G] < This command only works while hovering over a card. Rerun it while hovering over a card. -INFO - [G] > value set extra Emult 1e+308 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra Emult 1e+309 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra Emult 1e+308 -INFO - [G] < Value set successfully. -INFO - [G] > value get -INFO - [G] < Values: -emult 1e+301 -extra Emult 1e+308 -extra Emult_mod 0.03 -Emult 9 -INFO - [G] > value Emult_mod 1e+308 -INFO - [G] < Invalid argument. Use 'get' or 'set' or 'set_center'. -INFO - [G] > value get Emult_mod 1e+308 -INFO - [G] < Values: -emult 1e+301 -extra Emult 1e+308 -extra Emult_mod 0.03 -Emult 9 -INFO - [G] > value set extra Emult_mod 1e+308 -INFO - [G] < This command only works while hovering over a card. Rerun it while hovering over a card. -INFO - [G] > value set extra Emult_mod 1e+308 -INFO - [G] < Value set successfully. -INFO - [G] 2025-01-10 21:43:27 :: INFO :: TIMER :: [0032] Injected Atlas in 762.058 ms -INFO - [G] [DebugPlus] Reloaded Atlases -INFO - [G] 2025-01-10 21:43:29 :: INFO :: TIMER :: [0032] Injected Atlas in 759.027 ms -INFO - [G] [DebugPlus] Reloaded Atlases -INFO - [G] 2025-01-10 21:48:55 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-10 21:48:55 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.112 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0032] Injected Atlas in 750.030 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0025] Injected Sound in 17.579 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0032] Injected Stake in 0.100 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0008] Injected Rarity in 0.019 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.032 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0392] Injected Center in 1.404 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.008 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0027] Injected Blind in 0.031 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0002] Injected Seal in 0.039 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0004] Injected Suit in 0.043 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0013] Injected Rank in 0.052 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.126 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.058 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0031] Injected Challenge in 0.022 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0028] Injected Tag in 0.033 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0009] Injected Sticker in 0.064 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0009] Injected Shader in 28.218 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0020] Injected Achievement in 0.109 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 13.057 ms -INFO - [G] 2025-01-10 21:48:56 :: INFO :: TIMER :: [0011] Injected Event in 0.012 ms diff --git a/lovely/log/lovely-2025.01.11-14.30.44.log b/lovely/log/lovely-2025.01.11-14.30.44.log deleted file mode 100644 index a1c134e..0000000 --- a/lovely/log/lovely-2025.01.11-14.30.44.log +++ /dev/null @@ -1,151 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 160ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-11 14:30:45 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-11 14:30:46 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-11 14:30:46 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-11 14:30:46 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-11 14:30:46 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-11 14:30:46 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-11 14:30:46 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-11 14:30:46 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-11 14:30:46 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-11 14:30:46 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-11 14:30:46 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-11 14:30:46 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-11 14:30:46 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-11 14:30:46 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-11 14:30:46 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-11 14:30:47 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-11 14:30:47 :: INFO :: TIMER :: [0000] Injected Language in 0.003 ms -INFO - [G] 2025-01-11 14:30:47 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 2.096 ms -INFO - [G] 2025-01-11 14:30:47 :: INFO :: TIMER :: [0032] Injected Atlas in 832.546 ms -INFO - [G] 2025-01-11 14:30:47 :: INFO :: TIMER :: [0025] Injected Sound in 111.684 ms -INFO - [G] 2025-01-11 14:30:47 :: INFO :: TIMER :: [0032] Injected Stake in 0.774 ms -INFO - [G] 2025-01-11 14:30:47 :: INFO :: TIMER :: [0008] Injected Rarity in 0.021 ms -INFO - [G] 2025-01-11 14:30:47 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.070 ms -INFO - [G] 2025-01-11 14:30:47 :: INFO :: TIMER :: [0392] Injected Center in 2.300 ms -INFO - [G] 2025-01-11 14:30:47 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.013 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0027] Injected Blind in 0.074 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0002] Injected Seal in 0.137 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0004] Injected Suit in 0.067 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0013] Injected Rank in 0.083 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.029 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.086 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0031] Injected Challenge in 0.162 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0028] Injected Tag in 0.306 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0009] Injected Sticker in 0.602 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0009] Injected Shader in 116.075 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0020] Injected Achievement in 0.121 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 8.327 ms -INFO - [G] 2025-01-11 14:30:48 :: INFO :: TIMER :: [0011] Injected Event in 0.015 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] 2025-01-11 14:30:57 :: INFO :: TIMER :: [0000] Injected Language in 0.002 ms -INFO - [G] 2025-01-11 14:30:57 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 4.288 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0032] Injected Atlas in 806.544 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0025] Injected Sound in 19.484 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0032] Injected Stake in 0.231 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0008] Injected Rarity in 0.019 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.054 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0392] Injected Center in 1.293 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.011 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0027] Injected Blind in 0.061 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0002] Injected Seal in 0.072 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0004] Injected Suit in 0.060 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0013] Injected Rank in 0.102 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.022 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.038 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0031] Injected Challenge in 0.078 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0028] Injected Tag in 0.047 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0009] Injected Sticker in 0.076 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0009] Injected Shader in 22.948 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0020] Injected Achievement in 0.153 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 21.668 ms -INFO - [G] 2025-01-11 14:30:58 :: INFO :: TIMER :: [0011] Injected Event in 0.017 ms diff --git a/lovely/log/lovely-2025.01.11-16.33.51.log b/lovely/log/lovely-2025.01.11-16.33.51.log deleted file mode 100644 index f5be140..0000000 --- a/lovely/log/lovely-2025.01.11-16.33.51.log +++ /dev/null @@ -1,164 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 136ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-11 16:33:52 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-11 16:33:53 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-11 16:33:53 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-11 16:33:53 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-11 16:33:53 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-11 16:33:53 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-11 16:33:53 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-11 16:33:53 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-11 16:33:53 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-11 16:33:53 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-11 16:33:53 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-11 16:33:53 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-11 16:33:53 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-11 16:33:53 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-11 16:33:53 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-11 16:33:53 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-11 16:33:53 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-11 16:33:53 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.644 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0032] Injected Atlas in 767.253 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0025] Injected Sound in 18.101 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0032] Injected Stake in 0.474 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0008] Injected Rarity in 0.020 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.053 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0392] Injected Center in 1.746 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.012 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0027] Injected Blind in 0.057 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0002] Injected Seal in 0.061 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0004] Injected Suit in 0.065 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0013] Injected Rank in 0.068 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.032 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.083 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0031] Injected Challenge in 0.163 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0028] Injected Tag in 0.315 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0009] Injected Sticker in 0.912 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0009] Injected Shader in 81.992 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0000] Injected Keybind in 0.002 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0020] Injected Achievement in 0.100 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 5.940 ms -INFO - [G] 2025-01-11 16:33:54 :: INFO :: TIMER :: [0011] Injected Event in 0.014 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] > value get -INFO - [G] < Values: -extra scale_mod 3.2e82 -extra scale 8.8e84 -extra shadow_scale 8.8e84 -extra shadow_scale_mod 3.2e82 -hands_played_at_create 3.6e+84 -INFO - [G] > value set extra scale_mod 1e300 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra scale 1e300 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra shadow_scale 1e300 -INFO - [G] < Value set successfully. -INFO - [G] > value set extra shadow_scale_mod 1e300 -INFO - [G] < Value set successfully. -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] > value get -INFO - [G] < Values: -extra scale_mod 5.392e367 -extra scale 1.219e370 -extra shadow_scale 1.219e370 -extra shadow_scale_mod 5.392e367 -hands_played_at_create 1.1e+152 -INFO - [G] > value set extra scale_mod 1e500 -INFO - [G] < Value set successfully. diff --git a/lovely/log/lovely-2025.01.13-03.39.25.log b/lovely/log/lovely-2025.01.13-03.39.25.log deleted file mode 100644 index 51461c5..0000000 --- a/lovely/log/lovely-2025.01.13-03.39.25.log +++ /dev/null @@ -1,264 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 174ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-13 03:39:27 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-13 03:39:28 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-13 03:39:28 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-13 03:39:28 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-13 03:39:28 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-13 03:39:29 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-13 03:39:29 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-13 03:39:29 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-13 03:39:29 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-13 03:39:29 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-13 03:39:29 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-13 03:39:29 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-13 03:39:29 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-13 03:39:29 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-13 03:39:29 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-13 03:39:29 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-13 03:39:29 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-13 03:39:29 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 1.225 ms -INFO - [G] 2025-01-13 03:39:29 :: INFO :: TIMER :: [0032] Injected Atlas in 850.444 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0025] Injected Sound in 115.481 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0032] Injected Stake in 0.946 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0008] Injected Rarity in 0.028 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.186 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0392] Injected Center in 1.805 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.013 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0027] Injected Blind in 0.045 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0002] Injected Seal in 0.049 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0004] Injected Suit in 0.052 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0013] Injected Rank in 0.053 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.054 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.070 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0031] Injected Challenge in 0.148 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0028] Injected Tag in 0.283 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0009] Injected Sticker in 0.610 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0009] Injected Shader in 153.250 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0020] Injected Achievement in 0.105 ms -INFO - [G] 2025-01-13 03:39:30 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 7.810 ms -INFO - [G] 2025-01-13 03:39:31 :: INFO :: TIMER :: [0011] Injected Event in 0.025 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-01-13 03:39:48 :: ERROR :: StackTrace :: Oops! The game crashed -[SMODS Cryptid "Items/Exotic.lua"]:801: attempt to call method 'start_dissolve' (a nil value) -Stack Traceback -=============== -(1) Lua upvalue 'orig' at file 'main.lua:612' - Local variables: - msg = string: "[SMODS Cryptid \"Items/Exotic.lua\"]:801: attempt to call method 'start_dissolve' (a nil value)" - (*temporary) = Lua function '?' (defined at line 31 of chunk [SMODS _ "src/logging.lua"]) - (*temporary) = string: "Oops! The game crashed\ -" -(2) Lua local 'handler' at file 'console.lua:551' (from lovely module debugplus.console) - Local variables: - msg = string: "[SMODS Cryptid \"Items/Exotic.lua\"]:801: attempt to call method 'start_dissolve' (a nil value)" -(3) LÖVE method at file 'boot.lua:352' - Local variables: - errhand = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) - handler = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) -(4) Lua method 'remove_from_deck' at file 'Items/Exotic.lua:801' (from mod with id Cryptid) - Local variables: - self = table: 0x0468eb50 {alerted:true, loc_vars:function: 0x0468ed88, object_type:Joker, _saved_d_u:true (more...)} - card = table: 0x062cbde8 {shadow_parrallax:table: 0x062cc908, click_offset:table: 0x062cc0b8, children:table: 0x062d2c98 (more...)} - from_debuff = nil - (*temporary) = nil - (*temporary) = string: "\"MANUAL_REPLACE\"" - (*temporary) = string: "attempt to call method 'start_dissolve' (a nil value)" -(5) Lua method 'remove_from_deck' at file 'card.lua:820' - Local variables: - self = table: 0x062cbde8 {shadow_parrallax:table: 0x062cc908, click_offset:table: 0x062cc0b8, children:table: 0x062d2c98 (more...)} - from_debuff = nil - obj = table: 0x0468eb50 {alerted:true, loc_vars:function: 0x0468ed88, object_type:Joker, _saved_d_u:true (more...)} -(6) Lua method 'remove' at file 'card.lua:5391' - Local variables: - self = table: 0x062cbde8 {shadow_parrallax:table: 0x062cc908, click_offset:table: 0x062cc0b8, children:table: 0x062d2c98 (more...)} -(7) Lua upvalue 'rma' at file 'functions/misc_functions.lua:153' - Local variables: - t = table: 0x04336fd0 {1:table: 0x04de7ef8, 2:table: 0x04de1680, 3:table: 0x04e70608, 4:table: 0x047634f0 (more...)} - (for index) = number: 461 - (for limit) = number: 1 - (for step) = number: -1 - i = number: 461 - v = table: 0x062cbde8 {shadow_parrallax:table: 0x062cc908, click_offset:table: 0x062cc0b8, children:table: 0x062d2c98 (more...)} -(8) Lua global 'remove_all' at file 'Items/Misc.lua:1904' (from mod with id Cryptid) - Local variables: - t = table: 0x04336fd0 {1:table: 0x04de7ef8, 2:table: 0x04de1680, 3:table: 0x04e70608, 4:table: 0x047634f0 (more...)} -(9) Lua method 'delete_run' at file 'game.lua:1258' - Local variables: - self = table: 0x043329d8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x077952d8 (more...)} -(10) Lua field 'func' at file 'functions/button_callbacks.lua:3022' -(11) Lua method 'handle' at file 'engine/event.lua:99' - Local variables: - self = table: 0x06417550 {start_timer:true, timer:REAL, func:function: 0x069f77a8, blockable:true (more...)} - _results = table: 0x13cea148 {blocking:true, pause_skip:false, time_done:false, completed:false} -(12) Lua method 'update' at file 'engine/event.lua:182' - Local variables: - self = table: 0x04f271d8 {queue_last_processed:9.7500000000001, queues:table: 0x04f27200, queue_dt:0.016666666666667 (more...)} - dt = number: 0.0135071 - forced = nil - (for generator) = C function: next - (for state) = table: 0x04f27200 {unlock:table: 0x04f27228, other:table: 0x04f276a0, tutorial:table: 0x04f27278 (more...)} - (for control) = number: nan - k = string: "base" - v = table: 0x04f27250 {1:table: 0x06417550, 2:table: 0x06417578, 3:table: 0x06423430, 4:table: 0x06424918 (more...)} - blocked = boolean: false - i = number: 1 - results = table: 0x13cea148 {blocking:true, pause_skip:false, time_done:false, completed:false} -(13) Lua upvalue 'gameUpdateRef' at file 'game.lua:2734' - Local variables: - self = table: 0x043329d8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x077952d8 (more...)} - dt = number: 0 - http_resp = nil -(14) Lua upvalue 'upd' at Steamodded file 'src/ui.lua:81' - Local variables: - self = table: 0x043329d8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x077952d8 (more...)} - dt = number: 0.0135071 -(15) Lua upvalue 'upd' at file 'main.lua:4093' - Local variables: - self = table: 0x043329d8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x077952d8 (more...)} - dt = number: 0.0135071 -(16) Lua upvalue 'upd' at file 'Items/Blinds.lua:1310' (from mod with id Cryptid) - Local variables: - self = table: 0x043329d8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x077952d8 (more...)} - dt = number: 0.0135071 -(17) Lua upvalue 'upd' at file 'Items/CodeCards.lua:4106' (from mod with id Cryptid) - Local variables: - self = table: 0x043329d8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x077952d8 (more...)} - dt = number: 0.0135071 -(18) Lua upvalue 'upd' at file 'Items/Decks.lua:429' (from mod with id Cryptid) - Local variables: - self = table: 0x043329d8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x077952d8 (more...)} - dt = number: 0.0135071 -(19) Lua upvalue 'upd' at file 'Items/MiscJokers.lua:6658' (from mod with id Cryptid) - Local variables: - self = table: 0x043329d8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x077952d8 (more...)} - dt = number: 0.0135071 -(20) Lua method 'update' at file 'Cryptid.lua:2948' (from mod with id Cryptid) - Local variables: - self = table: 0x043329d8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x077952d8 (more...)} - dt = number: 0.0135071 -(21) Lua upvalue 'love_update_ref' at file 'main.lua:1141' - Local variables: - dt = number: 0.0135071 -(22) Lua upvalue 'oldupd' at file 'main.lua:2951' - Local variables: - dt = number: 0.0135071 -(23) Lua field 'update' at file 'main.lua:4120' - Local variables: - dt = number: 0.0135071 -(24) Lua function '?' at file 'main.lua:1079' (best guess) -(25) global C function 'xpcall' -(26) LÖVE function at file 'boot.lua:377' (best guess) - Local variables: - func = Lua function '?' (defined at line 1050 of chunk main.lua) - inerror = boolean: true - deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"]) - earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"]) - -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-01-13 03:39:48 :: INFO :: StackTrace :: Additional Context: -Balatro Version: 1.0.1n-FULL -Modded Version: 1.0.0~ALPHA-1220a-STEAMODDED -LÖVE Version: 11.5.0 -Lovely Version: 0.6.0 -Steamodded Mods: - 1: J Cursor by Jie65535, MarioMak967 [ID: JCursor] - 2: Cryptid by MathIsFun_, Cryptid and Balatro Discords [ID: Cryptid, Priority: 1e+299, Version: 0.5.3a, Uses Lovely] - 3: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.2, Uses Lovely] - Break Infinity: omeganum - 4: Cartomancer by stupxd aka stupid [ID: cartomancer, Priority: 69, Version: 4.10, Uses Lovely] - 5: Handy by SleepyG11 [ID: Handy, Version: 1.1.5, Uses Lovely] - 6: Incantation by jenwalter666, MathIsFun_ [ID: incantation, Priority: 9e+301, Version: 0.5.10, Uses Lovely] - 7: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.3.0, Uses Lovely] -Lovely Mods: diff --git a/lovely/log/lovely-2025.01.14-00.56.45.log b/lovely/log/lovely-2025.01.14-00.56.45.log deleted file mode 100644 index a02d182..0000000 --- a/lovely/log/lovely-2025.01.14-00.56.45.log +++ /dev/null @@ -1,128 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 159ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-14 00:56:48 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-14 00:56:49 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-14 00:56:49 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-14 00:56:49 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-14 00:56:49 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-14 00:56:49 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-14 00:56:49 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-14 00:56:49 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-14 00:56:49 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-14 00:56:49 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-14 00:56:49 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-14 00:56:49 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-14 00:56:49 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-14 00:56:49 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-14 00:56:49 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-14 00:56:49 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-14 00:56:49 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-14 00:56:49 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 1.039 ms -INFO - [G] 2025-01-14 00:56:50 :: INFO :: TIMER :: [0032] Injected Atlas in 872.290 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0025] Injected Sound in 262.811 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0032] Injected Stake in 0.477 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0008] Injected Rarity in 0.020 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.133 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0392] Injected Center in 1.843 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.011 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0027] Injected Blind in 0.053 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0002] Injected Seal in 0.089 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0004] Injected Suit in 0.052 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0013] Injected Rank in 0.055 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.027 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.081 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0031] Injected Challenge in 0.162 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0028] Injected Tag in 0.297 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0009] Injected Sticker in 0.775 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0009] Injected Shader in 56.400 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0020] Injected Achievement in 0.096 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 7.712 ms -INFO - [G] 2025-01-14 00:56:51 :: INFO :: TIMER :: [0011] Injected Event in 0.012 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews diff --git a/lovely/log/lovely-2025.01.14-22.28.58.log b/lovely/log/lovely-2025.01.14-22.28.58.log deleted file mode 100644 index a21f9fd..0000000 --- a/lovely/log/lovely-2025.01.14-22.28.58.log +++ /dev/null @@ -1,128 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 212ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-14 22:29:00 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-14 22:29:01 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-14 22:29:01 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-14 22:29:01 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-14 22:29:01 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-14 22:29:02 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-14 22:29:02 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-14 22:29:02 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-14 22:29:02 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-14 22:29:02 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-14 22:29:02 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-14 22:29:02 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-14 22:29:02 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-14 22:29:02 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-14 22:29:02 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-14 22:29:02 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-14 22:29:02 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-14 22:29:02 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 1.478 ms -INFO - [G] 2025-01-14 22:29:02 :: INFO :: TIMER :: [0032] Injected Atlas in 858.054 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0025] Injected Sound in 198.016 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0032] Injected Stake in 0.478 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0008] Injected Rarity in 0.021 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.134 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0392] Injected Center in 1.534 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.009 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0027] Injected Blind in 0.040 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0002] Injected Seal in 0.036 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0004] Injected Suit in 0.054 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0013] Injected Rank in 0.039 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.026 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.074 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0031] Injected Challenge in 0.153 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0028] Injected Tag in 0.273 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0009] Injected Sticker in 0.662 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0009] Injected Shader in 181.900 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0020] Injected Achievement in 0.094 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 7.321 ms -INFO - [G] 2025-01-14 22:29:03 :: INFO :: TIMER :: [0011] Injected Event in 0.012 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews diff --git a/lovely/log/lovely-2025.01.18-16.12.50.log b/lovely/log/lovely-2025.01.18-16.12.50.log deleted file mode 100644 index e23a4b6..0000000 --- a/lovely/log/lovely-2025.01.18-16.12.50.log +++ /dev/null @@ -1,131 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 141ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-18 16:12:53 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-18 16:12:54 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-18 16:12:54 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-18 16:12:54 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-18 16:12:54 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-18 16:12:54 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-18 16:12:54 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-18 16:12:54 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-18 16:12:54 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-18 16:12:54 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-18 16:12:54 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-18 16:12:54 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-18 16:12:54 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-18 16:12:54 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-18 16:12:54 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-18 16:12:54 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-18 16:12:54 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-18 16:12:54 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.683 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0032] Injected Atlas in 780.652 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0025] Injected Sound in 20.941 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0032] Injected Stake in 0.489 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0008] Injected Rarity in 0.026 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.059 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0392] Injected Center in 2.139 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.008 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0027] Injected Blind in 0.043 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0002] Injected Seal in 0.127 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0004] Injected Suit in 0.052 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0013] Injected Rank in 0.063 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.040 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.082 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0031] Injected Challenge in 0.038 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0028] Injected Tag in 0.871 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0009] Injected Sticker in 0.290 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0009] Injected Shader in 58.620 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0020] Injected Achievement in 0.123 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.579 ms -INFO - [G] 2025-01-18 16:12:55 :: INFO :: TIMER :: [0011] Injected Event in 0.014 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load diff --git a/lovely/log/lovely-2025.01.19-16.12.21.log b/lovely/log/lovely-2025.01.19-16.12.21.log deleted file mode 100644 index dfa9954..0000000 --- a/lovely/log/lovely-2025.01.19-16.12.21.log +++ /dev/null @@ -1,128 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 139ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-19 16:12:26 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-19 16:12:27 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-19 16:12:27 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-19 16:12:27 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-19 16:12:27 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-19 16:12:27 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-19 16:12:27 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-19 16:12:27 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-19 16:12:27 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-19 16:12:27 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-19 16:12:27 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-19 16:12:27 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-19 16:12:27 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-19 16:12:27 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-19 16:12:27 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-19 16:12:27 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-19 16:12:27 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-19 16:12:27 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.719 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0032] Injected Atlas in 781.765 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0025] Injected Sound in 20.566 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0032] Injected Stake in 0.626 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0008] Injected Rarity in 0.026 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.068 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0392] Injected Center in 1.969 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.012 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0027] Injected Blind in 0.061 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0002] Injected Seal in 0.072 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0004] Injected Suit in 0.114 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0013] Injected Rank in 0.082 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.040 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.081 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0031] Injected Challenge in 0.175 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0028] Injected Tag in 0.233 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0009] Injected Sticker in 0.811 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0009] Injected Shader in 56.200 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0020] Injected Achievement in 0.073 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.984 ms -INFO - [G] 2025-01-19 16:12:28 :: INFO :: TIMER :: [0011] Injected Event in 0.015 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews diff --git a/lovely/log/lovely-2025.01.19-23.45.43.log b/lovely/log/lovely-2025.01.19-23.45.43.log deleted file mode 100644 index 0e655c7..0000000 --- a/lovely/log/lovely-2025.01.19-23.45.43.log +++ /dev/null @@ -1,128 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 132ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-19 23:45:44 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-19 23:45:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-19 23:45:45 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-19 23:45:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-19 23:45:45 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-19 23:45:45 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-19 23:45:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-19 23:45:45 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-19 23:45:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-19 23:45:45 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-19 23:45:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-19 23:45:45 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-19 23:45:45 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-19 23:45:45 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-19 23:45:45 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-19 23:45:45 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-19 23:45:45 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-19 23:45:45 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.681 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0032] Injected Atlas in 784.764 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0025] Injected Sound in 19.919 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0032] Injected Stake in 0.748 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0008] Injected Rarity in 0.023 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.072 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0392] Injected Center in 1.766 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.018 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0027] Injected Blind in 0.050 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0002] Injected Seal in 0.054 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0004] Injected Suit in 0.079 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0013] Injected Rank in 0.094 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.045 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.178 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0031] Injected Challenge in 0.188 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0028] Injected Tag in 0.241 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0009] Injected Sticker in 1.077 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0009] Injected Shader in 56.128 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0020] Injected Achievement in 0.092 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.203 ms -INFO - [G] 2025-01-19 23:45:46 :: INFO :: TIMER :: [0011] Injected Event in 0.013 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews diff --git a/lovely/log/lovely-2025.01.20-20.46.32.log b/lovely/log/lovely-2025.01.20-20.46.32.log deleted file mode 100644 index e976f60..0000000 --- a/lovely/log/lovely-2025.01.20-20.46.32.log +++ /dev/null @@ -1,128 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 152ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-20 20:46:35 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-20 20:46:36 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-20 20:46:36 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-20 20:46:36 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-20 20:46:36 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-20 20:46:36 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-20 20:46:36 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-20 20:46:36 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-20 20:46:36 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-20 20:46:36 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-20 20:46:36 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-20 20:46:36 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-20 20:46:36 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-20 20:46:36 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-20 20:46:36 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-20 20:46:36 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-20 20:46:36 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-20 20:46:36 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 1.464 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0032] Injected Atlas in 845.405 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0025] Injected Sound in 114.390 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0032] Injected Stake in 0.611 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0008] Injected Rarity in 0.023 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.057 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0392] Injected Center in 1.980 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.010 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0027] Injected Blind in 0.039 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0002] Injected Seal in 0.038 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0004] Injected Suit in 0.058 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0013] Injected Rank in 0.041 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.025 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.102 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0031] Injected Challenge in 0.157 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0028] Injected Tag in 0.178 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0009] Injected Sticker in 0.587 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0009] Injected Shader in 104.318 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0020] Injected Achievement in 0.080 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 23.693 ms -INFO - [G] 2025-01-20 20:46:37 :: INFO :: TIMER :: [0011] Injected Event in 0.033 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews diff --git a/lovely/log/lovely-2025.01.20-20.47.45.log b/lovely/log/lovely-2025.01.20-20.47.45.log deleted file mode 100644 index 2be2c6a..0000000 --- a/lovely/log/lovely-2025.01.20-20.47.45.log +++ /dev/null @@ -1,128 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 158ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-20 20:47:48 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-20 20:47:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-20 20:47:48 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-20 20:47:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-20 20:47:48 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-20 20:47:48 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-20 20:47:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-20 20:47:48 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-20 20:47:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-20 20:47:48 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-20 20:47:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-20 20:47:48 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-20 20:47:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-20 20:47:48 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-20 20:47:48 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-20 20:47:49 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.706 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0032] Injected Atlas in 808.787 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0025] Injected Sound in 22.145 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0032] Injected Stake in 0.423 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0008] Injected Rarity in 0.020 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.059 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0392] Injected Center in 1.763 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.012 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0027] Injected Blind in 0.042 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0002] Injected Seal in 0.278 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0004] Injected Suit in 0.063 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0013] Injected Rank in 0.066 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.029 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.107 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0031] Injected Challenge in 0.035 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0028] Injected Tag in 0.071 ms -INFO - [G] 2025-01-20 20:47:49 :: INFO :: TIMER :: [0009] Injected Sticker in 0.295 ms -INFO - [G] 2025-01-20 20:47:50 :: INFO :: TIMER :: [0009] Injected Shader in 93.768 ms -INFO - [G] 2025-01-20 20:47:50 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-20 20:47:50 :: INFO :: TIMER :: [0020] Injected Achievement in 0.108 ms -INFO - [G] 2025-01-20 20:47:50 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.442 ms -INFO - [G] 2025-01-20 20:47:50 :: INFO :: TIMER :: [0011] Injected Event in 0.013 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews diff --git a/lovely/log/lovely-2025.01.22-01.21.54.log b/lovely/log/lovely-2025.01.22-01.21.54.log deleted file mode 100644 index 83c8621..0000000 --- a/lovely/log/lovely-2025.01.22-01.21.54.log +++ /dev/null @@ -1,128 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 319ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-22 01:21:58 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-22 01:22:00 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-22 01:22:00 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-22 01:22:00 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-22 01:22:00 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-22 01:22:00 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-22 01:22:00 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-22 01:22:00 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-22 01:22:00 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-22 01:22:00 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-22 01:22:00 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-22 01:22:00 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-22 01:22:00 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-22 01:22:00 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-22 01:22:00 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-22 01:22:00 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-22 01:22:00 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-22 01:22:00 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 1.183 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0032] Injected Atlas in 1022.137 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0025] Injected Sound in 497.088 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0032] Injected Stake in 0.475 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0008] Injected Rarity in 0.028 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.066 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0392] Injected Center in 1.674 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.009 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0027] Injected Blind in 0.047 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0002] Injected Seal in 0.052 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0004] Injected Suit in 0.056 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0013] Injected Rank in 0.076 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.026 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.107 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0031] Injected Challenge in 0.123 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0028] Injected Tag in 0.237 ms -INFO - [G] 2025-01-22 01:22:02 :: INFO :: TIMER :: [0009] Injected Sticker in 0.817 ms -INFO - [G] 2025-01-22 01:22:03 :: INFO :: TIMER :: [0009] Injected Shader in 850.893 ms -INFO - [G] 2025-01-22 01:22:03 :: INFO :: TIMER :: [0000] Injected Keybind in 0.002 ms -INFO - [G] 2025-01-22 01:22:03 :: INFO :: TIMER :: [0020] Injected Achievement in 0.085 ms -INFO - [G] 2025-01-22 01:22:03 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 11.235 ms -INFO - [G] 2025-01-22 01:22:03 :: INFO :: TIMER :: [0011] Injected Event in 0.016 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews diff --git a/lovely/log/lovely-2025.01.26-23.01.38.log b/lovely/log/lovely-2025.01.26-23.01.38.log deleted file mode 100644 index fbb003d..0000000 --- a/lovely/log/lovely-2025.01.26-23.01.38.log +++ /dev/null @@ -1,229 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 157ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-26 23:01:40 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-26 23:01:41 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-26 23:01:41 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-26 23:01:41 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-26 23:01:41 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-26 23:01:41 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-26 23:01:41 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-26 23:01:41 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-26 23:01:41 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-26 23:01:41 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-26 23:01:41 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-26 23:01:41 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-26 23:01:41 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-26 23:01:41 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-26 23:01:41 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-26 23:01:41 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-26 23:01:41 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-26 23:01:41 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 1.248 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0032] Injected Atlas in 1076.432 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0025] Injected Sound in 119.396 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0032] Injected Stake in 0.497 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0008] Injected Rarity in 0.045 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.050 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0392] Injected Center in 1.968 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.018 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0027] Injected Blind in 0.045 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0002] Injected Seal in 0.038 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0004] Injected Suit in 0.068 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0013] Injected Rank in 0.054 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.029 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.115 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0031] Injected Challenge in 0.033 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0028] Injected Tag in 0.168 ms -INFO - [G] 2025-01-26 23:01:42 :: INFO :: TIMER :: [0009] Injected Sticker in 0.848 ms -INFO - [G] 2025-01-26 23:01:43 :: INFO :: TIMER :: [0009] Injected Shader in 167.743 ms -INFO - [G] 2025-01-26 23:01:43 :: INFO :: TIMER :: [0000] Injected Keybind in 0.002 ms -INFO - [G] 2025-01-26 23:01:43 :: INFO :: TIMER :: [0020] Injected Achievement in 0.080 ms -INFO - [G] 2025-01-26 23:01:43 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 8.242 ms -INFO - [G] 2025-01-26 23:01:43 :: INFO :: TIMER :: [0011] Injected Event in 0.020 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-01-26 23:02:11 :: ERROR :: StackTrace :: Oops! The game crashed -[SMODS Cryptid "Cryptid.lua"]:120: attempt to index field 'events' (a nil value) -Stack Traceback -=============== -(1) Lua upvalue 'orig' at file 'main.lua:612' - Local variables: - msg = string: "[SMODS Cryptid \"Cryptid.lua\"]:120: attempt to index field 'events' (a nil value)" - (*temporary) = Lua function '?' (defined at line 31 of chunk [SMODS _ "src/logging.lua"]) - (*temporary) = string: "Oops! The game crashed\ -" -(2) Lua local 'handler' at file 'console.lua:551' (from lovely module debugplus.console) - Local variables: - msg = string: "[SMODS Cryptid \"Cryptid.lua\"]:120: attempt to index field 'events' (a nil value)" -(3) LÖVE metamethod at file 'boot.lua:352' - Local variables: - errhand = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) - handler = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) -(4) Lua method 'update_round_eval' at file 'Cryptid.lua:120' (from mod with id Cryptid) - Local variables: - self = table: 0x04e04dc8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x09fb7138 (more...)} - dt = number: 0 - (*temporary) = nil - (*temporary) = C function: next - (*temporary) = table: 0x06be00a0 {unlock:table: 0x06be00c8, other:table: 0x06be0540, tutorial:table: 0x06be0118 (more...)} - (*temporary) = number: nan - (*temporary) = string: "achievement" - (*temporary) = table: 0x06be0518 {} - (*temporary) = boolean: false - (*temporary) = number: 1 - (*temporary) = string: "attempt to index field 'events' (a nil value)" -(5) Lua upvalue 'gameUpdateRef' at file 'game.lua:2804' - Local variables: - self = table: 0x04e04dc8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x09fb7138 (more...)} - dt = number: 0 - http_resp = nil -(6) Lua upvalue 'upd' at Steamodded file 'src/ui.lua:81' - Local variables: - self = table: 0x04e04dc8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x09fb7138 (more...)} - dt = number: 0.00610519 -(7) Lua upvalue 'upd' at file 'main.lua:4093' - Local variables: - self = table: 0x04e04dc8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x09fb7138 (more...)} - dt = number: 0.00610519 -(8) Lua upvalue 'upd' at file 'Items/Blinds.lua:1310' (from mod with id Cryptid) - Local variables: - self = table: 0x04e04dc8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x09fb7138 (more...)} - dt = number: 0.00610519 -(9) Lua upvalue 'upd' at file 'Items/CodeCards.lua:4106' (from mod with id Cryptid) - Local variables: - self = table: 0x04e04dc8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x09fb7138 (more...)} - dt = number: 0.00610519 -(10) Lua upvalue 'upd' at file 'Items/Decks.lua:429' (from mod with id Cryptid) - Local variables: - self = table: 0x04e04dc8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x09fb7138 (more...)} - dt = number: 0.00610519 -(11) Lua upvalue 'upd' at file 'Items/MiscJokers.lua:6658' (from mod with id Cryptid) - Local variables: - self = table: 0x04e04dc8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x09fb7138 (more...)} - dt = number: 0.00610519 -(12) Lua method 'update' at file 'Cryptid.lua:2948' (from mod with id Cryptid) - Local variables: - self = table: 0x04e04dc8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x09fb7138 (more...)} - dt = number: 0.00610519 -(13) Lua upvalue 'love_update_ref' at file 'main.lua:1141' - Local variables: - dt = number: 0.00610519 -(14) Lua upvalue 'oldupd' at file 'main.lua:2951' - Local variables: - dt = number: 0.00610519 -(15) Lua field 'update' at file 'main.lua:4120' - Local variables: - dt = number: 0.00610519 -(16) Lua function '?' at file 'main.lua:1079' (best guess) -(17) global C function 'xpcall' -(18) LÖVE function at file 'boot.lua:377' (best guess) - Local variables: - func = Lua function '?' (defined at line 1050 of chunk main.lua) - inerror = boolean: true - deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"]) - earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"]) - -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-01-26 23:02:11 :: INFO :: StackTrace :: Additional Context: -Balatro Version: 1.0.1n-FULL -Modded Version: 1.0.0~ALPHA-1220a-STEAMODDED -LÖVE Version: 11.5.0 -Lovely Version: 0.6.0 -Steamodded Mods: - 1: J Cursor by Jie65535, MarioMak967 [ID: JCursor] - 2: Cryptid by MathIsFun_, Cryptid and Balatro Discords [ID: Cryptid, Priority: 1e+299, Version: 0.5.3a, Uses Lovely] - 3: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.2, Uses Lovely] - Break Infinity: omeganum - 4: Cartomancer by stupxd aka stupid [ID: cartomancer, Priority: 69, Version: 4.10, Uses Lovely] - 5: Handy by SleepyG11 [ID: Handy, Version: 1.1.5, Uses Lovely] - 6: Incantation by jenwalter666, MathIsFun_ [ID: incantation, Priority: 9e+301, Version: 0.5.10, Uses Lovely] - 7: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.3.0, Uses Lovely] -Lovely Mods: diff --git a/lovely/log/lovely-2025.01.26-23.02.32.log b/lovely/log/lovely-2025.01.26-23.02.32.log deleted file mode 100644 index ae9dc23..0000000 --- a/lovely/log/lovely-2025.01.26-23.02.32.log +++ /dev/null @@ -1,128 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 142ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-01-26 23:02:34 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-01-26 23:02:35 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-01-26 23:02:35 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-01-26 23:02:35 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-01-26 23:02:35 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-01-26 23:02:35 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-01-26 23:02:35 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-01-26 23:02:35 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-01-26 23:02:35 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-01-26 23:02:35 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-01-26 23:02:35 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-01-26 23:02:35 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-01-26 23:02:35 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-01-26 23:02:35 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-01-26 23:02:35 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-01-26 23:02:35 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-01-26 23:02:35 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-01-26 23:02:35 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.747 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0032] Injected Atlas in 784.647 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0025] Injected Sound in 22.166 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0032] Injected Stake in 0.705 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0008] Injected Rarity in 0.030 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.065 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0392] Injected Center in 2.035 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.081 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0027] Injected Blind in 0.153 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0002] Injected Seal in 0.065 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0004] Injected Suit in 0.085 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0013] Injected Rank in 0.226 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.030 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.101 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0031] Injected Challenge in 0.036 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0028] Injected Tag in 0.059 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0009] Injected Sticker in 0.098 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0009] Injected Shader in 109.877 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0020] Injected Achievement in 0.076 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.699 ms -INFO - [G] 2025-01-26 23:02:36 :: INFO :: TIMER :: [0011] Injected Event in 0.013 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews diff --git a/lovely/log/lovely-2025.02.11-01.14.44.log b/lovely/log/lovely-2025.02.11-01.14.44.log deleted file mode 100644 index cdc2ce1..0000000 --- a/lovely/log/lovely-2025.02.11-01.14.44.log +++ /dev/null @@ -1,139 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 233ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 83 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 100 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 126 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 55 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'elseif self.ability.name == \'Blueprint\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'Blueprint\' or self.ability.name == \'Brainstorm\' then' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 210 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-02-11 01:14:47 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-02-11 01:14:48 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-02-11 01:14:48 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:14:48 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:14:48 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Mod UnStable was unable to load: Missing Dependencies: 1: Steamodded (>=1.0.0~ALPHA-1318b) - - -INFO - [G] 2025-02-11 01:14:48 :: TRACE :: Loader :: Mod UnStableEX was unable to load: Missing Dependencies: 1: Steamodded (>=1.0.0~ALPHA-1307d) -2: UnStable - - -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-02-11 01:14:48 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-02-11 01:14:48 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-02-11 01:14:48 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 1.196 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0032] Injected Atlas in 849.797 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0025] Injected Sound in 209.452 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0032] Injected Stake in 0.878 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0008] Injected Rarity in 0.026 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.067 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0392] Injected Center in 2.221 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.010 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0027] Injected Blind in 0.052 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0002] Injected Seal in 0.046 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0004] Injected Suit in 0.100 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0013] Injected Rank in 0.080 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.031 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.084 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0031] Injected Challenge in 0.038 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0028] Injected Tag in 0.052 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0009] Injected Sticker in 0.117 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0009] Injected Shader in 56.258 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0020] Injected Achievement in 0.066 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 7.994 ms -INFO - [G] 2025-02-11 01:14:49 :: INFO :: TIMER :: [0011] Injected Event in 0.014 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews diff --git a/lovely/log/lovely-2025.02.11-01.21.30.log b/lovely/log/lovely-2025.02.11-01.21.30.log deleted file mode 100644 index 42e3bbc..0000000 --- a/lovely/log/lovely-2025.02.11-01.21.30.log +++ /dev/null @@ -1,199 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 135ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 35 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 13 patches to 'engine/controller.lua' -INFO - [♥] Applied 15 patches to 'back.lua' -INFO - [♥] Applied 15 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 48 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 85 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 110 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern '--calculate the card edition effects\nif effects[ii].edition then\n hand_chips = mod_chips(hand_chips + (effects[ii].edition.chip_mod or 0))\n mult = mult + (effects[ii].edition.mult_mod or 0)\n mult = mod_mult(mult*(effects[ii].edition.x_mult_mod or 1))\n update_hand_text({delay = 0}, {\n chips = effects[ii].edition.chip_mod and hand_chips or nil,\n mult = (effects[ii].edition.mult_mod or effects[ii].edition.x_mult_mod) and mult or nil,\n })\n card_eval_status_text(scoring_hand[i], \'extra\', nil, percent, nil, {\n message = (effects[ii].edition.chip_mod and localize{type=\'variable\',key=\'a_chips\',vars={effects[ii].edition.chip_mod}}) or\n (effects[ii].edition.mult_mod and localize{type=\'variable\',key=\'a_mult\',vars={effects[ii].edition.mult_mod}}) or\n (effects[ii].edition.x_mult_mod and localize{type=\'variable\',key=\'a_xmult\',vars={effects[ii].edition.x_mult_mod}}),\n chip_mod = effects[ii].edition.chip_mod,\n mult_mod = effects[ii].edition.mult_mod,\n x_mult_mod = effects[ii].edition.x_mult_mod,\n colour = G.C.DARK_EDITION,\n edition = true})\nend\n' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern ' scoring_hand[i].lucky_trigger = nil\n\n for ii = 1, #effects do\n --If chips added, do chip add event and add the chips to the total\n if effects[ii].chips then \n if effects[ii].card then juice_card(effects[ii].card) end\n hand_chips = mod_chips(hand_chips + effects[ii].chips)\n update_hand_text({delay = 0}, {chips = hand_chips})\n card_eval_status_text(scoring_hand[i], \'chips\', effects[ii].chips, percent)\n end\n\n --If mult added, do mult add event and add the mult to the total\n if effects[ii].mult then \n if effects[ii].card then juice_card(effects[ii].card) end\n mult = mod_mult(mult + effects[ii].mult)\n update_hand_text({delay = 0}, {mult = mult})\n card_eval_status_text(scoring_hand[i], \'mult\', effects[ii].mult, percent)\n end\n\n --If play dollars added, add dollars to total\n if effects[ii].p_dollars then \n if effects[ii].card then juice_card(effects[ii].card) end\n ease_dollars(effects[ii].p_dollars)\n card_eval_status_text(scoring_hand[i], \'dollars\', effects[ii].p_dollars, percent)\n end\n\n --If dollars added, add dollars to total\n if effects[ii].dollars then \n if effects[ii].card then juice_card(effects[ii].card) end\n ease_dollars(effects[ii].dollars)\n card_eval_status_text(scoring_hand[i], \'dollars\', effects[ii].dollars, percent)\n end\n\n --Any extra effects\n if effects[ii].extra then \n if effects[ii].card then juice_card(effects[ii].card) end\n local extras = {mult = false, hand_chips = false}\n if effects[ii].extra.mult_mod then mult =mod_mult( mult + effects[ii].extra.mult_mod);extras.mult = true end\n if effects[ii].extra.chip_mod then hand_chips = mod_chips(hand_chips + effects[ii].extra.chip_mod);extras.hand_chips = true end\n if effects[ii].extra.swap then \n local old_mult = mult\n mult = mod_mult(hand_chips)\n hand_chips = mod_chips(old_mult)\n extras.hand_chips = true; extras.mult = true\n end\n if effects[ii].extra.func then effects[ii].extra.func() end\n update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult})\n card_eval_status_text(scoring_hand[i], \'extra\', nil, percent, nil, effects[ii].extra)\n end\n\n --If x_mult added, do mult add event and mult the mult to the total\n if effects[ii].x_mult then \n if effects[ii].card then juice_card(effects[ii].card) end\n mult = mod_mult(mult*effects[ii].x_mult)\n update_hand_text({delay = 0}, {mult = mult})\n card_eval_status_text(scoring_hand[i], \'x_mult\', effects[ii].x_mult, percent)\n end\n\n\n end\n end\nend\n' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local percent = (i-0.999)/(#G.hand.cards-0.998) + (j-1)*0.1' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.effect ~= \'Stone Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'G.GAME.cards_played[scoring_hand[i].base.value].suits[scoring_hand[i].base.suit] = true' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local effects = {G.hand.cards[i]:get_end_of_round_effect()}' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.name == \'Glass Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i = 1, #G.jokers.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(_card, \'jokers\', nil, percent, nil, effects.jokers)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if extras.mult or extras.hand_chips then card_eval_status_text(v, \'jokers\', nil, percent, nil, effect) end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if extras.mult or extras.hand_chips then card_eval_status_text(v, \'jokers\', nil, percent, nil, effect) end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(scoring_hand[i], \'x_mult\', effects[ii].x_mult, percent)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(G.hand.cards[i], \'x_mult\', effects[ii].x_mult, percent)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'edition = true})' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i=1, #G.hand.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if reps[j] ~= 1 then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if destroyed then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if cards_destroyed[i].ability.name == \'Glass Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local edition_effects = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, edition = true})' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i=1, #G.jokers.cards + #G.consumeables.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local hand_space = e or math.min(#G.deck.cards, G.hand.config.card_limit - #G.hand.cards)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local effects = {G.hand.cards[i]:get_end_of_round_effect()}' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.name == \'Glass Card\' and not scoring_hand[i].debuff and pseudorandom(\'glass\') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].card then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects.jokers.Xmult_mod then mult = mod_mult(mult*effects.jokers.Xmult_mod);extras.mult = true end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effect.Xmult_mod then mult = mod_mult(mult*effect.Xmult_mod);extras.mult = true end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].message then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern '--calculate the card edition effects' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].edition.p_dollars_mod then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if edition_effects.jokers.x_mult_mod then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if destroyed then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if destroyed then \\n' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 62 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, hide_desc, main_start, main_end)' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = localize(\'$\')..config.dollars, scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif _c.name == \'Cryptid\' then loc_vars = {_c.config.extra}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif _c.name == \"Clearance Sale\" or _c.name == \"Liquidation\" then loc_vars = {_c.config.extra}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'if v == \'negative_consumable\' then info_queue[#info_queue+1] = {key = \'e_negative_consumable\', set = \'Edition\', config = {extra = 1}} end' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 141 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'if card.area and (not nc or card.area == G.pack_cards) then card.area:remove_card(card) end\n' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 65 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if center_table.name == \'Overstock\' or center_table.name == \'Overstock Plus\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'self:calculate_joker{selling_self = true}' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name:find(\'Arcana\') then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if center_table.name == \'Overstock\' or center_table.name == \'Overstock Plus\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Regex 'message = localize\\{type = \'variable\', key = \'a_xmult\', vars = \\{G.P_CENTERS.v_observatory.config.extra}},\\n\\s+Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'The Hermit\' or self.ability.consumeable.hand_type or self.ability.name == \'Temperance\' or self.ability.name == \'Black Hole\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.queue_negative_removal then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'elseif self.ability.name == \'Blueprint\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'Blueprint\' or self.ability.name == \'Brainstorm\' then' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 227 patches to 'card.lua' -WARN - [♥] Pattern 'table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end)' on target 'cardarea.lua' resulted in no matches -INFO - [♥] Applied 19 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-02-11 01:21:33 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-02-11 01:21:34 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-02-11 01:21:34 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-02-11 01:21:34 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-02-11 01:21:34 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-02-11 01:21:34 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:21:34 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-02-11 01:21:34 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-02-11 01:21:34 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-02-11 01:21:34 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-02-11 01:21:34 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-02-11 01:21:34 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-02-11 01:21:34 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-02-11 01:21:34 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-02-11 01:21:34 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:21:34 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnStable] - Starting Unstable -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [Unstable_Suit] - Registering suit: Spades with the type suit_black -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [Unstable_Suit] - Registering suit: Clubs with the type suit_black -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [Unstable_Suit] - Registering suit: Hearts with the type suit_red -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [Unstable_Suit] - Registering suit: Diamonds with the type suit_red -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Starting UnstableEX -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_??? -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_e -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_0 -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_161 -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_r2 -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_13 -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_12 -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_11 -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_21 -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_Pi -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_25 -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_0.5 -INFO - [G] 2025-02-11 01:21:34 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_1 -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-02-11 01:21:34 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-02-11 01:21:34 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-02-11 01:21:34 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.729 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0065] Injected Atlas in 1309.479 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0029] Injected Sound in 19.334 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0032] Injected Stake in 0.852 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0008] Injected Rarity in 0.027 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0008] Injected ObjectType in 0.055 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0527] Injected Center in 2.581 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0012] Injected Undiscovered Sprite in 0.032 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0027] Injected Blind in 0.083 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0012] Injected Seal in 0.296 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0004] Injected Suit in 0.185 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0026] Injected Rank in 0.202 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0020] Injected DeckSkin in 0.186 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.293 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0031] Injected Challenge in 0.638 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0028] Injected Tag in 0.636 ms -INFO - [G] 2025-02-11 01:21:35 :: INFO :: TIMER :: [0009] Injected Sticker in 0.306 ms -INFO - [G] 2025-02-11 01:21:36 :: INFO :: TIMER :: [0009] Injected Shader in 50.625 ms -INFO - [G] 2025-02-11 01:21:36 :: INFO :: TIMER :: [0001] Injected Keybind in 0.005 ms -INFO - [G] 2025-02-11 01:21:36 :: INFO :: TIMER :: [0020] Injected Achievement in 0.104 ms -INFO - [G] 2025-02-11 01:21:36 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 12.730 ms -INFO - [G] 2025-02-11 01:21:36 :: INFO :: TIMER :: [0011] Injected Event in 0.014 ms -INFO - [G] 2025-02-11 01:21:36 :: DEBUG :: DefaultLogger :: [UnStable] - Initialize Remaining Previous Rank Data -INFO - [G] 2025-02-11 01:21:36 :: DEBUG :: DefaultLogger :: [UnStable] - Start initializing localization-independent info -INFO - [G] 2025-02-11 01:21:36 :: DEBUG :: DefaultLogger :: [UnStable] - Finished initializing localization-independent info -INFO - [G] 2025-02-11 01:21:36 :: DEBUG :: DefaultLogger :: [UnstableEX] - Inject new nominal code override for Cryptid -INFO - [G] 2025-02-11 01:21:36 :: DEBUG :: DefaultLogger :: [UnstableEX] - Inject Blind effects for Cryptid -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews diff --git a/lovely/log/lovely-2025.02.11-01.21.59.log b/lovely/log/lovely-2025.02.11-01.21.59.log deleted file mode 100644 index bb95ea5..0000000 --- a/lovely/log/lovely-2025.02.11-01.21.59.log +++ /dev/null @@ -1,326 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 125ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 35 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 13 patches to 'engine/controller.lua' -INFO - [♥] Applied 15 patches to 'back.lua' -INFO - [♥] Applied 15 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 48 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 85 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 110 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern '--calculate the card edition effects\nif effects[ii].edition then\n hand_chips = mod_chips(hand_chips + (effects[ii].edition.chip_mod or 0))\n mult = mult + (effects[ii].edition.mult_mod or 0)\n mult = mod_mult(mult*(effects[ii].edition.x_mult_mod or 1))\n update_hand_text({delay = 0}, {\n chips = effects[ii].edition.chip_mod and hand_chips or nil,\n mult = (effects[ii].edition.mult_mod or effects[ii].edition.x_mult_mod) and mult or nil,\n })\n card_eval_status_text(scoring_hand[i], \'extra\', nil, percent, nil, {\n message = (effects[ii].edition.chip_mod and localize{type=\'variable\',key=\'a_chips\',vars={effects[ii].edition.chip_mod}}) or\n (effects[ii].edition.mult_mod and localize{type=\'variable\',key=\'a_mult\',vars={effects[ii].edition.mult_mod}}) or\n (effects[ii].edition.x_mult_mod and localize{type=\'variable\',key=\'a_xmult\',vars={effects[ii].edition.x_mult_mod}}),\n chip_mod = effects[ii].edition.chip_mod,\n mult_mod = effects[ii].edition.mult_mod,\n x_mult_mod = effects[ii].edition.x_mult_mod,\n colour = G.C.DARK_EDITION,\n edition = true})\nend\n' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern ' scoring_hand[i].lucky_trigger = nil\n\n for ii = 1, #effects do\n --If chips added, do chip add event and add the chips to the total\n if effects[ii].chips then \n if effects[ii].card then juice_card(effects[ii].card) end\n hand_chips = mod_chips(hand_chips + effects[ii].chips)\n update_hand_text({delay = 0}, {chips = hand_chips})\n card_eval_status_text(scoring_hand[i], \'chips\', effects[ii].chips, percent)\n end\n\n --If mult added, do mult add event and add the mult to the total\n if effects[ii].mult then \n if effects[ii].card then juice_card(effects[ii].card) end\n mult = mod_mult(mult + effects[ii].mult)\n update_hand_text({delay = 0}, {mult = mult})\n card_eval_status_text(scoring_hand[i], \'mult\', effects[ii].mult, percent)\n end\n\n --If play dollars added, add dollars to total\n if effects[ii].p_dollars then \n if effects[ii].card then juice_card(effects[ii].card) end\n ease_dollars(effects[ii].p_dollars)\n card_eval_status_text(scoring_hand[i], \'dollars\', effects[ii].p_dollars, percent)\n end\n\n --If dollars added, add dollars to total\n if effects[ii].dollars then \n if effects[ii].card then juice_card(effects[ii].card) end\n ease_dollars(effects[ii].dollars)\n card_eval_status_text(scoring_hand[i], \'dollars\', effects[ii].dollars, percent)\n end\n\n --Any extra effects\n if effects[ii].extra then \n if effects[ii].card then juice_card(effects[ii].card) end\n local extras = {mult = false, hand_chips = false}\n if effects[ii].extra.mult_mod then mult =mod_mult( mult + effects[ii].extra.mult_mod);extras.mult = true end\n if effects[ii].extra.chip_mod then hand_chips = mod_chips(hand_chips + effects[ii].extra.chip_mod);extras.hand_chips = true end\n if effects[ii].extra.swap then \n local old_mult = mult\n mult = mod_mult(hand_chips)\n hand_chips = mod_chips(old_mult)\n extras.hand_chips = true; extras.mult = true\n end\n if effects[ii].extra.func then effects[ii].extra.func() end\n update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult})\n card_eval_status_text(scoring_hand[i], \'extra\', nil, percent, nil, effects[ii].extra)\n end\n\n --If x_mult added, do mult add event and mult the mult to the total\n if effects[ii].x_mult then \n if effects[ii].card then juice_card(effects[ii].card) end\n mult = mod_mult(mult*effects[ii].x_mult)\n update_hand_text({delay = 0}, {mult = mult})\n card_eval_status_text(scoring_hand[i], \'x_mult\', effects[ii].x_mult, percent)\n end\n\n\n end\n end\nend\n' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local percent = (i-0.999)/(#G.hand.cards-0.998) + (j-1)*0.1' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.effect ~= \'Stone Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'G.GAME.cards_played[scoring_hand[i].base.value].suits[scoring_hand[i].base.suit] = true' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local effects = {G.hand.cards[i]:get_end_of_round_effect()}' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.name == \'Glass Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i = 1, #G.jokers.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(_card, \'jokers\', nil, percent, nil, effects.jokers)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if extras.mult or extras.hand_chips then card_eval_status_text(v, \'jokers\', nil, percent, nil, effect) end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if extras.mult or extras.hand_chips then card_eval_status_text(v, \'jokers\', nil, percent, nil, effect) end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(scoring_hand[i], \'x_mult\', effects[ii].x_mult, percent)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(G.hand.cards[i], \'x_mult\', effects[ii].x_mult, percent)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'edition = true})' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i=1, #G.hand.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if reps[j] ~= 1 then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if destroyed then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if cards_destroyed[i].ability.name == \'Glass Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local edition_effects = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, edition = true})' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i=1, #G.jokers.cards + #G.consumeables.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local hand_space = e or math.min(#G.deck.cards, G.hand.config.card_limit - #G.hand.cards)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local effects = {G.hand.cards[i]:get_end_of_round_effect()}' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.name == \'Glass Card\' and not scoring_hand[i].debuff and pseudorandom(\'glass\') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].card then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects.jokers.Xmult_mod then mult = mod_mult(mult*effects.jokers.Xmult_mod);extras.mult = true end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effect.Xmult_mod then mult = mod_mult(mult*effect.Xmult_mod);extras.mult = true end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].message then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern '--calculate the card edition effects' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].edition.p_dollars_mod then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if edition_effects.jokers.x_mult_mod then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if destroyed then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if destroyed then \\n' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 62 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, hide_desc, main_start, main_end)' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = localize(\'$\')..config.dollars, scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif _c.name == \'Cryptid\' then loc_vars = {_c.config.extra}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif _c.name == \"Clearance Sale\" or _c.name == \"Liquidation\" then loc_vars = {_c.config.extra}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'if v == \'negative_consumable\' then info_queue[#info_queue+1] = {key = \'e_negative_consumable\', set = \'Edition\', config = {extra = 1}} end' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 141 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'if card.area and (not nc or card.area == G.pack_cards) then card.area:remove_card(card) end\n' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 65 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if center_table.name == \'Overstock\' or center_table.name == \'Overstock Plus\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'self:calculate_joker{selling_self = true}' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name:find(\'Arcana\') then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if center_table.name == \'Overstock\' or center_table.name == \'Overstock Plus\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Regex 'message = localize\\{type = \'variable\', key = \'a_xmult\', vars = \\{G.P_CENTERS.v_observatory.config.extra}},\\n\\s+Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'The Hermit\' or self.ability.consumeable.hand_type or self.ability.name == \'Temperance\' or self.ability.name == \'Black Hole\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.queue_negative_removal then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'elseif self.ability.name == \'Blueprint\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'Blueprint\' or self.ability.name == \'Brainstorm\' then' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 227 patches to 'card.lua' -WARN - [♥] Pattern 'table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end)' on target 'cardarea.lua' resulted in no matches -INFO - [♥] Applied 19 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-02-11 01:22:02 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-02-11 01:22:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-02-11 01:22:03 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-02-11 01:22:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-02-11 01:22:03 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-02-11 01:22:03 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:22:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-02-11 01:22:03 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-02-11 01:22:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-02-11 01:22:03 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-02-11 01:22:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-02-11 01:22:03 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-02-11 01:22:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-02-11 01:22:03 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-02-11 01:22:03 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:22:03 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnStable] - Starting Unstable -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [Unstable_Suit] - Registering suit: Spades with the type suit_black -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [Unstable_Suit] - Registering suit: Clubs with the type suit_black -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [Unstable_Suit] - Registering suit: Hearts with the type suit_red -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [Unstable_Suit] - Registering suit: Diamonds with the type suit_red -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Starting UnstableEX -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_??? -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_e -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_0 -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_161 -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_r2 -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_13 -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_12 -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_11 -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_21 -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_Pi -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_25 -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_0.5 -INFO - [G] 2025-02-11 01:22:03 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_1 -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-02-11 01:22:03 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-02-11 01:22:03 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-02-11 01:22:03 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.791 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0065] Injected Atlas in 1323.703 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0029] Injected Sound in 18.386 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0032] Injected Stake in 0.674 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0008] Injected Rarity in 0.040 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0008] Injected ObjectType in 0.068 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0527] Injected Center in 3.509 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0012] Injected Undiscovered Sprite in 0.023 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0027] Injected Blind in 0.044 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0012] Injected Seal in 0.402 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0004] Injected Suit in 0.155 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0026] Injected Rank in 0.223 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0020] Injected DeckSkin in 0.118 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.125 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0031] Injected Challenge in 0.057 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0028] Injected Tag in 0.058 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0009] Injected Sticker in 0.210 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0009] Injected Shader in 118.781 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0001] Injected Keybind in 0.005 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0020] Injected Achievement in 0.080 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 11.917 ms -INFO - [G] 2025-02-11 01:22:05 :: INFO :: TIMER :: [0011] Injected Event in 0.013 ms -INFO - [G] 2025-02-11 01:22:05 :: DEBUG :: DefaultLogger :: [UnStable] - Initialize Remaining Previous Rank Data -INFO - [G] 2025-02-11 01:22:05 :: DEBUG :: DefaultLogger :: [UnStable] - Start initializing localization-independent info -INFO - [G] 2025-02-11 01:22:05 :: DEBUG :: DefaultLogger :: [UnStable] - Finished initializing localization-independent info -INFO - [G] 2025-02-11 01:22:05 :: DEBUG :: DefaultLogger :: [UnstableEX] - Inject new nominal code override for Cryptid -INFO - [G] 2025-02-11 01:22:05 :: DEBUG :: DefaultLogger :: [UnstableEX] - Inject Blind effects for Cryptid -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-02-11 01:23:05 :: ERROR :: StackTrace :: Oops! The game crashed -[SMODS _ "src/utils.lua"]:1344: bad argument #1 to 'ipairs' (table expected, got nil) -Stack Traceback -=============== -(1) Lua upvalue 'orig' at file 'main.lua:756' - Local variables: - msg = string: "[SMODS _ \"src/utils.lua\"]:1344: bad argument #1 to 'ipairs' (table expected, got nil)" - (*temporary) = Lua function '?' (defined at line 31 of chunk [SMODS _ "src/logging.lua"]) - (*temporary) = string: "Oops! The game crashed\ -" -(2) Lua local 'handler' at file 'console.lua:551' (from lovely module debugplus.console) - Local variables: - msg = string: "[SMODS _ \"src/utils.lua\"]:1344: bad argument #1 to 'ipairs' (table expected, got nil)" -(3) LÖVE function at file 'boot.lua:352' (best guess) - Local variables: - errhand = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) - handler = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) -(4) global C function 'ipairs' -(5) Lua field 'calculate_context' at Steamodded file 'src/utils.lua:1344' - Local variables: - context = table: 0x087d2c40 {main_eval:true, buying_card:true, cardarea:table: 0x08951050, card:table: 0x0ab94cd0 (more...)} - return_table = nil - (for generator) = C function: builtin#6 - (for state) = table: 0x087d2d50 {1:table: 0x08951050, 2:table: 0x08969998, 3:table: 0x0882bdc8} - (for control) = number: 1 - _ = number: 1 - area = table: 0x08951050 {click_offset:table: 0x085b4790, children:table: 0x08d7dcb8, shuffle_amt:0 (more...)} - (for generator) = C function: builtin#6 - (for state) = table: 0x092b1000 {1:table: 0x0ab94cd0} - (for control) = number: 1 - _ = number: 1 - _card = table: 0x0ab94cd0 {added_to_deck:true, from_area:table: 0x13fe29d0, click_offset:table: 0x08c21190 (more...)} - eval = table: 0x087d2d98 {} - post = nil - effects = table: 0x087d36c8 {1:table: 0x087d2d98} -(6) Lua field 'func' at file 'functions/button_callbacks.lua:2487' -(7) Lua method 'handle' at file 'engine/event.lua:55' - Local variables: - self = table: 0x0bab9118 {start_timer:true, timer:TOTAL, blockable:true, trigger:after, func:function: 0x0bab90f0 (more...)} - _results = table: 0x0a0dda10 {blocking:true, pause_skip:false, time_done:true, completed:false} -(8) Lua method 'update' at file 'engine/event.lua:182' - Local variables: - self = table: 0x0a0dfdd8 {queue_last_processed:59.533333333331, queues:table: 0x0a0dfe00, queue_dt:0.016666666666667 (more...)} - dt = number: 0.00607273 - forced = nil - (for generator) = C function: next - (for state) = table: 0x0a0dfe00 {unlock:table: 0x0a0dfe28, other:table: 0x0a0e02a0, tutorial:table: 0x0a0dfe78 (more...)} - (for control) = number: nan - k = string: "base" - v = table: 0x0a0dfe50 {1:table: 0x09eeb660, 2:table: 0x0bab9118, 3:table: 0x089b3e68} - blocked = boolean: false - i = number: 2 - results = table: 0x0a0dda10 {blocking:true, pause_skip:false, time_done:true, completed:false} -(9) Lua upvalue 'gameUpdateRef' at file 'game.lua:2740' - Local variables: - self = table: 0x042376f8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0861f7f0 (more...)} - dt = number: 0.00607273 - http_resp = nil -(10) Lua upvalue 'upd' at Steamodded file 'src/ui.lua:84' - Local variables: - self = table: 0x042376f8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0861f7f0 (more...)} - dt = number: 0.00607273 -(11) Lua upvalue 'upd' at file 'main.lua:4094' - Local variables: - self = table: 0x042376f8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0861f7f0 (more...)} - dt = number: 0.00607273 -(12) Lua upvalue 'upd' at file 'Items/Blinds.lua:1310' (from mod with id Cryptid) - Local variables: - self = table: 0x042376f8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0861f7f0 (more...)} - dt = number: 0.00607273 -(13) Lua upvalue 'upd' at file 'Items/CodeCards.lua:4106' (from mod with id Cryptid) - Local variables: - self = table: 0x042376f8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0861f7f0 (more...)} - dt = number: 0.00607273 -(14) Lua upvalue 'upd' at file 'Items/Decks.lua:429' (from mod with id Cryptid) - Local variables: - self = table: 0x042376f8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0861f7f0 (more...)} - dt = number: 0.00607273 -(15) Lua upvalue 'upd' at file 'Items/MiscJokers.lua:6658' (from mod with id Cryptid) - Local variables: - self = table: 0x042376f8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0861f7f0 (more...)} - dt = number: 0.00607273 -(16) Lua method 'update' at file 'Cryptid.lua:2948' (from mod with id Cryptid) - Local variables: - self = table: 0x042376f8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x0861f7f0 (more...)} - dt = number: 0.00607273 -(17) Lua upvalue 'love_update_ref' at file 'main.lua:1146' - Local variables: - dt = number: 0.00607273 -(18) Lua upvalue 'oldupd' at file 'main.lua:3038' - Local variables: - dt = number: 0.00607273 -(19) Lua field 'update' at file 'main.lua:4121' - Local variables: - dt = number: 0.00607273 -(20) Lua function '?' at file 'main.lua:1079' (best guess) -(21) global C function 'xpcall' -(22) LÖVE function at file 'boot.lua:377' (best guess) - Local variables: - func = Lua function '?' (defined at line 1050 of chunk main.lua) - inerror = boolean: true - deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"]) - earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"]) - -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-02-11 01:23:05 :: INFO :: StackTrace :: Additional Context: -Balatro Version: 1.0.1n-FULL -Modded Version: 1.0.0~ALPHA-1410b-STEAMODDED -LÖVE Version: 11.5.0 -Lovely Version: 0.6.0 -Platform: Windows -Steamodded Mods: - 1: J Cursor by Jie65535, MarioMak967 [ID: JCursor] - 2: Cryptid by MathIsFun_, Cryptid and Balatro Discords [ID: Cryptid, Priority: 1e+299, Version: 0.5.3a, Uses Lovely] - 3: UnStableEX by Kirbio [ID: UnStableEX, Priority: 99999, Version: 0.2.2a] - 4: UnStable by Kirbio, RamChops Games [ID: UnStable, Priority: 777, Version: 1.1.2a, Uses Lovely] - 5: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.2, Uses Lovely] - Break Infinity: omeganum - 6: Cartomancer by stupxd aka stupid [ID: cartomancer, Priority: 69, Version: 4.10, Uses Lovely] - 7: Handy by SleepyG11 [ID: Handy, Version: 1.1.5, Uses Lovely] - 8: Incantation by jenwalter666, MathIsFun_ [ID: incantation, Priority: 9e+301, Version: 0.5.10, Uses Lovely] - 9: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.3.0, Uses Lovely] -Lovely Mods: diff --git a/lovely/log/lovely-2025.02.11-01.23.18.log b/lovely/log/lovely-2025.02.11-01.23.18.log deleted file mode 100644 index cfc3ab5..0000000 --- a/lovely/log/lovely-2025.02.11-01.23.18.log +++ /dev/null @@ -1,326 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 145ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 35 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 13 patches to 'engine/controller.lua' -INFO - [♥] Applied 15 patches to 'back.lua' -INFO - [♥] Applied 15 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 48 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 85 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 110 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern '--calculate the card edition effects\nif effects[ii].edition then\n hand_chips = mod_chips(hand_chips + (effects[ii].edition.chip_mod or 0))\n mult = mult + (effects[ii].edition.mult_mod or 0)\n mult = mod_mult(mult*(effects[ii].edition.x_mult_mod or 1))\n update_hand_text({delay = 0}, {\n chips = effects[ii].edition.chip_mod and hand_chips or nil,\n mult = (effects[ii].edition.mult_mod or effects[ii].edition.x_mult_mod) and mult or nil,\n })\n card_eval_status_text(scoring_hand[i], \'extra\', nil, percent, nil, {\n message = (effects[ii].edition.chip_mod and localize{type=\'variable\',key=\'a_chips\',vars={effects[ii].edition.chip_mod}}) or\n (effects[ii].edition.mult_mod and localize{type=\'variable\',key=\'a_mult\',vars={effects[ii].edition.mult_mod}}) or\n (effects[ii].edition.x_mult_mod and localize{type=\'variable\',key=\'a_xmult\',vars={effects[ii].edition.x_mult_mod}}),\n chip_mod = effects[ii].edition.chip_mod,\n mult_mod = effects[ii].edition.mult_mod,\n x_mult_mod = effects[ii].edition.x_mult_mod,\n colour = G.C.DARK_EDITION,\n edition = true})\nend\n' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern ' scoring_hand[i].lucky_trigger = nil\n\n for ii = 1, #effects do\n --If chips added, do chip add event and add the chips to the total\n if effects[ii].chips then \n if effects[ii].card then juice_card(effects[ii].card) end\n hand_chips = mod_chips(hand_chips + effects[ii].chips)\n update_hand_text({delay = 0}, {chips = hand_chips})\n card_eval_status_text(scoring_hand[i], \'chips\', effects[ii].chips, percent)\n end\n\n --If mult added, do mult add event and add the mult to the total\n if effects[ii].mult then \n if effects[ii].card then juice_card(effects[ii].card) end\n mult = mod_mult(mult + effects[ii].mult)\n update_hand_text({delay = 0}, {mult = mult})\n card_eval_status_text(scoring_hand[i], \'mult\', effects[ii].mult, percent)\n end\n\n --If play dollars added, add dollars to total\n if effects[ii].p_dollars then \n if effects[ii].card then juice_card(effects[ii].card) end\n ease_dollars(effects[ii].p_dollars)\n card_eval_status_text(scoring_hand[i], \'dollars\', effects[ii].p_dollars, percent)\n end\n\n --If dollars added, add dollars to total\n if effects[ii].dollars then \n if effects[ii].card then juice_card(effects[ii].card) end\n ease_dollars(effects[ii].dollars)\n card_eval_status_text(scoring_hand[i], \'dollars\', effects[ii].dollars, percent)\n end\n\n --Any extra effects\n if effects[ii].extra then \n if effects[ii].card then juice_card(effects[ii].card) end\n local extras = {mult = false, hand_chips = false}\n if effects[ii].extra.mult_mod then mult =mod_mult( mult + effects[ii].extra.mult_mod);extras.mult = true end\n if effects[ii].extra.chip_mod then hand_chips = mod_chips(hand_chips + effects[ii].extra.chip_mod);extras.hand_chips = true end\n if effects[ii].extra.swap then \n local old_mult = mult\n mult = mod_mult(hand_chips)\n hand_chips = mod_chips(old_mult)\n extras.hand_chips = true; extras.mult = true\n end\n if effects[ii].extra.func then effects[ii].extra.func() end\n update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult})\n card_eval_status_text(scoring_hand[i], \'extra\', nil, percent, nil, effects[ii].extra)\n end\n\n --If x_mult added, do mult add event and mult the mult to the total\n if effects[ii].x_mult then \n if effects[ii].card then juice_card(effects[ii].card) end\n mult = mod_mult(mult*effects[ii].x_mult)\n update_hand_text({delay = 0}, {mult = mult})\n card_eval_status_text(scoring_hand[i], \'x_mult\', effects[ii].x_mult, percent)\n end\n\n\n end\n end\nend\n' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local percent = (i-0.999)/(#G.hand.cards-0.998) + (j-1)*0.1' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.effect ~= \'Stone Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'G.GAME.cards_played[scoring_hand[i].base.value].suits[scoring_hand[i].base.suit] = true' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local effects = {G.hand.cards[i]:get_end_of_round_effect()}' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.name == \'Glass Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i = 1, #G.jokers.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(_card, \'jokers\', nil, percent, nil, effects.jokers)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if extras.mult or extras.hand_chips then card_eval_status_text(v, \'jokers\', nil, percent, nil, effect) end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if extras.mult or extras.hand_chips then card_eval_status_text(v, \'jokers\', nil, percent, nil, effect) end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(scoring_hand[i], \'x_mult\', effects[ii].x_mult, percent)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(G.hand.cards[i], \'x_mult\', effects[ii].x_mult, percent)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'edition = true})' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i=1, #G.hand.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if reps[j] ~= 1 then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if destroyed then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if cards_destroyed[i].ability.name == \'Glass Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local edition_effects = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, edition = true})' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i=1, #G.jokers.cards + #G.consumeables.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local hand_space = e or math.min(#G.deck.cards, G.hand.config.card_limit - #G.hand.cards)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local effects = {G.hand.cards[i]:get_end_of_round_effect()}' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.name == \'Glass Card\' and not scoring_hand[i].debuff and pseudorandom(\'glass\') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].card then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects.jokers.Xmult_mod then mult = mod_mult(mult*effects.jokers.Xmult_mod);extras.mult = true end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effect.Xmult_mod then mult = mod_mult(mult*effect.Xmult_mod);extras.mult = true end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].message then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern '--calculate the card edition effects' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].edition.p_dollars_mod then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if edition_effects.jokers.x_mult_mod then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if destroyed then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if destroyed then \\n' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 62 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, hide_desc, main_start, main_end)' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = localize(\'$\')..config.dollars, scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif _c.name == \'Cryptid\' then loc_vars = {_c.config.extra}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif _c.name == \"Clearance Sale\" or _c.name == \"Liquidation\" then loc_vars = {_c.config.extra}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'if v == \'negative_consumable\' then info_queue[#info_queue+1] = {key = \'e_negative_consumable\', set = \'Edition\', config = {extra = 1}} end' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 141 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'if card.area and (not nc or card.area == G.pack_cards) then card.area:remove_card(card) end\n' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 65 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if center_table.name == \'Overstock\' or center_table.name == \'Overstock Plus\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'self:calculate_joker{selling_self = true}' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name:find(\'Arcana\') then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if center_table.name == \'Overstock\' or center_table.name == \'Overstock Plus\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Regex 'message = localize\\{type = \'variable\', key = \'a_xmult\', vars = \\{G.P_CENTERS.v_observatory.config.extra}},\\n\\s+Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'The Hermit\' or self.ability.consumeable.hand_type or self.ability.name == \'Temperance\' or self.ability.name == \'Black Hole\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.queue_negative_removal then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'elseif self.ability.name == \'Blueprint\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'Blueprint\' or self.ability.name == \'Brainstorm\' then' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 227 patches to 'card.lua' -WARN - [♥] Pattern 'table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end)' on target 'cardarea.lua' resulted in no matches -INFO - [♥] Applied 19 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-02-11 01:23:22 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-02-11 01:23:23 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-02-11 01:23:23 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-02-11 01:23:23 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-02-11 01:23:23 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-02-11 01:23:23 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:23:23 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-02-11 01:23:23 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-02-11 01:23:23 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-02-11 01:23:23 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-02-11 01:23:23 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-02-11 01:23:23 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-02-11 01:23:23 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-02-11 01:23:23 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-02-11 01:23:23 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:23:23 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnStable] - Starting Unstable -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [Unstable_Suit] - Registering suit: Spades with the type suit_black -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [Unstable_Suit] - Registering suit: Clubs with the type suit_black -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [Unstable_Suit] - Registering suit: Hearts with the type suit_red -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [Unstable_Suit] - Registering suit: Diamonds with the type suit_red -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Starting UnstableEX -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_??? -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_e -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_0 -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_161 -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_r2 -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_13 -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_12 -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_11 -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_21 -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_Pi -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_25 -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_0.5 -INFO - [G] 2025-02-11 01:23:23 :: DEBUG :: DefaultLogger :: [UnstableEX] - Injecting the graphic for rank unstb_1 -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-02-11 01:23:23 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-02-11 01:23:23 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-02-11 01:23:23 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.723 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0065] Injected Atlas in 1293.110 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0029] Injected Sound in 18.756 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0032] Injected Stake in 0.799 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0008] Injected Rarity in 0.018 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0008] Injected ObjectType in 0.075 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0527] Injected Center in 2.810 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0012] Injected Undiscovered Sprite in 0.009 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0027] Injected Blind in 0.040 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0012] Injected Seal in 0.351 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0004] Injected Suit in 0.139 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0026] Injected Rank in 0.107 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0020] Injected DeckSkin in 0.178 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.105 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0031] Injected Challenge in 0.068 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0028] Injected Tag in 0.075 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0009] Injected Sticker in 0.118 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0009] Injected Shader in 52.104 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0001] Injected Keybind in 0.019 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0020] Injected Achievement in 0.067 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 12.056 ms -INFO - [G] 2025-02-11 01:23:24 :: INFO :: TIMER :: [0011] Injected Event in 0.012 ms -INFO - [G] 2025-02-11 01:23:24 :: DEBUG :: DefaultLogger :: [UnStable] - Initialize Remaining Previous Rank Data -INFO - [G] 2025-02-11 01:23:24 :: DEBUG :: DefaultLogger :: [UnStable] - Start initializing localization-independent info -INFO - [G] 2025-02-11 01:23:24 :: DEBUG :: DefaultLogger :: [UnStable] - Finished initializing localization-independent info -INFO - [G] 2025-02-11 01:23:24 :: DEBUG :: DefaultLogger :: [UnstableEX] - Inject new nominal code override for Cryptid -INFO - [G] 2025-02-11 01:23:24 :: DEBUG :: DefaultLogger :: [UnstableEX] - Inject Blind effects for Cryptid -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-02-11 01:24:19 :: ERROR :: StackTrace :: Oops! The game crashed -[SMODS _ "src/utils.lua"]:1344: bad argument #1 to 'ipairs' (table expected, got nil) -Stack Traceback -=============== -(1) Lua upvalue 'orig' at file 'main.lua:756' - Local variables: - msg = string: "[SMODS _ \"src/utils.lua\"]:1344: bad argument #1 to 'ipairs' (table expected, got nil)" - (*temporary) = Lua function '?' (defined at line 31 of chunk [SMODS _ "src/logging.lua"]) - (*temporary) = string: "Oops! The game crashed\ -" -(2) Lua local 'handler' at file 'console.lua:551' (from lovely module debugplus.console) - Local variables: - msg = string: "[SMODS _ \"src/utils.lua\"]:1344: bad argument #1 to 'ipairs' (table expected, got nil)" -(3) LÖVE function at file 'boot.lua:352' (best guess) - Local variables: - errhand = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) - handler = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) -(4) global C function 'ipairs' -(5) Lua field 'calculate_context' at Steamodded file 'src/utils.lua:1344' - Local variables: - context = table: 0x08849928 {main_eval:true, buying_card:true, cardarea:table: 0x097683b0, card:table: 0x087620f0 (more...)} - return_table = nil - (for generator) = C function: builtin#6 - (for state) = table: 0x046227c8 {1:table: 0x097683b0, 2:table: 0x06749e98, 3:table: 0x067f2050} - (for control) = number: 1 - _ = number: 1 - area = table: 0x097683b0 {click_offset:table: 0x099e1010, children:table: 0x099e1180, shuffle_amt:0 (more...)} - (for generator) = C function: builtin#6 - (for state) = table: 0x099e1158 {1:table: 0x087620f0} - (for control) = number: 1 - _ = number: 1 - _card = table: 0x087620f0 {added_to_deck:true, from_area:table: 0x0a793f10, click_offset:table: 0x08762498 (more...)} - eval = table: 0x04622810 {} - post = nil - effects = table: 0x04fb4280 {1:table: 0x04622810} -(6) Lua field 'func' at file 'functions/button_callbacks.lua:2487' -(7) Lua method 'handle' at file 'engine/event.lua:55' - Local variables: - self = table: 0x0a783800 {start_timer:true, timer:TOTAL, blockable:true, trigger:after, func:function: 0x10b8a300 (more...)} - _results = table: 0x14613508 {blocking:true, pause_skip:false, time_done:true, completed:false} -(8) Lua method 'update' at file 'engine/event.lua:182' - Local variables: - self = table: 0x0a0c6d40 {queue_last_processed:54.716666666665, queues:table: 0x0a0c6d68, queue_dt:0.016666666666667 (more...)} - dt = number: 0.00607149 - forced = nil - (for generator) = C function: next - (for state) = table: 0x0a0c6d68 {unlock:table: 0x0a0c6d90, other:table: 0x0a0c7208, tutorial:table: 0x0a0c6de0 (more...)} - (for control) = number: nan - k = string: "base" - v = table: 0x0a0c6db8 {1:table: 0x08fe8578, 2:table: 0x0a783800, 3:table: 0x0db7e358} - blocked = boolean: false - i = number: 2 - results = table: 0x14613508 {blocking:true, pause_skip:false, time_done:true, completed:false} -(9) Lua upvalue 'gameUpdateRef' at file 'game.lua:2740' - Local variables: - self = table: 0x042273c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x13e72bd0 (more...)} - dt = number: 0.00607149 - http_resp = nil -(10) Lua upvalue 'upd' at Steamodded file 'src/ui.lua:84' - Local variables: - self = table: 0x042273c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x13e72bd0 (more...)} - dt = number: 0.00607149 -(11) Lua upvalue 'upd' at file 'main.lua:4094' - Local variables: - self = table: 0x042273c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x13e72bd0 (more...)} - dt = number: 0.00607149 -(12) Lua upvalue 'upd' at file 'Items/Blinds.lua:1310' (from mod with id Cryptid) - Local variables: - self = table: 0x042273c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x13e72bd0 (more...)} - dt = number: 0.00607149 -(13) Lua upvalue 'upd' at file 'Items/CodeCards.lua:4106' (from mod with id Cryptid) - Local variables: - self = table: 0x042273c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x13e72bd0 (more...)} - dt = number: 0.00607149 -(14) Lua upvalue 'upd' at file 'Items/Decks.lua:429' (from mod with id Cryptid) - Local variables: - self = table: 0x042273c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x13e72bd0 (more...)} - dt = number: 0.00607149 -(15) Lua upvalue 'upd' at file 'Items/MiscJokers.lua:6658' (from mod with id Cryptid) - Local variables: - self = table: 0x042273c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x13e72bd0 (more...)} - dt = number: 0.00607149 -(16) Lua method 'update' at file 'Cryptid.lua:2948' (from mod with id Cryptid) - Local variables: - self = table: 0x042273c0 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x13e72bd0 (more...)} - dt = number: 0.00607149 -(17) Lua upvalue 'love_update_ref' at file 'main.lua:1146' - Local variables: - dt = number: 0.00607149 -(18) Lua upvalue 'oldupd' at file 'main.lua:3038' - Local variables: - dt = number: 0.00607149 -(19) Lua field 'update' at file 'main.lua:4121' - Local variables: - dt = number: 0.00607149 -(20) Lua function '?' at file 'main.lua:1079' (best guess) -(21) global C function 'xpcall' -(22) LÖVE function at file 'boot.lua:377' (best guess) - Local variables: - func = Lua function '?' (defined at line 1050 of chunk main.lua) - inerror = boolean: true - deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"]) - earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"]) - -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-02-11 01:24:19 :: INFO :: StackTrace :: Additional Context: -Balatro Version: 1.0.1n-FULL -Modded Version: 1.0.0~ALPHA-1410b-STEAMODDED -LÖVE Version: 11.5.0 -Lovely Version: 0.6.0 -Platform: Windows -Steamodded Mods: - 1: J Cursor by Jie65535, MarioMak967 [ID: JCursor] - 2: Cryptid by MathIsFun_, Cryptid and Balatro Discords [ID: Cryptid, Priority: 1e+299, Version: 0.5.3a, Uses Lovely] - 3: UnStableEX by Kirbio [ID: UnStableEX, Priority: 99999, Version: 0.2.2a] - 4: UnStable by Kirbio, RamChops Games [ID: UnStable, Priority: 777, Version: 1.1.2a, Uses Lovely] - 5: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.2, Uses Lovely] - Break Infinity: omeganum - 6: Cartomancer by stupxd aka stupid [ID: cartomancer, Priority: 69, Version: 4.10, Uses Lovely] - 7: Handy by SleepyG11 [ID: Handy, Version: 1.1.5, Uses Lovely] - 8: Incantation by jenwalter666, MathIsFun_ [ID: incantation, Priority: 9e+301, Version: 0.5.10, Uses Lovely] - 9: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.3.0, Uses Lovely] -Lovely Mods: diff --git a/lovely/log/lovely-2025.02.11-01.24.59.log b/lovely/log/lovely-2025.02.11-01.24.59.log deleted file mode 100644 index fc3d893..0000000 --- a/lovely/log/lovely-2025.02.11-01.24.59.log +++ /dev/null @@ -1,298 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 134ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 35 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 13 patches to 'engine/controller.lua' -INFO - [♥] Applied 15 patches to 'back.lua' -INFO - [♥] Applied 15 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 48 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 84 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 110 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern '--calculate the card edition effects\nif effects[ii].edition then\n hand_chips = mod_chips(hand_chips + (effects[ii].edition.chip_mod or 0))\n mult = mult + (effects[ii].edition.mult_mod or 0)\n mult = mod_mult(mult*(effects[ii].edition.x_mult_mod or 1))\n update_hand_text({delay = 0}, {\n chips = effects[ii].edition.chip_mod and hand_chips or nil,\n mult = (effects[ii].edition.mult_mod or effects[ii].edition.x_mult_mod) and mult or nil,\n })\n card_eval_status_text(scoring_hand[i], \'extra\', nil, percent, nil, {\n message = (effects[ii].edition.chip_mod and localize{type=\'variable\',key=\'a_chips\',vars={effects[ii].edition.chip_mod}}) or\n (effects[ii].edition.mult_mod and localize{type=\'variable\',key=\'a_mult\',vars={effects[ii].edition.mult_mod}}) or\n (effects[ii].edition.x_mult_mod and localize{type=\'variable\',key=\'a_xmult\',vars={effects[ii].edition.x_mult_mod}}),\n chip_mod = effects[ii].edition.chip_mod,\n mult_mod = effects[ii].edition.mult_mod,\n x_mult_mod = effects[ii].edition.x_mult_mod,\n colour = G.C.DARK_EDITION,\n edition = true})\nend\n' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern ' scoring_hand[i].lucky_trigger = nil\n\n for ii = 1, #effects do\n --If chips added, do chip add event and add the chips to the total\n if effects[ii].chips then \n if effects[ii].card then juice_card(effects[ii].card) end\n hand_chips = mod_chips(hand_chips + effects[ii].chips)\n update_hand_text({delay = 0}, {chips = hand_chips})\n card_eval_status_text(scoring_hand[i], \'chips\', effects[ii].chips, percent)\n end\n\n --If mult added, do mult add event and add the mult to the total\n if effects[ii].mult then \n if effects[ii].card then juice_card(effects[ii].card) end\n mult = mod_mult(mult + effects[ii].mult)\n update_hand_text({delay = 0}, {mult = mult})\n card_eval_status_text(scoring_hand[i], \'mult\', effects[ii].mult, percent)\n end\n\n --If play dollars added, add dollars to total\n if effects[ii].p_dollars then \n if effects[ii].card then juice_card(effects[ii].card) end\n ease_dollars(effects[ii].p_dollars)\n card_eval_status_text(scoring_hand[i], \'dollars\', effects[ii].p_dollars, percent)\n end\n\n --If dollars added, add dollars to total\n if effects[ii].dollars then \n if effects[ii].card then juice_card(effects[ii].card) end\n ease_dollars(effects[ii].dollars)\n card_eval_status_text(scoring_hand[i], \'dollars\', effects[ii].dollars, percent)\n end\n\n --Any extra effects\n if effects[ii].extra then \n if effects[ii].card then juice_card(effects[ii].card) end\n local extras = {mult = false, hand_chips = false}\n if effects[ii].extra.mult_mod then mult =mod_mult( mult + effects[ii].extra.mult_mod);extras.mult = true end\n if effects[ii].extra.chip_mod then hand_chips = mod_chips(hand_chips + effects[ii].extra.chip_mod);extras.hand_chips = true end\n if effects[ii].extra.swap then \n local old_mult = mult\n mult = mod_mult(hand_chips)\n hand_chips = mod_chips(old_mult)\n extras.hand_chips = true; extras.mult = true\n end\n if effects[ii].extra.func then effects[ii].extra.func() end\n update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult})\n card_eval_status_text(scoring_hand[i], \'extra\', nil, percent, nil, effects[ii].extra)\n end\n\n --If x_mult added, do mult add event and mult the mult to the total\n if effects[ii].x_mult then \n if effects[ii].card then juice_card(effects[ii].card) end\n mult = mod_mult(mult*effects[ii].x_mult)\n update_hand_text({delay = 0}, {mult = mult})\n card_eval_status_text(scoring_hand[i], \'x_mult\', effects[ii].x_mult, percent)\n end\n\n\n end\n end\nend\n' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local percent = (i-0.999)/(#G.hand.cards-0.998) + (j-1)*0.1' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.effect ~= \'Stone Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'G.GAME.cards_played[scoring_hand[i].base.value].suits[scoring_hand[i].base.suit] = true' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local effects = {G.hand.cards[i]:get_end_of_round_effect()}' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.name == \'Glass Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i = 1, #G.jokers.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(_card, \'jokers\', nil, percent, nil, effects.jokers)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if extras.mult or extras.hand_chips then card_eval_status_text(v, \'jokers\', nil, percent, nil, effect) end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if extras.mult or extras.hand_chips then card_eval_status_text(v, \'jokers\', nil, percent, nil, effect) end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(scoring_hand[i], \'x_mult\', effects[ii].x_mult, percent)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(G.hand.cards[i], \'x_mult\', effects[ii].x_mult, percent)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'edition = true})' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i=1, #G.hand.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if reps[j] ~= 1 then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if destroyed then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if cards_destroyed[i].ability.name == \'Glass Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local edition_effects = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, edition = true})' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i=1, #G.jokers.cards + #G.consumeables.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local hand_space = e or math.min(#G.deck.cards, G.hand.config.card_limit - #G.hand.cards)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local effects = {G.hand.cards[i]:get_end_of_round_effect()}' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.name == \'Glass Card\' and not scoring_hand[i].debuff and pseudorandom(\'glass\') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].card then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects.jokers.Xmult_mod then mult = mod_mult(mult*effects.jokers.Xmult_mod);extras.mult = true end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effect.Xmult_mod then mult = mod_mult(mult*effect.Xmult_mod);extras.mult = true end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].message then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern '--calculate the card edition effects' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].edition.p_dollars_mod then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if edition_effects.jokers.x_mult_mod then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if destroyed then \\n' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 61 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, hide_desc, main_start, main_end)' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = localize(\'$\')..config.dollars, scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif _c.name == \'Cryptid\' then loc_vars = {_c.config.extra}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif _c.name == \"Clearance Sale\" or _c.name == \"Liquidation\" then loc_vars = {_c.config.extra}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'if v == \'negative_consumable\' then info_queue[#info_queue+1] = {key = \'e_negative_consumable\', set = \'Edition\', config = {extra = 1}} end' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 139 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'if card.area and (not nc or card.area == G.pack_cards) then card.area:remove_card(card) end\n' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 63 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if center_table.name == \'Overstock\' or center_table.name == \'Overstock Plus\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'self:calculate_joker{selling_self = true}' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name:find(\'Arcana\') then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if center_table.name == \'Overstock\' or center_table.name == \'Overstock Plus\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Regex 'message = localize\\{type = \'variable\', key = \'a_xmult\', vars = \\{G.P_CENTERS.v_observatory.config.extra}},\\n\\s+Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'The Hermit\' or self.ability.consumeable.hand_type or self.ability.name == \'Temperance\' or self.ability.name == \'Black Hole\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.queue_negative_removal then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 223 patches to 'card.lua' -WARN - [♥] Pattern 'table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end)' on target 'cardarea.lua' resulted in no matches -INFO - [♥] Applied 19 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-02-11 01:25:02 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-02-11 01:25:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-02-11 01:25:03 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-02-11 01:25:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-02-11 01:25:03 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-02-11 01:25:03 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:25:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-02-11 01:25:03 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-02-11 01:25:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-02-11 01:25:03 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-02-11 01:25:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-02-11 01:25:03 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-02-11 01:25:03 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-02-11 01:25:03 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-02-11 01:25:03 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-02-11 01:25:03 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-02-11 01:25:03 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-02-11 01:25:03 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.861 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0032] Injected Atlas in 791.179 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0026] Injected Sound in 17.836 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0032] Injected Stake in 0.832 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0008] Injected Rarity in 0.038 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.052 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0393] Injected Center in 2.042 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.009 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0027] Injected Blind in 0.051 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0006] Injected Seal in 0.295 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0004] Injected Suit in 0.102 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0013] Injected Rank in 0.064 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0020] Injected DeckSkin in 0.148 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.097 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0031] Injected Challenge in 0.034 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0028] Injected Tag in 0.111 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0009] Injected Sticker in 0.156 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0009] Injected Shader in 55.077 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0001] Injected Keybind in 0.005 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0020] Injected Achievement in 0.068 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.540 ms -INFO - [G] 2025-02-11 01:25:04 :: INFO :: TIMER :: [0011] Injected Event in 0.014 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-02-11 01:25:13 :: ERROR :: StackTrace :: Oops! The game crashed -[SMODS _ "src/utils.lua"]:1344: bad argument #1 to 'ipairs' (table expected, got nil) -Stack Traceback -=============== -(1) Lua upvalue 'orig' at file 'main.lua:756' - Local variables: - msg = string: "[SMODS _ \"src/utils.lua\"]:1344: bad argument #1 to 'ipairs' (table expected, got nil)" - (*temporary) = Lua function '?' (defined at line 31 of chunk [SMODS _ "src/logging.lua"]) - (*temporary) = string: "Oops! The game crashed\ -" -(2) Lua local 'handler' at file 'console.lua:551' (from lovely module debugplus.console) - Local variables: - msg = string: "[SMODS _ \"src/utils.lua\"]:1344: bad argument #1 to 'ipairs' (table expected, got nil)" -(3) LÖVE function at file 'boot.lua:352' (best guess) - Local variables: - errhand = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) - handler = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) -(4) global C function 'ipairs' -(5) Lua field 'calculate_context' at Steamodded file 'src/utils.lua:1344' - Local variables: - context = table: 0x0607fda0 {main_eval:true, buying_card:true, cardarea:table: 0x14235fe8, card:table: 0x04360488 (more...)} - return_table = nil - (for generator) = C function: builtin#6 - (for state) = table: 0x0607fe30 {1:table: 0x14235fe8, 2:table: 0x14222340, 3:table: 0x1969f1d8} - (for control) = number: 1 - _ = number: 1 - area = table: 0x14235fe8 {click_offset:table: 0x14236358, children:table: 0x0450f6b0, shuffle_amt:0 (more...)} - (for generator) = C function: builtin#6 - (for state) = table: 0x0450f688 {1:table: 0x04360488} - (for control) = number: 1 - _ = number: 1 - _card = table: 0x04360488 {added_to_deck:true, from_area:table: 0x0628ccf8, click_offset:table: 0x1bdd8720 (more...)} - eval = table: 0x0607fe78 {} - post = nil - effects = table: 0x13aaac08 {1:table: 0x0607fe78} -(6) Lua field 'func' at file 'functions/button_callbacks.lua:2480' -(7) Lua method 'handle' at file 'engine/event.lua:55' - Local variables: - self = table: 0x044e9e20 {start_timer:true, timer:TOTAL, blockable:true, trigger:after, func:function: 0x044e9df8 (more...)} - _results = table: 0x0419aa68 {blocking:true, pause_skip:false, time_done:true, completed:false} -(8) Lua method 'update' at file 'engine/event.lua:182' - Local variables: - self = table: 0x09c988e8 {queue_last_processed:9.1833333333334, queues:table: 0x09c98910, queue_dt:0.016666666666667 (more...)} - dt = number: 0.00606218 - forced = nil - (for generator) = C function: next - (for state) = table: 0x09c98910 {unlock:table: 0x09c98938, other:table: 0x09c98db0, tutorial:table: 0x09c98988 (more...)} - (for control) = number: nan - k = string: "base" - v = table: 0x09c98960 {1:table: 0x13acfe10, 2:table: 0x044e9e20, 3:table: 0x0bdff4c8} - blocked = boolean: false - i = number: 2 - results = table: 0x0419aa68 {blocking:true, pause_skip:false, time_done:true, completed:false} -(9) Lua upvalue 'gameUpdateRef' at file 'game.lua:2739' - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06408c98 (more...)} - dt = number: 0.00606218 - http_resp = nil -(10) Lua upvalue 'upd' at Steamodded file 'src/ui.lua:84' - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06408c98 (more...)} - dt = number: 0.00606218 -(11) Lua upvalue 'upd' at file 'main.lua:4094' - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06408c98 (more...)} - dt = number: 0.00606218 -(12) Lua upvalue 'upd' at file 'Items/Blinds.lua:1310' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06408c98 (more...)} - dt = number: 0.00606218 -(13) Lua upvalue 'upd' at file 'Items/CodeCards.lua:4106' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06408c98 (more...)} - dt = number: 0.00606218 -(14) Lua upvalue 'upd' at file 'Items/Decks.lua:429' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06408c98 (more...)} - dt = number: 0.00606218 -(15) Lua upvalue 'upd' at file 'Items/MiscJokers.lua:6658' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06408c98 (more...)} - dt = number: 0.00606218 -(16) Lua method 'update' at file 'Cryptid.lua:2948' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x06408c98 (more...)} - dt = number: 0.00606218 -(17) Lua upvalue 'love_update_ref' at file 'main.lua:1146' - Local variables: - dt = number: 0.00606218 -(18) Lua upvalue 'oldupd' at file 'main.lua:3038' - Local variables: - dt = number: 0.00606218 -(19) Lua field 'update' at file 'main.lua:4121' - Local variables: - dt = number: 0.00606218 -(20) Lua function '?' at file 'main.lua:1079' (best guess) -(21) global C function 'xpcall' -(22) LÖVE function at file 'boot.lua:377' (best guess) - Local variables: - func = Lua function '?' (defined at line 1050 of chunk main.lua) - inerror = boolean: true - deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"]) - earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"]) - -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-02-11 01:25:13 :: INFO :: StackTrace :: Additional Context: -Balatro Version: 1.0.1n-FULL -Modded Version: 1.0.0~ALPHA-1410b-STEAMODDED -LÖVE Version: 11.5.0 -Lovely Version: 0.6.0 -Platform: Windows -Steamodded Mods: - 1: J Cursor by Jie65535, MarioMak967 [ID: JCursor] - 2: Cryptid by MathIsFun_, Cryptid and Balatro Discords [ID: Cryptid, Priority: 1e+299, Version: 0.5.3a, Uses Lovely] - 3: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.2, Uses Lovely] - Break Infinity: omeganum - 4: Cartomancer by stupxd aka stupid [ID: cartomancer, Priority: 69, Version: 4.10, Uses Lovely] - 5: Handy by SleepyG11 [ID: Handy, Version: 1.1.5, Uses Lovely] - 6: Incantation by jenwalter666, MathIsFun_ [ID: incantation, Priority: 9e+301, Version: 0.5.10, Uses Lovely] - 7: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.3.0, Uses Lovely] -Lovely Mods: diff --git a/lovely/log/lovely-2025.02.11-01.26.34.log b/lovely/log/lovely-2025.02.11-01.26.34.log deleted file mode 100644 index d375a2e..0000000 --- a/lovely/log/lovely-2025.02.11-01.26.34.log +++ /dev/null @@ -1,298 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 172ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 35 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 13 patches to 'engine/controller.lua' -INFO - [♥] Applied 15 patches to 'back.lua' -INFO - [♥] Applied 15 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 48 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 84 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 110 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern '--calculate the card edition effects\nif effects[ii].edition then\n hand_chips = mod_chips(hand_chips + (effects[ii].edition.chip_mod or 0))\n mult = mult + (effects[ii].edition.mult_mod or 0)\n mult = mod_mult(mult*(effects[ii].edition.x_mult_mod or 1))\n update_hand_text({delay = 0}, {\n chips = effects[ii].edition.chip_mod and hand_chips or nil,\n mult = (effects[ii].edition.mult_mod or effects[ii].edition.x_mult_mod) and mult or nil,\n })\n card_eval_status_text(scoring_hand[i], \'extra\', nil, percent, nil, {\n message = (effects[ii].edition.chip_mod and localize{type=\'variable\',key=\'a_chips\',vars={effects[ii].edition.chip_mod}}) or\n (effects[ii].edition.mult_mod and localize{type=\'variable\',key=\'a_mult\',vars={effects[ii].edition.mult_mod}}) or\n (effects[ii].edition.x_mult_mod and localize{type=\'variable\',key=\'a_xmult\',vars={effects[ii].edition.x_mult_mod}}),\n chip_mod = effects[ii].edition.chip_mod,\n mult_mod = effects[ii].edition.mult_mod,\n x_mult_mod = effects[ii].edition.x_mult_mod,\n colour = G.C.DARK_EDITION,\n edition = true})\nend\n' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern ' scoring_hand[i].lucky_trigger = nil\n\n for ii = 1, #effects do\n --If chips added, do chip add event and add the chips to the total\n if effects[ii].chips then \n if effects[ii].card then juice_card(effects[ii].card) end\n hand_chips = mod_chips(hand_chips + effects[ii].chips)\n update_hand_text({delay = 0}, {chips = hand_chips})\n card_eval_status_text(scoring_hand[i], \'chips\', effects[ii].chips, percent)\n end\n\n --If mult added, do mult add event and add the mult to the total\n if effects[ii].mult then \n if effects[ii].card then juice_card(effects[ii].card) end\n mult = mod_mult(mult + effects[ii].mult)\n update_hand_text({delay = 0}, {mult = mult})\n card_eval_status_text(scoring_hand[i], \'mult\', effects[ii].mult, percent)\n end\n\n --If play dollars added, add dollars to total\n if effects[ii].p_dollars then \n if effects[ii].card then juice_card(effects[ii].card) end\n ease_dollars(effects[ii].p_dollars)\n card_eval_status_text(scoring_hand[i], \'dollars\', effects[ii].p_dollars, percent)\n end\n\n --If dollars added, add dollars to total\n if effects[ii].dollars then \n if effects[ii].card then juice_card(effects[ii].card) end\n ease_dollars(effects[ii].dollars)\n card_eval_status_text(scoring_hand[i], \'dollars\', effects[ii].dollars, percent)\n end\n\n --Any extra effects\n if effects[ii].extra then \n if effects[ii].card then juice_card(effects[ii].card) end\n local extras = {mult = false, hand_chips = false}\n if effects[ii].extra.mult_mod then mult =mod_mult( mult + effects[ii].extra.mult_mod);extras.mult = true end\n if effects[ii].extra.chip_mod then hand_chips = mod_chips(hand_chips + effects[ii].extra.chip_mod);extras.hand_chips = true end\n if effects[ii].extra.swap then \n local old_mult = mult\n mult = mod_mult(hand_chips)\n hand_chips = mod_chips(old_mult)\n extras.hand_chips = true; extras.mult = true\n end\n if effects[ii].extra.func then effects[ii].extra.func() end\n update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult})\n card_eval_status_text(scoring_hand[i], \'extra\', nil, percent, nil, effects[ii].extra)\n end\n\n --If x_mult added, do mult add event and mult the mult to the total\n if effects[ii].x_mult then \n if effects[ii].card then juice_card(effects[ii].card) end\n mult = mod_mult(mult*effects[ii].x_mult)\n update_hand_text({delay = 0}, {mult = mult})\n card_eval_status_text(scoring_hand[i], \'x_mult\', effects[ii].x_mult, percent)\n end\n\n\n end\n end\nend\n' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local percent = (i-0.999)/(#G.hand.cards-0.998) + (j-1)*0.1' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.effect ~= \'Stone Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'G.GAME.cards_played[scoring_hand[i].base.value].suits[scoring_hand[i].base.suit] = true' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local effects = {G.hand.cards[i]:get_end_of_round_effect()}' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.name == \'Glass Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i = 1, #G.jokers.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(_card, \'jokers\', nil, percent, nil, effects.jokers)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if extras.mult or extras.hand_chips then card_eval_status_text(v, \'jokers\', nil, percent, nil, effect) end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if extras.mult or extras.hand_chips then card_eval_status_text(v, \'jokers\', nil, percent, nil, effect) end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(scoring_hand[i], \'x_mult\', effects[ii].x_mult, percent)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(G.hand.cards[i], \'x_mult\', effects[ii].x_mult, percent)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'edition = true})' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i=1, #G.hand.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if reps[j] ~= 1 then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if destroyed then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if cards_destroyed[i].ability.name == \'Glass Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local edition_effects = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, edition = true})' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i=1, #G.jokers.cards + #G.consumeables.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local hand_space = e or math.min(#G.deck.cards, G.hand.config.card_limit - #G.hand.cards)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local effects = {G.hand.cards[i]:get_end_of_round_effect()}' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.name == \'Glass Card\' and not scoring_hand[i].debuff and pseudorandom(\'glass\') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].card then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects.jokers.Xmult_mod then mult = mod_mult(mult*effects.jokers.Xmult_mod);extras.mult = true end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effect.Xmult_mod then mult = mod_mult(mult*effect.Xmult_mod);extras.mult = true end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].message then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern '--calculate the card edition effects' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].edition.p_dollars_mod then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if edition_effects.jokers.x_mult_mod then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if destroyed then \\n' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 61 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, hide_desc, main_start, main_end)' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = localize(\'$\')..config.dollars, scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif _c.name == \'Cryptid\' then loc_vars = {_c.config.extra}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif _c.name == \"Clearance Sale\" or _c.name == \"Liquidation\" then loc_vars = {_c.config.extra}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'if v == \'negative_consumable\' then info_queue[#info_queue+1] = {key = \'e_negative_consumable\', set = \'Edition\', config = {extra = 1}} end' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 139 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'if card.area and (not nc or card.area == G.pack_cards) then card.area:remove_card(card) end\n' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 63 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if center_table.name == \'Overstock\' or center_table.name == \'Overstock Plus\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'self:calculate_joker{selling_self = true}' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name:find(\'Arcana\') then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if center_table.name == \'Overstock\' or center_table.name == \'Overstock Plus\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Regex 'message = localize\\{type = \'variable\', key = \'a_xmult\', vars = \\{G.P_CENTERS.v_observatory.config.extra}},\\n\\s+Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'The Hermit\' or self.ability.consumeable.hand_type or self.ability.name == \'Temperance\' or self.ability.name == \'Black Hole\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.queue_negative_removal then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 223 patches to 'card.lua' -WARN - [♥] Pattern 'table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end)' on target 'cardarea.lua' resulted in no matches -INFO - [♥] Applied 19 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-02-11 01:26:37 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-02-11 01:26:38 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-02-11 01:26:38 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-02-11 01:26:38 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-02-11 01:26:38 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-02-11 01:26:38 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:26:38 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-02-11 01:26:38 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-02-11 01:26:38 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-02-11 01:26:38 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-02-11 01:26:38 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-02-11 01:26:38 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-02-11 01:26:38 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-02-11 01:26:38 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-02-11 01:26:38 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-02-11 01:26:38 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-02-11 01:26:38 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-02-11 01:26:38 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.719 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0032] Injected Atlas in 781.089 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0026] Injected Sound in 17.477 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0032] Injected Stake in 0.616 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0008] Injected Rarity in 0.040 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.043 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0393] Injected Center in 1.956 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.009 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0027] Injected Blind in 0.093 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0006] Injected Seal in 0.181 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0004] Injected Suit in 0.071 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0013] Injected Rank in 0.059 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0020] Injected DeckSkin in 0.280 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.122 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0031] Injected Challenge in 0.190 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0028] Injected Tag in 0.339 ms -INFO - [G] 2025-02-11 01:26:39 :: INFO :: TIMER :: [0009] Injected Sticker in 0.682 ms -INFO - [G] 2025-02-11 01:26:40 :: INFO :: TIMER :: [0009] Injected Shader in 802.807 ms -INFO - [G] 2025-02-11 01:26:40 :: INFO :: TIMER :: [0001] Injected Keybind in 0.027 ms -INFO - [G] 2025-02-11 01:26:40 :: INFO :: TIMER :: [0020] Injected Achievement in 0.069 ms -INFO - [G] 2025-02-11 01:26:40 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.255 ms -INFO - [G] 2025-02-11 01:26:40 :: INFO :: TIMER :: [0011] Injected Event in 0.009 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-02-11 01:26:56 :: ERROR :: StackTrace :: Oops! The game crashed -[SMODS _ "src/utils.lua"]:1344: bad argument #1 to 'ipairs' (table expected, got nil) -Stack Traceback -=============== -(1) Lua upvalue 'orig' at file 'main.lua:756' - Local variables: - msg = string: "[SMODS _ \"src/utils.lua\"]:1344: bad argument #1 to 'ipairs' (table expected, got nil)" - (*temporary) = Lua function '?' (defined at line 31 of chunk [SMODS _ "src/logging.lua"]) - (*temporary) = string: "Oops! The game crashed\ -" -(2) Lua local 'handler' at file 'console.lua:551' (from lovely module debugplus.console) - Local variables: - msg = string: "[SMODS _ \"src/utils.lua\"]:1344: bad argument #1 to 'ipairs' (table expected, got nil)" -(3) LÖVE function at file 'boot.lua:352' (best guess) - Local variables: - errhand = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) - handler = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) -(4) global C function 'ipairs' -(5) Lua field 'calculate_context' at Steamodded file 'src/utils.lua:1344' - Local variables: - context = table: 0x0edc71a0 {main_eval:true, buying_card:true, cardarea:table: 0x144fe080, card:table: 0x0bee5fa8 (more...)} - return_table = nil - (for generator) = C function: builtin#6 - (for state) = table: 0x0edc7268 {1:table: 0x144fe080, 2:table: 0x1aab2a88, 3:table: 0x14533560} - (for control) = number: 1 - _ = number: 1 - area = table: 0x144fe080 {click_offset:table: 0x14588450, children:table: 0x13ddc268, shuffle_amt:0 (more...)} - (for generator) = C function: builtin#6 - (for state) = table: 0x04661b28 {1:table: 0x0bee5fa8} - (for control) = number: 1 - _ = number: 1 - _card = table: 0x0bee5fa8 {added_to_deck:true, from_area:table: 0x0449ef68, click_offset:table: 0x04fbf8a0 (more...)} - eval = table: 0x0edc72b0 {} - post = nil - effects = table: 0x0bed8b18 {1:table: 0x0edc72b0} -(6) Lua field 'func' at file 'functions/button_callbacks.lua:2480' -(7) Lua method 'handle' at file 'engine/event.lua:55' - Local variables: - self = table: 0x09cb36e0 {start_timer:true, timer:TOTAL, blockable:true, trigger:after, func:function: 0x09cb36b8 (more...)} - _results = table: 0x050450d0 {blocking:true, pause_skip:false, time_done:true, completed:false} -(8) Lua method 'update' at file 'engine/event.lua:182' - Local variables: - self = table: 0x0b018a58 {queue_last_processed:15.633333333334, queues:table: 0x0b018a80, queue_dt:0.016666666666667 (more...)} - dt = number: 0.00608305 - forced = nil - (for generator) = C function: next - (for state) = table: 0x0b018a80 {unlock:table: 0x0b018aa8, other:table: 0x0b018f20, tutorial:table: 0x0b018af8 (more...)} - (for control) = number: nan - k = string: "base" - v = table: 0x0b018ad0 {1:table: 0x144f0dc0, 2:table: 0x09cb36e0, 3:table: 0x0edc7178} - blocked = boolean: false - i = number: 2 - results = table: 0x050450d0 {blocking:true, pause_skip:false, time_done:true, completed:false} -(9) Lua upvalue 'gameUpdateRef' at file 'game.lua:2739' - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x1170d808 (more...)} - dt = number: 0.00608305 - http_resp = nil -(10) Lua upvalue 'upd' at Steamodded file 'src/ui.lua:84' - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x1170d808 (more...)} - dt = number: 0.00608305 -(11) Lua upvalue 'upd' at file 'main.lua:4094' - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x1170d808 (more...)} - dt = number: 0.00608305 -(12) Lua upvalue 'upd' at file 'Items/Blinds.lua:1310' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x1170d808 (more...)} - dt = number: 0.00608305 -(13) Lua upvalue 'upd' at file 'Items/CodeCards.lua:4106' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x1170d808 (more...)} - dt = number: 0.00608305 -(14) Lua upvalue 'upd' at file 'Items/Decks.lua:429' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x1170d808 (more...)} - dt = number: 0.00608305 -(15) Lua upvalue 'upd' at file 'Items/MiscJokers.lua:6658' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x1170d808 (more...)} - dt = number: 0.00608305 -(16) Lua method 'update' at file 'Cryptid.lua:2948' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x1170d808 (more...)} - dt = number: 0.00608305 -(17) Lua upvalue 'love_update_ref' at file 'main.lua:1146' - Local variables: - dt = number: 0.00608305 -(18) Lua upvalue 'oldupd' at file 'main.lua:3038' - Local variables: - dt = number: 0.00608305 -(19) Lua field 'update' at file 'main.lua:4121' - Local variables: - dt = number: 0.00608305 -(20) Lua function '?' at file 'main.lua:1079' (best guess) -(21) global C function 'xpcall' -(22) LÖVE function at file 'boot.lua:377' (best guess) - Local variables: - func = Lua function '?' (defined at line 1050 of chunk main.lua) - inerror = boolean: true - deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"]) - earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"]) - -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-02-11 01:26:56 :: INFO :: StackTrace :: Additional Context: -Balatro Version: 1.0.1n-FULL -Modded Version: 1.0.0~ALPHA-1410b-STEAMODDED -LÖVE Version: 11.5.0 -Lovely Version: 0.6.0 -Platform: Windows -Steamodded Mods: - 1: J Cursor by Jie65535, MarioMak967 [ID: JCursor] - 2: Cryptid by MathIsFun_, Cryptid and Balatro Discords [ID: Cryptid, Priority: 1e+299, Version: 0.5.3a, Uses Lovely] - 3: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.2, Uses Lovely] - Break Infinity: omeganum - 4: Cartomancer by stupxd aka stupid [ID: cartomancer, Priority: 69, Version: 4.10, Uses Lovely] - 5: Handy by SleepyG11 [ID: Handy, Version: 1.1.5, Uses Lovely] - 6: Incantation by jenwalter666, MathIsFun_ [ID: incantation, Priority: 9e+301, Version: 0.5.10, Uses Lovely] - 7: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.3.0, Uses Lovely] -Lovely Mods: diff --git a/lovely/log/lovely-2025.02.11-01.27.22.log b/lovely/log/lovely-2025.02.11-01.27.22.log deleted file mode 100644 index 1591e49..0000000 --- a/lovely/log/lovely-2025.02.11-01.27.22.log +++ /dev/null @@ -1,132 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 133ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 30 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 12 patches to 'engine/controller.lua' -INFO - [♥] Applied 13 patches to 'back.lua' -INFO - [♥] Applied 14 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 46 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 82 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 118 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 98 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'local cfg = (card and card.ability) or _c[\'config\']' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if G\\.F_NO_ACHIEVEMENTS then return end\\n[\\s\\S][\\s\\S]{16}--\\|LOCAL SETTINGS FILE' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 124 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'G.pack_cards:emplace(v)' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 53 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 206 patches to 'card.lua' -INFO - [♥] Applied 20 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-02-11 01:27:26 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-02-11 01:27:27 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-02-11 01:27:27 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-02-11 01:27:27 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-02-11 01:27:27 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-02-11 01:27:27 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:27:27 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-02-11 01:27:27 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-02-11 01:27:27 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-02-11 01:27:27 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-02-11 01:27:27 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-02-11 01:27:27 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-02-11 01:27:27 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-02-11 01:27:27 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-02-11 01:27:27 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-02-11 01:27:27 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-02-11 01:27:27 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-02-11 01:27:27 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.767 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0032] Injected Atlas in 784.495 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0025] Injected Sound in 20.943 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0032] Injected Stake in 0.580 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0008] Injected Rarity in 0.045 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.058 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0392] Injected Center in 2.721 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.026 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0027] Injected Blind in 0.048 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0002] Injected Seal in 0.060 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0004] Injected Suit in 0.060 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0013] Injected Rank in 0.062 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0016] Injected DeckSkin in 0.030 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.138 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0031] Injected Challenge in 0.128 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0028] Injected Tag in 0.254 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0009] Injected Sticker in 0.852 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0009] Injected Shader in 125.826 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0000] Injected Keybind in 0.001 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0020] Injected Achievement in 0.133 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.643 ms -INFO - [G] 2025-02-11 01:27:28 :: INFO :: TIMER :: [0011] Injected Event in 0.018 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load diff --git a/lovely/log/lovely-2025.02.11-01.28.56.log b/lovely/log/lovely-2025.02.11-01.28.56.log deleted file mode 100644 index 2747cc7..0000000 --- a/lovely/log/lovely-2025.02.11-01.28.56.log +++ /dev/null @@ -1,298 +0,0 @@ -INFO - [♥] Lovely 0.6.0 -INFO - [♥] Game directory is at "Z:\\run\\media\\vomitblood\\DataDisk1\\SteamLibrary\\steamapps\\common\\Balatro" -INFO - [♥] Writing logs to "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\log" -INFO - [♥] Using mod directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods" -INFO - [♥] Cleaning up dumps directory at "C:\\users\\steamuser\\AppData\\Roaming\\Balatro\\Mods\\lovely\\dump" -INFO - [♥] Initialization complete in 131ms -INFO - [♥] Applied 1 patch to 'conf.lua' -WARN - [♥] Pattern 'G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensity.required_score > 0 and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'if type(G.GAME.current_round.current_hand.chips) ~= \'number\' or type(G.GAME.current_round.current_hand.mult) ~= \'number\' then' on target 'main.lua' resulted in no matches -WARN - [♥] Pattern 'modded and {' on target 'main.lua' resulted in no matches -INFO - [♥] Applied 35 patches to 'main.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [♥] Applied 13 patches to 'engine/controller.lua' -INFO - [♥] Applied 15 patches to 'back.lua' -INFO - [♥] Applied 15 patches to 'tag.lua' -INFO - [♥] Applied 2 patches to 'engine/moveable.lua' -INFO - [♥] Applied 2 patches to 'engine/sprite.lua' -INFO - [♥] Applied 2 patches to 'engine/animatedsprite.lua' -WARN - [♥] Pattern 'assembled_string = assembled_string..(type(subpart) == \'string\' and subpart or args.vars[tonumber(subpart[1])] or \'ERROR\')' on target 'functions/misc_functions.lua' resulted in no matches -INFO - [♥] Applied 48 patches to 'functions/misc_functions.lua' -INFO - [♥] Applied 84 patches to 'game.lua' -INFO - [♥] Applied 1 patch to 'globals.lua' -WARN - [♥] Pattern 'self.config.chosen = true' on target 'engine/ui.lua' resulted in no matches -INFO - [♥] Applied 7 patches to 'engine/ui.lua' -WARN - [♥] Pattern '{card_limit = _size, type = \'consumeable\', highlight_limit = 1}' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}},' on target 'functions/UI_definitions.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}' on target 'functions/UI_definitions.lua' resulted in no matches -INFO - [♥] Applied 110 patches to 'functions/UI_definitions.lua' -WARN - [♥] Pattern '--calculate the card edition effects\nif effects[ii].edition then\n hand_chips = mod_chips(hand_chips + (effects[ii].edition.chip_mod or 0))\n mult = mult + (effects[ii].edition.mult_mod or 0)\n mult = mod_mult(mult*(effects[ii].edition.x_mult_mod or 1))\n update_hand_text({delay = 0}, {\n chips = effects[ii].edition.chip_mod and hand_chips or nil,\n mult = (effects[ii].edition.mult_mod or effects[ii].edition.x_mult_mod) and mult or nil,\n })\n card_eval_status_text(scoring_hand[i], \'extra\', nil, percent, nil, {\n message = (effects[ii].edition.chip_mod and localize{type=\'variable\',key=\'a_chips\',vars={effects[ii].edition.chip_mod}}) or\n (effects[ii].edition.mult_mod and localize{type=\'variable\',key=\'a_mult\',vars={effects[ii].edition.mult_mod}}) or\n (effects[ii].edition.x_mult_mod and localize{type=\'variable\',key=\'a_xmult\',vars={effects[ii].edition.x_mult_mod}}),\n chip_mod = effects[ii].edition.chip_mod,\n mult_mod = effects[ii].edition.mult_mod,\n x_mult_mod = effects[ii].edition.x_mult_mod,\n colour = G.C.DARK_EDITION,\n edition = true})\nend\n' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern ' scoring_hand[i].lucky_trigger = nil\n\n for ii = 1, #effects do\n --If chips added, do chip add event and add the chips to the total\n if effects[ii].chips then \n if effects[ii].card then juice_card(effects[ii].card) end\n hand_chips = mod_chips(hand_chips + effects[ii].chips)\n update_hand_text({delay = 0}, {chips = hand_chips})\n card_eval_status_text(scoring_hand[i], \'chips\', effects[ii].chips, percent)\n end\n\n --If mult added, do mult add event and add the mult to the total\n if effects[ii].mult then \n if effects[ii].card then juice_card(effects[ii].card) end\n mult = mod_mult(mult + effects[ii].mult)\n update_hand_text({delay = 0}, {mult = mult})\n card_eval_status_text(scoring_hand[i], \'mult\', effects[ii].mult, percent)\n end\n\n --If play dollars added, add dollars to total\n if effects[ii].p_dollars then \n if effects[ii].card then juice_card(effects[ii].card) end\n ease_dollars(effects[ii].p_dollars)\n card_eval_status_text(scoring_hand[i], \'dollars\', effects[ii].p_dollars, percent)\n end\n\n --If dollars added, add dollars to total\n if effects[ii].dollars then \n if effects[ii].card then juice_card(effects[ii].card) end\n ease_dollars(effects[ii].dollars)\n card_eval_status_text(scoring_hand[i], \'dollars\', effects[ii].dollars, percent)\n end\n\n --Any extra effects\n if effects[ii].extra then \n if effects[ii].card then juice_card(effects[ii].card) end\n local extras = {mult = false, hand_chips = false}\n if effects[ii].extra.mult_mod then mult =mod_mult( mult + effects[ii].extra.mult_mod);extras.mult = true end\n if effects[ii].extra.chip_mod then hand_chips = mod_chips(hand_chips + effects[ii].extra.chip_mod);extras.hand_chips = true end\n if effects[ii].extra.swap then \n local old_mult = mult\n mult = mod_mult(hand_chips)\n hand_chips = mod_chips(old_mult)\n extras.hand_chips = true; extras.mult = true\n end\n if effects[ii].extra.func then effects[ii].extra.func() end\n update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult})\n card_eval_status_text(scoring_hand[i], \'extra\', nil, percent, nil, effects[ii].extra)\n end\n\n --If x_mult added, do mult add event and mult the mult to the total\n if effects[ii].x_mult then \n if effects[ii].card then juice_card(effects[ii].card) end\n mult = mod_mult(mult*effects[ii].x_mult)\n update_hand_text({delay = 0}, {mult = mult})\n card_eval_status_text(scoring_hand[i], \'x_mult\', effects[ii].x_mult, percent)\n end\n\n\n end\n end\nend\n' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local percent = (i-0.999)/(#G.hand.cards-0.998) + (j-1)*0.1' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.effect ~= \'Stone Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'G.GAME.cards_played[scoring_hand[i].base.value].suits[scoring_hand[i].base.suit] = true' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local effects = {G.hand.cards[i]:get_end_of_round_effect()}' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.name == \'Glass Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i = 1, #G.jokers.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(_card, \'jokers\', nil, percent, nil, effects.jokers)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if extras.mult or extras.hand_chips then card_eval_status_text(v, \'jokers\', nil, percent, nil, effect) end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if extras.mult or extras.hand_chips then card_eval_status_text(v, \'jokers\', nil, percent, nil, effect) end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(scoring_hand[i], \'x_mult\', effects[ii].x_mult, percent)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'card_eval_status_text(G.hand.cards[i], \'x_mult\', effects[ii].x_mult, percent)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'edition = true})' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i=1, #G.hand.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if reps[j] ~= 1 then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if destroyed then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if cards_destroyed[i].ability.name == \'Glass Card\' then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local edition_effects = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, edition = true})' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'for i=1, #G.jokers.cards + #G.consumeables.cards do' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local hand_space = e or math.min(#G.deck.cards, G.hand.config.card_limit - #G.hand.cards)' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'local effects = {G.hand.cards[i]:get_end_of_round_effect()}' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if scoring_hand[i].ability.name == \'Glass Card\' and not scoring_hand[i].debuff and pseudorandom(\'glass\') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].card then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects.jokers.Xmult_mod then mult = mod_mult(mult*effects.jokers.Xmult_mod);extras.mult = true end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effect.Xmult_mod then mult = mod_mult(mult*effect.Xmult_mod);extras.mult = true end' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].message then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern '--calculate the card edition effects' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if effects[ii].edition.p_dollars_mod then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Pattern 'if edition_effects.jokers.x_mult_mod then' on target 'functions/state_events.lua' resulted in no matches -WARN - [♥] Regex '(?[\\t ]*)if destroyed then \\n' on target 'functions/state_events.lua' resulted in no matches -INFO - [♥] Applied 61 patches to 'functions/state_events.lua' -WARN - [♥] Pattern 'function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, hide_desc, main_start, main_end)' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern '{n=G.UIT.T, config={text = localize(\'$\')..config.dollars, scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif _c.name == \'Cryptid\' then loc_vars = {_c.config.extra}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif _c.name == \"Clearance Sale\" or _c.name == \"Liquidation\" then loc_vars = {_c.config.extra}' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'if v == \'negative_consumable\' then info_queue[#info_queue+1] = {key = \'e_negative_consumable\', set = \'Edition\', config = {extra = 1}} end' on target 'functions/common_events.lua' resulted in no matches -WARN - [♥] Pattern 'func = (function() if eval_func(card) then if not first or first then card:juice_up(0.1, 0.1) end;juice_card_until(card, eval_func, nil, 0.8) end return true end)' on target 'functions/common_events.lua' resulted in no matches -INFO - [♥] Applied 139 patches to 'functions/common_events.lua' -WARN - [♥] Pattern 'if card.area and (not nc or card.area == G.pack_cards) then card.area:remove_card(card) end\n' on target 'functions/button_callbacks.lua' resulted in no matches -INFO - [♥] Applied 63 patches to 'functions/button_callbacks.lua' -WARN - [♥] Pattern 'if k ~= \'focused_ui\' and k ~= \"front\" and k ~= \"back\" and k ~= \"soul_parts\" and k ~= \"center\" and k ~= \'floating_sprite\' and k~= \"shadow\" and k~= \"use_button\" and k ~= \'buy_button\' and k ~= \'buy_and_use_button\' and k~= \"debuff\" and k ~= \'price\' and k~= \'particles\' and k ~= \'h_popup\' then v:draw() end' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if center_table.name == \'Overstock\' or center_table.name == \'Overstock Plus\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'self:calculate_joker{selling_self = true}' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'Campfire\' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name:find(\'Arcana\') then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if center_table.name == \'Overstock\' or center_table.name == \'Overstock Plus\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Regex 'message = localize\\{type = \'variable\', key = \'a_xmult\', vars = \\{G.P_CENTERS.v_observatory.config.extra}},\\n\\s+Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.name == \'The Hermit\' or self.ability.consumeable.hand_type or self.ability.name == \'Temperance\' or self.ability.name == \'Black Hole\' then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if self.ability.queue_negative_removal then' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'Xmult_mod = G.P_CENTERS.v_observatory.config.extra' on target 'card.lua' resulted in no matches -WARN - [♥] Pattern 'if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end' on target 'card.lua' resulted in no matches -INFO - [♥] Applied 223 patches to 'card.lua' -WARN - [♥] Pattern 'table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end)' on target 'cardarea.lua' resulted in no matches -INFO - [♥] Applied 19 patches to 'cardarea.lua' -INFO - [♥] Applied 32 patches to 'blind.lua' -INFO - [♥] Applied 5 patches to 'engine/text.lua' -INFO - [G] Totally applied 4 replacements to overrides.lua -INFO - [G] Failed to connect to the debug server -INFO - [G] 2025-02-11 01:29:00 :: DEBUG :: DebugConsole :: Steamodded Debug Socket started ! -INFO - [♥] Applied 9 patches to 'engine/sound_manager.lua' -INFO - [♥] Applied 2 patches to 'engine/string_packer.lua' -INFO - [G] 2025-02-11 01:29:00 :: TRACE :: Loader :: Processing Mod file (Legacy header): mod.lua -INFO - [G] 2025-02-11 01:29:00 :: TRACE :: Loader :: Saving Mod Info: cartomancer -INFO - [G] 2025-02-11 01:29:00 :: TRACE :: Loader :: Processing Mod file (Legacy header): Cryptid.lua -INFO - [G] 2025-02-11 01:29:00 :: TRACE :: Loader :: Saving Mod Info: Cryptid -INFO - [G] 2025-02-11 01:29:00 :: INFO :: DefaultLogger :: Valid JSON file found -INFO - [G] 2025-02-11 01:29:00 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded.lua -INFO - [G] 2025-02-11 01:29:00 :: TRACE :: Loader :: Saving Mod Info: Handy -INFO - [G] 2025-02-11 01:29:00 :: TRACE :: Loader :: Processing Mod file (Legacy header): Incantation.lua -INFO - [G] 2025-02-11 01:29:00 :: TRACE :: Loader :: Saving Mod Info: incantation -INFO - [G] 2025-02-11 01:29:00 :: TRACE :: Loader :: Processing Mod file (Legacy header): JCursor.lua -INFO - [G] 2025-02-11 01:29:00 :: TRACE :: Loader :: Saving Mod Info: JCursor -INFO - [G] 2025-02-11 01:29:00 :: TRACE :: Loader :: Processing Mod file (Legacy header): steamodded_metadata.lua -INFO - [G] 2025-02-11 01:29:00 :: TRACE :: Loader :: Saving Mod Info: Talisman -INFO - [G] 2025-02-11 01:29:00 :: DEBUG :: DefaultLogger :: JCursor loaded! -INFO - [G] Loading file Achievements.lua -INFO - [G] Loading file Antimatter.lua -INFO - [G] Loading file Blinds.lua -INFO - [G] Loading file Challenges.lua -INFO - [G] Loading file CodeCards.lua -INFO - [G] Loading file CryptidJokerDisplay.lua -INFO - [G] Warning: CryptidJokerDisplay.lua has no items -INFO - [G] Loading file Decks.lua -INFO - [G] Loading file Enhanced.lua -INFO - [G] Loading file EpicJokers.lua -INFO - [G] Loading file Exotic.lua -INFO - [G] Loading file M.lua -INFO - [G] Loading file Misc.lua -INFO - [G] Loading file MiscJokers.lua -INFO - [G] Loading file Planets.lua -INFO - [G] Loading file Sleeves.lua -INFO - [G] Loading file Spectrals.lua -INFO - [G] Loading file Spooky.lua -INFO - [G] Loading file Stakes.lua -INFO - [G] Loading file Tags.lua -INFO - [G] Loading file Vouchers.lua -INFO - [G] Loading file dummy_https.lua -INFO - [G] Warning: dummy_https.lua has no items -INFO - [G] Loading file dummy_timerblinds.lua -INFO - [G] Warning: dummy_timerblinds.lua has no items -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Atlas :: Detected duplicate register call on object cry_modicon -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Atlas :: Detected duplicate register call on object cry_placeholders -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasepic -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasone -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlastwo -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasthree -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasspooky -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasexotic -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Atlas :: Detected duplicate register call on object cry_atlasnotjokers -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Atlas :: Detected duplicate register call on object cry_tag_cry -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Atlas :: Detected duplicate register call on object cry_misc -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Sticker :: Detected duplicate register call on object perishable -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Sticker :: Detected duplicate register call on object pinned -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Sticker :: Detected duplicate register call on object eternal -INFO - [G] 2025-02-11 01:29:01 :: WARN :: Sticker :: Detected duplicate register call on object rental -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0000] Injected Language in 0.001 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 0.706 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0032] Injected Atlas in 799.965 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0026] Injected Sound in 18.012 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0032] Injected Stake in 0.745 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0008] Injected Rarity in 0.020 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0007] Injected ObjectType in 0.061 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0393] Injected Center in 2.240 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0011] Injected Undiscovered Sprite in 0.027 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0027] Injected Blind in 0.051 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0006] Injected Seal in 0.167 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0004] Injected Suit in 0.076 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0013] Injected Rank in 0.067 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0020] Injected DeckSkin in 0.127 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0016] Injected PokerHand in 0.094 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0031] Injected Challenge in 0.150 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0028] Injected Tag in 0.049 ms -INFO - [G] 2025-02-11 01:29:01 :: INFO :: TIMER :: [0009] Injected Sticker in 0.114 ms -INFO - [G] 2025-02-11 01:29:02 :: INFO :: TIMER :: [0009] Injected Shader in 117.972 ms -INFO - [G] 2025-02-11 01:29:02 :: INFO :: TIMER :: [0001] Injected Keybind in 0.005 ms -INFO - [G] 2025-02-11 01:29:02 :: INFO :: TIMER :: [0020] Injected Achievement in 0.076 ms -INFO - [G] 2025-02-11 01:29:02 :: INFO :: TIMER :: [0000] Injected [INTERNAL] in 6.732 ms -INFO - [G] 2025-02-11 01:29:02 :: INFO :: TIMER :: [0011] Injected Event in 0.012 ms -INFO - [G] [DebugPlus] Press [/] to toggle console and press [shift] + [/] to toggle new log previews -INFO - [G] ERROR LOADING GAME: Card area 'shop_jokers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_vouchers' not instantiated before load -INFO - [G] ERROR LOADING GAME: Card area 'shop_booster' not instantiated before load -INFO - [G] line not found -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-02-11 01:29:28 :: ERROR :: StackTrace :: Oops! The game crashed -[SMODS _ "src/utils.lua"]:1344: bad argument #1 to 'ipairs' (table expected, got nil) -Stack Traceback -=============== -(1) Lua upvalue 'orig' at file 'main.lua:756' - Local variables: - msg = string: "[SMODS _ \"src/utils.lua\"]:1344: bad argument #1 to 'ipairs' (table expected, got nil)" - (*temporary) = Lua function '?' (defined at line 31 of chunk [SMODS _ "src/logging.lua"]) - (*temporary) = string: "Oops! The game crashed\ -" -(2) Lua local 'handler' at file 'console.lua:551' (from lovely module debugplus.console) - Local variables: - msg = string: "[SMODS _ \"src/utils.lua\"]:1344: bad argument #1 to 'ipairs' (table expected, got nil)" -(3) LÖVE function at file 'boot.lua:352' (best guess) - Local variables: - errhand = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) - handler = Lua function '(LÖVE Function)' (defined at line 550 of chunk [lovely debugplus.console "console.lua"]) -(4) global C function 'ipairs' -(5) Lua field 'calculate_context' at Steamodded file 'src/utils.lua:1344' - Local variables: - context = table: 0x14195988 {main_eval:true, buying_card:true, cardarea:table: 0x066b4d48, card:table: 0x1410dd58 (more...)} - return_table = nil - (for generator) = C function: builtin#6 - (for state) = table: 0x14193d18 {1:table: 0x066b4d48, 2:table: 0x064ab010, 3:table: 0x09ccc760} - (for control) = number: 1 - _ = number: 1 - area = table: 0x066b4d48 {click_offset:table: 0x066b50f0, children:table: 0x062f0980, shuffle_amt:0 (more...)} - (for generator) = C function: builtin#6 - (for state) = table: 0x062f0958 {1:table: 0x062f09a8, 2:table: 0x1410dd58} - (for control) = number: 1 - _ = number: 1 - _card = table: 0x062f09a8 {click_offset:table: 0x062f0cf0, children:table: 0x066c9318, ambient_tilt:0.2 (more...)} - eval = table: 0x14195a50 {} - post = nil - effects = table: 0x13e0eed8 {1:table: 0x14195a50} -(6) Lua field 'func' at file 'functions/button_callbacks.lua:2480' -(7) Lua method 'handle' at file 'engine/event.lua:55' - Local variables: - self = table: 0x0607fe28 {start_timer:true, timer:TOTAL, blockable:true, trigger:after, func:function: 0x0607fe00 (more...)} - _results = table: 0x04540d98 {blocking:true, pause_skip:false, time_done:true, completed:false} -(8) Lua method 'update' at file 'engine/event.lua:182' - Local variables: - self = table: 0x0b015908 {queue_last_processed:22.1, queues:table: 0x0b015930, queue_dt:0.016666666666667 (more...)} - dt = number: 0.00607317 - forced = nil - (for generator) = C function: next - (for state) = table: 0x0b015930 {unlock:table: 0x0b015958, other:table: 0x0b015dd0, tutorial:table: 0x0b0159a8 (more...)} - (for control) = number: nan - k = string: "base" - v = table: 0x0b015980 {1:table: 0x062f05b0, 2:table: 0x0607fe28, 3:table: 0x14193cf0} - blocked = boolean: false - i = number: 2 - results = table: 0x04540d98 {blocking:true, pause_skip:false, time_done:true, completed:false} -(9) Lua upvalue 'gameUpdateRef' at file 'game.lua:2739' - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x066dd1c0 (more...)} - dt = number: 0.00607317 - http_resp = nil -(10) Lua upvalue 'upd' at Steamodded file 'src/ui.lua:84' - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x066dd1c0 (more...)} - dt = number: 0.00607317 -(11) Lua upvalue 'upd' at file 'main.lua:4094' - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x066dd1c0 (more...)} - dt = number: 0.00607317 -(12) Lua upvalue 'upd' at file 'Items/Blinds.lua:1310' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x066dd1c0 (more...)} - dt = number: 0.00607317 -(13) Lua upvalue 'upd' at file 'Items/CodeCards.lua:4106' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x066dd1c0 (more...)} - dt = number: 0.00607317 -(14) Lua upvalue 'upd' at file 'Items/Decks.lua:429' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x066dd1c0 (more...)} - dt = number: 0.00607317 -(15) Lua upvalue 'upd' at file 'Items/MiscJokers.lua:6658' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x066dd1c0 (more...)} - dt = number: 0.00607317 -(16) Lua method 'update' at file 'Cryptid.lua:2948' (from mod with id Cryptid) - Local variables: - self = table: 0x04237730 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:true, HUD_tags:table: 0x066dd1c0 (more...)} - dt = number: 0.00607317 -(17) Lua upvalue 'love_update_ref' at file 'main.lua:1146' - Local variables: - dt = number: 0.00607317 -(18) Lua upvalue 'oldupd' at file 'main.lua:3038' - Local variables: - dt = number: 0.00607317 -(19) Lua field 'update' at file 'main.lua:4121' - Local variables: - dt = number: 0.00607317 -(20) Lua function '?' at file 'main.lua:1079' (best guess) -(21) global C function 'xpcall' -(22) LÖVE function at file 'boot.lua:377' (best guess) - Local variables: - func = Lua function '?' (defined at line 1050 of chunk main.lua) - inerror = boolean: true - deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"]) - earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"]) - -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] file not found: main.lua: No such file or directory -INFO - [G] 2025-02-11 01:29:28 :: INFO :: StackTrace :: Additional Context: -Balatro Version: 1.0.1n-FULL -Modded Version: 1.0.0~ALPHA-1410b-STEAMODDED -LÖVE Version: 11.5.0 -Lovely Version: 0.6.0 -Platform: Windows -Steamodded Mods: - 1: J Cursor by Jie65535, MarioMak967 [ID: JCursor] - 2: Cryptid by MathIsFun_, Cryptid and Balatro Discords [ID: Cryptid, Priority: 1e+299, Version: 0.5.3a, Uses Lovely] - 3: Talisman by MathIsFun_, Mathguy24, jenwalter666, cg-223 [ID: Talisman, Version: 2.0.2, Uses Lovely] - Break Infinity: omeganum - 4: Cartomancer by stupxd aka stupid [ID: cartomancer, Priority: 69, Version: 4.10, Uses Lovely] - 5: Handy by SleepyG11 [ID: Handy, Version: 1.1.5, Uses Lovely] - 6: Incantation by jenwalter666, MathIsFun_ [ID: incantation, Priority: 9e+301, Version: 0.5.10, Uses Lovely] - 7: DebugPlus by WilsontheWolf [ID: DebugPlus, Version: 1.3.0, Uses Lovely] -Lovely Mods: diff --git a/smods-main/.gitattributes b/smods-main/.gitattributes new file mode 100644 index 0000000..94f480d --- /dev/null +++ b/smods-main/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf \ No newline at end of file diff --git a/smods-main/.github/.keep b/smods-main/.github/.keep new file mode 100644 index 0000000..e69de29 diff --git a/smods-main/.github/workflows/version-bumper.yml b/smods-main/.github/workflows/version-bumper.yml new file mode 100644 index 0000000..ae8baeb --- /dev/null +++ b/smods-main/.github/workflows/version-bumper.yml @@ -0,0 +1,70 @@ +name: Version Bumper and Tagger + +on: push + +jobs: + check-version-change: + if: github.repository_owner == 'Steamopollys' + runs-on: ubuntu-latest + outputs: + version_changed: ${{ steps.detect-version-change.outputs.version_changed }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 2 # Fetch the current and previous commit for comparison + + - name: Detect version change + id: detect-version-change + run: | + echo ::set-output name=version_changed::$(git diff HEAD^ HEAD -- manifest.json | grep -q '"version_number":' && echo "true" || echo "false") + + bump-and-tag-version: + needs: check-version-change + if: needs.check-version-change.outputs.version_changed == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Necessary for tagging to include all history + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + + - name: Bump version and create tag + run: | + import json + import re + from pathlib import Path + + # Load and parse manifest.json + manifest_path = Path('manifest.json') + manifest = json.loads(manifest_path.read_text()) + version_number = manifest['version_number'] + + # Update core/core.lua + core_lua_path = Path('core/core.lua') + core_lua_content = core_lua_path.read_text() + core_lua_content = re.sub(r'MODDED_VERSION = "\d+\.\d+\.\d+-STEAMODDED"', f'MODDED_VERSION = "{version_number}-STEAMODDED"', core_lua_content) + core_lua_path.write_text(core_lua_content) + + # Output version number for later steps + print(f"::set-output name=version_number::{version_number}") + id: bump-version + shell: python + + - name: Commit and push if changed + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: "Automatically bump version to ${{ needs.bump-and-tag-version.outputs.version_number }}" + file_pattern: core/core.lua injector.ps1 + + - name: Create and push tag + if: steps.bump-version.outputs.version_number + env: + VERSION: ${{ steps.bump-version.outputs.version_number }} + run: | + git tag $VERSION + git push origin $VERSION + diff --git a/smods-main/.gitignore b/smods-main/.gitignore new file mode 100644 index 0000000..390eb80 --- /dev/null +++ b/smods-main/.gitignore @@ -0,0 +1,199 @@ +# Created by https://www.toptal.com/developers/gitignore/api/python +# Edit at https://www.toptal.com/developers/gitignore?templates=python + +*~ + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +### Python Patch ### +# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration +poetry.toml + +# ruff +.ruff_cache/ + +# LSP config files +pyrightconfig.json + +## IntelliJ +/.idea/ +/shelf/ +/workspace.xml +/httpRequests/ +/dataSources/ +/dataSources.local.xml + +# End of https://www.toptal.com/developers/gitignore/api/python + +# Mac +.DS_Store + +/injector/steamodded_injector.dist/ +/injector/steamodded_injector.exe +/steamodded_injector.build/ +/steamodded_injector.dist/ +/steamodded_injector.onefile-build/ +/steamodded_injector.exe + +*.Identifier +core/EditionAPI.lua diff --git a/Steamodded/LICENSE b/smods-main/LICENSE similarity index 100% rename from Steamodded/LICENSE rename to smods-main/LICENSE diff --git a/Steamodded/README.md b/smods-main/README.md similarity index 100% rename from Steamodded/README.md rename to smods-main/README.md diff --git a/Steamodded/TODO b/smods-main/TODO similarity index 100% rename from Steamodded/TODO rename to smods-main/TODO diff --git a/Steamodded/assets/1x/default_achievements.png b/smods-main/assets/1x/default_achievements.png similarity index 100% rename from Steamodded/assets/1x/default_achievements.png rename to smods-main/assets/1x/default_achievements.png diff --git a/smods-main/assets/1x/mod_tags.png b/smods-main/assets/1x/mod_tags.png new file mode 100644 index 0000000..c236b92 Binary files /dev/null and b/smods-main/assets/1x/mod_tags.png differ diff --git a/Steamodded/assets/2x/default_achievements.png b/smods-main/assets/2x/default_achievements.png similarity index 100% rename from Steamodded/assets/2x/default_achievements.png rename to smods-main/assets/2x/default_achievements.png diff --git a/smods-main/assets/2x/mod_tags.png b/smods-main/assets/2x/mod_tags.png new file mode 100644 index 0000000..2ada9aa Binary files /dev/null and b/smods-main/assets/2x/mod_tags.png differ diff --git a/smods-main/assets/sounds/xchips.ogg b/smods-main/assets/sounds/xchips.ogg new file mode 100644 index 0000000..ae47dfa Binary files /dev/null and b/smods-main/assets/sounds/xchips.ogg differ diff --git a/Steamodded/config.lua b/smods-main/config.lua similarity index 100% rename from Steamodded/config.lua rename to smods-main/config.lua diff --git a/Steamodded/icon.png b/smods-main/icon.png similarity index 100% rename from Steamodded/icon.png rename to smods-main/icon.png diff --git a/Steamodded/libs/json/init.lua b/smods-main/libs/json/init.lua similarity index 100% rename from Steamodded/libs/json/init.lua rename to smods-main/libs/json/init.lua diff --git a/Steamodded/libs/json/json.lua b/smods-main/libs/json/json.lua similarity index 100% rename from Steamodded/libs/json/json.lua rename to smods-main/libs/json/json.lua diff --git a/Steamodded/libs/nativefs/LICENSE b/smods-main/libs/nativefs/LICENSE similarity index 100% rename from Steamodded/libs/nativefs/LICENSE rename to smods-main/libs/nativefs/LICENSE diff --git a/Steamodded/libs/nativefs/README.md b/smods-main/libs/nativefs/README.md similarity index 100% rename from Steamodded/libs/nativefs/README.md rename to smods-main/libs/nativefs/README.md diff --git a/Steamodded/libs/nativefs/icon.png b/smods-main/libs/nativefs/icon.png similarity index 100% rename from Steamodded/libs/nativefs/icon.png rename to smods-main/libs/nativefs/icon.png diff --git a/Steamodded/libs/nativefs/init.lua b/smods-main/libs/nativefs/init.lua similarity index 100% rename from Steamodded/libs/nativefs/init.lua rename to smods-main/libs/nativefs/init.lua diff --git a/Steamodded/libs/nativefs/manifest.json b/smods-main/libs/nativefs/manifest.json similarity index 100% rename from Steamodded/libs/nativefs/manifest.json rename to smods-main/libs/nativefs/manifest.json diff --git a/smods-main/libs/nativefs/nativefs.lua b/smods-main/libs/nativefs/nativefs.lua new file mode 100644 index 0000000..c6f36e0 --- /dev/null +++ b/smods-main/libs/nativefs/nativefs.lua @@ -0,0 +1,495 @@ +--[[ +Copyright 2020 megagrump@pm.me + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +]]-- + +-- module("nativefs", package.seeall) + +local ffi, bit = require('ffi'), require('bit') +local C = ffi.C + +local fopen, getcwd, chdir, unlink, mkdir, rmdir +local BUFFERMODE, MODEMAP +local ByteArray = ffi.typeof('unsigned char[?]') +local function _ptr(p) return p ~= nil and p or nil end -- NULL pointer to nil + +local File = { + getBuffer = function(self) return self._bufferMode, self._bufferSize end, + getFilename = function(self) return self._name end, + getMode = function(self) return self._mode end, + isOpen = function(self) return self._mode ~= 'c' and self._handle ~= nil end, +} + +function File:open(mode) + if self._mode ~= 'c' then return false, "File " .. self._name .. " is already open" end + if not MODEMAP[mode] then return false, "Invalid open mode for " .. self._name .. ": " .. mode end + + local handle = _ptr(fopen(self._name, MODEMAP[mode])) + if not handle then return false, "Could not open " .. self._name .. " in mode " .. mode end + + self._handle, self._mode = ffi.gc(handle, C.fclose), mode + self:setBuffer(self._bufferMode, self._bufferSize) + + return true +end + +function File:close() + if self._mode == 'c' then return false, "File is not open" end + C.fclose(ffi.gc(self._handle, nil)) + self._handle, self._mode = nil, 'c' + return true +end + +function File:setBuffer(mode, size) + local bufferMode = BUFFERMODE[mode] + if not bufferMode then + return false, "Invalid buffer mode " .. mode .. " (expected 'none', 'full', or 'line')" + end + + if mode == 'none' then + size = math.max(0, size or 0) + else + size = math.max(2, size or 2) -- Windows requires buffer to be at least 2 bytes + end + + local success = self._mode == 'c' or C.setvbuf(self._handle, nil, bufferMode, size) == 0 + if not success then + self._bufferMode, self._bufferSize = 'none', 0 + return false, "Could not set buffer mode" + end + + self._bufferMode, self._bufferSize = mode, size + return true +end + +function File:getSize() + -- NOTE: The correct way to do this would be a stat() call, which requires a + -- lot more (system-specific) code. This is a shortcut that requires the file + -- to be readable. + local mustOpen = not self:isOpen() + if mustOpen and not self:open('r') then return 0 end + + local pos = mustOpen and 0 or self:tell() + C.fseek(self._handle, 0, 2) + local size = self:tell() + if mustOpen then + self:close() + else + self:seek(pos) + end + return size +end + +function File:read(containerOrBytes, bytes) + if self._mode ~= 'r' then return nil, 0 end + + local container = bytes ~= nil and containerOrBytes or 'string' + if container ~= 'string' and container ~= 'data' then + error("Invalid container type: " .. container) + end + + bytes = not bytes and containerOrBytes or 'all' + bytes = bytes == 'all' and self:getSize() - self:tell() or math.min(self:getSize() - self:tell(), bytes) + + if bytes <= 0 then + local data = container == 'string' and '' or love.data.newFileData('', self._name) + return data, 0 + end + + local data = love.data.newByteData(bytes) + local r = tonumber(C.fread(data:getFFIPointer(), 1, bytes, self._handle)) + + if container == 'data' then + -- FileData from ByteData requires LÖVE 11.4+ + local ok, fd = pcall(love.filesystem.newFileData, data, self._name) + if ok then return fd end + end + + local str = data:getString() + data:release() + data = container == 'data' and love.filesystem.newFileData(str, self._name) or str + return data, r +end + +local function lines(file, autoclose) + local BUFFERSIZE = 4096 + local buffer, bufferPos = ByteArray(BUFFERSIZE), 0 + local bytesRead = tonumber(C.fread(buffer, 1, BUFFERSIZE, file._handle)) + + local offset = file:tell() + return function() + file:seek(offset) + + local line = {} + while bytesRead > 0 do + for i = bufferPos, bytesRead - 1 do + if buffer[i] == 10 then -- end of line + bufferPos = i + 1 + return table.concat(line) + end + + if buffer[i] ~= 13 then -- ignore CR + table.insert(line, string.char(buffer[i])) + end + end + + bytesRead = tonumber(C.fread(buffer, 1, BUFFERSIZE, file._handle)) + offset, bufferPos = offset + bytesRead, 0 + end + + if not line[1] then + if autoclose then file:close() end + return nil + end + return table.concat(line) + end +end + +function File:lines() + if self._mode ~= 'r' then error("File is not opened for reading") end + return lines(self) +end + +function File:write(data, size) + if self._mode ~= 'w' and self._mode ~= 'a' then + return false, "File " .. self._name .. " not opened for writing" + end + + local toWrite, writeSize + if type(data) == 'string' then + writeSize = (size == nil or size == 'all') and #data or size + toWrite = data + else + writeSize = (size == nil or size == 'all') and data:getSize() or size + toWrite = data:getFFIPointer() + end + + if tonumber(C.fwrite(toWrite, 1, writeSize, self._handle)) ~= writeSize then + return false, "Could not write data" + end + return true +end + +function File:seek(pos) + return self._handle and C.fseek(self._handle, pos, 0) == 0 +end + +function File:tell() + if not self._handle then return nil, "Invalid position" end + return tonumber(C.ftell(self._handle)) +end + +function File:flush() + if self._mode ~= 'w' and self._mode ~= 'a' then + return nil, "File is not opened for writing" + end + return C.fflush(self._handle) == 0 +end + +function File:isEOF() + return not self:isOpen() or C.feof(self._handle) ~= 0 or self:tell() == self:getSize() +end + +function File:release() + if self._mode ~= 'c' then self:close() end + self._handle = nil +end + +function File:type() return 'File' end + +function File:typeOf(t) return t == 'File' end + +File.__index = File + +----------------------------------------------------------------------------- + +local nativefs = {} +local loveC = ffi.os == 'Windows' and ffi.load('love') or C + +function nativefs.newFile(name) + if type(name) ~= 'string' then + error("bad argument #1 to 'newFile' (string expected, got " .. type(name) .. ")") + end + return setmetatable({ + _name = name, + _mode = 'c', + _handle = nil, + _bufferSize = 0, + _bufferMode = 'none' + }, File) +end + +function nativefs.newFileData(filepath) + local f = nativefs.newFile(filepath) + local ok, err = f:open('r') + if not ok then return nil, err end + + local data, err = f:read('data', 'all') + f:close() + return data, err +end + +function nativefs.mount(archive, mountPoint, appendToPath) + return loveC.PHYSFS_mount(archive, mountPoint, appendToPath and 1 or 0) ~= 0 +end + +function nativefs.unmount(archive) + return loveC.PHYSFS_unmount(archive) ~= 0 +end + +function nativefs.read(containerOrName, nameOrSize, sizeOrNil) + local container, name, size + if sizeOrNil then + container, name, size = containerOrName, nameOrSize, sizeOrNil + elseif not nameOrSize then + container, name, size = 'string', containerOrName, 'all' + else + if type(nameOrSize) == 'number' or nameOrSize == 'all' then + container, name, size = 'string', containerOrName, nameOrSize + else + container, name, size = containerOrName, nameOrSize, 'all' + end + end + + local file = nativefs.newFile(name) + local ok, err = file:open('r') + if not ok then return nil, err end + + local data, size = file:read(container, size) + file:close() + return data, size +end + +local function writeFile(mode, name, data, size) + local file = nativefs.newFile(name) + local ok, err = file:open(mode) + if not ok then return nil, err end + + ok, err = file:write(data, size or 'all') + file:close() + return ok, err +end + +function nativefs.write(name, data, size) + return writeFile('w', name, data, size) +end + +function nativefs.append(name, data, size) + return writeFile('a', name, data, size) +end + +function nativefs.lines(name) + local f = nativefs.newFile(name) + local ok, err = f:open('r') + if not ok then return nil, err end + return lines(f, true) +end + +function nativefs.load(name) + local chunk, err = nativefs.read(name) + if not chunk then return nil, err end + return loadstring(chunk, name) +end + +function nativefs.getWorkingDirectory() + return getcwd() +end + +function nativefs.setWorkingDirectory(path) + if not chdir(path) then return false, "Could not set working directory" end + return true +end + +function nativefs.getDriveList() + if ffi.os ~= 'Windows' then return { '/' } end + local drives, bits = {}, C.GetLogicalDrives() + for i = 0, 25 do + if bit.band(bits, 2 ^ i) > 0 then + table.insert(drives, string.char(65 + i) .. ':/') + end + end + return drives +end + +function nativefs.createDirectory(path) + local current = path:sub(1, 1) == '/' and '/' or '' + for dir in path:gmatch('[^/\\]+') do + current = current .. dir .. '/' + local info = nativefs.getInfo(current, 'directory') + if not info and not mkdir(current) then return false, "Could not create directory " .. current end + end + return true +end + +function nativefs.remove(name) + local info = nativefs.getInfo(name) + if not info then return false, "Could not remove " .. name end + if info.type == 'directory' then + if not rmdir(name) then return false, "Could not remove directory " .. name end + return true + end + if not unlink(name) then return false, "Could not remove file " .. name end + return true +end + +local function withTempMount(dir, fn, ...) + local mountPoint = _ptr(loveC.PHYSFS_getMountPoint(dir)) + if mountPoint then return fn(ffi.string(mountPoint), ...) end + if not nativefs.mount(dir, '__nativefs__temp__') then return false, "Could not mount " .. dir end + local a, b = fn('__nativefs__temp__', ...) + nativefs.unmount(dir) + return a, b +end + +function nativefs.getDirectoryItems(dir) + local result, err = withTempMount(dir, love.filesystem.getDirectoryItems) + return result or {} +end + +local function getDirectoryItemsInfo(path, filtertype) + local items = {} + local files = love.filesystem.getDirectoryItems(path) + for i = 1, #files do + local filepath = string.format('%s/%s', path, files[i]) + local info = love.filesystem.getInfo(filepath, filtertype) + if info then + info.name = files[i] + table.insert(items, info) + end + end + return items +end + +function nativefs.getDirectoryItemsInfo(path, filtertype) + local result, err = withTempMount(path, getDirectoryItemsInfo, filtertype) + return result or {} +end + +local function getInfo(path, file, filtertype) + local filepath = string.format('%s/%s', path, file) + return love.filesystem.getInfo(filepath, filtertype) +end + +local function leaf(p) + p = p:gsub('\\', '/') + local last, a = p, 1 + while a do + a = p:find('/', a + 1) + if a then + last = p:sub(a + 1) + end + end + return last +end + +function nativefs.getInfo(path, filtertype) + local dir = path:match("(.*[\\/]).*$") or './' + local file = leaf(path) + local result, err = withTempMount(dir, getInfo, file, filtertype) + return result or nil +end + +----------------------------------------------------------------------------- + +MODEMAP = { r = 'rb', w = 'wb', a = 'ab' } +local MAX_PATH = 4096 + +ffi.cdef([[ + int PHYSFS_mount(const char* dir, const char* mountPoint, int appendToPath); + int PHYSFS_unmount(const char* dir); + const char* PHYSFS_getMountPoint(const char* dir); + + typedef struct FILE FILE; + + FILE* fopen(const char* path, const char* mode); + size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream); + size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream); + int fclose(FILE* stream); + int fflush(FILE* stream); + size_t fseek(FILE* stream, size_t offset, int whence); + size_t ftell(FILE* stream); + int setvbuf(FILE* stream, char* buffer, int mode, size_t size); + int feof(FILE* stream); +]]) + +if ffi.os == 'Windows' then + ffi.cdef([[ + int MultiByteToWideChar(unsigned int cp, uint32_t flags, const char* mb, int cmb, const wchar_t* wc, int cwc); + int WideCharToMultiByte(unsigned int cp, uint32_t flags, const wchar_t* wc, int cwc, const char* mb, + int cmb, const char* def, int* used); + int GetLogicalDrives(void); + int CreateDirectoryW(const wchar_t* path, void*); + int _wchdir(const wchar_t* path); + wchar_t* _wgetcwd(wchar_t* buffer, int maxlen); + FILE* _wfopen(const wchar_t* path, const wchar_t* mode); + int _wunlink(const wchar_t* path); + int _wrmdir(const wchar_t* path); + ]]) + + BUFFERMODE = { full = 0, line = 64, none = 4 } + + local function towidestring(str) + local size = C.MultiByteToWideChar(65001, 0, str, #str, nil, 0) + local buf = ffi.new('wchar_t[?]', size + 1) + C.MultiByteToWideChar(65001, 0, str, #str, buf, size) + return buf + end + + local function toutf8string(wstr) + local size = C.WideCharToMultiByte(65001, 0, wstr, -1, nil, 0, nil, nil) + local buf = ffi.new('char[?]', size + 1) + C.WideCharToMultiByte(65001, 0, wstr, -1, buf, size, nil, nil) + return ffi.string(buf) + end + + local nameBuffer = ffi.new('wchar_t[?]', MAX_PATH + 1) + + fopen = function(path, mode) return C._wfopen(towidestring(path), towidestring(mode)) end + getcwd = function() return toutf8string(C._wgetcwd(nameBuffer, MAX_PATH)) end + chdir = function(path) return C._wchdir(towidestring(path)) == 0 end + unlink = function(path) return C._wunlink(towidestring(path)) == 0 end + mkdir = function(path) return C.CreateDirectoryW(towidestring(path), nil) ~= 0 end + rmdir = function(path) return C._wrmdir(towidestring(path)) == 0 end +else + BUFFERMODE = { full = 0, line = 1, none = 2 } + + ffi.cdef([[ + char* getcwd(char *buffer, int maxlen); + int chdir(const char* path); + int unlink(const char* path); + int mkdir(const char* path, int mode); + int rmdir(const char* path); + ]]) + + local nameBuffer = ByteArray(MAX_PATH) + + fopen = C.fopen + unlink = function(path) return ffi.C.unlink(path) == 0 end + chdir = function(path) return ffi.C.chdir(path) == 0 end + mkdir = function(path) return ffi.C.mkdir(path, 0x1ed) == 0 end + rmdir = function(path) return ffi.C.rmdir(path) == 0 end + + getcwd = function() + local cwd = _ptr(C.getcwd(nameBuffer, MAX_PATH)) + return cwd and ffi.string(cwd) or nil + end +end + +return nativefs diff --git a/smods-main/localization/en-us.lua b/smods-main/localization/en-us.lua new file mode 100644 index 0000000..e4ff077 --- /dev/null +++ b/smods-main/localization/en-us.lua @@ -0,0 +1,132 @@ +return { + descriptions = { + Other = { + load_success = { + text = { + 'Mod loaded', + '{C:green}successfully!' + } + }, + load_failure_d = { + text = { + 'Missing {C:attention}dependencies!', + '#1#', + } + }, + load_failure_c = { + text = { + 'Unresolved {C:attention}conflicts!', + '#1#' + } + }, + load_failure_d_c = { + text = { + 'Missing {C:attention}dependencies!', + '#1#', + 'Unresolved {C:attention}conflicts!', + '#2#' + } + }, + load_failure_o = { + text = { + '{C:attention}Outdated!{} Steamodded', + 'versions {C:money}0.9.8{} and below', + 'are no longer supported.' + } + }, + load_failure_i = { + text = { + '{C:attention}Incompatible!{} Needs version', + '#1# of Steamodded,', + 'but #2# is installed.' + } + }, + load_failure_p = { + text = { + '{C:attention}Prefix Conflict!{}', + 'This mod\'s prefix is', + 'the same as another mod\'s.', + '({C:attention}#1#{})' + } + }, + load_failure_m = { + text = { + '{C:attention}Main File Not Found!{}', + 'This mod\'s main file', + 'could not be found.', + '({C:attention}#1#{})' + } + }, + load_disabled = { + text = { + 'This mod has been', + '{C:attention}disabled!{}' + } + } + }, + Edition = { + e_negative_playing_card = { + name = "Negative", + text = { + "{C:dark_edition}+#1#{} hand size" + }, + }, + } + }, + misc = { + achievement_names = { + hidden_achievement = "???", + }, + achievement_descriptions = { + hidden_achievement = "Play more to find out!", + }, + dictionary = { + b_mods = 'Mods', + b_mods_cap = 'MODS', + b_modded_version = 'Modded Version!', + b_steamodded = 'Steamodded', + b_credits = 'Credits', + b_open_mods_dir = 'Open Mods directory', + b_no_mods = 'No mods have been detected...', + b_mod_list = 'List of Activated Mods', + b_mod_loader = 'Mod Loader', + b_developed_by = 'developed by ', + b_rewrite_by = 'Rewrite by ', + b_github_project = 'Github Project', + b_github_bugs_1 = 'You can report bugs and', + b_github_bugs_2 = 'submit contributions there.', + b_disable_mod_badges = 'Disable Mod Badges', + b_author = 'Author', + b_authors = 'Authors', + b_unknown = 'Unknown', + b_lovely_mod = '(Lovely Mod) ', + b_by = ' By: ', + b_config = "Config", + b_additions = 'Additions', + b_stickers = 'Stickers', + b_achievements = "Achievements", + b_applies_stakes_1 = 'Applies ', + b_applies_stakes_2 = '', + b_graphics_mipmap_level = "Mipmap level", + b_browse = 'Browse', + b_search_prompt = 'Search for mods', + b_search_button = 'Search', + b_seeded_unlocks = 'Seeded unlocks', + b_seeded_unlocks_info = 'Enable unlocks and discoveries in seeded runs', + ml_achievement_settings = { + 'Disabled', + 'Enabled', + 'Bypass Restrictions' + }, + b_deckskins_lc = 'Low Contrast Colors', + b_deckskins_hc = 'High Contrast Colors', + b_deckskins_def = 'Default Colors', + }, + v_dictionary = { + c_types = '#1# Types', + cashout_hidden = '...and #1# more', + a_xchips = "X#1# Chips", + a_xchips_minus = "-X#1# Chips", + }, + } +} diff --git a/Steamodded/localization/es_419.lua b/smods-main/localization/es_419.lua similarity index 100% rename from Steamodded/localization/es_419.lua rename to smods-main/localization/es_419.lua diff --git a/Steamodded/localization/es_ES.lua b/smods-main/localization/es_ES.lua similarity index 100% rename from Steamodded/localization/es_ES.lua rename to smods-main/localization/es_ES.lua diff --git a/smods-main/localization/pt_BR.lua b/smods-main/localization/pt_BR.lua new file mode 100644 index 0000000..9c41dd0 --- /dev/null +++ b/smods-main/localization/pt_BR.lua @@ -0,0 +1,127 @@ +return { + descriptions = { + Other = { + load_success = { + text = { + 'Mod carregado', + '{C:green}com sucesso!' + } + }, + load_failure_d = { + text = { + 'Faltam {C:attention}dependências!', + '#1#', + } + }, + load_failure_c = { + text = { + '{C:attention}Conflitos{} não resolvidos!', + '#1#' + } + }, + load_failure_d_c = { + text = { + 'Faltam {C:attention}dependências!', + '#1#', + '{C:attention}Conflitos{} não resolvidos!', + '#2#' + } + }, + load_failure_o = { + text = { + '{C:attention}Desatualizado!{} As versões', + '{C:money}0.9.8{} e abaxido do Steamodded', + 'não são mais suportadas.' + } + }, + load_failure_i = { + text = { + '{C:attention}Incompatível!{} Precisa da versão', + '#1# do Steamodded,', + 'mas a #2# está instalada.' + } + }, + load_failure_p = { + text = { + '{C:attention}Conflito de Prefixo!{}', + 'O prefixo deste mod é', + 'igual ao de outro mod.', + '({C:attention}#1#{})' + } + }, + load_failure_m = { + text = { + '{C:attention}Arquivo Principal Não Encontrado!{}', + 'O arquivo principal deste mod', + 'não pôde ser encontrado.', + '({C:attention}#1#{})' + } + }, + load_disabled = { + text = { + 'Este mod foi', + '{C:attention}desabilitado!{}' + } + } + }, + Edition = { + e_negative_playing_card = { + name = "Negativo", + text = { + "{C:dark_edition}+#1#{} tamanho de mão" + }, + }, + } + }, + misc = { + achievement_names = { + hidden_achievement = "???", + }, + achievement_descriptions = { + hidden_achievement = "Jogue mais para descobrir!", + }, + dictionary = { + b_mods = 'Mods', + b_mods_cap = 'MODS', + b_modded_version = 'Versão Modificada!', + b_steamodded = 'Steamodded', + b_credits = 'Créditos', + b_open_mods_dir = 'Abrir pasta Mods', + b_no_mods = 'Nenhum mod foi detectado...', + b_mod_list = 'Lista de Mods Ativos', + b_mod_loader = 'Mod Loader', + b_developed_by = 'desenvolvido por ', + b_rewrite_by = 'Reescrito por ', + b_github_project = 'Projeto no Github', + b_github_bugs_1 = 'Você pode reportar bugs e', + b_github_bugs_2 = 'submeter contribuições por lá.', + b_disable_mod_badges = 'Desabilitar Ícones de mods', + b_author = 'Autor', + b_authors = 'Autores', + b_unknown = 'Desconhecido', + b_lovely_mod = '(Mod do Lovely) ', + b_by = ' Por: ', + b_config = "Config.", + b_additions = 'Adições', + b_stickers = 'Adesivos', + b_achievements = "Conquistas", + b_applies_stakes_1 = 'Aplica ', + b_applies_stakes_2 = '', + b_graphics_mipmap_level = "Nível de Mipmap", + b_browse = 'Navegar', + b_search_prompt = 'Procurar por mods', + b_search_button = 'Procurar', + b_seeded_unlocks = 'Desbloquear com código', + b_seeded_unlocks_info = 'Permite descobertas e desbloqueios em tentativas com código', + ml_achievement_settings = { + 'Desabilitado', + 'Habilitado', + 'Ignorar Restrições' + } + }, + v_dictionary = { + c_types = '#1# Tipos', + cashout_hidden = '...e mais #1#', + }, + } +} diff --git a/Steamodded/localization/zh_CN.lua b/smods-main/localization/zh_CN.lua similarity index 100% rename from Steamodded/localization/zh_CN.lua rename to smods-main/localization/zh_CN.lua diff --git a/smods-main/lovely/achievements.toml b/smods-main/lovely/achievements.toml new file mode 100644 index 0000000..f9338e9 --- /dev/null +++ b/smods-main/lovely/achievements.toml @@ -0,0 +1,118 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +## Achievement API + +# fetch_achievements() +[[patches]] +[patches.regex] +target = "functions/common_events.lua" +pattern = '''(?[\t ]*)if G\.F_NO_ACHIEVEMENTS then return end[\n\s]*?--\|FROM LOCAL SETTINGS FILE''' +position = 'before' +# match_indent = true +line_prepend = '$indent' +payload = ''' +G.SETTINGS.ACHIEVEMENTS_EARNED = G.SETTINGS.ACHIEVEMENTS_EARNED or {} +for k, v in pairs(G.ACHIEVEMENTS) do + if not v.key then v.key = k end + for kk, vv in pairs(G.SETTINGS.ACHIEVEMENTS_EARNED) do + if G.ACHIEVEMENTS[kk] and G.ACHIEVEMENTS[kk].mod then + G.ACHIEVEMENTS[kk].earned = true + end + end +end +''' + +# check_for_unlock +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = '''if G.GAME.challenge then return end''' +position = "after" +payload = ''' +fetch_achievements() -- Refreshes achievements +for k, v in pairs(G.ACHIEVEMENTS) do + if (not v.earned) and (v.unlock_condition and type(v.unlock_condition) == 'function') and v:unlock_condition(args) then + unlock_achievement(k) + end +end''' +match_indent = true + +# unlock_achievement() +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = '''if G.PROFILES[G.SETTINGS.profile].all_unlocked then return end''' +position = "at" +payload = '''if G.PROFILES[G.SETTINGS.profile].all_unlocked and (G.ACHIEVEMENTS and G.ACHIEVEMENTS[achievement_name] and not G.ACHIEVEMENTS[achievement_name].bypass_all_unlocked and SMODS.config.achievements < 3) or (SMODS.config.achievements < 3 and (G.GAME.seeded or G.GAME.challenge)) then return true end''' +match_indent = true + +# unlock_achievement() - fix event queue leaking +# fixed smods achievements not unlocking due to above comment's memory leak fix +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = '''local achievement_set = false +if G.F_NO_ACHIEVEMENTS then return end''' +position = "at" +payload = '''local achievement_set = false +if not G.ACHIEVEMENTS then fetch_achievements() end +G.SETTINGS.ACHIEVEMENTS_EARNED[achievement_name] = true +G:save_progress() + +if G.ACHIEVEMENTS[achievement_name] and G.ACHIEVEMENTS[achievement_name].mod then + if not G.ACHIEVEMENTS[achievement_name].earned then + --|THIS IS THE FIRST TIME THIS ACHIEVEMENT HAS BEEN EARNED + achievement_set = true + G.FILE_HANDLER.force = true + end + G.ACHIEVEMENTS[achievement_name].earned = true +end + +if achievement_set then + notify_alert(achievement_name) + return true +end +if G.F_NO_ACHIEVEMENTS and not (G.ACHIEVEMENTS[achievement_name] or {}).mod then return true end''' +match_indent = true + +# create_UIBox_notify_alert +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''local t_s = Sprite(0,0,1.5*(_atlas.px/_atlas.py),1.5,_atlas, _c and _c.pos or {x=3, y=0})''' +position = "before" +payload = '''if SMODS.Achievements[_achievement] then _c = SMODS.Achievements[_achievement]; _atlas = G.ASSET_ATLAS[_c.atlas] end''' +match_indent = true + +# option to allow unlocks and discoveries in seeded runs +[[patches]] +[patches.regex] +target = 'functions/common_events.lua' +pattern = 'if G\.GAME\.seeded or G\.GAME\.challenge then return end' +position = 'at' +payload = 'if not SMODS.config.seeded_unlocks and (G.GAME.seeded or G.GAME.challenge) then return end' + +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +match_indent = true +position = 'at' +pattern = 'if not G.GAME.seeded and not G.GAME.challenge then' +payload = 'if (not G.GAME.seeded and not G.GAME.challenge) or SMODS.config.seeded_unlocks then' + +[[patches]] +[patches.regex] +target = 'functions/common_events.lua' +pattern = 'if G\.GAME\.seeded then' +position = 'at' +payload = 'if false then' + +[[patches]] +[patches.regex] +target = 'functions/common_events.lua' +pattern = 'if G\.GAME\.challenge then' +position = 'at' +payload = 'if false then' diff --git a/smods-main/lovely/atlas.toml b/smods-main/lovely/atlas.toml new file mode 100644 index 0000000..f08094d --- /dev/null +++ b/smods-main/lovely/atlas.toml @@ -0,0 +1,105 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Sprite API + +# Card:set_sprites() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = 'G.ASSET_ATLAS\["centers"\]' +position = 'at' +payload = "G.ASSET_ATLAS[(G.GAME.viewed_back or G.GAME.selected_back) and ((G.GAME.viewed_back or G.GAME.selected_back)[G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or (G.GAME.viewed_back or G.GAME.selected_back).atlas) or 'centers']" + +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = 'G.ASSET_ATLAS\[_center.atlas or _center.set\]' +position = 'at' +payload = ''' +G.ASSET_ATLAS[(_center.undiscovered and (_center.undiscovered[G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or _center.undiscovered.atlas)) + or (SMODS.UndiscoveredSprites[_center.set] and (SMODS.UndiscoveredSprites[_center.set][G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or SMODS.UndiscoveredSprites[_center.set].atlas)) + or _center.set] or G.ASSET_ATLAS["Joker"]''' + +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = "G.ASSET_ATLAS\\['Joker'\\]" +position = 'at' +payload = "G.ASSET_ATLAS[_center[G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or _center.atlas or _center.set]" + +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = 'G.ASSET_ATLAS\[_center.set\]' +position = 'at' +payload = "G.ASSET_ATLAS[_center[G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or _center.atlas or _center.set]" + +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = "(_center.set == 'Joker' and G.j_undiscovered.pos) or" +position = 'before' +payload = '(_center.undiscovered and _center.undiscovered.pos) or (SMODS.UndiscoveredSprites[_center.set] and SMODS.UndiscoveredSprites[_center.set].pos) or' +match_indent = true + +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''(_center.set == 'Booster' and G.booster_undiscovered.pos))''' +position = 'at' +payload = '''(_center.set == 'Booster' and G.booster_undiscovered.pos) or G.j_undiscovered.pos)''' +match_indent = true + +# get_front_spriteinfo() + +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +pattern = 'return G.ASSET_ATLAS[_front.atlas] or G.ASSET_ATLAS["cards_"..(G.SETTINGS.colourblind_option and 2 or 1)], _front.pos' +position = 'at' +match_indent = true +payload = 'return G.ASSET_ATLAS[G.SETTINGS.colourblind_option and _front.hc_atlas or _front.lc_atlas or {}] or G.ASSET_ATLAS[_front.atlas] or G.ASSET_ATLAS["cards_"..(G.SETTINGS.colourblind_option and 2 or 1)], _front.pos' + + +# Game:set_render_settings() +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = "G:set_render_settings()" +position = 'at' +match_indent = true +payload = "SMODS.injectObjects(SMODS.Atlas)" + + +# create_UIBox_notify_alert() +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = 'G.ASSET_ATLAS["icons"]' +position = 'after' +match_indent = false +payload = ''' + local _smods_atlas = _c and ((G.SETTINGS.colourblind_option and _c.hc_atlas or _c.lc_atlas) or _c.atlas) + if _smods_atlas then + _atlas = G.ASSET_ATLAS[_smods_atlas] or _atlas + end''' + +## Hide floating ? from undiscovered types +# Card:draw() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''shared_sprite:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod)''' +position = 'at' +match_indent = true +payload = ''' +if (self.config.center.undiscovered and not self.config.center.undiscovered.no_overlay) or not( SMODS.UndiscoveredSprites[self.ability.set] and SMODS.UndiscoveredSprites[self.ability.set].no_overlay) then + shared_sprite:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod) +else + if SMODS.UndiscoveredSprites[self.ability.set] and SMODS.UndiscoveredSprites[self.ability.set].overlay_sprite then + SMODS.UndiscoveredSprites[self.ability.set].overlay_sprite:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod) + end +end''' diff --git a/Steamodded/lovely/back.toml b/smods-main/lovely/back.toml similarity index 75% rename from Steamodded/lovely/back.toml rename to smods-main/lovely/back.toml index 02d9a4c..6c69fa6 100644 --- a/Steamodded/lovely/back.toml +++ b/smods-main/lovely/back.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Back API @@ -46,7 +46,7 @@ match_indent = true payload = ''' local obj = self.effect.center if obj.apply and type(obj.apply) == 'function' then - obj:apply() + obj:apply(self) end''' # Back:trigger_effect(args) @@ -58,9 +58,16 @@ position = 'after' match_indent = true payload = ''' local obj = self.effect.center - if obj.trigger_effect and type(obj.trigger_effect) == 'function' then + if type(obj.calculate) == 'function' then + local o = {obj:calculate(self, args)} + if next(o) ~= nil then return unpack(o) end + elseif type(obj.trigger_effect) == 'function' then + -- kept for compatibility local o = {obj:trigger_effect(args)} - if o then return unpack(o) end + if next(o) ~= nil then + sendWarnMessage(('Found `trigger_effect` function on SMODS.Back object "%s". This field is deprecated; please use `calculate` instead.'):format(obj.key), 'Back') + return unpack(o) + end end''' ## Back:generate_UI @@ -137,4 +144,30 @@ elseif name_to_check == 'Blue Deck' then loc_args = {effect_config.hands}''' target = 'back.lua' pattern = "key = back_config\\.key" position = 'at' -payload = "key = key_override or back_config.key" \ No newline at end of file +payload = "key = key_override or back_config.key" + +# Back:apply_to_run() - add jokers support to config +[[patches]] +[patches.pattern] +target = 'back.lua' +match_indent = true +position = 'before' +pattern = ''' +if self.effect.config.voucher then +''' +payload = ''' +if self.effect.config.jokers then + delay(0.4) + G.E_MANAGER:add_event(Event({ + func = function() + for k, v in ipairs(self.effect.config.jokers) do + local card = create_card('Joker', G.jokers, nil, nil, nil, nil, v, 'deck') + card:add_to_deck() + G.jokers:emplace(card) + card:start_materialize() + end + return true + end + })) + end +''' diff --git a/smods-main/lovely/better_calc.toml b/smods-main/lovely/better_calc.toml new file mode 100644 index 0000000..020a233 --- /dev/null +++ b/smods-main/lovely/better_calc.toml @@ -0,0 +1,1322 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 +# temp solution, nothing matches if -10 + +## G.FUNCS.evaluate_play() +# evaluate main scoring + +[[patches]] +[patches.regex] +target = 'functions/state_events.lua' +pattern = '''(?[\t ]*)(?if modded then update_hand_text\(\{sound = 'chips2', modded = modded\}, \{chips = hand_chips, mult = mult\}\) end)(.*\n)*?\s+(?--\++--)''' +position = 'at' +line_prepend = '$indent' +payload = '''$handtext +delay(0.3) +for _, v in ipairs(SMODS.get_card_areas('playing_cards')) do + SMODS.calculate_main_scoring({cardarea = v, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands}, v == G.play and scoring_hand or nil) + delay(0.3) +end +$delimiter''' +## eval_card() +# handle debuffed playing cards +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = ''' +function eval_card(card, context) + context = context or {} + local ret = {} +''' +position = 'at' +match_indent = true +payload = ''' +function eval_card(card, context) + if card.ability.set ~= 'Joker' and card.debuff then return {}, {} end + context = context or {} + local ret = {} +''' + +# built in config values +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = ''' +if context.cardarea == G.play then + local chips = card:get_chip_bonus() + if chips > 0 then + ret.chips = chips + end + + local mult = card:get_chip_mult() + if mult > 0 then + ret.mult = mult + end + + local x_mult = card:get_chip_x_mult(context) + if x_mult > 0 then + ret.x_mult = x_mult + end + + local p_dollars = card:get_p_dollars() + if p_dollars > 0 then + ret.p_dollars = p_dollars + end + + local jokers = card:calculate_joker(context) + if jokers then + ret.jokers = jokers + end + + local edition = card:get_edition(context) + if edition then + ret.edition = edition + end +end +''' +match_indent = true +position = "at" +payload = """ +if context.cardarea == G.play and context.main_scoring then + ret.playing_card = {} + local chips = card:get_chip_bonus() + if chips ~= 0 then + ret.playing_card.chips = chips + end + + local mult = card:get_chip_mult() + if mult ~= 0 then + ret.playing_card.mult = mult + end + + local x_mult = card:get_chip_x_mult(context) + if x_mult > 0 then + ret.playing_card.x_mult = x_mult + end + + local p_dollars = card:get_p_dollars() + if p_dollars > 0 then + ret.playing_card.p_dollars = p_dollars + end + + -- TARGET: main scoring on played cards + + local jokers = card:calculate_joker(context) + if jokers then + ret.jokers = jokers + end + + local edition = card:calculate_edition(context) + if edition then + ret.edition = edition + end +end +if context.end_of_round and context.cardarea == G.hand and context.playing_card_end_of_round then + local end_of_round = card:get_end_of_round_effect(context) + if end_of_round then + ret.end_of_round = end_of_round + end +end +""" +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = ''' +if context.cardarea == G.hand then + local h_mult = card:get_chip_h_mult() + if h_mult > 0 then + ret.h_mult = h_mult + end + + local h_x_mult = card:get_chip_h_x_mult() + if h_x_mult > 0 then + ret.x_mult = h_x_mult + end +''' +match_indent = true +position = "at" +payload = """ +if context.cardarea == G.hand and context.main_scoring then + ret.playing_card = {} + local h_mult = card:get_chip_h_mult() + if h_mult ~= 0 then + ret.playing_card.h_mult = h_mult + end + + local h_x_mult = card:get_chip_h_x_mult() + if h_x_mult > 0 then + ret.playing_card.x_mult = h_x_mult + end + + -- TARGET: main scoring on held cards +""" + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = ''' +local seals = card:calculate_seal(context) +if seals then + ret.seals = seals +end +''' +match_indent = true +position = "at" +payload = """ +if card.ability.set == 'Enhanced' then + local enhancement = card:calculate_enhancement(context) + if enhancement then + ret.enhancement = enhancement + end +end +if card.edition then + local edition = card:calculate_edition(context) + if edition then + ret.edition = edition + end +end +if card.seal then + local seals = card:calculate_seal(context) + if seals then + ret.seals = seals + end +end +for k,v in pairs(SMODS.Stickers) do + local sticker = card:calculate_sticker(context, k) + if sticker then + ret[v] = sticker + end +end + +-- TARGET: evaluate your own repetition effects +""" +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if context.cardarea == G.jokers or context.card == G.consumeables then" +match_indent = true +position = "before" +payload = """ +if card.ability.set == 'Enhanced' then + local enhancement = card:calculate_enhancement(context) + if enhancement then + ret.enhancement = enhancement + end +end +if card.edition then + local edition = card:calculate_edition(context) + if edition then + ret.edition = edition + end +end +if card.seal and not card.ability.extra_enhancement then + local seals = card:calculate_seal(context) + if seals then + ret.seals = seals + end +end +for k,v in pairs(SMODS.Stickers) do + local sticker = card:calculate_sticker(context, k) + if sticker then + ret[v] = sticker + end +end + +-- TARGET: evaluate your own general effects +""" +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = ''' +if context.cardarea == G.jokers or context.card == G.consumeables then + local jokers = nil + if context.edition then + jokers = card:get_edition(context) + elseif context.other_joker then + jokers = context.other_joker:calculate_joker(context) + else + jokers = card:calculate_joker(context) + end + if jokers then + ret.jokers = jokers + end +end + +return ret''' +match_indent = true +position = "at" +payload = """ +local post_trig = {} +local areas = SMODS.get_card_areas('jokers') +local area_set = {} +for _,v in ipairs(areas) do area_set[v] = true end +if card.area and area_set[card.area] then + local jokers, triggered = card:calculate_joker(context) + if jokers or triggered then + ret.jokers = jokers + if not (context.retrigger_joker_check or context.retrigger_joker) then + local retriggers = SMODS.calculate_retriggers(card, context, ret) + if next(retriggers) then + ret.retriggers = retriggers + end + end + if not context.post_trigger and not context.retrigger_joker_check and SMODS.optional_features.post_trigger then + SMODS.calculate_context({blueprint_card = context.blueprint_card, post_trigger = true, other_card = card, other_context = context, other_ret = ret}, post_trig) + end + end +end + +return ret, post_trig +""" +# patch card_eval_status_text to allow G.deck usage +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = ''' +elseif card.area == G.hand then''' +match_indent = true +position = "at" +payload = """ +elseif card.area == G.hand or card.area == G.deck then +""" + +# card_eval_status_text alignment patches +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'before' +pattern = '''elseif card.area == G.hand or card.area == G.deck then''' +payload = '''elseif card == G.deck then + y_off = -0.05*G.CARD_H + card_aligned = 'tm' +elseif card.area == G.discard or card.area == G.vouchers then + y_off = card.area == G.discard and -0.35*G.CARD_H or -0.65*G.CARD_H + card = G.deck.cards[1] or G.deck + card_aligned = 'tm' +''' + +# G.FUNCS.evaluate_play() + + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +--calculate the card edition effects +if effects[ii].edition then + hand_chips = mod_chips(hand_chips + (effects[ii].edition.chip_mod or 0)) + mult = mult + (effects[ii].edition.mult_mod or 0) + mult = mod_mult(mult*(effects[ii].edition.x_mult_mod or 1)) + update_hand_text({delay = 0}, { + chips = effects[ii].edition.chip_mod and hand_chips or nil, + mult = (effects[ii].edition.mult_mod or effects[ii].edition.x_mult_mod) and mult or nil, + }) + card_eval_status_text(scoring_hand[i], 'extra', nil, percent, nil, { + message = (effects[ii].edition.chip_mod and localize{type='variable',key='a_chips',vars={effects[ii].edition.chip_mod}}) or + (effects[ii].edition.mult_mod and localize{type='variable',key='a_mult',vars={effects[ii].edition.mult_mod}}) or + (effects[ii].edition.x_mult_mod and localize{type='variable',key='a_xmult',vars={effects[ii].edition.x_mult_mod}}), + chip_mod = effects[ii].edition.chip_mod, + mult_mod = effects[ii].edition.mult_mod, + x_mult_mod = effects[ii].edition.x_mult_mod, + colour = G.C.DARK_EDITION, + edition = true}) +end +''' +match_indent = true +position = "at" +payload = '' + +## Remove base game calculations +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' + scoring_hand[i].lucky_trigger = nil + + for ii = 1, #effects do + --If chips added, do chip add event and add the chips to the total + if effects[ii].chips then + if effects[ii].card then juice_card(effects[ii].card) end + hand_chips = mod_chips(hand_chips + effects[ii].chips) + update_hand_text({delay = 0}, {chips = hand_chips}) + card_eval_status_text(scoring_hand[i], 'chips', effects[ii].chips, percent) + end + + --If mult added, do mult add event and add the mult to the total + if effects[ii].mult then + if effects[ii].card then juice_card(effects[ii].card) end + mult = mod_mult(mult + effects[ii].mult) + update_hand_text({delay = 0}, {mult = mult}) + card_eval_status_text(scoring_hand[i], 'mult', effects[ii].mult, percent) + end + + --If play dollars added, add dollars to total + if effects[ii].p_dollars then + if effects[ii].card then juice_card(effects[ii].card) end + ease_dollars(effects[ii].p_dollars) + card_eval_status_text(scoring_hand[i], 'dollars', effects[ii].p_dollars, percent) + end + + --If dollars added, add dollars to total + if effects[ii].dollars then + if effects[ii].card then juice_card(effects[ii].card) end + ease_dollars(effects[ii].dollars) + card_eval_status_text(scoring_hand[i], 'dollars', effects[ii].dollars, percent) + end + + --Any extra effects + if effects[ii].extra then + if effects[ii].card then juice_card(effects[ii].card) end + local extras = {mult = false, hand_chips = false} + if effects[ii].extra.mult_mod then mult =mod_mult( mult + effects[ii].extra.mult_mod);extras.mult = true end + if effects[ii].extra.chip_mod then hand_chips = mod_chips(hand_chips + effects[ii].extra.chip_mod);extras.hand_chips = true end + if effects[ii].extra.swap then + local old_mult = mult + mult = mod_mult(hand_chips) + hand_chips = mod_chips(old_mult) + extras.hand_chips = true; extras.mult = true + end + if effects[ii].extra.func then effects[ii].extra.func() end + update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult}) + card_eval_status_text(scoring_hand[i], 'extra', nil, percent, nil, effects[ii].extra) + end + + --If x_mult added, do mult add event and mult the mult to the total + if effects[ii].x_mult then + if effects[ii].card then juice_card(effects[ii].card) end + mult = mod_mult(mult*effects[ii].x_mult) + update_hand_text({delay = 0}, {mult = mult}) + card_eval_status_text(scoring_hand[i], 'x_mult', effects[ii].x_mult, percent) + end + + + end + end +end +''' +match_indent = true +position = "at" +payload = ''' + -- Base game calculation removed + SMODS.trigger_effects(effects, scoring_hand[i]) + local deck_effect = G.GAME.selected_back:trigger_effect({cardarea = G.play, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, other_card = scoring_hand[i], individual = true}) + if deck_effect then SMODS.calculate_effect(deck_effect, G.deck.cards[1] or G.deck) end + scoring_hand[i].lucky_trigger = nil + end + scoring_hand[i].extra_enhancements = nil +end +''' + +# Add deck/discard individual contexts +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +position = 'before' +match_indent = true +pattern = ''' +--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- +--Joker Effects +--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++--''' +payload = ''' + +''' + +# Joker Effects +# Edition effects +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +--calculate the joker edition effects +local edition_effects = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, edition = true}) +if edition_effects.jokers then + edition_effects.jokers.edition = true + if edition_effects.jokers.chip_mod then + hand_chips = mod_chips(hand_chips + edition_effects.jokers.chip_mod) + update_hand_text({delay = 0}, {chips = hand_chips}) + card_eval_status_text(_card, 'jokers', nil, percent, nil, { + message = localize{type='variable',key='a_chips',vars={edition_effects.jokers.chip_mod}}, + chip_mod = edition_effects.jokers.chip_mod, + colour = G.C.EDITION, + edition = true}) + end + if edition_effects.jokers.mult_mod then + mult = mod_mult(mult + edition_effects.jokers.mult_mod) + update_hand_text({delay = 0}, {mult = mult}) + card_eval_status_text(_card, 'jokers', nil, percent, nil, { + message = localize{type='variable',key='a_mult',vars={edition_effects.jokers.mult_mod}}, + mult_mod = edition_effects.jokers.mult_mod, + colour = G.C.DARK_EDITION, + edition = true}) + end + percent = percent+percent_delta +end''' +match_indent = true +position = "at" +payload = ''' +local effects = {} +-- remove base game joker edition calc +local eval = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, edition = true, pre_joker = true}) +if eval.edition then effects[#effects+1] = eval end + +''' +# Edition mult effects +## extra end to fix syntax from adding joker-like areas +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' + if edition_effects.jokers then + if edition_effects.jokers.x_mult_mod then + mult = mod_mult(mult*edition_effects.jokers.x_mult_mod) + update_hand_text({delay = 0}, {mult = mult}) + card_eval_status_text(_card, 'jokers', nil, percent, nil, { + message = localize{type='variable',key='a_xmult',vars={edition_effects.jokers.x_mult_mod}}, + x_mult_mod = edition_effects.jokers.x_mult_mod, + colour = G.C.EDITION, + edition = true}) + end + percent = percent+percent_delta + end +end''' +match_indent = false +position = "at" +payload = ''' + -- calculate edition multipliers + local eval = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, edition = true, post_joker = true}) + if eval.edition then effects[#effects+1] = eval end + + SMODS.trigger_effects(effects, _card) + local deck_effect = G.GAME.selected_back:trigger_effect({full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, other_joker = _card.ability.set == 'Joker' and _card or false, other_consumeable = _card.ability.set ~= 'Joker' and _card or false}) + if deck_effect then SMODS.calculate_effect(deck_effect, G.deck.cards[1] or G.deck) end + end end +''' +# Joker effects + +# allows adding other areas (syntax is fixed further down) +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +match_indent = true +position = 'at' +pattern = '''for i=1, #G.jokers.cards + #G.consumeables.cards do + local _card = G.jokers.cards[i] or G.consumeables.cards[i - #G.jokers.cards]''' +payload = '''for _, area in ipairs(SMODS.get_card_areas('jokers')) do for _, _card in ipairs(area.cards) do''' + +## I am NOT converting this to regex (yet) +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' + --calculate the joker effects + local effects = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, joker_main = true}) + + --Any Joker effects + if effects.jokers then + local extras = {mult = false, hand_chips = false} + if effects.jokers.mult_mod then mult = mod_mult(mult + effects.jokers.mult_mod);extras.mult = true end + if effects.jokers.chip_mod then hand_chips = mod_chips(hand_chips + effects.jokers.chip_mod);extras.hand_chips = true end + if effects.jokers.Xmult_mod then mult = mod_mult(mult*effects.jokers.Xmult_mod);extras.mult = true end + update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult}) + card_eval_status_text(_card, 'jokers', nil, percent, nil, effects.jokers) + percent = percent+percent_delta + end''' +match_indent = true +position = "at" +payload = ''' +-- Calculate context.joker_main +local joker_eval, post = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, joker_main = true}) +if next(joker_eval) then + if joker_eval.edition then joker_eval.edition = {} end + table.insert(effects, joker_eval) + for _, v in ipairs(post) do effects[#effects+1] = v end + if joker_eval.retriggers then + for rt = 1, #joker_eval.retriggers do + local rt_eval, rt_post = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, joker_main = true, retrigger_joker = true}) + table.insert(effects, {joker_eval.retriggers[rt]}) + table.insert(effects, rt_eval) + for _, v in ipairs(rt_post) do effects[#effects+1] = v end + end + end +end''' +# Joker on Joker effects +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +--Joker on Joker effects +for _, v in ipairs(G.jokers.cards) do + local effect = v:calculate_joker{full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, other_joker = _card} + if effect then + local extras = {mult = false, hand_chips = false} + if effect.mult_mod then mult = mod_mult(mult + effect.mult_mod);extras.mult = true end + if effect.chip_mod then hand_chips = mod_chips(hand_chips + effect.chip_mod);extras.hand_chips = true end + if effect.Xmult_mod then mult = mod_mult(mult*effect.Xmult_mod);extras.mult = true end + if extras.mult or extras.hand_chips then update_hand_text({delay = 0}, {chips = extras.hand_chips and hand_chips, mult = extras.mult and mult}) end + if extras.mult or extras.hand_chips then card_eval_status_text(v, 'jokers', nil, percent, nil, effect) end + percent = percent+percent_delta + end +end''' +match_indent = true +position = "at" +payload = ''' +-- Calculate context.other_joker effects +for _, _area in ipairs(SMODS.get_card_areas('jokers')) do + for _, _joker in ipairs(_area.cards) do + local other_key = 'other_unknown' + if _card.ability.set == 'Joker' then other_key = 'other_joker' end + if _card.ability.consumeable then other_key = 'other_consumeable' end + if _card.ability.set == 'Voucher' then other_key = 'other_voucher' end + -- TARGET: add context.other_something identifier to your cards + local joker_eval,post = eval_card(_joker, {full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, [other_key] = _card, other_main = _card }) + if next(joker_eval) then + if joker_eval.edition then joker_eval.edition = {} end + joker_eval.jokers.juice_card = _joker + table.insert(effects, joker_eval) + for _, v in ipairs(post) do effects[#effects+1] = v end + if joker_eval.retriggers then + for rt = 1, #joker_eval.retriggers do + local rt_eval, rt_post = eval_card(_card, {full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, [other_key] = _card, retrigger_joker = true}) + table.insert(effects, {joker_eval.retriggers[rt]}) + table.insert(effects, rt_eval) + for _, v in ipairs(rt_post) do effects[#effects+1] = v end + end + end + end + end +end +''' + +## Fix other evaluations +# Discarding cards +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +for j = 1, #G.jokers.cards do + local eval = nil + eval = G.jokers.cards[j]:calculate_joker({discard = true, other_card = G.hand.highlighted[i], full_hand = G.hand.highlighted}) + if eval then + if eval.remove then removed = true end + card_eval_status_text(G.jokers.cards[j], 'jokers', nil, 1, nil, eval) + end +end''' +match_indent = true +position = "at" +payload = ''' +local effects = {} +SMODS.calculate_context({discard = true, other_card = G.hand.highlighted[i], full_hand = G.hand.highlighted}, effects) +SMODS.trigger_effects(effects) +for _, eval in pairs(effects) do + if type(eval) == 'table' then + for key, eval2 in pairs(eval) do + if key == 'remove' or (type(eval2) == 'table' and eval2.remove) then removed = true end + end + end +end''' + +# context.before +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +for i=1, #G.jokers.cards do + --calculate the joker effects + local effects = eval_card(G.jokers.cards[i], {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, before = true}) + if effects.jokers then + card_eval_status_text(G.jokers.cards[i], 'jokers', nil, percent, nil, effects.jokers) + percent = percent + percent_delta + if effects.jokers.level_up then + level_up_hand(G.jokers.cards[i], text) + end + end +end''' +match_indent = true +position = "at" +payload = ''' +-- context.before calculations +SMODS.calculate_context({full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, before = true}) + +-- TARGET: effects before scoring starts''' + +# context.final_scoring_step +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = '''local nu_chip, nu_mult = G.GAME.selected_back:trigger_effect{context = 'final_scoring_step', chips = hand_chips, mult = mult}''' +match_indent = true +position = "before" +payload = ''' +-- context.final_scoring_step calculations +SMODS.calculate_context({full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, final_scoring_step = true}) + +-- TARGET: effects before deck final_scoring_step +''' + +# context.destroying_card +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +for j = 1, #G.jokers.cards do + destroyed = G.jokers.cards[j]:calculate_joker({destroying_card = scoring_hand[i], full_hand = G.play.cards}) + if destroyed then break end +end + +if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then + destroyed = true +end''' +match_indent = true +position = "at" +payload = ''' +-- context.destroying_card calculations +for j = 1, #G.jokers.cards do + local eval, post = eval_card(G.jokers.cards[j], {destroying_card = scoring_hand[i], full_hand = G.play.cards}) + SMODS.trigger_effects({eval, post}, scoring_hand[i]) + if eval.jokers then destroyed = true end + +end + +if SMODS.has_enhancement(scoring_hand[i], 'm_glass') and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/(scoring_hand[i].ability.name == 'Glass Card' and scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) then + destroyed = true +end + +local eval, post = eval_card(scoring_hand[i], {destroying_card = scoring_hand[i], full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, cardarea = G.play}) +local self_destroy = false +for key, effect in pairs(eval) do + self_destroy = SMODS.calculate_effect(effect, scoring_hand[i]) +end +SMODS.trigger_effects({post}, scoring_hand[i]) +if self_destroy then destroyed = true end + +-- TARGET: card destroyed when played +''' + +# context.remove_playing_cards +[[patches]] +[patches.regex] +target = "functions/state_events.lua" +pattern = '''(?[\t ]*)local cards_destroyed = \{\}\n(.*\n)*?\s+for j=1, #G\.jokers\.cards do\n\s+eval_card\(G\.jokers\.cards\[j\], \{cardarea = G\.jokers, remove_playing_cards = true, removed = cards_destroyed\}\)\n\s+end''' +line_prepend = '$indent' +position = "at" +payload = ''' +local cards_destroyed = {} +for _,v in ipairs(SMODS.get_card_areas('playing_cards', 'destroying_cards')) do + SMODS.calculate_destroying_cards({ full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, cardarea = v }, cards_destroyed, v == G.play and scoring_hand or nil) +end + +-- context.remove_playing_cards calculations +if cards_destroyed[1] then + SMODS.calculate_context({scoring_hand = scoring_hand, remove_playing_cards = true, removed = cards_destroyed}) +end + +-- TARGET: effects when cards are removed + +''' + +[[patches]] +[patches.regex] +target = 'card.lua' +line_prepend = '$indent' +position = 'at' +pattern = '(?[\t ]*)for i = 1, #G.jokers.cards do[\n\s]*G.jokers.cards\[i\]:calculate_joker\(\{remove_playing_cards = true, removed = destroyed_cards\}\)[\s\n]*end' +payload = '''SMODS.calculate_context({ remove_playing_cards = true, removed = destroyed_cards })''' + +# context.remove_playing_cards from discard +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +if destroyed_cards[1] then + for j=1, #G.jokers.cards do + eval_card(G.jokers.cards[j], {cardarea = G.jokers, remove_playing_cards = true, removed = destroyed_cards}) + end +end +''' +position = "at" +match_indent = true +payload = ''' +-- context.remove_playing_cards from discard +if destroyed_cards[1] then + SMODS.calculate_context({remove_playing_cards = true, removed = destroyed_cards}) +end + +-- TARGET: effects after cards destroyed in discard''' + + +# context.debuffed_hand +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +for i=1, #G.jokers.cards do + + --calculate the joker effects + local effects = eval_card(G.jokers.cards[i], {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, debuffed_hand = true}) + + --Any Joker effects + if effects.jokers then + card_eval_status_text(G.jokers.cards[i], 'jokers', nil, percent, nil, effects.jokers) + percent = percent+percent_delta + end +end''' +match_indent = true +position = "at" +payload = ''' +-- context.debuffed_hand calculations +SMODS.calculate_context({full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, debuffed_hand = true}) + +-- TARGET: effects after hand debuffed by blind''' + +# context.after +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +for i=1, #G.jokers.cards do + --calculate the joker after hand played effects + local effects = eval_card(G.jokers.cards[i], {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, after = true}) + if effects.jokers then + card_eval_status_text(G.jokers.cards[i], 'jokers', nil, percent, nil, effects.jokers) + percent = percent + percent_delta + end +end''' +match_indent = true +position = "at" +payload = ''' +-- context.after calculations +SMODS.calculate_context({full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, after = true}) + +-- TARGET: effects after hand evaluation''' + +# calc_dollar_bonus call through consumeables +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = ''' +for i = 1, #G.jokers.cards do + local ret = G.jokers.cards[i]:calculate_dollar_bonus() + if ret then + add_round_eval_row({dollars = ret, bonus = true, name='joker'..i, pitch = pitch, card = G.jokers.cards[i]}) + pitch = pitch + 0.06 + dollars = dollars + ret + end +end +''' +position = 'at' +match_indent = true +payload = ''' +local i = 0 +for _, area in ipairs(SMODS.get_card_areas('jokers')) do + for _, _card in ipairs(area.cards) do + local ret = _card:calculate_dollar_bonus() + + -- TARGET: calc_dollar_bonus per card + if ret then + i = i+1 + add_round_eval_row({dollars = ret, bonus = true, name='joker'..i, pitch = pitch, card = _card}) + pitch = pitch + 0.06 + dollars = dollars + ret + end + end +end +''' + +# context.end_of_round +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = ''' +for i = 1, #G.jokers.cards do + local eval = nil + eval = G.jokers.cards[i]:calculate_joker({end_of_round = true, game_over = game_over}) + if eval then + if eval.saved then + game_over = false + end + card_eval_status_text(G.jokers.cards[i], 'jokers', nil, nil, nil, eval) + end + G.jokers.cards[i]:calculate_rental() + G.jokers.cards[i]:calculate_perishable() +end +''' +position = 'at' +match_indent = true +payload = ''' +-- context.end_of_round calculations +SMODS.saved = false +SMODS.calculate_context({end_of_round = true, game_over = game_over }) +if SMODS.saved then game_over = false end +-- TARGET: main end_of_round evaluation +''' + +# context.end_of_round individual effects +[[patches]] +[patches.regex] +target = 'functions/state_events.lua' +position = 'at' +pattern = '''(?[\t ]*)for i=1, #G\.hand\.cards do\n\s+--Check for hand doubling\n(.*\n)*?\s+delay\(0\.3\)''' +line_prepend = '$indent' +payload = '''for _,v in ipairs(SMODS.get_card_areas('playing_cards', 'end_of_round')) do + SMODS.calculate_end_of_round_effects({ cardarea = v, end_of_round = true }) +end +''' + + +# context.setting_blind +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = ''' +for i = 1, #G.jokers.cards do + G.jokers.cards[i]:calculate_joker({setting_blind = true, blind = G.GAME.round_resets.blind}) +end +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.calculate_context({setting_blind = true, blind = G.GAME.round_resets.blind}) + +-- TARGET: setting_blind effects +''' + +# context.pre_discard +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = ''' +for j = 1, #G.jokers.cards do + G.jokers.cards[j]:calculate_joker({pre_discard = true, full_hand = G.hand.highlighted, hook = hook}) +end +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.calculate_context({pre_discard = true, full_hand = G.hand.highlighted, hook = hook}) + +-- TARGET: pre_discard +''' + +# context.selling_self in cards +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = ''' +self:calculate_joker{selling_self = true} +''' +position = 'at' +match_indent = true +payload = ''' +local eval, post = eval_card(self, {selling_self = true}) +SMODS.trigger_effects({eval, post}, self) +''' + +# context.open_booster +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = ''' + for i = 1, #G.jokers.cards do + G.jokers.cards[i]:calculate_joker({open_booster = true, card = self}) + end +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.calculate_context({open_booster = true, card = self}) +''' + +# context.buying_card +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = ''' + for i = 1, #G.jokers.cards do + G.jokers.cards[i]:calculate_joker({buying_card = true, card = self}) + end +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.calculate_context({buying_card = true, card = self}) +''' + +# context.first_hand_drawn +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = ''' + for i = 1, #G.jokers.cards do + G.jokers.cards[i]:calculate_joker({first_hand_drawn = true}) + end +end +''' +position = 'at' +match_indent = true +payload = ''' + SMODS.calculate_context({first_hand_drawn = true}) +end +SMODS.calculate_context({hand_drawn = true}) +''' + +# context.using_consumeable +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = ''' + for i = 1, #G.jokers.cards do + G.jokers.cards[i]:calculate_joker({using_consumeable = true, consumeable = card}) + end +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.calculate_context({using_consumeable = true, consumeable = card, area = card.from_area}) +''' +# save area of used card +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +match_indent = true +position = 'before' +pattern = ''' +c1.area:remove_card(c1) +''' +payload = ''' +c1.from_area = c1.area +''' +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +match_indent = true +position = 'before' +pattern = ''' +if card.area and (not nc or card.area == G.pack_cards) then card.area:remove_card(card) end +''' +payload = ''' +if not card.from_area then card.from_area = card.area end +''' + +# context.selling_card +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = ''' + for i = 1, #G.jokers.cards do + if G.jokers.cards[i] ~= card then + G.jokers.cards[i]:calculate_joker({selling_card = true, card = card}) + end + end +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.calculate_context({selling_card = true, card = card}) +''' + + +# context.buying_card +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = ''' +G.E_MANAGER:add_event(Event({func = function() c1:calculate_joker({buying_card = true, card = c1}) return true end})) +''' +position = 'at' +match_indent = true +payload = ''' +G.E_MANAGER:add_event(Event({func = function() + local eval, post = eval_card(c1, {buying_card = true, card = c1}) + SMODS.trigger_effects({eval, post}, c1) + return true + end})) +''' + +# context.buying_card +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = ''' + for i = 1, #G.jokers.cards do + G.jokers.cards[i]:calculate_joker({buying_card = true, card = c1}) + end +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.calculate_context({buying_card = true, card = c1}) +''' + +# context.ending_shop +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = ''' + for i = 1, #G.jokers.cards do + G.jokers.cards[i]:calculate_joker({ending_shop = true}) + end +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.calculate_context({ending_shop = true}) +''' + +# context.skipping_booster +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = ''' + for i = 1, #G.jokers.cards do + G.jokers.cards[i]:calculate_joker({skipping_booster = true}) + end +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.calculate_context({skipping_booster = true}) +''' +# context.skip_blind +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = ''' + for i = 1, #G.jokers.cards do + G.jokers.cards[i]:calculate_joker({skip_blind = true}) + end +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.calculate_context({skip_blind = true}) +''' + +# context.reroll_shop +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = ''' + for i = 1, #G.jokers.cards do + G.jokers.cards[i]:calculate_joker({reroll_shop = true}) + end +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.calculate_context({reroll_shop = true}) +''' + + +# Fix purple seal calc +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = ''' +if context.discard then + if self.seal == 'Purple' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then''' +position = 'at' +match_indent = true +payload = ''' +if context.discard and context.other_card == self then + if self.seal == 'Purple' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then''' + +# Fix context.blueprint persisting +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'after' +pattern = 'local other_joker_ret = other_joker:calculate_joker(context)' +payload = ''' +context.blueprint = nil +local eff_card = context.blueprint_card or self +context.blueprint_card = nil''' + +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = 'other_joker_ret.card = context.blueprint_card or self' +payload = '''other_joker_ret.card = eff_card''' + +# Auto deal with negative chips card_eval_status_text() +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'at' +pattern = ''' +text = localize{type='variable',key='a_chips',vars={amt}} +''' +payload = ''' +text = localize{type='variable',key='a_chips'..(amt<0 and '_minus' or ''),vars={math.abs(amt)}} +''' + +# Auto deal with negative mult card_eval_status_text() +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'at' +pattern = ''' +text = localize{type='variable',key='a_mult',vars={amt}} +''' +payload = ''' +text = localize{type='variable',key='a_mult'..(amt<0 and '_minus' or ''),vars={math.abs(amt)}} +''' + +# Auto deal with negative xmult card_eval_status_text() +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'at' +pattern = ''' +text = localize{type='variable',key='a_xmult',vars={amt}} +''' +payload = ''' +text = localize{type='variable',key='a_xmult'..(amt<0 and '_minus' or ''),vars={math.abs(amt)}} +''' +# Make percent and percent_delta globals +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +match_indent = true +position = 'at' +pattern = '''local percent = 0.3 +local percent_delta = 0.08 +''' +payload = '''percent = 0.3 +percent_delta = 0.08 +''' + +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +match_indent = true +position = 'at' +pattern = '''local percent = (i-0.999)/(#G.hand.cards-0.998) + (j-1)*0.1''' +payload = '''percent = (i-0.999)/(#G.hand.cards-0.998) + (j-1)*0.1''' + +# Add support for pitch and volume returns in effects +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'after' +pattern = ''' +volume = extra.edition and 0.3 or sound == 'multhit2' and 0.7 or 1 +''' +payload = ''' +sound = extra.sound or sound +percent = extra.pitch or percent +volume = extra.volume or volume +''' + +# Voucher cardarea +[[patches]] +[patches.pattern] +target = 'game.lua' +match_indent = true +position = 'before' +pattern = 'self.deck = CardArea(' +payload = '''self.vouchers = CardArea( + G.discard.T.x, G.discard.T.y, + G.discard.T.w, G.discard.T.h, + { type = "discard", card_limit = 1e308 } +) +''' + +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'after' +pattern = 'function Card:apply_to_run(center)' +payload = '''local card_to_save = self and copy_card(self) or Card(0, 0, G.CARD_W, G.CARD_H, G.P_CARDS.empty, center) +card_to_save.VT.x, card_to_save.VT.y = G.vouchers.T.x, G.vouchers.T.y +G.vouchers:emplace(card_to_save) +''' + +[[patches]] +[patches.pattern] +target = 'card.lua' +position = 'at' +match_indent = false +pattern = '''if self.ability.set == "Planet" and not self.debuff then + if context.joker_main then + if G.GAME.used_vouchers.v_observatory and self.ability.consumeable.hand_type == context.scoring_name then + return { + message = localize{type = 'variable', key = 'a_xmult', vars = {G.P_CENTERS.v_observatory.config.extra}}, + Xmult_mod = G.P_CENTERS.v_observatory.config.extra + } + end + end +end''' +payload = '' + +[[patches]] +[patches.regex] +target = 'back.lua' +position = 'at' +line_prepend = '$indent' +pattern = '(?[\t ]*)(?Card.apply_to_run\(nil, G\.P_CENTERS\[.*?\]\))' +payload = '''G.E_MANAGER:add_event(Event({ + func = function() + $line + return true + end +}))''' + +#wtf +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = '''self.discard_pos = { + r = 3.6*(math.random()-0.5), + x = math.random(), + y = math.random() +}''' +payload = '''self.discard_pos = { + r = 0, + x = 0, + y = 0, +} +''' + +# xchip support +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'before' +pattern = ''' +elseif (eval_type == 'x_mult') or (eval_type == 'h_x_mult') then +''' +payload = ''' +elseif eval_type == 'x_chips' then + sound = 'xchips' + volume = 0.7 + amt = amt + text = localize{type='variable',key='a_xchips'..(amt<0 and '_minus' or ''),vars={math.abs(amt)}} + colour = G.C.BLUE + config.type = 'fade' + config.scale = 0.7 +''' +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'at' +pattern = ''' +if extra.chip_mod then +''' +payload = ''' +if extra.chip_mod or extra.Xchip_mod then +''' diff --git a/Steamodded/lovely/blind.toml b/smods-main/lovely/blind.toml similarity index 74% rename from Steamodded/lovely/blind.toml rename to smods-main/lovely/blind.toml index 9464dd2..8ca1152 100644 --- a/Steamodded/lovely/blind.toml +++ b/smods-main/lovely/blind.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Blind API @@ -57,10 +57,10 @@ position = 'before' match_indent = true payload = ''' if not reset then - local obj = self.config.blind - if obj.set_blind and type(obj.set_blind) == 'function' then - obj:set_blind() - end + local obj = self.config.blind + if obj.set_blind and type(obj.set_blind) == 'function' then + obj:set_blind() + end end''' # Blind:disable() @@ -73,7 +73,7 @@ match_indent = true payload = ''' local obj = self.config.blind if obj.disable and type(obj.disable) == 'function' then - obj:disable() + obj:disable() end''' # Blind:defeat() @@ -86,7 +86,7 @@ match_indent = true payload = ''' local obj = self.config.blind if obj.defeat and type(obj.defeat) == 'function' then - obj:defeat() + obj:defeat() end''' # Blind:debuff_card() @@ -99,22 +99,22 @@ match_indent = true payload = ''' local obj = self.config.blind if not self.disabled and obj.recalc_debuff and type(obj.recalc_debuff) == 'function' then - if obj:recalc_debuff(card, from_blind) then - card:set_debuff(true) - if card.debuff then card.debuffed_by_blind = true end - else - card:set_debuff(false) - end - return + if obj:recalc_debuff(card, from_blind) then + card:set_debuff(true) + if card.debuff then card.debuffed_by_blind = true end + else + card:set_debuff(false) + end + return elseif not self.disabled and obj.debuff_card and type(obj.debuff_card) == 'function' then - sendWarnMessage(("Blind object %s has debuff_card function, recalc_debuff is preferred"):format(obj.key), obj.set) - if obj:debuff_card(card, from_blind) then - card:set_debuff(true) - if card.debuff then card.debuffed_by_blind = true end - else - card:set_debuff(false) - end - return + sendWarnMessage(("Blind object %s has debuff_card function, recalc_debuff is preferred"):format(obj.key), obj.set) + if obj:debuff_card(card, from_blind) then + card:set_debuff(true) + if card.debuff then card.debuffed_by_blind = true end + else + card:set_debuff(false) + end + return end''' # Blind:stay_flipped() @@ -127,7 +127,7 @@ match_indent = true payload = ''' local obj = self.config.blind if obj.stay_flipped and type(obj.stay_flipped) == 'function' then - return obj:stay_flipped(area, card) + return obj:stay_flipped(area, card) end''' # Blind:drawn_to_hand() @@ -140,7 +140,7 @@ line_prepend = '$indent' payload = ''' local obj = self.config.blind if obj.drawn_to_hand and type(obj.drawn_to_hand) == 'function' then - obj:drawn_to_hand() + obj:drawn_to_hand() end''' # Blind:debuff_hand() @@ -153,7 +153,7 @@ match_indent = true payload = ''' local obj = self.config.blind if obj.debuff_hand and type(obj.debuff_hand) == 'function' then - return obj:debuff_hand(cards, hand, handname, check) + return obj:debuff_hand(cards, hand, handname, check) end''' # Blind:modify_hand() @@ -166,7 +166,7 @@ match_indent = true payload = ''' local obj = self.config.blind if obj.modify_hand and type(obj.modify_hand) == 'function' then - return obj:modify_hand(cards, poker_hands, text, mult, hand_chips) + return obj:modify_hand(cards, poker_hands, text, mult, hand_chips) end''' # Blind:press_play() @@ -179,7 +179,7 @@ match_indent = true payload = ''' local obj = self.config.blind if obj.press_play and type(obj.press_play) == 'function' then - return obj:press_play() + return obj:press_play() end''' # Blind:get_loc_debuff_text() @@ -190,24 +190,27 @@ pattern = 'function Blind:get_loc_debuff_text()' position = 'after' match_indent = true payload = ''' - local obj = self.config.blind - if obj.get_loc_debuff_text and type(obj.get_loc_debuff_text) == 'function' then - return obj:get_loc_debuff_text() - end''' + local obj = self.config.blind + if obj.get_loc_debuff_text and type(obj.get_loc_debuff_text) == 'function' then + return obj:get_loc_debuff_text() + end''' # Blind:set_text() [[patches]] [patches.pattern] target = 'blind.lua' pattern = "local loc_target = localize{type = 'raw_descriptions', key = self.config.blind.key, set = 'Blind', vars = loc_vars or self.config.blind.vars}" -position = 'before' +position = 'at' match_indent = true payload = ''' +local target = {type = 'raw_descriptions', key = self.config.blind.key, set = 'Blind', vars = loc_vars or self.config.blind.vars} local obj = self.config.blind if obj.loc_vars and type(obj.loc_vars) == 'function' then - local res = obj:loc_vars() or {} - loc_vars = res.vars or {} -end''' + local res = obj:loc_vars() or {} + target.vars = res.vars or target.vars + target.key = res.key or target.key +end +local loc_target = localize(target)''' # Blind:load() [[patches]] @@ -218,7 +221,7 @@ position = 'after' match_indent = true payload = ''' if self.config.blind.atlas then - self.children.animatedSprite.atlas = G.ANIMATION_ATLAS[self.config.blind.atlas] + self.children.animatedSprite.atlas = G.ANIMATION_ATLAS[self.config.blind.atlas] end''' @@ -242,7 +245,7 @@ payload = ''' local s = 1.3 if math.ceil(#blind_tab/6) > 6 then - s = s * 6/math.ceil(#blind_tab/6) + s = s * 6/math.ceil(#blind_tab/6) end local temp_blind = AnimatedSprite(0,0,s,s, G.ANIMATION_ATLAS[discovered and v.atlas or 'blind_chips'], discovered and v.pos or G.b_undiscovered.pos)''' line_prepend = '$indent' @@ -257,13 +260,13 @@ payload = ''' local blinds_per_row = math.ceil(#blind_tab / 6) local row = math.ceil((k - 1) / blinds_per_row + 0.001) table.insert(blind_matrix[row], { - n = G.UIT.C, - config = { align = "cm", padding = 0.1 }, - nodes = { - ((k - blinds_per_row) % (2 * blinds_per_row) == 1) and { n = G.UIT.B, config = { h = 0.2, w = 0.5 } } or nil, - { n = G.UIT.O, config = { object = temp_blind, focus_with_object = true } }, - ((k - blinds_per_row) % (2 * blinds_per_row) == 0) and { n = G.UIT.B, config = { h = 0.2, w = 0.5 } } or nil, - } + n = G.UIT.C, + config = { align = "cm", padding = 0.1 }, + nodes = { + ((k - blinds_per_row) % (2 * blinds_per_row) == 1) and { n = G.UIT.B, config = { h = 0.2, w = 0.5 } } or nil, + { n = G.UIT.O, config = { object = temp_blind, focus_with_object = true } }, + ((k - blinds_per_row) % (2 * blinds_per_row) == 0) and { n = G.UIT.B, config = { h = 0.2, w = 0.5 } } or nil, + } })''' [[patches]] @@ -301,16 +304,17 @@ pattern = "local loc_target = localize{type = 'raw_descriptions', key = blind_ch match_indent = true position = 'at' payload = ''' -local loc_vars = nil +local target = {type = 'raw_descriptions', key = blind_choice.config.key, set = 'Blind', vars = {}} if blind_choice.config.name == 'The Ox' then - loc_vars = {localize(G.GAME.current_round.most_played_poker_hand, 'poker_hands')} + target.vars = {localize(G.GAME.current_round.most_played_poker_hand, 'poker_hands')} end local obj = blind_choice.config if obj.loc_vars and _G['type'](obj.loc_vars) == 'function' then - local res = obj:loc_vars() or {} - loc_vars = res.vars or {} + local res = obj:loc_vars() or {} + target.vars = res.vars or target.vars + target.key = res.key or target.key end -local loc_target = localize{type = 'raw_descriptions', key = blind_choice.config.key, set = 'Blind', vars = loc_vars or blind_choice.config.vars}''' +local loc_target = localize(target)''' # create_UIBox_blind_popup() [[patches]] @@ -320,12 +324,13 @@ pattern = '''local loc_target = localize{type = 'raw_descriptions', key = blind. match_indent = true position = 'at' payload = ''' -local loc_vars = nil +local target = {type = 'raw_descriptions', key = blind.key, set = 'Blind', vars = vars or blind.vars} if blind.collection_loc_vars and type(blind.collection_loc_vars) == 'function' then - local res = blind:collection_loc_vars() or {} - loc_vars = res.vars + local res = blind:collection_loc_vars() or {} + target.vars = res.vars or target.vars + target.key = res.key or target.key end -local loc_target = localize{type = 'raw_descriptions', key = blind.key, set = 'Blind', vars = loc_vars or vars or blind.vars}''' +local loc_target = localize(target)''' # get_new_boss() [[patches]] @@ -336,16 +341,16 @@ match_indent = true position = 'before' payload = ''' elseif v.in_pool and type(v.in_pool) == 'function' then - local res, options = v:in_pool() - if - ( - ((G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2) == - (v.boss.showdown or false) - ) or - (options or {}).ignore_showdown_check - then - eligible_bosses[k] = res and true or nil - end''' + local res, options = v:in_pool() + if + ( + ((G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2) == + (v.boss.showdown or false) + ) or + (options or {}).ignore_showdown_check + then + eligible_bosses[k] = res and true or nil + end''' # G.UIDEF.challenge_description_tab [[patches]] @@ -354,4 +359,4 @@ target = 'functions/UI_definitions.lua' pattern = "local temp_blind = AnimatedSprite(0,0,1,1, G.ANIMATION_ATLAS['blind_chips'], v.pos)" position = 'at' match_indent = true -payload = "local temp_blind = AnimatedSprite(0,0,1,1, G.ANIMATION_ATLAS[v.atlas or ''] or G.ANIMATION_ATLAS['blind_chips'], v.pos)" \ No newline at end of file +payload = "local temp_blind = AnimatedSprite(0,0,1,1, G.ANIMATION_ATLAS[v.atlas or ''] or G.ANIMATION_ATLAS['blind_chips'], v.pos)" diff --git a/Steamodded/lovely/blind_ui.toml b/smods-main/lovely/blind_ui.toml similarity index 98% rename from Steamodded/lovely/blind_ui.toml rename to smods-main/lovely/blind_ui.toml index a5dac7a..8c84f3f 100644 --- a/Steamodded/lovely/blind_ui.toml +++ b/smods-main/lovely/blind_ui.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Allow blinds to have more than 2 lines @@ -104,7 +104,7 @@ target = "functions/UI_definitions.lua" pattern = """{n=G.UIT.R, config={align = "cm", id = 'row_blind', minw = 1, minh = 3.75}, nodes={}},""" position = 'at' payload = """{n=G.UIT.R, config={align = "cm", id = 'row_blind', minw = 1, minh = 3.75}, nodes={ - {n=G.UIT.B, config={w=0, h=3.64, id = 'row_blind_bottom'}, nodes={}} + {n=G.UIT.B, config={w=0, h=3.64, id = 'row_blind_bottom'}, nodes={}} }},""" match_indent = true @@ -147,4 +147,4 @@ line_prepend = '$indent' target = 'functions/UI_definitions.lua' pattern = '''\(k ==1 and blind\.name == 'The Wheel' and '1' or ''\)\.\.''' position = 'at' -payload = '' \ No newline at end of file +payload = '' diff --git a/smods-main/lovely/booster.toml b/smods-main/lovely/booster.toml new file mode 100644 index 0000000..c2131c0 --- /dev/null +++ b/smods-main/lovely/booster.toml @@ -0,0 +1,264 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +## Booster Pack API + +# Card:open +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''(?[\t ]*)if self\.ability\.name:find\('Arcana'\) then \n[\s\S]{12}G\.STATE''' +position = "before" +payload = ''' +booster_obj = self.config.center +if booster_obj and SMODS.Centers[booster_obj.key] then + G.STATE = G.STATES.SMODS_BOOSTER_OPENED + SMODS.OPENED_BOOSTER = self +end''' +line_prepend = '$indent' + +# Card:open +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''(?[\t ]*)if self\.ability\.name:find\('Arcana'\) then[\t\n ]*if G\.GAME\.used_vouchers\.v_omen_globe and pseudorandom\('omen_globe'\) > 0\.8 then''' # Possibly try to target something else +position = "at" +payload = '''if booster_obj.create_card and type(booster_obj.create_card) == "function" then + local _card_to_spawn = booster_obj:create_card(self, i) + if type((_card_to_spawn or {}).is) == 'function' and _card_to_spawn:is(Card) then + card = _card_to_spawn + else + card = SMODS.create_card(_card_to_spawn) + end +elseif self.ability.name:find('Arcana') then + if G.GAME.used_vouchers.v_omen_globe and pseudorandom('omen_globe') > 0.8 then''' +line_prepend = '$indent' + +# Game:set_globals +[[patches]] +[patches.regex] +target = "globals.lua" +pattern = '''(?[\t ]*)self\.STATES = \{''' +position = "after" +payload = ''' + + SMODS_BOOSTER_OPENED = 999,''' +line_prepend = '$indent' + +# Game:update +[[patches]] +[patches.regex] +target = "game.lua" +pattern = '''(?[\t ]*)if self\.STATE == self\.STATES\.TAROT_PACK then''' +position = "before" +payload = ''' +if G.STATE == G.STATES.SMODS_BOOSTER_OPENED then + SMODS.OPENED_BOOSTER.config.center:update_pack(dt) +end + +''' +line_prepend = '$indent' + +# G.FUNC.can_skip_booster +# TODO customize whether pack can be skipped +[[patches]] +[patches.regex] +target = "functions/button_callbacks.lua" +pattern = '''(?[\t ]*)\(G\.STATE == G\.STATES\.PLANET_PACK or G\.STATE == G\.STATES\.STANDARD_PACK''' +position = "at" +payload = '''(G.STATE == G.STATES.SMODS_BOOSTER_OPENED or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.STANDARD_PACK''' + +# CardArea:draw() +[[patches]] +[patches.pattern] +target = "cardarea.lua" +pattern = "(self.config.type == 'deck' and self ~= G.deck) or" +position = "before" +payload = ''' +(self.config.type == 'hand' and state == G.STATES.SMODS_BOOSTER_OPENED) or''' +match_indent = true + +# G.FUNCS.use_card +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = "prev_state == G.STATES.SPECTRAL_PACK or prev_state == G.STATES.STANDARD_PACK or" +position = "after" +payload = ''' +prev_state == G.STATES.SMODS_BOOSTER_OPENED or''' +match_indent = true + +# CardArea:align_cards() +[[patches]] +[patches.pattern] +target = "cardarea.lua" +pattern = "if self.config.type == 'hand' and (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.PLANET_PACK) then" +position = "at" +payload = "if self.config.type == 'hand' and (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) then" +match_indent = true + +# CardArea:align_cards() +[[patches]] +[patches.pattern] +target = "cardarea.lua" +pattern = "if self.config.type == 'hand' and not (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.PLANET_PACK) then" +position = "at" +payload = "if self.config.type == 'hand' and not (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) then" +match_indent = true + +# Card:can_use_consumable() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if G.STATE == G.STATES.SELECTING_HAND or G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.PLANET_PACK then" +position = "at" +payload = "if G.STATE == G.STATES.SELECTING_HAND or G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED then" +match_indent = true + +# G.FUNCS.use_card() +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = "if G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.SPECTRAL_PACK then" +position = "at" +payload = """ +if nc then + if area then area:remove_from_highlighted(card) end + play_sound('cardSlide2', nil, 0.3) + dont_dissolve = true +end +if (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) then""" +match_indent = true + +# G.FUNC.use_card() +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = 'if area == G.consumeables then' +position = 'before' +match_indent = true +payload = ''' +if nc and area == G.pack_cards then G.pack_cards:remove_card(card); G.consumeables:emplace(card) end''' + +# G.FUNC.use_card() +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = "(G.STATE == G.STATES.BUFFOON_PACK and G.STATES.BUFFOON_PACK) or" +position = "before" +payload = "(G.STATE == G.STATES.SMODS_BOOSTER_OPENED and G.STATES.SMODS_BOOSTER_OPENED) or" +match_indent = true + +# G.FUNC.use_card() +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "if not (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK) and" +position = "at" +payload = "if not (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) and" +match_indent = true + +# Card:use_consumeable() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''(?[\t ]*)align = \(G\.STATE[\s\S]*and -0\.2 or 0},''' +position = "at" +payload = ''' +align = (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) and 'tm' or 'cm', +offset = {x = 0, y = (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) and -0.2 or 0},''' +line_prepend = '$indent' + +# G.FUNCS.use_card() +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = "e.config.ref_table:redeem()" +position = "before" +payload = "if area == G.pack_cards then e.config.ref_table.cost = 0 end" +match_indent = true + +## Stopping ease_dollars anim from playing when voucher is free +# Card:redeem() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''(?[\t ]*)ease_dollars\(-self\.cost\)\n[\s\S]{8}inc_career_stat\('c_shop_dollars_spent', self\.cost\)''' +position = "at" +payload = ''' +if self.cost ~= 0 then + ease_dollars(-self.cost) + inc_career_stat('c_shop_dollars_spent', self.cost) +end''' +line_prepend = '$indent' + +# Add support for saving consumables +# comment +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +match_indent = true +position = 'before' +pattern = ''' +if card.ability.consumeable then + if (card.area == G.pack_cards and G.pack_cards) then +''' +payload = ''' +if card.ability.consumeable and booster_obj and booster_obj.select_card then + if (card.area == G.pack_cards and G.pack_cards) then + return {n=G.UIT.ROOT, config = {padding = 0, colour = G.C.CLEAR}, nodes={ + {n=G.UIT.R, config={ref_table = card, r = 0.08, padding = 0.1, align = "bm", minw = 0.5*card.T.w - 0.15, maxw = 0.9*card.T.w - 0.15, minh = 0.3*card.T.h, hover = true, shadow = true, colour = G.C.UI.BACKGROUND_INACTIVE, one_press = true, button = 'use_card', func = 'can_select_from_booster'}, nodes={ + {n=G.UIT.T, config={text = localize('b_select'),colour = G.C.UI.TEXT_LIGHT, scale = 0.45, shadow = true}} + }}, + }} + end +end +''' + +# comment +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +match_indent = true +position = 'at' +pattern = ''' +if card.ability.consumeable then + if nc then +''' +payload = ''' +if booster_obj and booster_obj.select_card then + local area = type(booster_obj.select_card) == 'table' and (booster_obj.select_card[e.config.ref_table.ability.set] or nil) or booster_obj.select_card + G[area]:emplace(card) + play_sound('card1', 0.8, 0.6) + play_sound('generic1') + dont_dissolve = true + delay_fac = 0.2 +elseif card.ability.consumeable then + if nc then +''' +# comment +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +match_indent = true +position = 'before' +pattern = ''' +if area == G.consumeables then +''' +payload = ''' +booster_obj = nil +''' +# comment +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +match_indent = true +position = 'after' +pattern = ''' +G.FUNCS.skip_booster = function(e) +''' +payload = ''' +booster_obj = nil +''' diff --git a/smods-main/lovely/center.toml b/smods-main/lovely/center.toml new file mode 100644 index 0000000..b92a26d --- /dev/null +++ b/smods-main/lovely/center.toml @@ -0,0 +1,552 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Center API + +# Card:set_ability() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = "(?[\t ]*)if not G\\.OVERLAY_MENU then \n" +position = 'before' +payload = ''' +local obj = self.config.center +if obj.set_ability and type(obj.set_ability) == 'function' then + obj:set_ability(self, initial, delay_sprites) +end + +''' +line_prepend = '$indent' +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "self.ability.bonus = (self.ability.bonus or 0) + (center.config.bonus or 0)" +position = "after" +payload = """ +for k, v in pairs(center.config) do + if k ~= 'bonus' then + if type(v) == 'table' then + self.ability[k] = copy_table(v) + else + self.ability[k] = v + end + end +end""" +match_indent = true + +# Card:calculate_joker() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''function Card:calculate_joker(context) + if self.debuff then return nil end +''' +position = 'after' +payload = ''' + local obj = self.config.center + if self.ability.set ~= "Enhanced" and obj.calculate and type(obj.calculate) == 'function' then + local o, t = obj:calculate(self, context) + if o or t then return o, t end + end''' +match_indent = true + +# Card:update() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = 'if G.STAGE == G.STAGES.RUN then' +position = 'before' +match_indent = true +payload = ''' +local obj = self.config.center +if obj.update and type(obj.update) == 'function' then + obj:update(self, dt) +end''' + +# Card:generate_UIBox_ability_table() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = "(?else)\n[\t ]*if self.ability.name == 'Loyalty Card' then\n[\t ]*self.ability.loyalty_remaining" +root_capture = 'else' +position = 'at' +payload = 'elseif context.joker_main then' + + +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = 'return generate_card_ui(self.config.center, nil, loc_vars, card_type, badges, hide_desc, main_start, main_end)' +position = 'at' +match_indent = true +payload = 'return generate_card_ui(self.config.center, nil, loc_vars, card_type, badges, hide_desc, main_start, main_end, self)' + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "full_UI_table.name = localize{type = 'name', set = _c.set, key = _c.key, nodes = full_UI_table.name}" +position = 'at' +match_indent = true +payload = ''' +if not _c.generate_ui or type(_c.generate_ui) ~= 'function' then + full_UI_table.name = localize{type = 'name', set = _c.set, key = _c.key, nodes = full_UI_table.name} +end''' + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "elseif specific_vars and specific_vars.debuffed then" +position = 'before' +match_indent = true +payload = ''' +elseif _c.generate_ui and type(_c.generate_ui) == 'function' then + _c:generate_ui(info_queue, card, desc_nodes, specific_vars, full_UI_table) + if specific_vars and specific_vars.pinned then info_queue[#info_queue+1] = {key = 'pinned_left', set = 'Other'} end + if specific_vars and specific_vars.sticker then info_queue[#info_queue+1] = {key = string.lower(specific_vars.sticker)..'_sticker', set = 'Other'} end''' + +[[patches]] +[patches.regex] +target = 'functions/common_events.lua' +pattern = "(?[\t ]+)if (?_c.name == 'Golden Ticket' then)" +line_prepend = '$indent' +position = 'at' +payload = ''' +local res = {} +if _c.locked_loc_vars and type(_c.locked_loc_vars) == 'function' then + local _card = _c.create_fake_card and _c:create_fake_card() + res = _c:locked_loc_vars(info_queue, _card) or {} + loc_vars = res.vars or {} + specific_vars = specific_vars or {} + specific_vars.not_hidden = res.not_hidden or specific_vars.not_hidden + if res.main_start then desc_nodes[#desc_nodes+1] = res.main_start end + main_end = res.main_end or main_end +elseif $rest''' + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +position = 'at' +match_indent = true +pattern = "localize{type = 'unlocks', key = 'joker_locked_legendary', set = 'Other', nodes = desc_nodes, vars = loc_vars}" +payload = "localize{type = 'unlocks', key = res.key or 'joker_locked_legendary', set = res.set or 'Other', nodes = desc_nodes, vars = loc_vars, text_colour = res.text_colour, scale = res.scale}" + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +position = 'at' +match_indent = true +pattern = "localize{type = 'unlocks', key = _c.key, set = _c.set, nodes = desc_nodes, vars = loc_vars}" +payload = "localize{type = 'unlocks', key = res.key or _c.key, set = res.set or _c.set, nodes = desc_nodes, vars = loc_vars, text_colour = res.text_colour, scale = res.scale}" + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +position = 'at' +match_indent = true +pattern = 'elseif desc_nodes ~= full_UI_table.main then' +payload = 'elseif desc_nodes ~= full_UI_table.main and not desc_nodes.name then' + + + +# check_for_unlock() +[[patches]] +[patches.regex] +target = 'functions/common_events.lua' +pattern = "(?[\t ]*)if not card.unlocked and card.unlock_condition and args.type == 'career_stat' then" +line_prepend = '$indent' +position = 'before' +payload = ''' + +local custom_check +if not card.unlocked and card.check_for_unlock and type(card.check_for_unlock) == 'function' then + ret = card:check_for_unlock(args) + if ret then unlock_card(card) end + custom_check = true +end''' + +[[patches]] +[patches.regex] +target = 'functions/common_events.lua' +pattern = "(?[\t ]*)if(? )not card.unlocked and card.unlock_condition and args.type == 'career_stat' then" +position = 'at' +root_capture = 'a' +payload = ' not custom_check and ' + +[[patches]] +[patches.regex] +target = 'functions/common_events.lua' +pattern = "(?[\t ]*)if(? )not card.unlocked and card.unlock_condition and card.unlock_condition.type == args.type then" +position = 'at' +root_capture = 'a' +payload = ' not custom_check and ' + +#Card:use_consumable() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = "(?[\t ]*)if self.ability.consumeable.mod_conv or self.ability.consumeable.suit_conv then" +line_prepend = '$indent' +position = 'before' +payload = ''' +local obj = self.config.center +if obj.use and type(obj.use) == 'function' then + obj:use(self, area, copier) + return +end''' + +# Card:can_use_consumable() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = "(?[\t ]*)if self.ability.name == 'The Hermit' or self.ability.consumeable.hand_type" +line_prepend = '$indent' +position = 'before' +payload = ''' +local obj = self.config.center +if obj.can_use and type(obj.can_use) == 'function' then + return obj:can_use(self) +end''' + +# G.UIDEF.card_h_popup() +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = "(?[\t ]*)(?if AUT.badges.card_type or AUT.badges.force_rarity then)\n[\t ]*(?.*)\n[\t ]*end" +line_prepend = '$indent' +position = 'at' +payload = ''' +local obj = card.config.center +$if + if obj and (obj.set_card_type_badge or obj.type and obj.type.set_card_type_badge) then + if obj.type and type(obj.type.set_card_type_badge) == 'function' then + obj.type:set_card_type_badge(obj, card, badges) + end + if type(obj.set_card_type_badge) == 'function' then + obj:set_card_type_badge(card, badges) + end + else + $rest + end +end +if obj and obj.set_badges and type(obj.set_badges) == 'function' then + obj:set_badges(card, badges) +end''' + +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = "(?[\t ]*)if AUT.badges then\n([\t ]*.*\n){4}[\t ]*end" +line_prepend = '$indent' +position = 'after' +payload = ''' +if AUT.card_type ~= 'Locked' and AUT.card_type ~= 'Undiscovered' then + SMODS.create_mod_badges(card.config.center, badges) + if card.base then + SMODS.create_mod_badges(SMODS.Ranks[card.base.value], badges) + SMODS.create_mod_badges(SMODS.Suits[card.base.suit], badges) + end + if card.config and card.config.tag then + SMODS.create_mod_badges(SMODS.Tags[card.config.tag.key], badges) + end + badges.mod_set = nil +end''' + +# set_discover_tallies() +[[patches]] +[patches.regex] +target = 'functions/misc_functions.lua' +pattern = "(?[\t ]*)if v.set == 'Planet' then(\n[\t ]*.*){15}" +line_prepend = '$indent' +position = 'at' +payload = ''' +local tally = G.DISCOVER_TALLIES[v.set:lower()..'s'] +if tally then + tally.of = tally.of + 1 + if v.discovered then + tally.tally = tally.tally + 1 + end +end''' + +[[patches]] +[patches.regex] +target = 'functions/misc_functions.lua' +pattern = "[\t ]*tarots = \\{tally = 0, of = 0\\},\n(.*\n){2}" +line_prepend = '$indent' +position = 'at' +payload = '' + +[[patches]] +[patches.regex] +target = 'functions/misc_functions.lua' +pattern = "(?[\t ]*)for _, v in pairs\\(G.DISCOVER_TALLIES\\) do" +line_prepend = '$indent' +position = 'before' +payload = ''' +for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do + G.DISCOVER_TALLIES[v:lower()..'s'] = {tally = 0, of = 0} +end''' + +# create_UIBox_your_collection() +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = "(?[\t ]*)local t = create_UIBox_generic_options\\(\\{ back_func = G.STAGE" +line_prepend = '$indent' +position = 'before' +payload = ''' +local consumable_nodes = {} +if #SMODS.ConsumableType.ctype_buffer <= 3 then + for _, key in ipairs(SMODS.ConsumableType.ctype_buffer) do + local id = 'your_collection_'..key:lower()..'s' + consumable_nodes[#consumable_nodes+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = G.DISCOVER_TALLIES[key:lower()..'s'], minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) + end +else + consumable_nodes[#consumable_nodes+1] = UIBox_button({ button = 'your_collection_consumables', label = {localize('b_stat_consumables'), localize{ type = 'variable', key = 'c_types', vars = {#SMODS.ConsumableType.ctype_buffer} } }, count = G.DISCOVER_TALLIES['consumeables'], minw = 4, minh = 4, id = 'your_collection_consumables', colour = G.C.FILTER }) +end +''' + +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = "(?[\t ]*)nodes=\\{\n[\t ]*UIBox_button\\(\\{button = 'your_collection_tarots'(.*\n){3}[\t ]*}" +line_prepend = '$indent' +position = 'at' +payload = 'nodes = consumable_nodes' + +# Card:apply_to_run() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = "(?[\t ]*)if center_table.name == 'Overstock'" +line_prepend = '$indent' +position = 'before' +payload = ''' +local obj = center or self.config.center +if obj.redeem and type(obj.redeem) == 'function' then + obj:redeem(card_to_save) + return +end''' + +# create_card_for_shop() +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = "local total_rate = G.GAME.joker_rate + G.GAME.tarot_rate + G.GAME.planet_rate + G.GAME.playing_card_rate + G.GAME.spectral_rate" +match_indent = true +position = 'at' +payload = ''' +local total_rate = G.GAME.joker_rate + G.GAME.playing_card_rate +for _,v in ipairs(SMODS.ConsumableType.ctype_buffer) do + total_rate = total_rate + G.GAME[v:lower()..'_rate'] +end''' + +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = '(?[\t ]*)for _, v in ipairs\((?
  • \{\n(.*\n){5}[\t ]*\})\) do' +line_prepend = '$indent' +position = 'at' +payload = ''' +-- need to preserve order to leave RNG unchanged +local rates = $li +for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do + if not (v == 'Tarot' or v == 'Planet' or v == 'Spectral') then + table.insert(rates, { type = v, val = G.GAME[v:lower()..'_rate'] }) + end +end +for _, v in ipairs(rates) do''' + +# create_card() +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "if not forced_key and soulable and (not G.GAME.banned_keys['c_soul']) then" +match_indent = true +position = 'after' +payload = ''' + for _, v in ipairs(SMODS.Consumable.legendaries) do + if (_type == v.type.key or _type == v.soul_set) and not (G.GAME.used_jokers[v.key] and not next(find_joker("Showman")) and not v.can_repeat_soul) and (not v.in_pool or (type(v.in_pool) ~= "function") or v:in_pool()) then + if pseudorandom('soul_'..v.key.._type..G.GAME.round_resets.ante) > (1 - v.soul_rate) then + forced_key = v.key + end + end + end''' + +# Card:add_to_deck() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = '(?[\t ]*)if self.ability.h_size ~= 0 then\n[\t ]*G\.hand:change_size\(self.ability.h_size\)' +line_prepend = '$indent' +position = 'before' +payload = ''' +local obj = self.config.center +if obj and obj.add_to_deck and type(obj.add_to_deck) == 'function' then + obj:add_to_deck(self, from_debuff) +end''' + +# Card:remove_from_deck() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = '(?[\t ]*)if self.ability.h_size ~= 0 then\n[\t ]*G\.hand:change_size\(-self.ability.h_size\)' +line_prepend = '$indent' +position = 'before' +payload = ''' +local obj = self.config.center +if obj and obj.remove_from_deck and type(obj.remove_from_deck) == 'function' then + obj:remove_from_deck(self, from_debuff) +end''' + +# G.FUNCS.use_card() +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = "if card.area then card.area:remove_card(card) end" +match_indent = true +position = 'at' +payload = ''' +local nc +if card.ability.consumeable then + local obj = card.config.center + if obj.keep_on_use and type(obj.keep_on_use) == 'function' then + nc = obj:keep_on_use(card) + end +end +if card.area and (not nc or card.area == G.pack_cards) then card.area:remove_card(card) end''' + +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = "else draw_card(G.hand, G.play, 1, 'up', true, card, nil, mute) end" +match_indent = true +position = 'at' +payload = '''elseif not nc then draw_card(G.hand, G.play, 1, 'up', true, card, nil, mute) end''' + +# Card:set_sprites() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = "if not self.children.back then" +match_indent = true +position = 'at' +payload = ''' +if _center.set_sprites and type(_center.set_sprites) == 'function' then + _center:set_sprites(self, _front) +end +if true then''' + +# Card:load() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = 'if self.config.center.name == "Half Joker" then' +match_indent = true +position = 'at' +payload = ''' +local obj = self.config.center +if obj.load and type(obj.load) == 'function' then + obj:load(self, cardTable, other_card) +elseif self.config.center.name == "Half Joker" then''' + +# Card:calculate_dollar_bonus() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = """function Card:calculate_dollar_bonus() + if self.debuff then return end""" +position = "after" +match_indent = true +payload = ''' + local obj = self.config.center + if obj.calc_dollar_bonus and type(obj.calc_dollar_bonus) == 'function' then + return obj:calc_dollar_bonus(self) + end +''' + +# Card:draw() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '--If the card has any edition/seal, add that here' +position = 'before' +match_indent = true +payload = ''' +local center = self.config.center +if center.draw and type(center.draw) == 'function' then + center:draw(self, layer) +end +if center.set == 'Default' or center.set == 'Enhanced' and not center.replace_base_card then + if not center.no_suit then + local suit = SMODS.Suits[self.base.suit] or {} + if suit.draw and type(suit.draw) == 'function' then + suit:draw(self, layer) + end + end + if not center.no_rank then + local rank = SMODS.Ranks[self.base.value] or {} + if rank.draw and type(rank.draw) == 'function' then + rank:draw(self, layer) + end + end +end +''' + +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = 'if self.seal then' +position = 'at' +match_indent = true +payload = ''' +local seal = G.P_SEALS[self.seal or {}] or {} +if type(seal.draw) == 'function' then + seal:draw(self, layer) +elseif self.seal then +''' + +# no_blueprint check +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = 'if other_joker and other_joker ~= self then' +payload = 'if other_joker and other_joker ~= self and not context.no_blueprint then' + +# extract joker loc_vars +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = 'function Card:generate_UIBox_ability_table()' +payload = 'function Card:generate_UIBox_ability_table(vars_only)' + +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'before' +pattern = 'local badges = {}' +payload = 'if vars_only then return loc_vars, main_start, main_end end' + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'after' +pattern = "elseif _c.set == 'Joker' then" +payload = ''' + if not card then + local ability = copy_table(_c.config) + ability.set = 'Joker' + ability.name = _c.name + local ret = {Card.generate_UIBox_ability_table({ ability = ability, config = { center = _c }, bypass_lock = true}, true)} + specific_vars = ret[1] + if ret[2] then desc_nodes[#desc_nodes+1] = ret[2] end + main_end = ret[3] + end + ''' \ No newline at end of file diff --git a/Steamodded/lovely/challenge.toml b/smods-main/lovely/challenge.toml similarity index 94% rename from Steamodded/lovely/challenge.toml rename to smods-main/lovely/challenge.toml index e166a73..0db9203 100644 --- a/Steamodded/lovely/challenge.toml +++ b/smods-main/lovely/challenge.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -5 # function G.UIDEF.challenge_list_page() [[patches]] @@ -18,4 +18,4 @@ end challenge_unlocked = challenge_unlocked or G.PROFILES[G.SETTINGS.profile].all_unlocked """ -match_indent = true \ No newline at end of file +match_indent = true diff --git a/Steamodded/lovely/compact_cashout.toml b/smods-main/lovely/compact_cashout.toml similarity index 99% rename from Steamodded/lovely/compact_cashout.toml rename to smods-main/lovely/compact_cashout.toml index 3ce3b9b..98676f3 100644 --- a/Steamodded/lovely/compact_cashout.toml +++ b/smods-main/lovely/compact_cashout.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -5 # diff --git a/Steamodded/lovely/compat_0_9_8.toml b/smods-main/lovely/compat_0_9_8.toml similarity index 98% rename from Steamodded/lovely/compat_0_9_8.toml rename to smods-main/lovely/compat_0_9_8.toml index aefd252..a61c552 100644 --- a/Steamodded/lovely/compat_0_9_8.toml +++ b/smods-main/lovely/compat_0_9_8.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -5 # fallback for card.ability.name # Card:set_ability() diff --git a/Steamodded/lovely/core.toml b/smods-main/lovely/core.toml similarity index 96% rename from Steamodded/lovely/core.toml rename to smods-main/lovely/core.toml index 308ed41..899b0cc 100644 --- a/Steamodded/lovely/core.toml +++ b/smods-main/lovely/core.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -5 [[patches]] [patches.pattern] diff --git a/Steamodded/lovely/crash_handler.toml b/smods-main/lovely/crash_handler.toml similarity index 86% rename from Steamodded/lovely/crash_handler.toml rename to smods-main/lovely/crash_handler.toml index 078c3f0..cd590af 100644 --- a/Steamodded/lovely/crash_handler.toml +++ b/smods-main/lovely/crash_handler.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 [[patches]] [patches.pattern] @@ -16,5 +16,5 @@ match_indent = true target = "main.lua" position = "prepend" sources = [ - "src/crash_handler.lua", + "src/crash_handler.lua", ] diff --git a/smods-main/lovely/deck_skins.toml b/smods-main/lovely/deck_skins.toml new file mode 100644 index 0000000..c4e5c9f --- /dev/null +++ b/smods-main/lovely/deck_skins.toml @@ -0,0 +1,218 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +#========================================================# +# Choose any rank for custom deck and use provided atlas # +#========================================================# +[[patches]] +[patches.regex] +target = "functions/misc_functions.lua" +pattern = '''if _front and _front.suit and \(_front.value == 'Jack' or _front.value == 'Queen' or _front.value == 'King'\) then([\s\S]*?)end([\s\S]*?)end([\s\S]*?)end''' +position = "at" +payload = ''' +if _front and _front.suit and G.SETTINGS.CUSTOM_DECK and G.SETTINGS.CUSTOM_DECK.Collabs then + local collab = G.SETTINGS.CUSTOM_DECK.Collabs[_front.suit] + if collab then + local deckSkin = SMODS.DeckSkins[collab] + if deckSkin then + if deckSkin.outdated then + local hasRank = false + for i = 1, #deckSkin.ranks do + if deckSkin.ranks[i] == _front.value then hasRank = true break end + end + if hasRank then + local atlas = G.ASSET_ATLAS[G.SETTINGS.colour_palettes[_front.suit] == 'hc' and deckSkin.hc_atlas or deckSkin.lc_atlas] + if atlas then + if deckSkin.pos_style == 'collab' then + return atlas, G.COLLABS.pos[_front.value] + elseif deckSkin.pos_style == 'suit' then + return atlas, { x = _front.pos.x, y = 0} + elseif deckSkin.pos_style == 'deck' then + return atlas, _front.pos + elseif deckSkin.pos_style == 'ranks' or nil then + for i, rank in ipairs(deckSkin.ranks) do + if rank == _front.value then + return atlas, { x = i - 1, y = 0} + end + end + end + end + end + return G.ASSET_ATLAS[G.SETTINGS.colour_palettes[_front.suit] == 'hc' and _front.hc_atlas or _front.lc_atlas or {}] or G.ASSET_ATLAS[_front.atlas] or G.ASSET_ATLAS["cards_"..(G.SETTINGS.colour_palettes[_front.suit] == 'hc' and 2 or 1)], _front.pos + else + local palette = deckSkin.palette_map and deckSkin.palette_map[G.SETTINGS.colour_palettes[_front.suit] or ''] or (deckSkin.palettes or {})[1] + local hasRank = false + for i = 1, #palette.ranks do + if palette.ranks[i] == _front.value then hasRank = true break end + end + if hasRank then + local atlas = G.ASSET_ATLAS[palette.atlas] + if type(palette.pos_style) == "table" then + if palette.pos_style[_front.value] then + if palette.pos_style[_front.value].atlas then + atlas = G.ASSET_ATLAS[palette.pos_style[_front.value].atlas] + end + if palette.pos_style[_front.value].pos then + return atlas, palette.pos_style[_front.value].pos + end + elseif palette.pos_style.fallback_style then + if palette.pos_style.fallback_style == 'collab' then + return atlas, G.COLLABS.pos[_front.value] + elseif palette.pos_style.fallback_style == 'suit' then + return atlas, { x = _front.pos.x, y = 0} + elseif palette.pos_style.fallback_style == 'deck' then + return atlas, _front.pos + end + end + elseif palette.pos_style == 'collab' then + return atlas, G.COLLABS.pos[_front.value] + elseif palette.pos_style == 'suit' then + return atlas, { x = _front.pos.x, y = 0} + elseif palette.pos_style == 'deck' then + return atlas, _front.pos + elseif palette.pos_style == 'ranks' or nil then + for i, rank in ipairs(palette.ranks) do + if rank == _front.value then + return atlas, { x = i - 1, y = 0} + end + end + end + end + return G.ASSET_ATLAS[palette.hc_default and _front.hc_atlas or _front.lc_atlas or {}] or G.ASSET_ATLAS[_front.atlas] or G.ASSET_ATLAS["cards_"..(palette.hc_default and 2 or 1)], _front.pos + end + end + end +end +''' + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "{n=G.UIT.O, config={object = face_cards}}" +position = "at" +payload = "{n=G.UIT.O, config={object = G.cdds_cards}}" +match_indent = true +overwrite = false + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "table.insert(t, create_toggle({label = localize('b_high_contrast_cards'), ref_table = G.SETTINGS, ref_value = 'colourblind_option', callback = G.FUNCS.refresh_contrast_mode}))" +position = "at" +payload = ''' +local deckskin_key = G.COLLABS.options[_suit][current_option] + +local palette_loc_options = SMODS.DeckSkin.get_palette_loc_options(deckskin_key, _suit) + +local selected_palette = 1 +for i, v in ipairs(G.COLLABS.colour_palettes[deckskin_key]) do + if G.SETTINGS.colour_palettes[_suit] == v then + selected_palette = i + end +end + +table.insert(t, + {n=G.UIT.R, config={align = "cm", id = 'palette_selector'}, nodes={ + create_option_cycle({options = palette_loc_options, w = 5.5, cycle_shoulders = false, curr_suit = _suit, curr_skin = deckskin_key, opt_callback = 'change_colour_palette', current_option = selected_palette, colour = G.C.ORANGE, focus_args = {snap_to = true, nav = 'wide'}}), + }} + ) +''' +match_indent = true +overwrite = false + +#=======================# +# Extend custom deck ui # +#=======================# +[[patches]] +[patches.regex] +target = "functions/UI_definitions.lua" +pattern = '''local face_cards = CardArea\(([\s\S]*?)\)''' +position = "at" +payload = ''' +local rankCount = 0 +local lookup = {} +for i, s in ipairs(SMODS.Suit:obj_list(true)) do + local options = G.COLLABS.options[s.key] + for i = 1, #options do + local skin = SMODS.DeckSkins[options[i]] + if skin.palettes and not (skin.display_ranks or skin.ranks) then + for _, p in ipairs(skin.palettes) do + local p_ranks = p.display_ranks or p.ranks + for j = 1, #p_ranks do + if not lookup[p_ranks[j]] then + lookup[p_ranks[j]] = true + rankCount = rankCount + 1 + end + end + end + elseif not skin.palettes and (skin.display_ranks or skin.ranks) then + local ranks = skin.display_ranks or skin.ranks + for j = 1, #ranks do + if not lookup[skin.ranks[j]] then + lookup[skin.ranks[j]] = true + rankCount = rankCount + 1 + end + end + end + + end +end + +G.cdds_cards = CardArea( + 0,0, + math.min(math.max(rankCount*G.CARD_W*0.6, 4*G.CARD_W), 10*G.CARD_W), + 1.4*G.CARD_H, + {card_limit = rankCount, type = 'title', highlight_limit = 0}) + +G.cdds_cards.rankCount = rankCount + +''' + +[[patches]] +[patches.regex] +target = "functions/UI_definitions.lua" +pattern = '''for i = 1, 3 do([\s\S]*?)end''' +position = "at" +payload = ''' +G.FUNCS.update_collab_cards(current_option, _suit, true) +''' + +[[patches]] +[patches.regex] +target = "functions/UI_definitions.lua" +pattern = '''function create_UIBox_customize_deck()([\s\S]*?)end''' +position = "at" +payload = ''' +function create_UIBox_customize_deck() + local suitTabs = {} + + local index = 1 + for i, suit in ipairs(SMODS.Suit:obj_list(true)) do + if G.COLLABS.options[suit.key] then + suitTabs[index] = { + label = localize(suit.key, 'suits_plural'), + tab_definition_function = G.UIDEF.custom_deck_tab, + tab_definition_function_args = suit.key + } + index = index + 1 + end + end + + if suitTabs[1] then + suitTabs[1].chosen = true + end + + local t = create_UIBox_generic_options({ back_func = 'options', snap_back = nil, contents = { + {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ + create_tabs( + {tabs = suitTabs, snap_to_nav = true, no_shoulders = true} + )}}} + }) + + return t +end +''' + + diff --git a/smods-main/lovely/dollar_row.toml b/smods-main/lovely/dollar_row.toml new file mode 100644 index 0000000..4acb541 --- /dev/null +++ b/smods-main/lovely/dollar_row.toml @@ -0,0 +1,77 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Dollar row patches (API removed) + + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if num_dollars > 60 then" +position = "at" +payload = ''' +if num_dollars > 60 or num_dollars < -60 then''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "local dollar_string = localize('$')..num_dollars" +position = "at" +payload = ''' +if num_dollars < 0 then --if negative + G.E_MANAGER:add_event(Event({ + trigger = 'before',delay = 0.38, + func = function() + G.round_eval:add_child( + {n=G.UIT.R, config={align = "cm", id = 'dollar_row_'..(dollar_row+1)..'_'..config.name}, nodes={ + {n=G.UIT.O, config={object = DynaText({string = {'-'..localize('$')..format_ui_value(-num_dollars)}, colours = {G.C.MONEY}, shadow = true, pop_in = 0, scale = 0.65, float = true})}} + }}, + G.round_eval:get_UIE_by_ID('dollar_'..config.name)) + play_sound('coin3', 0.9+0.2*math.random(), 0.7) + play_sound('coin6', 1.3, 0.8) + return true + end + })) +else --if positive +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "for i = 1, num_dollars or 1 do" +position = "at" +payload = ''' +local dollars_to_loop +if num_dollars < 0 then dollars_to_loop = (num_dollars*-1)+1 else dollars_to_loop = num_dollars end +for i = 1, dollars_to_loop do''' +match_indent = true + +[[patches]] +[patches.regex] +target = "functions/common_events.lua" +pattern = '''(?[\t ]*)else\n[\t ]*local dollars_to_loop''' +position = "before" +line_prepend = "$indent" +payload = ''' +--asdf +end''' + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "local r = {n=G.UIT.T, config={text = localize('$'), colour = G.C.MONEY, scale = ((num_dollars > 20 and 0.28) or (num_dollars > 9 and 0.43) or 0.58), shadow = true, hover = true, can_collide = false, juice = true}}" +position = "at" +payload = ''' +local r +if i == 1 and num_dollars < 0 then + r = {n=G.UIT.T, config={text = '-', colour = G.C.RED, scale = ((num_dollars < -20 and 0.28) or (num_dollars < -9 and 0.43) or 0.58), shadow = true, hover = true, can_collide = false, juice = true}} + play_sound('coin3', 0.9+0.2*math.random(), 0.7 - (num_dollars < -20 and 0.2 or 0)) +else + if num_dollars < 0 then r = {n=G.UIT.T, config={text = localize('$'), colour = G.C.RED, scale = ((num_dollars > 20 and 0.28) or (num_dollars > 9 and 0.43) or 0.58), shadow = true, hover = true, can_collide = false, juice = true}} + else r = {n=G.UIT.T, config={text = localize('$'), colour = G.C.MONEY, scale = ((num_dollars > 20 and 0.28) or (num_dollars > 9 and 0.43) or 0.58), shadow = true, hover = true, can_collide = false, juice = true}} end +end''' +match_indent = true diff --git a/smods-main/lovely/edition.toml b/smods-main/lovely/edition.toml new file mode 100644 index 0000000..ccf477c --- /dev/null +++ b/smods-main/lovely/edition.toml @@ -0,0 +1,390 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +# Fix debug mode edition cycling +[[patches]] +[patches.regex] +target = "engine/controller.lua" +pattern = ''' +(?[\t ]*)local _edition = \{ +[\t ]*foil = not _card\.edition, +[\t ]*holo = _card\.edition and _card\.edition\.foil, +[\t ]*polychrome = _card\.edition and _card\.edition\.holo, +[\t ]*negative = _card\.edition and _card\.edition\.polychrome, +[\t ]*\}''' +position = "at" +payload = ''' +local found_index = 1 +if _card.edition then + for i, v in ipairs(G.P_CENTER_POOLS.Edition) do + if v.key == _card.edition.key then + found_index = i + break + end + end +end +found_index = found_index + 1 +if found_index > #G.P_CENTER_POOLS.Edition then found_index = found_index - #G.P_CENTER_POOLS.Edition end +local _edition = G.P_CENTER_POOLS.Edition[found_index].key''' +line_prepend = "$indent" + + +# Sort P_CENTER_POOLS["Editions"] +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = 'table.sort(self.P_CENTER_POOLS["Enhanced"], function (a, b) return a.order < b.order end)' +position = 'after' +payload = 'table.sort(self.P_CENTER_POOLS["Edition"], function (a, b) return a.order < b.order end)' +match_indent = true + + +# generate_card_ui() +# Adds tooltips for all editions +[[patches]] +[patches.regex] +target = 'functions/common_events.lua' +pattern = ''' +(?[\t ]*)if v == 'foil' then info_queue\[#info_queue\+1\] = G\.P_CENTERS\['e_foil'\] end +[\t ]*if v == 'holographic' then info_queue\[#info_queue\+1\] = G\.P_CENTERS\['e_holo'\] end +[\t ]*if v == 'polychrome' then info_queue\[#info_queue\+1\] = G\.P_CENTERS\['e_polychrome'\] end +[\t ]*if v == 'negative' then info_queue\[#info_queue\+1\] = G\.P_CENTERS\['e_negative'\] end +[\t ]*if v == 'negative_consumable' then info_queue\[#info_queue\+1\] = \{key = 'e_negative_consumable', set = 'Edition', config = \{extra = 1\}\} end''' +position = 'at' +payload = ''' +v = (v == 'holographic' and 'holo' or v) +if v:sub(1,9) == 'negative_' then + info_queue[#info_queue+1] = {key = 'e_'..v, set = 'Edition', config = {extra = G.P_CENTERS['e_negative'].config.card_limit}} +end +if G.P_CENTERS[v] and G.P_CENTERS[v].set == 'Edition' then + info_queue[#info_queue + 1] = G.P_CENTERS[v] +end +if G.P_CENTERS['e_'..v] and G.P_CENTERS['e_'..v].set == 'Edition' then + local t = {key = 'e_'..v, set = 'Edition', config = {}} + info_queue[#info_queue + 1] = t + if G.P_CENTERS['e_'..v].loc_vars and type(G.P_CENTERS['e_'..v].loc_vars) == 'function' then + local res = G.P_CENTERS['e_'..v]:loc_vars(info_queue, card) or {} + t.vars = res.vars + t.key = res.key or t.key + t.set = res.set or t.set + end +end''' +line_prepend = "$indent" +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = '''localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = loc_vars}''' +position = 'at' +match_indent = true +payload = '''localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = _c.vars or loc_vars}''' + + +# get_badge_colour() +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = 'return G.BADGE_COL[key] or {1, 0, 0, 1}' +position = 'before' +match_indent = true +payload = ''' +for _, v in ipairs(G.P_CENTER_POOLS.Edition) do + G.BADGE_COL[v.key:sub(3)] = v.badge_colour +end''' + +# Limit ARGS.send_to_shader[1] to wiggle between 0 and 2 instead of growing infinitely +# this makes shaders responsiveness on tilt reliable over time +# Card:draw() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +G\.TIMERS\.REAL/\(28\)''' +position = "at" +payload = '''math.sin(G.TIMERS.REAL/28) + 1''' + +# Allow editions to not draw shadow +# Card:draw() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +self\.ability\.effect ~= 'Glass Card' and not self\.greyed''' +position = "after" +payload = ''' and self:should_draw_shadow() ''' + +# If shader modifies shape of card, this will stop "back" layer of the card being rendered. +# Card:draw() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +elseif not self.greyed then''' +position = "before" +payload = ''' +elseif not self:should_draw_base_shader() then + -- Don't render base dissolve shader. +''' +match_indent = true + +# If shader modifies shape of card, this will stop "back" layer of the card being rendered. +# spectral cards and booster packs only. +# Card:draw() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +if self.ability.set == 'Booster' or self.ability.set == 'Spectral' then''' +position = "at" +payload = ''' +if (self.ability.set == 'Booster' or self.ability.set == 'Spectral') and self:should_draw_base_shader() then''' +match_indent = true + +# If shader modifies shape of card, this will stop "back" layer of the card being rendered. +# invisible joker and vouchers. +# Card:draw() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.children.center:draw_shader('voucher', nil, self.ARGS.send_to_shader)''' +position = "at" +payload = ''' +if self:should_draw_base_shader() then + self.children.center:draw_shader('voucher', nil, self.ARGS.send_to_shader) +end''' +match_indent = true + +# Inject shaders applying to cards +# Card:draw() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +(?[\t ]*)if self\.edition and self\.editi[A-z\.\:\n\t _(',)~=]*me', nil, self.ARGS.send_to_shader\) +[\t ]*end +[\t ]*end''' +position = "at" +payload = ''' +if self.edition then + for k, v in pairs(G.P_CENTER_POOLS.Edition) do + if self.edition[v.key:sub(3)] and v.shader then + if type(v.draw) == 'function' then + v:draw(self, layer) + else + self.children.center:draw_shader(v.shader, nil, self.ARGS.send_to_shader) + if self.children.front and self.ability.effect ~= 'Stone Card' and not self.config.center.replace_base_card then + self.children.front:draw_shader(v.shader, nil, self.ARGS.send_to_shader) + end + end + end + end +end''' +line_prepend = "$indent" + +# Inject shaders applying to floating sprites +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "self.children.floating_sprite:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod)" +position = "after" +payload = ''' +if self.edition then + for k, v in pairs(G.P_CENTER_POOLS.Edition) do + if v.apply_to_float then + if self.edition[v.key:sub(3)] then + self.children.floating_sprite:draw_shader(v.shader, nil, nil, nil, self.children.center, scale_mod, rotate_mod) + end + end + end +end''' +match_indent = true + +# Remove prefix from shader key when calling send() +[[patches]] +[patches.pattern] +target = "engine/sprite.lua" +pattern = "if _send then G.SHADERS[_shader or 'dissolve']:send(_shader,_send) end" +position = "at" +payload = ''' +if _send then + G.SHADERS[_shader or 'dissolve']:send((SMODS.Shaders[_shader or 'dissolve'] and SMODS.Shaders[_shader or 'dissolve'].original_key) or _shader,_send) +end''' +match_indent = true + +# Inject change to edition cost in shop +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '(?[\t ]*)self.ex([a-z._\s=+(0-9)]*)\n([\t ]*)([a-z._\s=+(0-9)]*)or 0\)' +position = "at" +payload = ''' +for k, v in pairs(G.P_CENTER_POOLS.Edition) do + if self.edition[v.key:sub(3)] then + if v.extra_cost then + self.extra_cost = self.extra_cost + v.extra_cost + end + end +end''' +line_prepend = "$indent" + +## Fix card_limit logic +# Card:add_to_deck() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''(?[\t ]*)if self\.edition[A-z\.\:\n\t _(',)~=+\-0-9]*limit \+ 1''' +position = "at" +payload = ''' +if true then + if from_debuff then + self.ability.joker_added_to_deck_but_debuffed = nil + else + if self.edition and self.edition.card_limit then + if self.ability.consumeable then + G.consumeables.config.card_limit = G.consumeables.config.card_limit + self.edition.card_limit + else + G.jokers.config.card_limit = G.jokers.config.card_limit + self.edition.card_limit + end''' +line_prepend = "$indent" +# Card:remove_from_deck() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''(?[\t ]*)if self\.edition[A-z\.\:\n\t _(',)~=+\-0-9]*limit \- 1''' +position = "at" +payload = ''' +if G.jokers then + if from_debuff then + self.ability.joker_added_to_deck_but_debuffed = true + else + if self.edition and self.edition.card_limit then + if self.ability.consumeable then + G.consumeables.config.card_limit = G.consumeables.config.card_limit - self.edition.card_limit + elseif self.ability.set == 'Joker' then + G.jokers.config.card_limit = G.jokers.config.card_limit - self.edition.card_limit + end''' +line_prepend = "$indent" +# Card:remove() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''(?[\t ]*)if self\.ability\.queue_neg[A-z\.\:\n\t _(',)~=+\-0-9]*limit \- 1''' +position = "at" +payload = ''' +if self.ability.joker_added_to_deck_but_debuffed then + if self.edition and self.edition.card_limit then + if self.ability.consumeable then + G.consumeables.config.card_limit = G.consumeables.config.card_limit - self.edition.card_limit + elseif self.ability.set == 'Joker' then + G.jokers.config.card_limit = G.jokers.config.card_limit - self.edition.card_limit + end''' +line_prepend = "$indent" +# Card:save() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "added_to_deck = self.added_to_deck," +position = "after" +payload = "joker_added_to_deck_but_debuffed = self.joker_added_to_deck_but_debuffed," +match_indent = true + + + +## Negative playing card logic +# CardArea:emplace() +[[patches]] +[patches.pattern] +target = "cardarea.lua" +pattern = "function CardArea:emplace(*" +position = "after" +payload = ''' + if card.edition and card.edition.card_limit and (self == G.hand) then + self.config.real_card_limit = (self.config.real_card_limit or self.config.card_limit) + card.edition.card_limit + self.config.card_limit = math.max(0, self.config.real_card_limit) + end''' +match_indent = true +# CardArea:remove_card() +[[patches]] +[patches.pattern] +target = "cardarea.lua" +pattern = "card:remove_from_area()" +position = "before" +payload = ''' +if card.edition and card.edition.card_limit and (self == G.hand) then + self.config.real_card_limit = (self.config.real_card_limit or self.config.card_limit) - card.edition.card_limit + self.config.card_limit = math.max(0, self.config.real_card_limit) +end''' +match_indent = true + +# G.FUNCS.draw_from_deck_to_hand() +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "local hand_space = e or*" +position = "at" +payload = """local hand_space = e +if not hand_space then + local limit = G.hand.config.card_limit - #G.hand.cards + local n = 0 + while n < #G.deck.cards do + local card = G.deck.cards[#G.deck.cards-n] + limit = limit - 1 + (card.edition and card.edition.card_limit or 0) + if limit < 0 then break end + n = n + 1 + end + hand_space = n +end""" +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "badges[#badges + 1] = 'negative_consumable'" +position = "after" +payload = """ +elseif self.edition.type == 'negative' and (self.ability.set == 'Enhanced' or self.ability.set == 'Default') then + badges[#badges + 1] = 'negative_playing_card'""" +match_indent = true + +[[patches]] +[patches.pattern] +target = "engine/sprite.lua" +pattern = "love.graphics.setShader( G.SHADERS[_shader or 'dissolve'], G.SHADERS[_shader or 'dissolve'])" +position = "before" +payload = ''' +local p_shader = SMODS.Shader.obj_table[_shader or 'dissolve'] +if p_shader and type(p_shader.send_vars) == "function" then + local sh = G.SHADERS[_shader or 'dissolve'] + local parent_card = self.role.major and self.role.major:is(Card) and self.role.major + local send_vars = p_shader.send_vars(self, parent_card) + + if type(send_vars) == "table" then + for key, value in pairs(send_vars) do + sh:send(key, value) + end + end +end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "if v == 'negative_consumable' then v = 'negative' end" +position = "at" +payload = '''if v == 'negative_consumable' or v == 'negative_playing_card' then v = 'negative' end''' +match_indent = true + +# +[[patches]] +[patches.regex] +target = 'functions/common_events.lua' +pattern = '''(?[\t ]*)(?local edition = poll_edition\('edi'\.\.\(key_append or ''\)\.\.G\.GAME\.round_resets\.ante\)(\n.*){2})''' +position = 'at' +line_prepend = '$indent' +payload = ''' +if not SMODS.bypass_create_card_edition then + $edi +end''' diff --git a/Steamodded/lovely/enhancement.toml b/smods-main/lovely/enhancement.toml similarity index 58% rename from Steamodded/lovely/enhancement.toml rename to smods-main/lovely/enhancement.toml index 843a2fd..ce5e769 100644 --- a/Steamodded/lovely/enhancement.toml +++ b/smods-main/lovely/enhancement.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ## no_rank, no_suit, all_suits @@ -12,7 +12,7 @@ target = "card.lua" pattern = "if self.ability.effect == 'Stone Card' and not self.vampired then" match_indent = true position = "at" -payload = "if (self.ability.effect == 'Stone Card' or self.config.center.no_rank) and not self.vampired then" +payload = '''if SMODS.has_no_rank(self) and not self.vampired then''' # Card:get_chip_bonus() [[patches]] @@ -37,8 +37,7 @@ target = "card.lua" pattern = "if temp_ID >= G.hand.cards[i].base.id and G.hand.cards[i].ability.effect ~= 'Stone Card' then temp_Mult = G.hand.cards[i].base.nominal; temp_ID = G.hand.cards[i].base.id; raised_card = G.hand.cards[i] end" match_indent = true position = "at" -payload = """ -if temp_ID >= G.hand.cards[i].base.id and (G.hand.cards[i].ability.effect ~= 'Stone Card' and not G.hand.cards[i].config.center.no_rank) then +payload = """if temp_ID >= G.hand.cards[i].base.id and not SMODS.has_no_rank(G.hand.cards[i]) then temp_Mult = G.hand.cards[i].base.nominal temp_ID = G.hand.cards[i].base.id raised_card = G.hand.cards[i] @@ -50,14 +49,15 @@ target = "card.lua" pattern = "if context.scoring_hand[i].ability.name ~= 'Wild Card' then" match_indent = true position = "at" -payload = "if context.scoring_hand[i].ability.name ~= 'Wild Card' and not context.scoring_hand[i].config.center.any_suit then" +payload = '''if not SMODS.has_any_suit(context.scoring_hand[i]) then''' + [[patches]] [patches.pattern] target = "card.lua" pattern = "if context.scoring_hand[i].ability.name == 'Wild Card' then" match_indent = true position = "at" -payload = "if context.scoring_hand[i].ability.name == 'Wild Card' or context.scoring_hand[i].config.center.any_suit then" +payload = '''if SMODS.has_any_suit(context.scoring_hand[i]) then''' # Card:get_suit() [[patches]] @@ -66,21 +66,21 @@ target = "card.lua" pattern = '''(?[\t ]*)if self\.ability\.effect == 'Stone Card' then''' line_prepend = '$indent' position = "at" -payload = "if self.ability.effect == 'Stone Card' or self.config.center.no_suit then" +payload = '''if SMODS.has_no_suit(self) then''' [[patches]] [patches.pattern] target = "card.lua" pattern = 'if self.ability.name == "Wild Card" then' match_indent = true position = "at" -payload = "if self.ability.name == 'Wild Card' or self.config.center.any_suit then" +payload = '''if SMODS.has_any_suit(self) then''' [[patches]] [patches.pattern] target = "card.lua" pattern = 'if self.ability.name == "Wild Card" and not self.debuff then' match_indent = true position = "at" -payload = "if (self.ability.name == 'Wild Card' or self.config.center.any_suit) and not self.debuff then" +payload = '''if SMODS.has_any_suit(self) and not self.debuff then''' # check_for_unlock [[patches]] @@ -89,7 +89,7 @@ target = "functions/common_events.lua" pattern = "if v.ability.name ~= 'Stone Card' and v.base.suit == 'Hearts' then" match_indent = true position = "at" -payload = "if (v.ability.name ~= 'Stone Card' and not v.config.center.no_suit) and v.base.suit == 'Hearts' then" +payload = "if not SMODS.has_no_suit(v) and v.base.suit == 'Hearts' then" # reset_idol_card() [[patches]] @@ -98,8 +98,7 @@ target = "functions/common_events.lua" pattern = "valid_idol_cards[#valid_idol_cards+1] = v" match_indent = true position = "at" -payload = """ -if (not v.config.center.no_suit) and (not v.config.center.no_rank) then +payload = """if not SMODS.has_no_suit(v) and not SMODS.has_no_rank(v) then valid_idol_cards[#valid_idol_cards+1] = v end""" @@ -110,8 +109,7 @@ target = "functions/common_events.lua" pattern = "valid_mail_cards[#valid_mail_cards+1] = v" match_indent = true position = "at" -payload = """ -if not v.config.center.no_rank then +payload = """if not SMODS.has_no_rank(v) then valid_mail_cards[#valid_mail_cards+1] = v end""" @@ -122,8 +120,7 @@ target = "functions/common_events.lua" pattern = "valid_castle_cards[#valid_castle_cards+1] = v" match_indent = true position = "at" -payload = """ -if not v.config.center.no_suit then +payload = """if not SMODS.has_no_suit(v) then valid_castle_cards[#valid_castle_cards+1] = v end""" @@ -134,22 +131,21 @@ target = "functions/state_events.lua" pattern = "if G.play.cards[i].ability.effect == 'Stone Card' then" match_indent = true position = "at" -payload = "if G.play.cards[i].ability.effect == 'Stone Card' or G.play.cards[i].config.center.always_scores then" +payload = '''if SMODS.always_scores(G.play.cards[i]) then''' [[patches]] [patches.pattern] target = "functions/state_events.lua" pattern = "if scoring_hand[i].ability.effect ~= 'Stone Card' then" match_indent = true position = "at" -payload = "if scoring_hand[i].ability.effect ~= 'Stone Card' and not scoring_hand[i].config.center.no_rank then" +payload = '''if not SMODS.has_no_rank(scoring_hand[i]) then''' [[patches]] [patches.pattern] target = "functions/state_events.lua" pattern = "G.GAME.cards_played[scoring_hand[i].base.value].suits[scoring_hand[i].base.suit] = true" match_indent = true position = "at" -payload = """ -if not scoring_hand[i].config.center.no_suit then +payload = """if not SMODS.has_no_suit(scoring_hand[i]) then G.GAME.cards_played[scoring_hand[i].base.value].suits[scoring_hand[i].base.suit] = true end""" @@ -182,95 +178,92 @@ match_indent = true position = "at" payload = "elseif specific_vars.playing_card then" -# eval_card() -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = "function eval_card(card, context)" -match_indent = true -position = "after" -payload = """ - local enhancement_calculated = false - local center = card.config.center""" -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = "local jokers = card:calculate_joker(context)" -match_indent = true -position = "before" -payload = """ -if card.ability.set == 'Enhanced' and center.calculate and type(center.calculate) == 'function' then - center:calculate(card, context, ret) - enhancement_calculated = true -end""" -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = "local seals = card:calculate_seal(context)" -match_indent = true -position = "before" -payload = """ -if card.ability.set == 'Enhanced' and center.calculate and type(center.calculate) == 'function' then - center:calculate(card, context, ret) - enhancement_calculated = true -end""" -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = "if context.cardarea == G.jokers or context.card == G.consumeables then" -match_indent = true -position = "before" -payload = """ -if not enhancement_calculated and card.ability.set == 'Enhanced' and center.calculate and type(center.calculate) == 'function' then - center:calculate(card, context, ret) - enhancement_calculated = true -end -local seals = card:calculate_seal(context) -if seals then - ret.seals = seals -end""" - - -## Add additional eval_card() calls - -# Game:update_draw_to_hand() - -[[patches]] -[patches.pattern] -target = "game.lua" -pattern = "G.GAME.current_round.discards_used == 0 and G.GAME.facing_blind then" -match_indent = true -position = "after" -payload = """ -for i = 1, #G.hand.cards do - eval_card(G.hand.cards[i], {first_hand_drawn = true}) -end""" - -# G.FUNCS.discard_cards_from_highlighted() +## Allow cards to function as multiple enhancements (e.g. from jokers) +# Calculate extra enhancements when held in hand at end of round [[patches]] [patches.pattern] target = "functions/state_events.lua" -pattern = "inc_career_stat('c_cards_discarded', highlighted_count)" -match_indent = true -position = "after" -payload = """ -for i = 1, #G.hand.cards do - eval_card(G.hand.cards[i], {pre_discard = true, full_hand = G.hand.highlighted, hook = hook}) -end""" -[[patches]] -[patches.regex] -target = "functions/state_events.lua" -pattern = ''' -(?[\t ]*)G\.hand\.highlighted\[i\]:calculate_seal\(\{discard = true\}\) -[\t ]*local removed = false''' -line_prepend = '$indent' +pattern = "local effects = {G.hand.cards[i]:get_end_of_round_effect()}" position = "at" -payload = """ -local removed = false -local eval = nil -eval = eval_card(G.hand.highlighted[i], {discard = true, full_hand = G.hand.highlighted}) -if eval and eval.remove then - removed = true - card_eval_status_text(G.hand.highlighted[i], 'jokers', nil, 1, nil, eval) -end""" +payload = ''' +local effects = {[1] = {playing_card = G.hand.cards[i]:get_end_of_round_effect()}} +local extra_enhancements = SMODS.get_enhancements(G.hand.cards[i], true) +local old_ability = copy_table(G.hand.cards[i].ability) +local old_center = G.hand.cards[i].config.center +local old_center_key = G.hand.cards[i].config.center_key +for k, _ in pairs(extra_enhancements) do + if G.P_CENTERS[k] then + G.hand.cards[i]:set_ability(G.P_CENTERS[k]) + G.hand.cards[i].ability.extra_enhancement = k + effects[#effects+1] = {[1] = {playing_card = G.hand.cards[i]:get_end_of_round_effect()}} + end +end +G.hand.cards[i].ability = old_ability +G.hand.cards[i].config.center = old_center +G.hand.cards[i].config.center_key = old_center_key +G.hand.cards[i]:set_sprites(old_center) +''' +match_indent = true + +# Prevent blue seal effect on extra enhancements at end of round +[[patches]] +[patches.pattern] +target = "card" +pattern = "if self.seal == 'Blue' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then" +position = "before" +payload = ''' +if self.extra_enhancement then return ret end +''' +match_indent = true + +# Use the has enhancement function for enhancement gates +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if vv.config.center.key == v.enhancement_gate then" +position = "at" +payload = "if SMODS.has_enhancement(vv, v.enhancement_gate) then" +match_indent = true + +# Glass Card shattering +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if card.ability.name == 'Glass Card' then" +position = "at" +payload = "if SMODS.has_enhancement(card, 'm_glass') then" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "if G.hand.highlighted[i].ability.name == 'Glass Card' then" +position = "at" +payload = "if SMODS.has_enhancement(G.hand.highlighted[i], 'm_glass') then" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "if scoring_hand[i].ability.name == 'Glass Card' then" +position = "at" +payload = "if SMODS.shatters(scoring_hand[i]) then" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "if cards_destroyed[i].ability.name == 'Glass Card' then" +position = "at" +payload = "if SMODS.has_enhancement(cards_destroyed[i], 'm_glass') then" +match_indent = true + +# Prevent blue seals from applying on quantum enhancement calc +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if self.seal == 'Blue' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then" +position = "at" +payload = "if self.seal == 'Blue' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit and not self.ability.extra_enhancement then" +match_indent = true \ No newline at end of file diff --git a/smods-main/lovely/fixes.toml b/smods-main/lovely/fixes.toml new file mode 100644 index 0000000..1d89b3e --- /dev/null +++ b/smods-main/lovely/fixes.toml @@ -0,0 +1,643 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Fixes for either base game code or general mod compatibility + +## Mods assume Game:start_run() is called with non-nil argument +# G.FUNCS.start_run() +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = "G.FUNCS.start_run = function(e, args)" +position = 'after' +match_indent = true +payload = "args = args or {}" + +## Allows running the game without Steam being active +# love.load() +[[patches]] +[patches.regex] +target = 'main.lua' +pattern = "(?[\t ]*)if not \\(st.init and st:init\\(\\)\\) then\n[\t ]*(?love.event.quit\\(\\))" +position = 'at' +root_capture = 'quit' +payload = 'st = nil' + + +## Prevents the game from crashing when hitting play with a corrupt/invalid save file +# G.FUNCS.can_continue(e) +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = "if G.SAVED_GAME ~= nil then G.SAVED_GAME = STR_UNPACK(G.SAVED_GAME) end" +position = 'after' +match_indent = true +payload = """ +if G.SAVED_GAME == nil then + e.config.colour = G.C.UI.BACKGROUND_INACTIVE + e.config.button = nil + return _can_continue +end +""" + +## Fix loading a blind with $0 reward +# Blind:load() +[[patches]] +[patches.regex] +target = 'blind.lua' +pattern = ''' +(?[\t ]*) G\.HUD_blind\.alignment\.offset\.y = 0 +[\t ]*end''' +position = 'at' +payload = ''' +end +if G.GAME.blind.name and G.GAME.blind.name ~= '' then + G.HUD_blind.alignment.offset.y = 0 +end''' +line_prepend = '$indent' + +## Remove incorrect check for Moveable alignment change +# Moveable:align_to_major() +[[patches]] +[patches.regex] +target = 'engine/moveable.lua' +pattern = ''' +(?[\t ]*)if +self\.alignment\.prev_offset\.x == self\.alignment\.offset\.x[\s\S]*?return end +''' +position = 'at' +payload = 'if not self.alignment.type_list then return end' +line_prepend = '$indent' + +## Prevent softlock if booster pack is empty +## Crashes the game when you skip too fast on this PR, along with being the culprit for allowing you to skip boosters early +# G.FUNCS.can_skip_booster() +# [[patches]] +# [patches.pattern] +# target = 'functions/button_callbacks.lua' +# pattern = 'if G.pack_cards and (G.pack_cards.cards[1]) and' +# position = 'at' +# payload = 'if G.pack_cards and' +# match_indent = true + +## Set `G.your_collection.config.collection` to true in all cases +# create_UIBox_your_collection_seals() +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = '''\{card_limit = 4, type = 'title', highlight_limit = 0\}''' +position = 'at' +payload = '''{card_limit = 4, type = 'title', highlight_limit = 0, collection = true}''' + +## Save and load Card.unique_val +# Card:save() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = "bypass_lock = self.bypass_lock," +position = "after" +payload = """ +unique_val = self.unique_val, +unique_val__saved_ID = self.ID, +ignore_base_shader = self.ignore_base_shader, +ignore_shadow = self.ignore_shadow,""" +match_indent = true + +# Card:load() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = "self.bypass_lock = cardTable.bypass_lock" +position = "after" +payload = """ +self.unique_val = cardTable.unique_val or self.unique_val +if cardTable.unique_val__saved_ID and G.ID <= cardTable.unique_val__saved_ID then + G.ID = cardTable.unique_val__saved_ID + 1 +end + +self.ignore_base_shader = cardTable.ignore_base_shader or {} +self.ignore_shadow = cardTable.ignore_shadow or {}""" +match_indent = true + +## Vars in card descriptions should use `card.ability` instead of `_c.config` where possible +## Allow passing in custom vars +# generate_card_ui() +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = 'function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, hide_desc, main_start, main_end)' +position = 'at' +match_indent = true +payload = '''function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, hide_desc, main_start, main_end, card) + if _c.specific_vars then specific_vars = _c.specific_vars end''' + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "if _c.set == 'Other' then" +position = 'before' +match_indent = true +payload = "local cfg = (card and card.ability) or _c['config']" # string index to make sure the next patch doesn't eat it + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "if _c.name ~= 'Stone Card' and ((specific_vars and specific_vars.bonus_chips) or _c.config.bonus) then" +position = 'at' +match_indent = true +payload = "if _c.name ~= 'Stone Card' and ((specific_vars and specific_vars.bonus_chips) or (cfg.bonus ~= 0 and cfg.bonus)) then" + +[[patches]] +[patches.regex] +target = 'functions/common_events.lua' +pattern = '_c.config' +position = 'at' +payload = 'cfg' + +## When overriding with set_ability and card is added to deck, call add / remove effects +# Card:set_ability() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = "self.config.center = center" +position = 'before' +match_indent = true +payload = ''' +if self.added_to_deck and old_center and not self.debuff then + self:remove_from_deck() + self.added_to_deck = true +end''' + +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = "if G.consumeables and self.area == G.consumeables then" +position = 'before' +match_indent = true +payload = ''' +if self.added_to_deck and old_center and not self.debuff then + self.added_to_deck = false + self:add_to_deck() +end''' + +## set_ability() transfers over old fields +# special cases: +# extra_value should be transferred +# name, effect, set, extra should always be overwritten +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = ''' +(?[\t ]*)self\.ability = (\{[\s\S]*? +[\t ]*\}) +''' +position = 'at' +line_prepend = '$indent' +payload = ''' +local new_ability = $2 +self.ability = self.ability or {} +new_ability.extra_value = nil +self.ability.extra_value = self.ability.extra_value or 0 +for k, v in pairs(new_ability) do + self.ability[k] = v +end +-- reset keys do not persist an ability change +local reset_keys = {'name', 'effect', 'set', 'extra', 'played_this_ante'} +for _, mod in ipairs(SMODS.mod_list) do + if mod.set_ability_reset_keys then + local keys = mod.set_ability_reset_keys() + for _, v in pairs(keys) do table.insert(reset_keys, v) end + end +end +for _, k in ipairs(reset_keys) do + self.ability[k] = new_ability[k] +end +''' + +## Fix crash if self.config.card == nil for non-vanilla set_ability() calls +# Card:set_ability() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = "self.label = center.label or self.config.card.label or self.ability.set" +position = 'at' +match_indent = true +payload = "self.label = center.label or self.config.card and self.config.card.label or self.ability.set" + +### Fix Matador + +# These patches have been removed for altering vanilla behavior. Git blame this line to see what they were + +### Fix Crimson Heart + +## Blind:drawn_to_hand() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = "if self.name == 'Crimson Heart' and self.prepped and G.jokers.cards[1] then" +position = 'after' +match_indent = true +payload = """ + local prev_chosen_set = {} + local fallback_jokers = {}""" +# Fix bad logic if not enough choices for debuff +[[patches]] +[patches.regex] +target = 'blind.lua' +pattern = ''' +(?[\t ]*)for i = 1, #G\.jokers\.cards do +[\t ]*if not G\.jokers\.cards\[i\]\.debuff or #G\.jokers\.cards < 2 then jokers\[#jokers\+1\] = ?G\.jokers\.cards\[i\] end +[\t ]*G\.jokers\.cards\[i\]:set_debuff\(false\) +[\t ]*end''' +position = 'at' +line_prepend = '$indent' +payload = """ +for i = 1, #G.jokers.cards do + if G.jokers.cards[i].ability.crimson_heart_chosen then + prev_chosen_set[G.jokers.cards[i]] = true + G.jokers.cards[i].ability.crimson_heart_chosen = nil + if G.jokers.cards[i].debuff then SMODS.recalc_debuff(G.jokers.cards[i]) end + end +end +for i = 1, #G.jokers.cards do + if not G.jokers.cards[i].debuff then + if not prev_chosen_set[G.jokers.cards[i]] then + jokers[#jokers+1] = G.jokers.cards[i] + end + table.insert(fallback_jokers, G.jokers.cards[i]) + end +end +if #jokers == 0 then jokers = fallback_jokers end""" +# Add variable for Crimson Heart's choice +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = "_card:set_debuff(true)" +position = "at" +match_indent = true +payload = """ +_card.ability.crimson_heart_chosen = true +SMODS.recalc_debuff(_card)""" + +## Blind:debuff_card() +[[patches]] +[patches.regex] +target = 'blind.lua' +pattern = ''' +if self\.name == 'Crimson Heart' and not self\.disabled and card\.area == G\.jokers then\s+ +((?[\t ]*)return)''' +root_capture = '$1' +position = "at" +line_prepend = '$indent' +payload = """ +if card.ability.crimson_heart_chosen then + card:set_debuff(true); + if card.debuff then card.debuffed_by_blind = true end + return +end""" + +## Blind:press_play() +# Shouldn't work with Matador +# yes it should + +## Blind:disable() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = "if self.name == 'The Water' then" +position = 'before' +payload = """ +if self.name == 'Crimson Heart' then + for _, v in ipairs(G.jokers.cards) do + v.ability.crimson_heart_chosen = nil + end +end""" +match_indent = true + +## Blind:defeat() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = "if self.name == 'The Manacle' and not self.disabled then" +position = 'before' +payload = """ +if self.name == 'Crimson Heart' then + for _, v in ipairs(G.jokers.cards) do + v.ability.crimson_heart_chosen = nil + end +end""" +match_indent = true + + +## Fix Manacle's unnecessary card draw after positive G.hand:change_size() +# Blind:disable() +[[patches]] +[patches.regex] +target = 'blind.lua' +pattern = 'G\.hand:change_size\(1\)(\s+G\.FUNCS\.draw_from_deck_to_hand\(1\))' +root_capture = '$1' +position = 'at' +payload = "" + +# +# Money scaling fix +# + +## create_UIBox_HUD +[[patches]] +[patches.regex] +target = "functions/UI_definitions.lua" +pattern = ''' +string = \{\{ref_table = G\.GAME\, ref_value = 'dollars'\, prefix = localize\('\$'\)\}\}\,''' +position = "after" +payload = ''' + + scale_function = function () + return scale_number(G.GAME.dollars, 2.2 * scale, 99999, 1000000) + end,''' + +## DynaText:update_text +[[patches]] +[patches.pattern] +target = "engine/text.lua" +pattern = 'self.config.H = 0' +position = "after" +payload = "self.scale = self.config.scale_function and self.config.scale_function() or self.scale" +match_indent = true + + +# +# Fix gold stake legendary infloop +# Do not try to roll for jokers that are not in_pool +# + +# generate_starting_seed() +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = '''if win_ante and (win_ante >= 8) then''' +match_indent = true +position = "at" +payload = '''if win_ante and (win_ante >= 8) or (v.in_pool and type(v.in_pool) == 'function' and not v:in_pool()) then''' + +# +# Fix G.GAME.blind:set_blind(nil, true, nil) +# being called when not in blind. +# + +# Card:add_to_deck +# Card:remove_from_deck +[[patches]] +[patches.regex] +target = "card.lua" +pattern = 'if G\.GAME\.blind then' +position = "at" +payload = "if G.GAME.blind and G.GAME.blind.in_blind then" + +# Blind:set_blind +[[patches]] +[patches.pattern] +target = "blind.lua" +match_indent = true +pattern = "if not reset then" +position = "after" +payload = ''' + if blind then + self.in_blind = true + end''' + +# end_round() +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "local game_over = true" +position = "before" +payload = "G.GAME.blind.in_blind = false" +match_indent = true + + + +# Make sure new param is loaded +[[patches]] +[patches.pattern] +target = "blind.lua" +match_indent = true +pattern = "function Blind:load(blindTable)" +position = "after" +payload = ''' + self.in_blind = blindTable.in_blind''' + +# Make sure new param is saved +[[patches]] +[patches.pattern] +target = "blind.lua" +match_indent = true +pattern = "local blindTable = {" +position = "after" +payload = ''' + in_blind = self.in_blind,''' + +# Cartomancer and astronomer unlock when *actually all* Tarot/Planet cards are discovered +# check_for_unlock() +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +match_indent = true +pattern = "if card.unlock_condition.tarot_count <= args.tarot_count then" +position = "at" +payload = 'if #G.P_CENTER_POOLS.Tarot <= args.tarot_count then' + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +match_indent = true +pattern = "if card.unlock_condition.planet_count <= args.planet_count then" +position = "at" +payload = 'if #G.P_CENTER_POOLS.Planet <= args.planet_count then' + +# wtf +[[patches]] +[patches.pattern] +target = "engine/animatedsprite.lua" +match_indent = true +pattern = "for _, v in pairs(G.ANIMATIONS) do" +position = "at" +payload = 'for k, v in pairs(G.ANIMATIONS) do' + +[[patches]] +[patches.pattern] +target = "engine/animatedsprite.lua" +match_indent = true +pattern = "for _, v in pairs(G.I.SPRITE) do" +position = "at" +payload = 'for k, v in pairs(G.I.SPRITE) do' + +## +## Card:draw() - improved mod compatibility +## +# Add option for sprites to not be drawn +[[patches]] +[patches.pattern] +target = "card.lua" +match_indent = true +pattern = ''' +if k ~= 'focused_ui' and k ~= "front" and k ~= "back" and k ~= "soul_parts" and k ~= "center" and k ~= 'floating_sprite' and k~= "shadow" and k~= "use_button" and k ~= 'buy_button' and k ~= 'buy_and_use_button' and k~= "debuff" and k ~= 'price' and k~= 'particles' and k ~= 'h_popup' then v:draw() end''' +position = "at" +payload = ''' +if not v.custom_draw and k ~= 'focused_ui' and k ~= "front" and k ~= "back" and k ~= "soul_parts" and k ~= "center" and k ~= 'floating_sprite' and k~= "shadow" and k~= "use_button" and k ~= 'buy_button' and k ~= 'buy_and_use_button' and k~= "debuff" and k ~= 'price' and k~= 'particles' and k ~= 'h_popup' then v:draw() end''' + +# This check is not necessary? +[[patches]] +[patches.pattern] +target = "card.lua" +match_indent = true +pattern = ''' +if self.edition or self.seal or self.ability.eternal or self.ability.rental or self.ability.perishable or self.sticker or ((self.sticker_run and self.sticker_run ~= 'NONE') and G.SETTINGS.run_stake_stickers) or (self.ability.set == 'Spectral') or self.debuff or self.greyed or (self.ability.name == 'The Soul') or (self.ability.set == 'Voucher') or (self.ability.set == 'Booster') or self.config.center.soul_pos or self.config.center.demo then''' +position = "at" +payload = ''' +if true then''' + +## Make vanilla enhancement jokers work with extra enhancements + +# Steel Joker +[[patches]] +[patches.pattern] +target = "card.lua" +match_indent = true +pattern = "if v.config.center == G.P_CENTERS.m_steel then self.ability.steel_tally = self.ability.steel_tally+1 end" +position = "at" +payload = "if SMODS.has_enhancement(v, 'm_steel') then self.ability.steel_tally = self.ability.steel_tally+1 end" + +# Stone Joker +[[patches]] +[patches.pattern] +target = "card.lua" +match_indent = true +pattern = "if v.config.center == G.P_CENTERS.m_stone then self.ability.stone_tally = self.ability.stone_tally+1 end" +position = "at" +payload = "if SMODS.has_enhancement(v, 'm_stone') then self.ability.stone_tally = self.ability.stone_tally+1 end" + +# Golden Ticket +[[patches]] +[patches.pattern] +target = "card.lua" +match_indent = true +pattern = "context.other_card.ability.name == 'Gold Card' then" +position = "at" +payload = "SMODS.has_enhancement(context.other_card, 'm_gold') then" + +# Golden Ticket Unlock +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +match_indent = true +pattern = "if args.cards[j].ability.name == 'Gold Card' then" +position = "at" +payload = "if SMODS.has_enhancement(args.cards[j], 'm_gold') then" + +# Glass Joker +[[patches]] +[patches.pattern] +target = "card.lua" +match_indent = true +pattern = "if val.ability.name == 'Glass Card' then shattered_glass = shattered_glass + 1 end" +position = "at" +payload = "if SMODS.has_enhancement(val, 'm_glass') then shattered_glass = shattered_glass + 1 end" + +# Driver's License +[[patches]] +[patches.pattern] +target = "card.lua" +match_indent = true +pattern = "if v.config.center ~= G.P_CENTERS.c_base then self.ability.driver_tally = self.ability.driver_tally+1 end" +position = "at" +payload = "if next(SMODS.get_enhancements(v)) then self.ability.driver_tally = self.ability.driver_tally+1 end" +# Basegame fix for the reroll vouchers redeem function when only the center but no card object exists + +# Card:apply_to_run +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = """G.GAME.round_resets.reroll_cost = G.GAME.round_resets.reroll_cost - self.ability.extra""" +position = 'at' +match_indent = true +payload = """G.GAME.round_resets.reroll_cost = G.GAME.round_resets.reroll_cost - center_table.extra""" + +# Card:apply_to_run +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = """G.GAME.current_round.reroll_cost = math.max(0, G.GAME.current_round.reroll_cost - self.ability.extra)""" +position = 'at' +match_indent = true +payload = """G.GAME.current_round.reroll_cost = math.max(0, G.GAME.current_round.reroll_cost - center_table.extra)""" + + +# Fix booster skip issues maybe? +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = "if G.pack_cards and (G.pack_cards.cards[1]) and" +position = "at" +payload = ''' +if G.pack_cards and (not (G.GAME.STOP_USE and G.GAME.STOP_USE > 0)) and +''' +match_indent = true + +# Due to STOP_USE being used we can remove this dumb check +# could probably remove the rest of it since it serves no purpose otherwise, but whatever +[[patches]] +[patches.regex] +target = "functions/button_callbacks.lua" +pattern = '''and \(G\.hand\.cards\[1\] or \(G\.hand\.config\.card_limit <= 0\)\)''' +position = "at" +payload = ''' ''' + +# Fixes Steam API not loading on unix +[[patches]] +[patches.pattern] +target = 'main.lua' +match_indent = true +position = 'after' +pattern = '--To control when steam communication happens, make sure to send updates to steam as little as possible' +payload = '''local cwd = NFS.getWorkingDirectory() +NFS.setWorkingDirectory(love.filesystem.getSourceBaseDirectory()) +''' + +[[patches]] +[patches.pattern] +target = 'main.lua' +match_indent = true +position = 'before' +pattern = '--Set up the render window and the stage for the splash screen, then enter the gameloop with :update' +payload = '''NFS.setWorkingDirectory(cwd) +''' + +[[patches]] +[patches.pattern] +target = "main.lua" +pattern = '''if os == 'OS X' or os == 'Windows' then''' +position = "at" +payload = '''if os == 'OS X' or os == 'Windows' or os == 'Linux' then''' +overwrite = true +match_indent = true + +[[patches]] +[patches.pattern] +target = "main.lua" +pattern = '''if os == 'OS X' then''' +position = "at" +payload = '''if os == 'OS X' or os == 'Linux' then''' +overwrite = true +match_indent = true + +[[patches]] +[patches.pattern] +target = "main.lua" +pattern = "st = require 'luasteam'" +position = "at" +payload = """local success, _st = pcall(require, 'luasteam') +if success then st = _st else sendWarnMessage(_st); st = {} end""" +overwrite = true +match_indent = true diff --git a/smods-main/lovely/joker_retriggers.toml b/smods-main/lovely/joker_retriggers.toml new file mode 100644 index 0000000..7fa637c --- /dev/null +++ b/smods-main/lovely/joker_retriggers.toml @@ -0,0 +1,364 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = 0 + + +# Luchador +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''[ \t]*G\.GAME\.blind:disable\(\) +(?[ \t]*)end''' +position = "at" +line_prepend = '$indent' +payload = ''' G.GAME.blind:disable() + return nil, true +end''' + +# Diet Cola +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*return true +[ \t]*end\) +[ \t]*\}\)\) +(?[ \t]*)end +''' +position = "at" +line_prepend = '$indent' +payload = ''' return true + end) + })) + return nil, true +end +''' + +# Invisible Joker +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''[ \t]*if card\.ability\.invis_rounds then card\.ability\.invis_rounds = 0 end +[ \t]*card:add_to_deck\(\) +(?[ \t]*)G\.jokers:emplace\(card\)''' +position = "after" +line_prepend = '$indent' +payload = "return nil, true" + +# Campfire +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''localize\('k_upgrade_ex'\)\}\); return true +[ \t]*end\}\)\) +[ \t]*end +(?[ \t]*)return''' +position = "at" +line_prepend = '$indent' +payload = '''localize('k_upgrade_ex')}); return true + end})) +end +if self.ability.name == 'Campfire' and not context.blueprint then return nil, true end''' + +# Flash Card +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''[ \t]*G\.C\.MULT\}\) +[ \t]*return true +[ \t]*end\)\}\)\) +(?[ \t]*)end''' +position = "at" +line_prepend = '$indent' +payload = '''G.C.MULT}) + return true + end)})) +end +if self.ability.name == 'Flash Card' and not context.blueprint then return nil, true end''' + +# Perkeo +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''[ \t]*card_eval_status_text\(context\.blueprint_card or self, 'extra', nil, nil, nil, \{message = localize\('k_duplicated_ex'\)\}\) +(?[ \t]*)end''' +position = "at" +line_prepend = '$indent' +payload = ''' card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_duplicated_ex')}) + return nil, true +end''' + +# Throwback +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +[ \t]*return +(?[ \t]*)elseif context\.skipping_booster''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Red Card +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +[ \t]*return +(?[ \t]*)elseif context\.playing_card_added''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Hologram +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +(?[ \t]*)elseif context\.first_hand_drawn''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Certificate +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +(?[ \t]*)if self\.ability\.name == 'DNA' and not context\.blueprint''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Chicot +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +(?[ \t]*)if self\.ability\.name == 'Madness' ''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Madness +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +(?[ \t]*)if self\.ability\.name == 'Burglar' ''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Burglar +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +(?[ \t]*)if self\.ability\.name == 'Riff-raff' ''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Riff-raff +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +(?[ \t]*)if self\.ability\.name == 'Cartomancer' ''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Cartomancer +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +(?[ \t]*)if self\.ability\.name == 'Ceremonial Dagger' and not context.blueprint''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Ceremonial Dagger +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +[ \t]*end +(?[ \t]*)if self\.ability\.name == 'Marble Joker' ''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Marble Joker +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +[ \t]*return +(?[ \t]*)elseif context.destroying_card''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Caino +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''[ \t]*func = function\(\) card_eval_status_text\(self, 'extra', nil, nil, nil, \{message = localize\{type = 'variable', key = 'a_xmult', vars = \{self\.ability\.caino_xmult\}\}\}\); return true +(?[ \t]*)end\}\)\)''' +position = "after" +line_prepend = '$indent' +payload = "return nil, true" + +# Glass Joker +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''glass_cards\}\}\}\) +[ \t]*return true +[ \t]*end +(?[ \t]*)\}\)\)''' +position = "after" +line_prepend = '$indent' +payload = "return nil, true" + +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +[ \t]*return +[ \t]*end +(?[ \t]*)if self\.ability\.name == 'Fortune Teller' and not context\.blueprint''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Fortune Teller +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +(?[ \t]*)if self\.ability\.name == 'Constellation' and not context\.blueprint''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Constellation +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +[ \t]*return +(?[ \t]*)elseif context.debuffed_hand''' +position = "before" +line_prepend = '$indent' +payload = "nil, true" + +# Burnt Joker +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +(?[ \t]*)elseif context.discard''' +position = "before" +line_prepend = '$indent' +payload = "return nil, true" + +# Faceless Joker +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +[ \t]*end +[ \t]*end +[ \t]*return +(?[ \t]*)elseif context.end_of_round''' +position = "before" +line_prepend = '$indent' +payload = "nil, true" + +# Yorick +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "self.ability.yorick_discards = self.ability.yorick_discards - 1" +position = "after" +match_indent = true +payload = "return nil, true" + +# Hallucination +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('k_plus_tarot'), colour = G.C.PURPLE})" +position = "after" +match_indent = true +payload = "return nil, true" + +## Change card returns +# Ramen +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +message = localize('k_eaten_ex'), +colour = G.C.FILTER''' +position = "before" +match_indent = true +payload = "card = self," +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''message = localize{type='variable',key='a_xmult_minus',vars={self.ability.extra}},''' +position = "before" +match_indent = true +payload = "card = self," + +# Yorick +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +delay = 0.2, +message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}},''' +position = "before" +match_indent = true +payload = "card = self," + +# To Do List +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''message = localize('$')..self.ability.extra.dollars, + dollars = self.ability.extra.dollars,''' +position = "at" +match_indent = true +payload = '''message = localize('$')..self.ability.extra.dollars,''' + +# Matador +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''message = localize('$')..self.ability.extra, + dollars = self.ability.extra,''' +position = "at" +match_indent = true +payload = '''message = localize('$')..self.ability.extra,''' diff --git a/smods-main/lovely/joker_size.toml b/smods-main/lovely/joker_size.toml new file mode 100644 index 0000000..8aa82ab --- /dev/null +++ b/smods-main/lovely/joker_size.toml @@ -0,0 +1,73 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = 0 + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +if _center.name == 'Square Joker' and (_center.discovered or self.bypass_discovery_center) then + self.children.center.scale.y = self.children.center.scale.x +end +''' +position = "after" +payload = ''' +if _center.pixel_size and _center.pixel_size.h and (_center.discovered or self.bypass_discovery_center) then + self.children.center.scale.y = self.children.center.scale.y*(_center.pixel_size.h/95) +end +if _center.pixel_size and _center.pixel_size.w and (_center.discovered or self.bypass_discovery_center) then + self.children.center.scale.x = self.children.center.scale.x*(_center.pixel_size.w/71) +end +''' +match_indent = true +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +if center.name == "Wee Joker" and (center.discovered or self.bypass_discovery_center) then + H = H*0.7 + W = W*0.7 + self.T.h = H + self.T.w = W +end +''' +position = "after" +payload = ''' +if center.display_size and center.display_size.h and (center.discovered or self.bypass_discovery_center) then + H = H*(center.display_size.h/95) + self.T.h = H +elseif center.pixel_size and center.pixel_size.h and (center.discovered or self.bypass_discovery_center) then + H = H*(center.pixel_size.h/95) + self.T.h = H +end +if center.display_size and center.display_size.w and (center.discovered or self.bypass_discovery_center) then + W = W*(center.display_size.w/71) + self.T.w = W +elseif center.pixel_size and center.pixel_size.w and (center.discovered or self.bypass_discovery_center) then + W = W*(center.pixel_size.w/71) + self.T.w = W +end +''' +match_indent = true +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.VT.h = self.T.H +self.VT.w = self.T.w +''' +position = "before" +payload = ''' +if self.config.center.display_size and self.config.center.display_size.h then + self.T.h = H*(self.config.center.display_size.h/95) +elseif self.config.center.pixel_size and self.config.center.pixel_size.h then + self.T.h = H*(self.config.center.pixel_size.h/95) +end +if self.config.center.display_size and self.config.center.display_size.w then + self.T.w = W*(self.config.center.display_size.w/71) +elseif self.config.center.pixel_size and self.config.center.pixel_size.w then + self.T.w = W*(self.config.center.pixel_size.w/71) +end +''' +match_indent = true diff --git a/smods-main/lovely/keybind.toml b/smods-main/lovely/keybind.toml new file mode 100644 index 0000000..80272b8 --- /dev/null +++ b/smods-main/lovely/keybind.toml @@ -0,0 +1,82 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + +# Check all registered keybinds +# inserted inside Controller:key_press_update + +[[patches]] +[patches.pattern] +target = 'engine/controller.lua' +pattern = "if not _RELEASE_MODE then" +position = "before" +payload = ''' +for _, keybind in pairs(SMODS.Keybinds) do + if keybind.action and keybind.key_pressed == key and keybind.event == 'pressed' then + local execute = true + for _, other_key in pairs(keybind.held_keys) do + if not self.held_keys[other_key] then + execute = false + break + end + end + if execute then + keybind:action() + end + end +end +''' +match_indent = true + +# Controller:key_release_update +[[patches]] +[patches.pattern] +target = 'engine/controller.lua' +pattern = "function Controller:key_release_update(key, dt)" +position = "after" +payload = ''' +for _, keybind in pairs(SMODS.Keybinds) do + if keybind.action and keybind.key_pressed == key and keybind.event == 'released' then + local execute = true + for _, other_key in pairs(keybind.held_keys) do + if not self.held_keys[other_key] then + execute = false + break + end + end + if execute then + keybind:action() + end + end +end +''' +match_indent = true + +[[patches]] +[patches.regex] +target = 'engine/controller.lua' +pattern = 'if key == "r"' +position = 'before' +line_prepend = '$indent' +payload = ''' +for _, keybind in pairs(SMODS.Keybinds) do + if keybind.key_pressed == key and keybind.event == 'held' and keybind.held_duration then + if self.held_key_times[key] > keybind.held_duration then + local execute = true + for _, other_key in pairs(keybind.held_keys) do + if not self.held_keys[other_key] then + execute = false + break + end + end + if execute then + keybind:action() + self.held_key_times[key] = nil + end + else + self.held_key_times[key] = self.held_key_times[key] + dt + end + end +end +''' diff --git a/Steamodded/lovely/language.toml b/smods-main/lovely/language.toml similarity index 68% rename from Steamodded/lovely/language.toml rename to smods-main/lovely/language.toml index 2d218d1..5c89e5d 100644 --- a/Steamodded/lovely/language.toml +++ b/smods-main/lovely/language.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Language API @@ -30,6 +30,25 @@ position = 'at' payload = "self.localization = assert(loadstring(love.filesystem.read('localization/'..G.SETTINGS.language..'.lua') or love.filesystem.read('localization/en-us.lua')))()" match_indent = true +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = "self.LANG = self.LANGUAGES[self.SETTINGS.language] or self.LANGUAGES['en-us']" +position = 'at' +payload = "self.LANG = self.LANGUAGES[self.SETTINGS.real_language or self.SETTINGS.language] or self.LANGUAGES['en-us']" +match_indent = true + +# G.FUNCS.change_lang + +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = "G.SETTINGS.language = lang.key" +position = 'at' +payload = """G.SETTINGS.language = lang.loc_key or lang.key +G.SETTINGS.real_language = lang.key""" +match_indent = true + # G.FUNCS.warn_lang (wtf) [[patches]] [patches.pattern] @@ -37,4 +56,4 @@ target = 'functions/button_callbacks.lua' pattern = 'if (_infotip_object.config.set ~= e.config.ref_table.label) and (not G.F_NO_ACHIEVEMENTS) then' position = 'at' payload = 'if (_infotip_object.config.set ~= e.config.ref_table.label) then' -match_indent = true \ No newline at end of file +match_indent = true diff --git a/Steamodded/lovely/libs.toml b/smods-main/lovely/libs.toml similarity index 87% rename from Steamodded/lovely/libs.toml rename to smods-main/lovely/libs.toml index 4e6d8a5..b7e8e9a 100644 --- a/Steamodded/lovely/libs.toml +++ b/smods-main/lovely/libs.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -5 [[patches]] [patches.module] @@ -13,4 +13,4 @@ name = "json" [patches.module] source = "libs/nativefs/nativefs.lua" before = "main.lua" -name = "nativefs" \ No newline at end of file +name = "nativefs" diff --git a/Steamodded/lovely/loader.toml b/smods-main/lovely/loader.toml similarity index 93% rename from Steamodded/lovely/loader.toml rename to smods-main/lovely/loader.toml index b829c59..dfe4bd9 100644 --- a/Steamodded/lovely/loader.toml +++ b/smods-main/lovely/loader.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -5 ### Supporting code for loader.lua @@ -24,4 +24,4 @@ for _, t in ipairs{ v._discovered_unlocked_overwritten = true end end''' -match_indent = true \ No newline at end of file +match_indent = true diff --git a/Steamodded/lovely/menu.toml b/smods-main/lovely/menu.toml similarity index 99% rename from Steamodded/lovely/menu.toml rename to smods-main/lovely/menu.toml index 8b20151..0e3e9fb 100644 --- a/Steamodded/lovely/menu.toml +++ b/smods-main/lovely/menu.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -5 [[patches]] [patches.pattern] diff --git a/Steamodded/lovely/mod.toml b/smods-main/lovely/mod.toml similarity index 98% rename from Steamodded/lovely/mod.toml rename to smods-main/lovely/mod.toml index 0065c12..225effb 100644 --- a/Steamodded/lovely/mod.toml +++ b/smods-main/lovely/mod.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -5 ### Per-mod functions @@ -67,4 +67,4 @@ payload = ''' should_debuff = should_debuff or v end -''' \ No newline at end of file +''' diff --git a/Steamodded/lovely/number_formatting.toml b/smods-main/lovely/number_formatting.toml similarity index 92% rename from Steamodded/lovely/number_formatting.toml rename to smods-main/lovely/number_formatting.toml index 10675b3..0107ffa 100644 --- a/Steamodded/lovely/number_formatting.toml +++ b/smods-main/lovely/number_formatting.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 # # Use number_format for... @@ -124,8 +124,8 @@ end local mantissa = round_number(x/(10^fac), 3) if mantissa >= 10 then - mantissa = mantissa / 10 - fac = fac + 1 + mantissa = mantissa / 10 + fac = fac + 1 end return sign..(string.format(fac >= 100 and "%.1fe%i" or fac >= 10 and "%.2fe%i" or "%.3fe%i", mantissa, fac))''' match_indent = true @@ -141,14 +141,14 @@ position = "at" payload = ''' local formatted if num ~= math.floor(num) and num < 100 then - formatted = string.format(num >= 10 and "%.1f" or "%.2f", num) - if formatted:sub(-1) == "0" then - formatted = formatted:gsub("%.?0+$", "") - end - -- Return already to avoid comas being added - if num < 0.01 then return tostring(num) end + formatted = string.format(num >= 10 and "%.1f" or "%.2f", num) + if formatted:sub(-1) == "0" then + formatted = formatted:gsub("%.?0+$", "") + end + -- Return already to avoid comas being added + if num < 0.01 then return tostring(num) end else - formatted = string.format("%.0f", num) + formatted = string.format("%.0f", num) end return sign..(formatted:reverse():gsub("(%d%d%d)", "%1,"):gsub(",$", ""):reverse())''' match_indent = true diff --git a/Steamodded/lovely/playing_card.toml b/smods-main/lovely/playing_card.toml similarity index 76% rename from Steamodded/lovely/playing_card.toml rename to smods-main/lovely/playing_card.toml index bd43d27..1f6a244 100644 --- a/Steamodded/lovely/playing_card.toml +++ b/smods-main/lovely/playing_card.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Playing Card API @@ -13,10 +13,10 @@ pattern = 'function Game:init_game_object()' position = 'after' match_indent = true payload = ''' - local cards_played = {} - for _,v in ipairs(SMODS.Rank.obj_buffer) do - cards_played[v] = { suits = {}, total = 0 } - end''' + local cards_played = {} + for _,v in ipairs(SMODS.Rank.obj_buffer) do + cards_played[v] = { suits = {}, total = 0 } + end''' [[patches]] [patches.regex] @@ -25,9 +25,9 @@ pattern = '(?[\t ]*)cards_played = \{\n(.*\n){13}[\t ]*\},' position = 'at' line_prepend = '$indent' payload = ''' - cards_played = cards_played, - disabled_suits = {}, - disabled_ranks = {},''' + cards_played = cards_played, + disabled_suits = {}, + disabled_ranks = {},''' # Game:start_run() [[patches]] @@ -37,9 +37,9 @@ pattern = 'local _ = nil' position = 'before' match_indent = true payload = ''' -if type(SMODS.Ranks[v.value].in_pool) == 'function' and not SMODS.Ranks[v.value]:in_pool({initial_deck = true}) -or type(SMODS.Suits[v.suit].in_pool) == 'function' and not SMODS.Suits[v.suit]:in_pool({initial_deck = true}) then - goto continue +if type(SMODS.Ranks[v.value].in_pool) == 'function' and not SMODS.Ranks[v.value]:in_pool({initial_deck = true, suit = v.suit}) +or type(SMODS.Suits[v.suit].in_pool) == 'function' and not SMODS.Suits[v.suit]:in_pool({initial_deck = true, rank = v.value}) then + goto continue end''' [[patches]] @@ -85,15 +85,15 @@ pattern = 'return G.ARGS.LOC_COLOURS[_c] or _default or G.C.UI.TEXT_DARK' position = 'before' match_indent = true payload = ''' - for _, v in ipairs(SMODS.Rarity.obj_buffer) do - G.ARGS.LOC_COLOURS[v:lower()] = G.C.RARITY[v] - end - for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do - G.ARGS.LOC_COLOURS[v:lower()] = G.C.SECONDARY_SET[v] - end - for _, v in ipairs(SMODS.Suit.obj_buffer) do - G.ARGS.LOC_COLOURS[v:lower()] = G.C.SUITS[v] - end''' + for _, v in ipairs(SMODS.Rarity.obj_buffer) do + G.ARGS.LOC_COLOURS[v:lower()] = G.C.RARITY[v] + end + for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do + G.ARGS.LOC_COLOURS[v:lower()] = G.C.SECONDARY_SET[v] + end + for _, v in ipairs(SMODS.Suit.obj_buffer) do + G.ARGS.LOC_COLOURS[v:lower()] = G.C.SUITS[v] + end''' # get_flush() [[patches]] @@ -116,7 +116,7 @@ match_indent = true payload = ''' local vals = {} for i = 1, SMODS.Rank.max_id.value do - vals[i] = {} + vals[i] = {} end''' [[patches]] @@ -143,17 +143,17 @@ pattern = 'function Card:get_nominal\(mod\)\n([\t ]+.*\n)*end' position = 'at' payload = ''' function Card:get_nominal(mod) - local mult = 1 - local rank_mult = 1 - if mod == 'suit' then mult = 10000 end - if self.ability.effect == 'Stone Card' or (self.config.center.no_suit and self.config.center.no_rank) then - mult = -10000 - elseif self.config.center.no_suit then - mult = 0 - elseif self.config.center.no_rank then - rank_mult = 0 - end - return 10*self.base.nominal*rank_mult + self.base.suit_nominal*mult + (self.base.suit_nominal_original or 0)*0.0001*mult + 10*self.base.face_nominal*rank_mult + 0.000001*self.unique_val + local mult = 1 + local rank_mult = 1 + if mod == 'suit' then mult = 10000 end + if self.ability.effect == 'Stone Card' or (self.config.center.no_suit and self.config.center.no_rank) then + mult = -10000 + elseif self.config.center.no_suit then + mult = 0 + elseif self.config.center.no_rank then + rank_mult = 0 + end + return 10*self.base.nominal*rank_mult + self.base.suit_nominal*mult + (self.base.suit_nominal_original or 0)*0.0001*mult + 10*self.base.face_nominal*rank_mult + 0.000001*self.unique_val end''' # Card:set_base() @@ -232,9 +232,9 @@ payload = ''' local SUITS = {} local suit_map = {} for i = #SMODS.Suit.obj_buffer, 1, -1 do - local suit = SMODS.Suits[SMODS.Suit.obj_buffer[i]] - SUITS[suit.card_key] = {} - suit_map[#suit_map+1] = suit.card_key + local suit = SMODS.Suits[SMODS.Suit.obj_buffer[i]] + SUITS[suit.card_key] = {} + suit_map[#suit_map+1] = suit.card_key end''' [[patches]] @@ -253,11 +253,11 @@ pattern = 'local keep, _e, _d, _g = true, nil, nil, nil' position = 'after' match_indent = true payload = ''' -if type(SMODS.Ranks[v.value].in_pool) == 'function' and not SMODS.Ranks[v.value]:in_pool({initial_deck = true}) then - keep = false +if type(SMODS.Ranks[v.value].in_pool) == 'function' and not SMODS.Ranks[v.value]:in_pool({initial_deck = true, suit = v.suit}) then + keep = false end -if type(SMODS.Suits[v.suit].in_pool) == 'function' and not SMODS.Suits[v.suit]:in_pool({initial_deck = true}) then - keep = false +if type(SMODS.Suits[v.suit].in_pool) == 'function' and not SMODS.Suits[v.suit]:in_pool({initial_deck = true, rank = v.value}) then + keep = false end''' [[patches]] @@ -269,11 +269,11 @@ line_prepend = '$indent' payload = ''' local num_suits = 0 for j = 1, #suit_map do - if SUITS[suit_map[j]][1] then num_suits = num_suits + 1 end + if SUITS[suit_map[j]][1] then num_suits = num_suits + 1 end end for j = 1, #suit_map do - $mid - (0.42 - (num_suits <= 4 and 0 or num_suits >= 8 and 0.28 or 0.07 * (num_suits - 4))) * G.CARD_H,''' + $mid + (0.42 - (num_suits <= 4 and 0 or num_suits >= 8 and 0.28 or 0.07 * (num_suits - 4))) * G.CARD_H,''' [[patches]] [patches.pattern] @@ -282,18 +282,18 @@ pattern = '--Fill all remaining info if this is the main desc' position = 'before' match_indent = true payload = '''if card_type == 'Default' or card_type == 'Enhanced' and not _c.replace_base_card and card and card.base then - if not _c.no_suit then - local suit = SMODS.Suits[card.base.suit] or {} - if suit.loc_vars and type(suit.loc_vars) == 'function' then - suit:loc_vars(info_queue, card) - end - end - if not _c.no_rank then - local rank = SMODS.Ranks[card.base.value] or {} - if rank.loc_vars and type(rank.loc_vars) == 'function' then - rank:loc_vars(info_queue, card) - end - end + if not _c.no_suit then + local suit = SMODS.Suits[card.base.suit] or {} + if suit.loc_vars and type(suit.loc_vars) == 'function' then + suit:loc_vars(info_queue, card) + end + end + if not _c.no_rank then + local rank = SMODS.Ranks[card.base.value] or {} + if rank.loc_vars and type(rank.loc_vars) == 'function' then + rank:loc_vars(info_queue, card) + end + end end ''' diff --git a/Steamodded/lovely/poker_hand.toml b/smods-main/lovely/poker_hand.toml similarity index 52% rename from Steamodded/lovely/poker_hand.toml rename to smods-main/lovely/poker_hand.toml index 14e8c50..d6f0f05 100644 --- a/Steamodded/lovely/poker_hand.toml +++ b/smods-main/lovely/poker_hand.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -5 ### Poker Hand API @@ -13,7 +13,7 @@ pattern = "local parts = {" position = 'before' payload = ''' for _,v in ipairs(SMODS.PokerHand.obj_buffer) do - results[v] = {} + results[v] = {} end''' match_indent = true @@ -24,9 +24,9 @@ pattern = "if next(parts._5) and next(parts._flush) then" position = 'before' payload = ''' for _,_hand in pairs(SMODS.PokerHands) do - if _hand.atomic_part and type(_hand.atomic_part) == 'function' then - parts[_hand.key] = _hand.atomic_part(hand) - end + if _hand.atomic_part and type(_hand.atomic_part) == 'function' then + parts[_hand.key] = _hand.atomic_part(hand) + end end''' match_indent = true @@ -37,24 +37,24 @@ pattern = "return results" position = 'before' payload = ''' for _,_hand in pairs(SMODS.PokerHands) do - if _hand.composite and type(_hand.composite) == 'function' then - local other_hands - results[_hand.key], other_hands = _hand.composite(parts) - results[_hand.key] = results[_hand.key] or {} - if other_hands and type(other_hands) == 'table' then - for k, v in pairs(other_hands) do - results[k] = v - end - end - else - results[_hand.key] = parts[_hand.key] - end + if _hand.composite and type(_hand.composite) == 'function' then + local other_hands + results[_hand.key], other_hands = _hand.composite(parts) + results[_hand.key] = results[_hand.key] or {} + if other_hands and type(other_hands) == 'table' then + for k, v in pairs(other_hands) do + results[k] = v + end + end + else + results[_hand.key] = parts[_hand.key] + end end results.top = nil for _, v in ipairs(G.handlist) do - if not results.top and results[v] then - results.top = results[v] - break - end + if not results.top and results[v] then + results.top = results[v] + break + end end''' match_indent = true diff --git a/Steamodded/lovely/pool.toml b/smods-main/lovely/pool.toml similarity index 72% rename from Steamodded/lovely/pool.toml rename to smods-main/lovely/pool.toml index 90cf268..e08d9f7 100644 --- a/Steamodded/lovely/pool.toml +++ b/smods-main/lovely/pool.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Functions that affect random selection from pools @@ -14,14 +14,14 @@ pattern = "function pseudorandom_element(_t, seed)" position = "at" payload = """function pseudorandom_element(_t, seed, args) -- TODO special cases for now - -- Preserves reverse nominal order for Suits, nominal+face_nominal order for Ranks - -- for vanilla RNG - if _t == SMODS.Suits then - _t = SMODS.Suit:obj_list(true) - end - if _t == SMODS.Ranks then - _t = SMODS.Rank:obj_list() - end + -- Preserves reverse nominal order for Suits, nominal+face_nominal order for Ranks + -- for vanilla RNG + if _t == SMODS.Suits then + _t = SMODS.Suit:obj_list(true) + end + if _t == SMODS.Ranks then + _t = SMODS.Rank:obj_list() + end """ match_indent = true @@ -33,17 +33,17 @@ position = "at" payload = """ local keep = true local in_pool_func = - args and args.in_pool - or type(v) == 'table' and type(v.in_pool) == 'function' and v.in_pool - or _t == G.P_CARDS and function(c) - --Handles special case for Erratic Deck - local initial_deck = args and args.starting_deck or false - - return not ( - type(SMODS.Ranks[c.value].in_pool) == 'function' and not SMODS.Ranks[c.value]:in_pool({initial_deck = initial_deck}) - or type(SMODS.Suits[c.suit].in_pool) == 'function' and not SMODS.Suits[c.suit]:in_pool({initial_deck = initial_deck}) - ) - end + args and args.in_pool + or type(v) == 'table' and type(v.in_pool) == 'function' and v.in_pool + or _t == G.P_CARDS and function(c) + --Handles special case for Erratic Deck + local initial_deck = args and args.starting_deck or false + + return not ( + type(SMODS.Ranks[c.value].in_pool) == 'function' and not SMODS.Ranks[c.value]:in_pool({initial_deck = initial_deck, suit = c.suit}) + or type(SMODS.Suits[c.suit].in_pool) == 'function' and not SMODS.Suits[c.suit]:in_pool({initial_deck = initial_deck, rank = c.value}) + ) + end if in_pool_func then keep = in_pool_func(v, args) end @@ -74,14 +74,14 @@ match_indent = true position = 'before' payload = ''' elseif SMODS.ObjectTypes[_type] and SMODS.ObjectTypes[_type].rarities then - local rarities = SMODS.ObjectTypes[_type].rarities - local rarity - if _legendary and rarities.legendary then - rarity = rarities.legendary.key - else - rarity = _rarity or SMODS.poll_rarity(_type, 'rarity_'.._type..G.GAME.round_resets.ante..(_append or '')) - end - _starting_pool, _pool_key = SMODS.ObjectTypes[_type].rarity_pools[rarity], _type..rarity..(_append or '')''' + local rarities = SMODS.ObjectTypes[_type].rarities + local rarity + if _legendary and rarities.legendary then + rarity = rarities.legendary.key + else + rarity = _rarity or SMODS.poll_rarity(_type, 'rarity_'.._type..G.GAME.round_resets.ante..(_append or '')) + end + _starting_pool, _pool_key = SMODS.ObjectTypes[_type].rarity_pools[rarity], _type..rarity..(_append or '')''' [[patches]] [patches.pattern] @@ -91,7 +91,7 @@ match_indent = true position = 'at' payload = ''' if SMODS.ObjectTypes[_type] and SMODS.ObjectTypes[_type].default and G.P_CENTERS[SMODS.ObjectTypes[_type].default] then - _pool[#_pool+1] = SMODS.ObjectTypes[_type].default + _pool[#_pool+1] = SMODS.ObjectTypes[_type].default elseif _type == 'Tarot' or _type == 'Tarot_Planet' then _pool[#_pool + 1] = "c_strength"''' [[patches]] @@ -111,7 +111,7 @@ position = 'before' payload = ''' local in_pool, pool_opts if v.in_pool and type(v.in_pool) == 'function' then - in_pool, pool_opts = v:in_pool({ source = _append }) + in_pool, pool_opts = v:in_pool({ source = _append }) end pool_opts = pool_opts or {} ''' @@ -132,7 +132,7 @@ match_indent = true position = 'before' payload = ''' if v.in_pool and type(v.in_pool) == 'function' then - add = in_pool and (add or pool_opts.override_base_checks) + add = in_pool and (add or pool_opts.override_base_checks) end ''' @@ -161,7 +161,7 @@ pattern = ''' position = "at" payload = ''' if self.config.center.key then - G.GAME.used_jokers[self.config.center.key] = true + G.GAME.used_jokers[self.config.center.key] = true end ''' line_prepend = "$indent" diff --git a/smods-main/lovely/rarity.toml b/smods-main/lovely/rarity.toml new file mode 100644 index 0000000..efaef67 --- /dev/null +++ b/smods-main/lovely/rarity.toml @@ -0,0 +1,61 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Rarity API + +# get_badge_colour +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = 'return G.BADGE_COL[key] or {1, 0, 0, 1}' +position = 'before' +match_indent = true +payload = ''' +for k, v in pairs(SMODS.Rarity.obj_buffer) do + G.BADGE_COL[k] = G.C.RARITY[v] +end''' + +# G.UIDEF.card_h_popup +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "if AUT.card_type == 'Joker' or (AUT.badges and AUT.badges.force_rarity) then card_type = ({localize('k_common'), localize('k_uncommon'), localize('k_rare'), localize('k_legendary')})[card.config.center.rarity] end" +position = "at" +payload = "if AUT.card_type == 'Joker' or (AUT.badges and AUT.badges.force_rarity) then card_type = SMODS.Rarity:get_rarity_badge(card.config.center.rarity) end" +match_indent = true + +# Game:update +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = "self.C.EDITION[2] = 0.7+0.2*(1+math.sin(self.TIMERS.REAL*1.5 + 6))" +position = "after" +payload = ''' +for k, v in pairs(SMODS.Rarities) do + if v.gradient and type(v.gradient) == "function" then v:gradient(dt) end +end''' +match_indent = true + +# get_current_pool +[[patches]] +[patches.regex] +target = "functions/common_events.lua" +pattern = '''(?[\t ]*)local rarity = _rarity or pseudorandom\('rarity'\.\.G\.GAME\.round_resets\.ante\.\.\(_append or ''\)\) \n[\s\S]{12}rarity = \(_legendary and 4\) or \(rarity > 0\.95 and 3\) or \(rarity > 0\.7 and 2\) or 1''' +position = "at" +payload = ''' +_rarity = (_legendary and 4) or (type(_rarity) == "number" and ((_rarity > 0.95 and 3) or (_rarity > 0.7 and 2) or 1)) or _rarity +_rarity = ({Common = 1, Uncommon = 2, Rare = 3, Legendary = 4})[_rarity] or _rarity +local rarity = _rarity or SMODS.poll_rarity("Joker", 'rarity'..G.GAME.round_resets.ante..(_append or '')) +''' + +## Ensure that other cards set to string rarity work the same as set for int rarity +# Card:calculate_joker +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if self.ability.name == 'Baseball Card' and context.other_joker.config.center.rarity == 2 and self ~= context.other_joker then" +position = "at" +payload = '''if self.ability.name == 'Baseball Card' and (context.other_joker.config.center.rarity == 2 or context.other_joker.config.center.rarity == "Uncommon") and self ~= context.other_joker then''' +match_indent = true diff --git a/smods-main/lovely/seal.toml b/smods-main/lovely/seal.toml new file mode 100644 index 0000000..2b65828 --- /dev/null +++ b/smods-main/lovely/seal.toml @@ -0,0 +1,222 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Seal API +# Card:open() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = ''' +(?[\t ]*)local seal_rate = 10 +[\n\t ]*local seal_poll = pseudorandom\(pseudoseed\('stdseal'..G.GAME.round_resets.ante\)\) +[\n\t ]*if seal_poll > 1 - 0.02\*seal_rate then +[\n\t ]*local seal_type = pseudorandom\(pseudoseed\('stdsealtype'..G.GAME.round_resets.ante\)\) +[\n\t ]*if seal_type > 0.75 then card:set_seal\('Red'\) +[\n\t ]*elseif seal_type > 0.5 then card:set_seal\('Blue'\) +[\n\t ]*elseif seal_type > 0.25 then card:set_seal\('Gold'\) +[\n\t ]*else card:set_seal\('Purple'\) +[\n\t ]*end +[\n\t ]*end''' +position = 'at' +line_prepend = '$indent' +payload = ''' +card:set_seal(SMODS.poll_seal({mod = 10}))''' + +# Card:calculate_joker() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = ''' +(?[\t ]*)local seal_type = pseudorandom\(pseudoseed\('certsl'\)\) +[\n\t ]*if seal_type > 0.75 then _card:set_seal\('Red', true\) +[\n\t ]*elseif seal_type > 0.5 then _card:set_seal\('Blue', true\) +[\n\t ]*elseif seal_type > 0.25 then _card:set_seal\('Gold', true\) +[\n\t ]*else _card:set_seal\('Purple', true\) +[\n\t ]*end''' +position = 'at' +line_prepend = '$indent' +payload = '''_card:set_seal(SMODS.poll_seal({guaranteed = true, type_key = 'certsl'}))''' + +# get_badge_colour() +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = 'return G.BADGE_COL[key] or {1, 0, 0, 1}' +position = 'before' +match_indent = true +payload = ''' +for k, v in pairs(SMODS.Seals) do + G.BADGE_COL[k:lower()..'_seal'] = v.badge_colour +end''' + +# Card:calculate_seal() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = 'function Card:calculate_seal\(context\)\n(?[\t ]*)if self.debuff then return nil end' +position = 'after' +line_prepend = '$indent' +payload = ''' +local obj = G.P_SEALS[self.seal] or {} +if obj.calculate and type(obj.calculate) == 'function' then + local o = obj:calculate(self, context) + if o then + if not o.card then o.card = self end + return o + end +end''' + +# Card:update() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = 'if G.STAGE == G.STAGES.RUN then' +position = 'before' +match_indent = true +payload = ''' +local obj = G.P_SEALS[self.seal] or {} +if obj.update and type(obj.update) == 'function' then + obj:update(self, dt) +end''' + +# Card:get_p_dollars() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''(?[\t ]*)if (?self\.seal == 'Gold' then\n)''' +position = 'at' +line_prepend = '$indent' +payload = ''' +local obj = G.P_SEALS[self.seal] or {} +if obj.get_p_dollars and type(obj.get_p_dollars) == 'function' then + ret = ret + obj:get_p_dollars(self) +elseif $cond''' + +# generate_card_ui() +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "if v == 'gold_seal'*" +match_indent = true +position = 'before' +payload = ''' +local seal = G.P_SEALS[v] or G.P_SEALS[SMODS.Seal.badge_to_key[v] or ''] +if seal then + info_queue[#info_queue+1] = seal +else''' +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "if v == 'purple_seal'*" +match_indent = true +position = 'after' +payload = 'end' + +[[patches]] +[patches.regex] +target = 'functions/common_events.lua' +position = 'at' +pattern = '''\{key = (?'.*?_seal'), set = 'Other'\}''' +payload = '''G.P_SEALS[$badge] or G.P_SEALS[SMODS.Seal.badge_to_key[$badge] or '']''' + +# Card:update_alert() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = "function Card:update_alert()" +match_indent = true +position = 'after' +payload = ''' + if self.ability.set == 'Default' and self.config.center and self.config.center.key == 'c_base' and self.seal then + if G.P_SEALS[self.seal].alerted and self.children.alert then + self.children.alert:remove() + self.children.alert = nil + elseif not G.P_SEALS[self.seal].alerted and not self.children.alert and G.P_SEALS[self.seal].discovered then + self.children.alert = UIBox{ + definition = create_UIBox_card_alert(), + config = {align="tli", + offset = {x = 0.1, y = 0.1}, + parent = self} + } + end + end''' + +# Card:hover() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = "G:save_progress()" +match_indent = false +position = "after" +payload = ''' + elseif self.children.alert and self.seal and not G.P_SEALS[self.seal].alerted then + G.P_SEALS[self.seal].alerted = true + G:save_progress()''' + +# Game:init_item_prototypes() +[[patches]] +[patches.regex] +target = 'game.lua' +pattern = '''(?[\t ]*)Gold =[ {A-z=1-4,"}\n]*},[\n\t ]*}''' +position = 'at' +line_prepend = '$indent' +payload = ''' +Red = {order = 1, discovered = false, set = "Seal"}, +Blue = {order = 2, discovered = false, set = "Seal"}, +Gold = {order = 3, discovered = false, set = "Seal"}, +Purple = {order = 4, discovered = false, set = "Seal"}, +} +''' + +# Card:set_seal() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''G.CONTROLLER.locks.seal = true''' +position = 'after' +match_indent = true +payload = '''local sound = G.P_SEALS[_seal].sound or {sound = 'gold_seal', per = 1.2, vol = 0.4}''' +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''play_sound('gold_seal', 1.2, 0.4)''' +position = 'at' +match_indent = true +payload = '''play_sound(sound.sound, sound.per, sound.vol)''' +## Populate Seal Ability Table +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''self.seal = _seal''' +position = 'after' +match_indent = true +payload = ''' +self.ability.seal = {} +for k, v in pairs(G.P_SEALS[_seal].config or {}) do + if type(v) == 'table' then + self.ability.seal[k] = copy_table(v) + else + self.ability.seal[k] = v + end +end +''' + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = '''new_card:set_seal(other.seal, true)''' +position = 'after' +match_indent = true +payload = ''' +if other.seal then + for k, v in pairs(other.ability.seal or {}) do + if type(v) == 'table' then + new_card.ability.seal[k] = copy_table(v) + else + new_card.ability.seal[k] = v + end + end +end +''' \ No newline at end of file diff --git a/Steamodded/lovely/sound.toml b/smods-main/lovely/sound.toml similarity index 73% rename from Steamodded/lovely/sound.toml rename to smods-main/lovely/sound.toml index cc77840..481300e 100644 --- a/Steamodded/lovely/sound.toml +++ b/smods-main/lovely/sound.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 #modulate_sound() [[patches]] @@ -18,11 +18,11 @@ local should_sync = true if (type(in_sync) == 'table' and not in_sync[SMODS.previous_track]) or in_sync == false then should_sync = false end if (type(out_sync) == 'table' and not out_sync[desired_track]) or out_sync == false then should_sync = false end if - SMODS.previous_track and SMODS.previous_track ~= desired_track and - not should_sync + SMODS.previous_track and SMODS.previous_track ~= desired_track and + not should_sync then - G.ARGS.push.type = 'restart_music' - G.SOUND_MANAGER.channel:push(G.ARGS.push) + G.ARGS.push.type = 'restart_music' + G.SOUND_MANAGER.channel:push(G.ARGS.push) end SMODS.previous_track = desired_track''' @@ -34,25 +34,25 @@ match_indent = true position = 'after' payload = ''' if SMODS.remove_replace_sound and SMODS.remove_replace_sound ~= desired_track then - SMODS.Sound.replace_sounds[SMODS.remove_replace_sound] = nil - SMODS.remove_replace_sound = nil + SMODS.Sound.replace_sounds[SMODS.remove_replace_sound] = nil + SMODS.remove_replace_sound = nil end local replace_sound = SMODS.Sound.replace_sounds[desired_track] if replace_sound then - local replaced_track = desired_track - desired_track = replace_sound.key - G.ARGS.push.desired_track = desired_track - if SMODS.previous_track ~= desired_track then - if replace_sound.times > 0 then replace_sound.times = replace_sound.times - 1 end - if replace_sound.times == 0 then SMODS.remove_replace_sound = replaced_track end - end + local replaced_track = desired_track + desired_track = replace_sound.key + G.ARGS.push.desired_track = desired_track + if SMODS.previous_track ~= desired_track then + if replace_sound.times > 0 then replace_sound.times = replace_sound.times - 1 end + if replace_sound.times == 0 then SMODS.remove_replace_sound = replaced_track end + end end local stop_sound = SMODS.Sound.stop_sounds[desired_track] if SMODS.Sound.stop_sounds[desired_track] then - if SMODS.previous_track ~= '' and stop_sound > 0 then stop_sound = stop_sound - 1 end - SMODS.Sound.stop_sounds[desired_track] = stop_sound ~= 0 and stop_sound or nil - SMODS.previous_track = '' - return + if SMODS.previous_track ~= '' and stop_sound > 0 then stop_sound = stop_sound - 1 end + SMODS.Sound.stop_sounds[desired_track] = stop_sound ~= 0 and stop_sound or nil + SMODS.previous_track = '' + return end ''' @@ -95,14 +95,14 @@ match_indent = true position = 'before' payload = ''' elseif request.type == 'sound_source' then - SMODS_Sounds[request.sound_code] = { - sound_code = request.sound_code, - data = request.data, - sound = sound, - per = request.per, - vol = request.vol, - } - SOURCES[request.sound_code] = {} + SMODS_Sounds[request.sound_code] = { + sound_code = request.sound_code, + data = request.data, + sound = sound, + per = request.per, + vol = request.vol, + } + SOURCES[request.sound_code] = {} ''' [[patches]] @@ -140,12 +140,12 @@ pattern = """(?[\t ]*)function MODULATE\\(args\\)(\n.*){9}""" line_prepend = '$indent' position = 'at' payload = """function MODULATE(args) - if args.desired_track ~= '' then - local sound = ((SOURCES[current_track or {}] or {})[1] or {}).sound - if not sound or not sound:isPlaying() then - RESTART_MUSIC(args) - end - end + if args.desired_track ~= '' then + local sound = ((SOURCES[current_track or {}] or {})[1] or {}).sound + if not sound or not sound:isPlaying() then + RESTART_MUSIC(args) + end + end """ [[patches]] [patches.pattern] @@ -164,4 +164,4 @@ for _, s in pairs(v) do""" # position = 'at' # payload = '''if s.sound and s.sound:isPlaying() then # s.sound:stop() -# elseif s.sound and not s.sound:isPlaying() then''' \ No newline at end of file +# elseif s.sound and not s.sound:isPlaying() then''' diff --git a/Steamodded/lovely/stake.toml b/smods-main/lovely/stake.toml similarity index 99% rename from Steamodded/lovely/stake.toml rename to smods-main/lovely/stake.toml index 07a5486..839175f 100644 --- a/Steamodded/lovely/stake.toml +++ b/smods-main/lovely/stake.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 # Fix areas where highest stake is hardcoded as Gold Stake [[patches]] diff --git a/smods-main/lovely/sticker.toml b/smods-main/lovely/sticker.toml new file mode 100644 index 0000000..92e329c --- /dev/null +++ b/smods-main/lovely/sticker.toml @@ -0,0 +1,132 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Sticker API + +# generate_UIBox_ability_table() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if self.sticker or ((self.sticker_run and self.sticker_run~='NONE') and G.SETTINGS.run_stake_stickers) then loc_vars = loc_vars or {}; loc_vars.sticker=(self.sticker or self.sticker_run) end" +position = "before" +match_indent = true +payload = ''' +for k, v in ipairs(SMODS.Sticker.obj_buffer) do + if self.ability[v] and not SMODS.Stickers[v].hide_badge then + badges[#badges+1] = v + end +end''' + +# generate_card_ui() +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if v == 'eternal' then*" +match_indent = true +position = "before" +payload = ''' +local sticker = SMODS.Stickers[v] +if sticker then + local t = { key = v, set = 'Other' } + local res = {} + if sticker.loc_vars and type(sticker.loc_vars) == 'function' then + res = sticker:loc_vars(info_queue, card) or {} + t.vars = res.vars or {} + t.key = res.key or t.key + t.set = res.set or t.set + end + info_queue[#info_queue+1] = t +else''' + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if v == 'rental' then*" +match_indent = true +position = "after" +payload = '''end''' + +# create_card() +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if card.ability.consumeable and not skip_materialize then card:start_materialize() end" +position = "after" +match_indent = true +payload = ''' +for k, v in ipairs(SMODS.Sticker.obj_buffer) do + local sticker = SMODS.Stickers[v] + if sticker.should_apply and type(sticker.should_apply) == 'function' and sticker:should_apply(card, center, area) then + sticker:apply(card, true) + end +end''' + +## Remove base game sticker rolls if one is added +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if G.GAME.modifiers.enable_eternals_in_shop and eternal_perishable_poll > 0.7 then" +position = "at" +match_indent = true +payload = '''if G.GAME.modifiers.enable_eternals_in_shop and eternal_perishable_poll > 0.7 and not SMODS.Stickers["eternal"].should_apply then''' + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "elseif G.GAME.modifiers.enable_perishables_in_shop and ((eternal_perishable_poll > 0.4) and (eternal_perishable_poll <= 0.7)) then" +position = "at" +match_indent = true +payload = '''elseif G.GAME.modifiers.enable_perishables_in_shop and ((eternal_perishable_poll > 0.4) and (eternal_perishable_poll <= 0.7)) and not SMODS.Stickers["perishable"].should_apply then''' + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if G.GAME.modifiers.enable_rentals_in_shop and pseudorandom((area == G.pack_cards and 'packssjr' or 'ssjr')..G.GAME.round_resets.ante) > 0.7 then" +position = "at" +match_indent = true +payload = '''if G.GAME.modifiers.enable_rentals_in_shop and pseudorandom((area == G.pack_cards and 'packssjr' or 'ssjr')..G.GAME.round_resets.ante) > 0.7 and not SMODS.Stickers["rental"].should_apply then''' + +# Card:draw() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if self.ability.name == 'The Soul' and (self.config.center.discovered or self.bypass_discovery_center) then''' +match_indent = true +position = "before" +payload = ''' +for k, v in pairs(SMODS.Stickers) do + if self.ability[v.key] then + if v and v.draw and type(v.draw) == 'function' then + v:draw(self, layer) + else + G.shared_stickers[v.key].role.draw_major = self + G.shared_stickers[v.key]:draw_shader('dissolve', nil, nil, nil, self.children.center) + G.shared_stickers[v.key]:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center) + end + end +end +''' + +# get_badge_colour() +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = 'return G.BADGE_COL[key] or {1, 0, 0, 1}' +position = 'before' +match_indent = true +payload = ''' +for k, v in pairs(SMODS.Stickers) do + G.BADGE_COL[k] = v.badge_colour +end''' + +## Remove Pinned effect when in Sticker collections +# CardArea:aling_cards +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +pattern = '''table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end)''' +position = 'at' +match_indent = true +payload = '''table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*((a.pinned and not a.ignore_pinned) and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*((b.pinned and not b.ignore_pinned) and b.sort_id or 0) end)''' diff --git a/smods-main/lovely/tag.toml b/smods-main/lovely/tag.toml new file mode 100644 index 0000000..7a885e3 --- /dev/null +++ b/smods-main/lovely/tag.toml @@ -0,0 +1,139 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Tag API +# Tag:apply_to_run() +[[patches]] +[patches.pattern] +target = "tag.lua" +pattern = "function Tag:apply_to_run(_context)" +position = 'after' +match_indent = true +payload = ''' + if self.triggered then return end + local obj = SMODS.Tags[self.key] + local res + if obj and obj.apply and type(obj.apply) == 'function' then + res = obj:apply(self, _context) + end + if res then return res end +''' + +# Tag:set_ability() +[[patches]] +[patches.pattern] +target = "tag.lua" +pattern = "function Tag:set_ability()" +position = 'after' +match_indent = true +payload = ''' + local obj = SMODS.Tags[self.key] + local res + if obj and obj.set_ability and type(obj.set_ability) == 'function' then + obj:set_ability(self) + end +''' + +# create_UIBox_your_collection_tags() +[[patches]] +[patches.regex] +target = "functions/UI_definitions.lua" +pattern = "(?[\t ]*)local tag_matrix = \\{(\n.*){6}" +position = 'at' +line_prepend = '$indent' +payload = ''' +local tag_matrix = {} +local counter = 0 +local tag_tab = {} +local tag_pool = {} +if G.ACTIVE_MOD_UI then + for k, v in pairs(G.P_TAGS) do + if v.mod and G.ACTIVE_MOD_UI.id == v.mod.id then tag_pool[k] = v end + end +else + tag_pool = G.P_TAGS +end +for k, v in pairs(tag_pool) do + counter = counter + 1 + tag_tab[#tag_tab+1] = v +end +for i = 1, math.ceil(counter / 6) do + table.insert(tag_matrix, {}) +end''' + +[[patches]] +[patches.regex] +target = "functions/UI_definitions.lua" +pattern = '''(?[\t ]*)v\.children\.alert\.states\.collide\.can = false\n[\s\S]{8}end\n[\s\S]{8}return true\n[\s\S]{4}end\)\n[\s\S]{2}\}\)\)\n{3}''' +position = 'after' +line_prepend = '$indent' +payload = ''' +local table_nodes = {} +for i = 1, math.ceil(counter / 6) do + table.insert(table_nodes, {n=G.UIT.R, config={align = "cm"}, nodes=tag_matrix[i]}) +end''' + +[[patches]] +[patches.regex] +target = "functions/UI_definitions.lua" +pattern = '''(?[\t ]*)\{\n[\s\S]{10}\{n=G\.UIT\.R, config=\{align = "cm"\}, nodes=tag_matrix\[1\]},[\s\S]*tag_matrix\[4\]\},\n[\s\S]{8}\}''' +position = 'at' +line_prepend = '$indent' +payload = '''table_nodes''' + +# Tag:generate_UI() +[[patches]] +[patches.regex] +target = "tag.lua" +pattern = 'G.ASSET_ATLAS\["tags"\]' +position = 'at' +payload = 'G.ASSET_ATLAS[(not self.hide_ability) and G.P_TAGS[self.key].atlas or "tags"]' + +# Tag:get_uibox_table() +[[patches]] +[patches.pattern] +target = "tag.lua" +pattern = '''function Tag:get_uibox_table(tag_sprite)''' +position = 'at' +match_indent = true +payload = '''function Tag:get_uibox_table(tag_sprite, vars_only)''' +[[patches]] +[patches.pattern] +target = "tag.lua" +pattern = '''tag_sprite.ability_UIBox_table = generate_card_ui(G.P_TAGS[self.key], nil, loc_vars, (self.hide_ability) and 'Undiscovered' or 'Tag', nil, (self.hide_ability))''' +position = 'at' +match_indent = true +payload = '''if vars_only then return loc_vars end +tag_sprite.ability_UIBox_table = generate_card_ui(G.P_TAGS[self.key], nil, loc_vars, (self.hide_ability) and 'Undiscovered' or 'Tag', nil, (self.hide_ability), nil, nil, self)''' + +# generate_card_ui() + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "elseif _c.set == 'Tag' then" +position = "after" +match_indent = true +payload = '''specific_vars = specific_vars or Tag.get_uibox_table({ name = _c.name, config = _c.config, ability = { orbital_hand = '['..localize('k_poker_hand')..']' }}, nil, true) +''' + +# Prevent Boss Tag from crashing when triggered at a bad time +# by quietly rerolling it if blind select UI is not there +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = "G.FUNCS.reroll_boss = function(e)" +position = "after" +match_indent = true +payload = '''if not G.blind_select_opts then + G.GAME.round_resets.boss_rerolled = true + if not G.from_boss_tag then ease_dollars(-10) end + G.from_boss_tag = nil + G.GAME.round_resets.blind_choices.Boss = get_new_boss() + for i = 1, #G.GAME.tags do + if G.GAME.tags[i]:apply_to_run({type = 'new_blind_choice'}) then break end + end + return true +end''' \ No newline at end of file diff --git a/Steamodded/lovely/threads.toml b/smods-main/lovely/threads.toml similarity index 95% rename from Steamodded/lovely/threads.toml rename to smods-main/lovely/threads.toml index 965673b..85c2580 100644 --- a/Steamodded/lovely/threads.toml +++ b/smods-main/lovely/threads.toml @@ -3,7 +3,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -5 [[patches]] [patches.pattern] @@ -27,4 +27,4 @@ target = "engine/sound_manager.lua" pattern = "if request then" position = "after" payload = "if request.type == 'kill' then return end" -match_indent = true \ No newline at end of file +match_indent = true diff --git a/smods-main/lovely/ui.toml b/smods-main/lovely/ui.toml new file mode 100644 index 0000000..5a2eff1 --- /dev/null +++ b/smods-main/lovely/ui.toml @@ -0,0 +1,213 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Addition Tab + +## Decks tab +# create_UIBox_your_collection_decks() +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''G.GAME.viewed_back = Back(G.P_CENTERS.b_red)''' +position = "at" +payload = ''' +local deck_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Back) +G.GAME.viewed_back = Back(G.ACTIVE_MOD_UI and deck_pool[1] or G.P_CENTERS.b_red)''' +match_indent = true + +# create_UIBox_your_collection_decks() +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = '''(?[\t ]*)for k, v in ipairs\(G\.P_CENTER_POOLS\.Back\) do\n[\s\S]{4}ordered_names\[#ordered_names\+1\] = v\.name\n[\s\S]{2}end''' +position = 'at' +payload = ''' +for k, v in ipairs(deck_pool) do + ordered_names[#ordered_names+1] = v.key +end''' +line_prepend = '$indent' + +# create_UIBox_your_collection_decks() +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''local t = create_UIBox_generic_options({ back_func = 'your_collection', contents = {''' +position = "at" +payload = '''local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = {''' +match_indent = true + +# G.FUNCS.your_collection_deck_page +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = '''G.GAME.viewed_back:change_to(G.P_CENTER_POOLS.Back[args.to_key])''' +position = "at" +payload = ''' +local deck_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Back) +G.GAME.viewed_back:change_to(deck_pool[args.to_key])''' +match_indent = true + +# create_UIBox_your_collection() +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = '''(?[\t ]*)UIBox_button\(\{button = 'your_collection_blinds', label = \{localize\('b_blinds'\)\}, count = G\.DISCOVER_TALLIES\.blinds, minw = 5, minh = 2.0, id = 'your_collection_blinds', focus_args = \{snap_to = true\}\}\),''' +position = 'after' +payload = '''UIBox_button({button = 'your_collection_other_gameobjects', label = {localize('k_other')}, minw = 5, id = 'your_collection_other_gameobjects', focus_args = {snap_to = true}}),''' + +# Fix UIElement.config.chosen being overriden if choice=true is set +# UIElement:click() +[[patches]] +[patches.pattern] +target = "engine/ui.lua" +match_indent = true +position = "after" +pattern = "if self.config.choice then" +payload = " local chosen_temp = self.config.chosen" + +[[patches]] +[patches.pattern] +target = "engine/ui.lua" +match_indent = true +position = "at" +pattern = "self.config.chosen = true" +payload = "self.config.chosen = chosen_temp or true" + +# Escape from mod menu saves config +# Needs to be before all checks +[[patches]] +[patches.pattern] +target = 'engine/controller.lua' +pattern = "function Controller:key_press_update(key, dt)" +position = "after" +payload = ''' + if key == "escape" and G.ACTIVE_MOD_UI then + G.FUNCS.exit_mods() + end +''' +match_indent = true + +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +position = 'before' +line_prepend = '$indent' +pattern = ''' +(?[\t ]*)return \{n=G\.UIT\.ROOT, config = \{align = 'cm', colour = G\.C\.CLEAR\}, nodes=\{ +[\t ]*\{n=G\.UIT\.C,''' +payload = ''' +local cols +if #info_boxes <= 3 then + cols = 1 +elseif #info_boxes <= 10 then + cols = 2 +elseif #info_boxes <= 24 then + cols = 3 +else + cols = 4 +end +local nodes_per_col = math.ceil(#info_boxes/cols) +local info_cols = {} +for i = 0, cols-1 do + local col = {} + for j = 1, nodes_per_col do + local info_box = info_boxes[i*nodes_per_col+j] + if info_box then + table.insert(col, info_box) + else break end + end + table.insert(info_cols, {n=G.UIT.C, config = {align="cm"}, nodes = col}) +end +info_boxes = {{n=G.UIT.R, config = {align="cm", padding = 0.05, card_pos = card.T.x }, nodes = info_cols}} +''' + +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +match_indent = true +position = 'at' +pattern = "config = {offset = {x=-0.03,y=0}, align = 'cl', parent = e}" +payload = """config = (not e.config.ref_table or not e.config.ref_table[1].config.card_pos or e.config.ref_table[1].config.card_pos > G.ROOM.T.w*0.4) and + {offset = {x=-0.03,y=0}, align = 'cl', parent = e} or + {offset = {x=0.03,y=0}, align = 'cr', parent = e}""" + +[[patches]] +[patches.pattern] +target = 'tag.lua' +match_indent = true +position = 'at' +pattern = "_self.config.h_popup_config ={align = 'cl', offset = {x=-0.1,y=0},parent = _self}" +payload = """_self.config.h_popup_config = (_self.T.x > G.ROOM.T.w*0.4) and + {align = 'cl', offset = {x=-0.1,y=0},parent = _self} or + {align = 'cr', offset = {x=0.1,y=0},parent = _self}""" + +# desc_from_rows +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +position = 'at' +pattern = 'colour = empty and G\.C\.CLEAR or G\.C\.UI\.BACKGROUND_WHITE' +payload = 'colour = desc_nodes.background_colour or empty and G.C.CLEAR or G.C.UI.BACKGROUND_WHITE' + +# info_tip_from_rows +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +position = 'at' +pattern = 'padding = 0\.05, colour = G\.C\.WHITE\}' +payload = 'padding = 0.05, colour = desc_nodes.background_colour or G.C.WHITE}' + +# localize +[[patches]] +[patches.regex] +target = 'functions/misc_functions.lua' +position = 'after' +pattern = '\(part\.control\.C and loc_colour\(part\.control\.C\)\)' +payload = ' or args.text_colour' + +[[patches]] +[patches.regex] +target = 'functions/misc_functions.lua' +position = 'at' +pattern = 'loc_colour\(part\.control\.C or nil, args\.default_col\)' +payload = 'not part.control.C and args.text_colour or loc_colour(part.control.C or nil, args.default_col)' + +[[patches]] +[patches.regex] +target = 'functions/misc_functions.lua' +position = 'after' +pattern = 'part\.control\.s and tonumber\(part\.control\.s\)' +payload = ' or args.scale ' + +# set_discover_tallies() +# exclude no_collection objects +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +match_indent = true +position = 'at' +pattern = "if not v.omit then" +payload = "if not v.omit and not v.no_collection then" + +[[patches]] +[patches.regex] +target = 'functions/misc_functions.lua' +line_prepend = '$indent' +position = 'at' +pattern = '(?[\t ]*)(?for _, v in pairs\(G\.P_[BT].*)(?(\n.*){7})' +payload = '''$start + if not v.no_collection then + $rest +end +''' + +#set_alerts() +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'at' +pattern = "if v.discovered and not v.alerted then" +payload = "if v.discovered and not v.alerted and not v.no_collection then" diff --git a/Steamodded/lovely/ui_elements.toml b/smods-main/lovely/ui_elements.toml similarity index 99% rename from Steamodded/lovely/ui_elements.toml rename to smods-main/lovely/ui_elements.toml index a665507..96050d0 100644 --- a/Steamodded/lovely/ui_elements.toml +++ b/smods-main/lovely/ui_elements.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ## colour argument fix # create_tabs() @@ -118,4 +118,4 @@ target = 'functions/button_callbacks.lua' pattern = '''if hook.children[i].config and hook.children[i].config.id:sub(1, 7) == 'letter_' and hook.children[i].config.text ~= '' then''' position = 'at' payload = '''if hook.children[i].config and hook.children[i].config.id:sub(1, 8+string.len(G.CONTROLLER.text_input_id)) == G.CONTROLLER.text_input_id..'_letter_' and hook.children[i].config.text ~= '' then''' -match_indent = true \ No newline at end of file +match_indent = true diff --git a/Steamodded/manifest.json b/smods-main/manifest.json similarity index 100% rename from Steamodded/manifest.json rename to smods-main/manifest.json diff --git a/Steamodded/src/compat_0_9_8.lua b/smods-main/src/compat_0_9_8.lua similarity index 100% rename from Steamodded/src/compat_0_9_8.lua rename to smods-main/src/compat_0_9_8.lua diff --git a/Steamodded/src/core.lua b/smods-main/src/core.lua similarity index 55% rename from Steamodded/src/core.lua rename to smods-main/src/core.lua index 4ebd125..e44e824 100644 --- a/Steamodded/src/core.lua +++ b/smods-main/src/core.lua @@ -7,6 +7,7 @@ SMODS.id = 'Steamodded' SMODS.version = MODDED_VERSION:gsub('%-STEAMODDED', '') SMODS.can_load = true SMODS.meta_mod = true +SMODS.config_file = 'config.lua' -- Include lovely and nativefs modules local nativefs = require "nativefs" @@ -33,12 +34,7 @@ local function set_mods_dir() if lovely_mod_dir:sub(1, #love_dir) == love_dir then -- relative path from love_dir SMODS.MODS_DIR = lovely_mod_dir:sub(#love_dir+2) - if nfs_success then - -- make sure NFS behaves the same as love.filesystem. - -- not perfect: NFS won't read from both getSaveDirectory() - -- and getSourceBaseDirectory() - NFS.setWorkingDirectory(love_dir) - end + NFS.setWorkingDirectory(love_dir) return end end @@ -47,35 +43,35 @@ end set_mods_dir() local function find_self(directory, target_filename, target_line, depth) - depth = depth or 1 - if depth > 3 then return end - for _, filename in ipairs(NFS.getDirectoryItems(directory)) do - local file_path = directory .. "/" .. filename - local file_type = NFS.getInfo(file_path).type - if file_type == 'directory' or file_type == 'symlink' then - local f = find_self(file_path, target_filename, target_line, depth+1) - if f then return f end - elseif filename == target_filename then - local first_line = NFS.read(file_path):match('^(.-)\n') - if first_line == target_line then - -- use parent directory - return directory:match('^(.+/)') - end - end - end + depth = depth or 1 + if depth > 3 then return end + for _, filename in ipairs(NFS.getDirectoryItems(directory)) do + local file_path = directory .. "/" .. filename + local file_type = NFS.getInfo(file_path).type + if file_type == 'directory' or file_type == 'symlink' then + local f = find_self(file_path, target_filename, target_line, depth+1) + if f then return f end + elseif filename == target_filename then + local first_line = NFS.read(file_path):match('^(.-)\n') + if first_line == target_line then + -- use parent directory + return directory:match('^(.+/)') + end + end + end end SMODS.path = find_self(SMODS.MODS_DIR, 'core.lua', '--- STEAMODDED CORE') for _, path in ipairs { - "src/ui.lua", - "src/index.lua", - "src/utils.lua", - "src/overrides.lua", - "src/game_object.lua", - "src/logging.lua", - "src/compat_0_9_8.lua", - "src/loader.lua", + "src/ui.lua", + "src/index.lua", + "src/utils.lua", + "src/overrides.lua", + "src/game_object.lua", + "src/logging.lua", + "src/compat_0_9_8.lua", + "src/loader.lua", } do - assert(load(NFS.read(SMODS.path..path), ('=[SMODS _ "%s"]'):format(path)))() + assert(load(NFS.read(SMODS.path..path), ('=[SMODS _ "%s"]'):format(path)))() end diff --git a/smods-main/src/crash_handler.lua b/smods-main/src/crash_handler.lua new file mode 100644 index 0000000..e762ad1 --- /dev/null +++ b/smods-main/src/crash_handler.lua @@ -0,0 +1,855 @@ +--- STEAMODDED CORE +--- MODULE STACKTRACE +-- NOTE: This is a modifed version of https://github.com/ignacio/StackTracePlus/blob/master/src/StackTracePlus.lua +-- Licensed under the MIT License. See https://github.com/ignacio/StackTracePlus/blob/master/LICENSE +-- The MIT License +-- Copyright (c) 2010 Ignacio Burgueño +-- Permission is hereby granted, free of charge, to any person obtaining a copy +-- of this software and associated documentation files (the "Software"), to deal +-- in the Software without restriction, including without limitation the rights +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +-- copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- The above copyright notice and this permission notice shall be included in +-- all copies or substantial portions of the Software. +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +-- THE SOFTWARE. +-- tables +function loadStackTracePlus() + local _G = _G + local string, io, debug, coroutine = string, io, debug, coroutine + + -- functions + local tostring, print, require = tostring, print, require + local next, assert = next, assert + local pcall, type, pairs, ipairs = pcall, type, pairs, ipairs + local error = error + + assert(debug, "debug table must be available at this point") + + local io_open = io.open + local string_gmatch = string.gmatch + local string_sub = string.sub + local table_concat = table.concat + + local _M = { + max_tb_output_len = 70 -- controls the maximum length of the 'stringified' table before cutting with ' (more...)' + } + + -- this tables should be weak so the elements in them won't become uncollectable + local m_known_tables = { + [_G] = "_G (global table)" + } + local function add_known_module(name, desc) + local ok, mod = pcall(require, name) + if ok then + m_known_tables[mod] = desc + end + end + + add_known_module("string", "string module") + add_known_module("io", "io module") + add_known_module("os", "os module") + add_known_module("table", "table module") + add_known_module("math", "math module") + add_known_module("package", "package module") + add_known_module("debug", "debug module") + add_known_module("coroutine", "coroutine module") + + -- lua5.2 + add_known_module("bit32", "bit32 module") + -- luajit + add_known_module("bit", "bit module") + add_known_module("jit", "jit module") + -- lua5.3 + if _VERSION >= "Lua 5.3" then + add_known_module("utf8", "utf8 module") + end + + local m_user_known_tables = {} + + local m_known_functions = {} + for _, name in ipairs { -- Lua 5.2, 5.1 + "assert", "collectgarbage", "dofile", "error", "getmetatable", "ipairs", "load", "loadfile", "next", "pairs", + "pcall", "print", "rawequal", "rawget", "rawlen", "rawset", "require", "select", "setmetatable", "tonumber", + "tostring", "type", "xpcall", -- Lua 5.1 + "gcinfo", "getfenv", "loadstring", "module", "newproxy", "setfenv", "unpack" -- TODO: add table.* etc functions + } do + if _G[name] then + m_known_functions[_G[name]] = name + end + end + + local m_user_known_functions = {} + + local function safe_tostring(value) + local ok, err = pcall(tostring, value) + if ok then + return err + else + return (": '%s'"):format(err) + end + end + + -- Private: + -- Parses a line, looking for possible function definitions (in a very naïve way) + -- Returns '(anonymous)' if no function name was found in the line + local function ParseLine(line) + assert(type(line) == "string") + -- print(line) + local match = line:match("^%s*function%s+(%w+)") + if match then + -- print("+++++++++++++function", match) + return match + end + match = line:match("^%s*local%s+function%s+(%w+)") + if match then + -- print("++++++++++++local", match) + return match + end + match = line:match("^%s*local%s+(%w+)%s+=%s+function") + if match then + -- print("++++++++++++local func", match) + return match + end + match = line:match("%s*function%s*%(") -- this is an anonymous function + if match then + -- print("+++++++++++++function2", match) + return "(anonymous)" + end + return "(anonymous)" + end + + -- Private: + -- Tries to guess a function's name when the debug info structure does not have it. + -- It parses either the file or the string where the function is defined. + -- Returns '?' if the line where the function is defined is not found + local function GuessFunctionName(info) + -- print("guessing function name") + if type(info.source) == "string" and info.source:sub(1, 1) == "@" then + local file, err = io_open(info.source:sub(2), "r") + if not file then + print("file not found: " .. tostring(err)) -- whoops! + return "?" + end + local line + for _ = 1, info.linedefined do + line = file:read("*l") + end + if not line then + print("line not found") -- whoops! + return "?" + end + return ParseLine(line) + elseif type(info.source) == "string" and info.source:sub(1, 6) == "=[love" then + return "(LÖVE Function)" + else + local line + local lineNumber = 0 + for l in string_gmatch(info.source, "([^\n]+)\n-") do + lineNumber = lineNumber + 1 + if lineNumber == info.linedefined then + line = l + break + end + end + if not line then + print("line not found") -- whoops! + return "?" + end + return ParseLine(line) + end + end + + --- + -- Dumper instances are used to analyze stacks and collect its information. + -- + local Dumper = {} + + Dumper.new = function(thread) + local t = { + lines = {} + } + for k, v in pairs(Dumper) do + t[k] = v + end + + t.dumping_same_thread = (thread == coroutine.running()) + + -- if a thread was supplied, bind it to debug.info and debug.get + -- we also need to skip this additional level we are introducing in the callstack (only if we are running + -- in the same thread we're inspecting) + if type(thread) == "thread" then + t.getinfo = function(level, what) + if t.dumping_same_thread and type(level) == "number" then + level = level + 1 + end + return debug.getinfo(thread, level, what) + end + t.getlocal = function(level, loc) + if t.dumping_same_thread then + level = level + 1 + end + return debug.getlocal(thread, level, loc) + end + else + t.getinfo = debug.getinfo + t.getlocal = debug.getlocal + end + + return t + end + + -- helpers for collecting strings to be used when assembling the final trace + function Dumper:add(text) + self.lines[#self.lines + 1] = text + end + function Dumper:add_f(fmt, ...) + self:add(fmt:format(...)) + end + function Dumper:concat_lines() + return table_concat(self.lines) + end + + --- + -- Private: + -- Iterates over the local variables of a given function. + -- + -- @param level The stack level where the function is. + -- + function Dumper:DumpLocals(level) + local prefix = "\t " + local i = 1 + + if self.dumping_same_thread then + level = level + 1 + end + + local name, value = self.getlocal(level, i) + if not name then + return + end + self:add("\tLocal variables:\r\n") + while name do + if type(value) == "number" then + self:add_f("%s%s = number: %g\r\n", prefix, name, value) + elseif type(value) == "boolean" then + self:add_f("%s%s = boolean: %s\r\n", prefix, name, tostring(value)) + elseif type(value) == "string" then + self:add_f("%s%s = string: %q\r\n", prefix, name, value) + elseif type(value) == "userdata" then + self:add_f("%s%s = %s\r\n", prefix, name, safe_tostring(value)) + elseif type(value) == "nil" then + self:add_f("%s%s = nil\r\n", prefix, name) + elseif type(value) == "table" then + if m_known_tables[value] then + self:add_f("%s%s = %s\r\n", prefix, name, m_known_tables[value]) + elseif m_user_known_tables[value] then + self:add_f("%s%s = %s\r\n", prefix, name, m_user_known_tables[value]) + else + local txt = "{" + for k, v in pairs(value) do + txt = txt .. safe_tostring(k) .. ":" .. safe_tostring(v) + if #txt > _M.max_tb_output_len then + txt = txt .. " (more...)" + break + end + if next(value, k) then + txt = txt .. ", " + end + end + self:add_f("%s%s = %s %s\r\n", prefix, name, safe_tostring(value), txt .. "}") + end + elseif type(value) == "function" then + local info = self.getinfo(value, "nS") + local fun_name = info.name or m_known_functions[value] or m_user_known_functions[value] + if info.what == "C" then + self:add_f("%s%s = C %s\r\n", prefix, name, + (fun_name and ("function: " .. fun_name) or tostring(value))) + else + local source = info.short_src + if source:sub(2, 7) == "string" then + source = source:sub(9) -- uno más, por el espacio que viene (string "Baragent.Main", por ejemplo) + end + -- for k,v in pairs(info) do print(k,v) end + fun_name = fun_name or GuessFunctionName(info) + self:add_f("%s%s = Lua function '%s' (defined at line %d of chunk %s)\r\n", prefix, name, fun_name, + info.linedefined, source) + end + elseif type(value) == "thread" then + self:add_f("%sthread %q = %s\r\n", prefix, name, tostring(value)) + end + i = i + 1 + name, value = self.getlocal(level, i) + end + end + + --- + -- Public: + -- Collects a detailed stack trace, dumping locals, resolving function names when they're not available, etc. + -- This function is suitable to be used as an error handler with pcall or xpcall + -- + -- @param thread An optional thread whose stack is to be inspected (defaul is the current thread) + -- @param message An optional error string or object. + -- @param level An optional number telling at which level to start the traceback (default is 1) + -- + -- Returns a string with the stack trace and a string with the original error. + -- + function _M.stacktrace(thread, message, level) + if type(thread) ~= "thread" then + -- shift parameters left + thread, message, level = nil, thread, message + end + + thread = thread or coroutine.running() + + level = level or 1 + + local dumper = Dumper.new(thread) + + local original_error + + if type(message) == "table" then + dumper:add("an error object {\r\n") + local first = true + for k, v in pairs(message) do + if first then + dumper:add(" ") + first = false + else + dumper:add(",\r\n ") + end + dumper:add(safe_tostring(k)) + dumper:add(": ") + dumper:add(safe_tostring(v)) + end + dumper:add("\r\n}") + original_error = dumper:concat_lines() + elseif type(message) == "string" then + dumper:add(message) + original_error = message + end + + dumper:add("\r\n") + dumper:add [[ +Stack Traceback +=============== +]] + -- print(error_message) + + local level_to_show = level + if dumper.dumping_same_thread then + level = level + 1 + end + + local info = dumper.getinfo(level, "nSlf") + while info do + if info.what == "main" then + if string_sub(info.source, 1, 1) == "@" then + dumper:add_f("(%d) main chunk of file '%s' at line %d\r\n", level_to_show, + string_sub(info.source, 2), info.currentline) + elseif info.source and info.source:sub(1, 1) == "=" then + local str = info.source:sub(3, -2) + local props = {} + -- Split by space + for v in string.gmatch(str, "[^%s]+") do + table.insert(props, v) + end + local source = table.remove(props, 1) + if source == "love" then + dumper:add_f("(%d) main chunk of LÖVE file '%s' at line %d\r\n", level_to_show, + table.concat(props, " "):sub(2, -2), info.currentline) + elseif source == "SMODS" then + local modID = table.remove(props, 1) + local fileName = table.concat(props, " ") + if modID == '_' then + dumper:add_f("(%d) main chunk of Steamodded file '%s' at line %d\r\n", level_to_show, + fileName:sub(2, -2), info.currentline) + else + dumper:add_f("(%d) main chunk of file '%s' at line %d (from mod with id %s)\r\n", + level_to_show, fileName:sub(2, -2), info.currentline, modID) + end + elseif source == "lovely" then + local module = table.remove(props, 1) + local fileName = table.concat(props, " ") + dumper:add_f("(%d) main chunk of file '%s' at line %d (from lovely module %s)\r\n", + level_to_show, fileName:sub(2, -2), info.currentline, module) + else + dumper:add_f("(%d) main chunk of %s at line %d\r\n", level_to_show, info.source, + info.currentline) + end + else + dumper:add_f("(%d) main chunk of %s at line %d\r\n", level_to_show, info.source, info.currentline) + end + elseif info.what == "C" then + -- print(info.namewhat, info.name) + -- for k,v in pairs(info) do print(k,v, type(v)) end + local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name or + tostring(info.func) + dumper:add_f("(%d) %s C function '%s'\r\n", level_to_show, info.namewhat, function_name) + -- dumper:add_f("%s%s = C %s\r\n", prefix, name, (m_known_functions[value] and ("function: " .. m_known_functions[value]) or tostring(value))) + elseif info.what == "tail" then + -- print("tail") + -- for k,v in pairs(info) do print(k,v, type(v)) end--print(info.namewhat, info.name) + dumper:add_f("(%d) tail call\r\n", level_to_show) + dumper:DumpLocals(level) + elseif info.what == "Lua" then + local source = info.short_src + local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name + if source:sub(2, 7) == "string" then + source = source:sub(9) + end + local was_guessed = false + if not function_name or function_name == "?" then + -- for k,v in pairs(info) do print(k,v, type(v)) end + function_name = GuessFunctionName(info) + was_guessed = true + end + -- test if we have a file name + local function_type = (info.namewhat == "") and "function" or info.namewhat + if info.source and info.source:sub(1, 1) == "@" then + dumper:add_f("(%d) Lua %s '%s' at file '%s:%d'%s\r\n", level_to_show, function_type, function_name, + info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "") + elseif info.source and info.source:sub(1, 1) == '#' then + dumper:add_f("(%d) Lua %s '%s' at template '%s:%d'%s\r\n", level_to_show, function_type, + function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "") + elseif info.source and info.source:sub(1, 1) == "=" then + local str = info.source:sub(3, -2) + local props = {} + -- Split by space + for v in string.gmatch(str, "[^%s]+") do + table.insert(props, v) + end + local source = table.remove(props, 1) + if source == "love" then + dumper:add_f("(%d) LÖVE %s at file '%s:%d'%s\r\n", level_to_show, function_type, + table.concat(props, " "):sub(2, -2), info.currentline, was_guessed and " (best guess)" or "") + elseif source == "SMODS" then + local modID = table.remove(props, 1) + local fileName = table.concat(props, " ") + if modID == '_' then + dumper:add_f("(%d) Lua %s '%s' at Steamodded file '%s:%d' %s\r\n", level_to_show, + function_type, function_name, fileName:sub(2, -2), info.currentline, + was_guessed and " (best guess)" or "") + else + dumper:add_f("(%d) Lua %s '%s' at file '%s:%d' (from mod with id %s)%s\r\n", level_to_show, + function_type, function_name, fileName:sub(2, -2), info.currentline, modID, + was_guessed and " (best guess)" or "") + end + elseif source == "lovely" then + local module = table.remove(props, 1) + local fileName = table.concat(props, " ") + dumper:add_f("(%d) Lua %s '%s' at file '%s:%d' (from lovely module %s)%s\r\n", level_to_show, + function_type, function_name, fileName:sub(2, -2), info.currentline, module, + was_guessed and " (best guess)" or "") + else + dumper:add_f("(%d) Lua %s '%s' at line %d of chunk '%s'\r\n", level_to_show, function_type, + function_name, info.currentline, source) + end + else + dumper:add_f("(%d) Lua %s '%s' at line %d of chunk '%s'\r\n", level_to_show, function_type, + function_name, info.currentline, source) + end + dumper:DumpLocals(level) + else + dumper:add_f("(%d) unknown frame %s\r\n", level_to_show, info.what) + end + + level = level + 1 + level_to_show = level_to_show + 1 + info = dumper.getinfo(level, "nSlf") + end + + return dumper:concat_lines(), original_error + end + + -- + -- Adds a table to the list of known tables + function _M.add_known_table(tab, description) + if m_known_tables[tab] then + error("Cannot override an already known table") + end + m_user_known_tables[tab] = description + end + + -- + -- Adds a function to the list of known functions + function _M.add_known_function(fun, description) + if m_known_functions[fun] then + error("Cannot override an already known function") + end + m_user_known_functions[fun] = description + end + + return _M +end + +-- Note: The below code is not from the original StackTracePlus.lua +local stackTraceAlreadyInjected = false + +function getDebugInfoForCrash() + local version = VERSION + if not version or type(version) ~= "string" then + local versionFile = love.filesystem.read("version.jkr") + if versionFile then + version = versionFile:match("[^\n]*") .. " (best guess)" + else + version = "???" + end + end + local modded_version = MODDED_VERSION + if not modded_version or type(modded_version) ~= "string" then + local moddedSuccess, reqVersion = pcall(require, "SMODS.version") + if moddedSuccess and type(reqVersion) == "string" then + modded_version = reqVersion + else + modded_version = "???" + end + end + + local info = "Additional Context:\nBalatro Version: " .. version .. "\nModded Version: " .. + (modded_version) + local major, minor, revision, codename = love.getVersion() + info = info .. string.format("\nLÖVE Version: %d.%d.%d", major, minor, revision) + local lovely_success, lovely = pcall(require, "lovely") + if lovely_success then + info = info .. "\nLovely Version: " .. lovely.version + end + info = info .. "\nPlatform: " .. (love.system.getOS() or "???") + if SMODS and SMODS.Mods then + local mod_strings = "" + local lovely_strings = "" + local i = 1 + local lovely_i = 1 + for _, v in pairs(SMODS.Mods) do + if (v.can_load and (not v.meta_mod or v.lovely_only)) or (v.lovely and not v.can_load and not v.disabled) then + if v.lovely_only or (v.lovely and not v.can_load) then + lovely_strings = lovely_strings .. "\n " .. lovely_i .. ": " .. v.name + lovely_i = lovely_i + 1 + if not v.can_load then + lovely_strings = lovely_strings .. "\n Has Steamodded mod that failed to load." + if #v.load_issues.dependencies > 0 then + lovely_strings = lovely_strings .. "\n Missing Dependencies:" + for k, v in ipairs(v.load_issues.dependencies) do + lovely_strings = lovely_strings .. "\n " .. k .. ". " .. v + end + end + if #v.load_issues.conflicts > 0 then + lovely_strings = lovely_strings .. "\n Conflicts:" + for k, v in ipairs(v.load_issues.conflicts) do + lovely_strings = lovely_strings .. "\n " .. k .. ". " .. v + end + end + if v.load_issues.outdated then + lovely_strings = lovely_strings .. "\n Outdated Mod." + end + if v.load_issues.main_file_not_found then + lovely_strings = lovely_strings .. "\n Main file not found. (" .. v.main_file ..")" + end + end + else + mod_strings = mod_strings .. "\n " .. i .. ": " .. v.name .. " by " .. + table.concat(v.author, ", ") .. " [ID: " .. v.id .. + (v.priority ~= 0 and (", Priority: " .. v.priority) or "") .. + (v.version and v.version ~= '0.0.0' and (", Version: " .. v.version) or "") .. + (v.lovely and (", Uses Lovely") or "") .. "]" + i = i + 1 + local debugInfo = v.debug_info + if debugInfo then + if type(debugInfo) == "string" then + if #debugInfo ~= 0 then + mod_strings = mod_strings .. "\n " .. debugInfo + end + elseif type(debugInfo) == "table" then + for kk, vv in pairs(debugInfo) do + if type(vv) ~= 'nil' then + vv = tostring(vv) + end + if #vv ~= 0 then + mod_strings = mod_strings .. "\n " .. kk .. ": " .. vv + end + end + end + end + end + end + end + info = info .. "\nSteamodded Mods:" .. mod_strings .. "\nLovely Mods:" .. lovely_strings + end + return info +end + +function injectStackTrace() + if (stackTraceAlreadyInjected) then + return + end + stackTraceAlreadyInjected = true + local STP = loadStackTracePlus() + local utf8 = require("utf8") + + -- Modifed from https://love2d.org/wiki/love.errorhandler + function love.errorhandler(msg) + msg = tostring(msg) + + if not sendErrorMessage then + function sendErrorMessage(msg) + print(msg) + end + end + if not sendInfoMessage then + function sendInfoMessage(msg) + print(msg) + end + end + + sendErrorMessage("Oops! The game crashed\n" .. STP.stacktrace(msg), 'StackTrace') + + if not love.window or not love.graphics or not love.event then + return + end + + if not love.graphics.isCreated() or not love.window.isOpen() then + local success, status = pcall(love.window.setMode, 800, 600) + if not success or not status then + return + end + end + + -- Reset state. + if love.mouse then + love.mouse.setVisible(true) + love.mouse.setGrabbed(false) + love.mouse.setRelativeMode(false) + if love.mouse.isCursorSupported() then + love.mouse.setCursor() + end + end + if love.joystick then + -- Stop all joystick vibrations. + for i, v in ipairs(love.joystick.getJoysticks()) do + v:setVibration() + end + end + if love.audio then + love.audio.stop() + end + + love.graphics.reset() + local font = love.graphics.setNewFont("resources/fonts/m6x11plus.ttf", 20) + + local background = {0, 0, 1} + if G and G.C and G.C.BLACK then + background = G.C.BLACK + end + love.graphics.clear(background) + love.graphics.origin() + + local trace = STP.stacktrace("", 3) + + local sanitizedmsg = {} + for char in msg:gmatch(utf8.charpattern) do + table.insert(sanitizedmsg, char) + end + sanitizedmsg = table.concat(sanitizedmsg) + + local err = {} + + table.insert(err, "Oops! The game crashed:") + if sanitizedmsg:find("Syntax error: game.lua:4: '=' expected near 'Game'") then + table.insert(err, + 'Duplicate installation of Steamodded detected! Please clean your installation: Steam Library > Balatro > Properties > Installed Files > Verify integrity of game files.') + else + table.insert(err, sanitizedmsg) + end + if #sanitizedmsg ~= #msg then + table.insert(err, "Invalid UTF-8 string in error message.") + end + + local success, msg = pcall(getDebugInfoForCrash) + if success and msg then + table.insert(err, '\n' .. msg) + sendInfoMessage(msg, 'StackTrace') + else + table.insert(err, "\n" .. "Failed to get additional context :/") + sendErrorMessage("Failed to get additional context :/\n" .. msg, 'StackTrace') + end + + for l in trace:gmatch("(.-)\n") do + table.insert(err, l) + end + + local p = table.concat(err, "\n") + + p = p:gsub("\t", "") + p = p:gsub("%[string \"(.-)\"%]", "%1") + + local scrollOffset = 0 + local endHeight = 0 + love.keyboard.setKeyRepeat(true) + + local function scrollDown(amt) + if amt == nil then + amt = 18 + end + scrollOffset = scrollOffset + amt + if scrollOffset > endHeight then + scrollOffset = endHeight + end + end + + local function scrollUp(amt) + if amt == nil then + amt = 18 + end + scrollOffset = scrollOffset - amt + if scrollOffset < 0 then + scrollOffset = 0 + end + end + + local pos = 70 + local arrowSize = 20 + + local function calcEndHeight() + local font = love.graphics.getFont() + local rw, lines = font:getWrap(p, love.graphics.getWidth() - pos * 2) + local lineHeight = font:getHeight() + local atBottom = scrollOffset == endHeight and scrollOffset ~= 0 + endHeight = #lines * lineHeight - love.graphics.getHeight() + pos * 2 + if (endHeight < 0) then + endHeight = 0 + end + if scrollOffset > endHeight or atBottom then + scrollOffset = endHeight + end + end + + local function draw() + if not love.graphics.isActive() then + return + end + love.graphics.clear(background) + calcEndHeight() + love.graphics.printf(p, pos, pos - scrollOffset, love.graphics.getWidth() - pos * 2) + if scrollOffset ~= endHeight then + love.graphics.polygon("fill", love.graphics.getWidth() - (pos / 2), + love.graphics.getHeight() - arrowSize, love.graphics.getWidth() - (pos / 2) + arrowSize, + love.graphics.getHeight() - (arrowSize * 2), love.graphics.getWidth() - (pos / 2) - arrowSize, + love.graphics.getHeight() - (arrowSize * 2)) + end + if scrollOffset ~= 0 then + love.graphics.polygon("fill", love.graphics.getWidth() - (pos / 2), arrowSize, + love.graphics.getWidth() - (pos / 2) + arrowSize, arrowSize * 2, + love.graphics.getWidth() - (pos / 2) - arrowSize, arrowSize * 2) + end + love.graphics.present() + end + + local fullErrorText = p + local function copyToClipboard() + if not love.system then + return + end + love.system.setClipboardText(fullErrorText) + p = p .. "\nCopied to clipboard!" + end + + p = p .. "\n\nPress ESC to exit\nPress R to restart the game" + if love.system then + p = p .. "\nPress Ctrl+C or tap to copy this error" + end + + if G then + -- Kill threads (makes restarting possible) + if G.SOUND_MANAGER and G.SOUND_MANAGER.channel then + G.SOUND_MANAGER.channel:push({ + type = 'kill' + }) + end + if G.SAVE_MANAGER and G.SAVE_MANAGER.channel then + G.SAVE_MANAGER.channel:push({ + type = 'kill' + }) + end + if G.HTTP_MANAGER and G.HTTP_MANAGER.channel then + G.HTTP_MANAGER.channel:push({ + type = 'kill' + }) + end + end + + return function() + love.event.pump() + + for e, a, b, c in love.event.poll() do + if e == "quit" then + return 1 + elseif e == "keypressed" and a == "escape" then + return 1 + elseif e == "keypressed" and a == "c" and love.keyboard.isDown("lctrl", "rctrl") then + copyToClipboard() + elseif e == "keypressed" and a == "r" then + SMODS.restart_game() + elseif e == "keypressed" and a == "down" then + scrollDown() + elseif e == "keypressed" and a == "up" then + scrollUp() + elseif e == "keypressed" and a == "pagedown" then + scrollDown(love.graphics.getHeight()) + elseif e == "keypressed" and a == "pageup" then + scrollUp(love.graphics.getHeight()) + elseif e == "keypressed" and a == "home" then + scrollOffset = 0 + elseif e == "keypressed" and a == "end" then + scrollOffset = endHeight + elseif e == "wheelmoved" then + scrollUp(b * 20) + elseif e == "gamepadpressed" and b == "dpdown" then + scrollDown() + elseif e == "gamepadpressed" and b == "dpup" then + scrollUp() + elseif e == "gamepadpressed" and b == "a" then + return "restart" + elseif e == "gamepadpressed" and b == "x" then + copyToClipboard() + elseif e == "gamepadpressed" and (b == "b" or b == "back" or b == "start") then + return 1 + elseif e == "touchpressed" then + local name = love.window.getTitle() + if #name == 0 or name == "Untitled" then + name = "Game" + end + local buttons = {"OK", "Cancel", "Restart"} + if love.system then + buttons[4] = "Copy to clipboard" + end + local pressed = love.window.showMessageBox("Quit " .. name .. "?", "", buttons) + if pressed == 1 then + return 1 + elseif pressed == 3 then + return "restart" + elseif pressed == 4 then + copyToClipboard() + end + end + end + + draw() + + if love.timer then + love.timer.sleep(0.1) + end + end + + end +end + +injectStackTrace() + +-- ---------------------------------------------- +-- --------MOD CORE API STACKTRACE END----------- diff --git a/smods-main/src/game_object.lua b/smods-main/src/game_object.lua new file mode 100644 index 0000000..e71d754 --- /dev/null +++ b/smods-main/src/game_object.lua @@ -0,0 +1,3289 @@ +--- STEAMODDED CORE +--- MODULE API + +function loadAPIs() + ------------------------------------------------------------------------------------------------- + --- API CODE GameObject + ------------------------------------------------------------------------------------------------- + + --- GameObject base class. You should always use the appropriate subclass to register your object. + SMODS.GameObject = Object:extend() + SMODS.GameObject.subclasses = {} + function SMODS.GameObject:extend(o) + local cls = Object.extend(self) + for k, v in pairs(o or {}) do + cls[k] = v + end + self.subclasses[#self.subclasses + 1] = cls + cls.subclasses = {} + return cls + end + + function SMODS.GameObject:__call(o) + o = o or {} + assert(o.mod == nil) + o.mod = SMODS.current_mod + setmetatable(o, self) + for _, v in ipairs(o.required_params or {}) do + assert(not (o[v] == nil), ('Missing required parameter for %s declaration: %s'):format(o.set, v)) + end + if o:check_duplicate_register() then return end + -- also updates o.prefix_config + SMODS.add_prefixes(self, o) + if o:check_duplicate_key() then return end + o:register() + return o + end + + function SMODS.modify_key(obj, prefix, condition, key) + key = key or 'key' + -- condition == nil counts as true + if condition ~= false and obj[key] and prefix then + if string.sub(obj[key], 1, #prefix + 1) == prefix..'_' then + -- this happens within steamodded itself and I don't want to spam the logs with warnings, leaving this disabled for now + -- sendWarnMessage(("Attempted to prefix field %s=%s on object %s, already prefixed"):format(key, obj[key], obj.key), obj.set) + return + end + obj[key] = prefix .. '_' .. obj[key] + end + end + + function SMODS.add_prefixes(cls, obj, from_take_ownership) + if obj.prefix_config == false then return end + obj.prefix_config = obj.prefix_config or {} + if obj.raw_key then + sendWarnMessage(([[The field `raw_key` on %s is deprecated. +Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj.set) + obj.prefix_config.key = false + end + -- keep class defaults for unmodified keys in prefix_config + obj.prefix_config = SMODS.merge_defaults(obj.prefix_config, cls.prefix_config) + local mod = SMODS.current_mod + obj.prefix_config = SMODS.merge_defaults(obj.prefix_config, mod and mod.prefix_config) + obj.original_key = obj.key + local key_cfg = obj.prefix_config.key + if key_cfg ~= false then + if type(key_cfg) ~= 'table' then key_cfg = {} end + if not from_take_ownership then + SMODS.modify_key(obj, mod and mod.prefix, key_cfg.mod) + end + SMODS.modify_key(obj, cls.class_prefix, key_cfg.class) + end + local atlas_cfg = obj.prefix_config.atlas + if atlas_cfg ~= false then + if type(atlas_cfg) ~= 'table' then atlas_cfg = {} end + for _, v in ipairs({ 'atlas', 'hc_atlas', 'lc_atlas', 'hc_ui_atlas', 'lc_ui_atlas', 'sticker_atlas' }) do + if rawget(obj, v) then SMODS.modify_key(obj, mod and mod.prefix, atlas_cfg, v) end + end + end + local shader_cfg = obj.prefix_config.shader + SMODS.modify_key(obj, mod and mod.prefix, shader_cfg, 'shader') + local card_key_cfg = obj.prefix_config.card_key + SMODS.modify_key(obj, mod and mod.prefix, card_key_cfg, 'card_key') + local above_stake_cfg = obj.prefix_config.above_stake + if above_stake_cfg ~= false then + if type(above_stake_cfg) ~= 'table' then above_stake_cfg = {} end + SMODS.modify_key(obj, mod and mod.prefix, above_stake_cfg.mod, 'above_stake') + SMODS.modify_key(obj, cls.class_prefix, above_stake_cfg.class, 'above_stake') + end + local applied_stakes_cfg = obj.prefix_config.applied_stakes + if applied_stakes_cfg ~= false and obj.applied_stakes then + if type(applied_stakes_cfg) ~= 'table' then applied_stakes_cfg = {} end + for k,v in pairs(obj.applied_stakes) do + SMODS.modify_key(obj.applied_stakes, mod and mod.prefix, (applied_stakes_cfg[k] or {}).mod or applied_stakes_cfg.mod, k) + SMODS.modify_key(obj.applied_stakes, cls.class_prefix, (applied_stakes_cfg[k] or {}).class or applied_stakes_cfg.class, k) + end + end + local unlocked_stake_cfg = obj.prefix_config.unlocked_stake + if unlocked_stake_cfg ~= false then + if type(unlocked_stake_cfg) ~= 'table' then unlocked_stake_cfg = {} end + SMODS.modify_key(obj, mod and mod.prefix, unlocked_stake_cfg.mod, 'unlocked_stake') + SMODS.modify_key(obj, cls.class_prefix, unlocked_stake_cfg.class, 'unlocked_stake') + end + end + + function SMODS.GameObject:check_duplicate_register() + if self.registered then + sendWarnMessage(('Detected duplicate register call on object %s'):format(self.key), self.set) + return true + end + return false + end + + -- Checked on __call but not take_ownership. For take_ownership, the key must exist + function SMODS.GameObject:check_duplicate_key() + if self.obj_table[self.key] or (self.get_obj and self:get_obj(self.key)) then + sendWarnMessage(('Object %s has the same key as an existing object, not registering.'):format(self.key), self.set) + sendWarnMessage('If you want to modify an existing object, use take_ownership()', self.set) + return true + end + return false + end + + function SMODS.GameObject:register() + if self:check_dependencies() then + self.obj_table[self.key] = self + self.obj_buffer[#self.obj_buffer + 1] = self.key + self.registered = true + end + end + + function SMODS.GameObject:check_dependencies() + local keep = true + if self.dependencies then + -- ensure dependencies are a table + if type(self.dependencies) == 'string' then self.dependencies = { self.dependencies } end + for _, v in ipairs(self.dependencies) do + self.mod.optional_dependencies[v] = true + if not next(SMODS.find_mod(v)) then keep = false end + end + end + return keep + end + + function SMODS.GameObject:process_loc_text() + SMODS.process_loc_text(G.localization.descriptions[self.set], self.key, self.loc_txt) + end + + --- Starting from this class, recursively searches for + --- functions with the given key on all subordinate classes + --- and run all found functions with the given arguments + function SMODS.GameObject:send_to_subclasses(func, ...) + if rawget(self, func) and type(self[func]) == 'function' then self[func](self, ...) end + for _, cls in ipairs(self.subclasses) do + cls:send_to_subclasses(func, ...) + end + end + + + -- Inject all direct instances `o` of the class by calling `o:inject()`. + -- Also inject anything necessary for the class itself. + function SMODS.GameObject:inject_class() + local inject_time = 0 + local start_time = love.timer.getTime() + self:send_to_subclasses('pre_inject_class') + local end_time = love.timer.getTime() + inject_time = end_time - start_time + start_time = end_time + local o = nil + for i, key in ipairs(self.obj_buffer) do + o = self.obj_table[key] + o.atlas = o.atlas or o.set + + if o._discovered_unlocked_overwritten then + assert(o._saved_d_u) + o.discovered, o.unlocked = o._d, o._u + o._discovered_unlocked_overwritten = false + else + SMODS._save_d_u(o) + end + + -- Add centers to pools + o:inject(i) + + -- Setup Localize text + o:process_loc_text() + if self.log_interval and i%(self.log_interval) == 0 then + end_time = love.timer.getTime() + inject_time = inject_time + end_time - start_time + start_time = end_time + local alert = ('[%s] Injecting %s: %.3f ms'):format(string.rep('0', 4-#tostring(i))..i, self.set, inject_time*1000) + sendTraceMessage(alert, 'TIMER') + boot_print_stage(alert) + end + end + self:send_to_subclasses('post_inject_class') + end_time = love.timer.getTime() + inject_time = inject_time + end_time - start_time + local n = #self.obj_buffer + local alert = ('[%s] Injected %s in %.3f ms'):format(string.rep('0',4-#tostring(n))..n, self.set, inject_time*1000) + sendInfoMessage(alert, 'TIMER') + boot_print_stage(alert) + end + + --- Takes control of vanilla objects. Child class must implement get_obj for this to function. + function SMODS.GameObject:take_ownership(key, obj, silent) + if self.check_duplicate_register(obj) then return end + obj.key = key + obj.mod = nil + SMODS.add_prefixes(self, obj, true) + key = obj.key + local orig_o = self.obj_table[key] or (self.get_obj and self:get_obj(key)) + if not orig_o then + sendWarnMessage( + ('Cannot take ownership of %s: Does not exist.'):format(key), self.set + ) + return + end + local is_loc_modified = obj.loc_txt or obj.loc_vars or obj.generate_ui + if is_loc_modified then orig_o.is_loc_modified = true end + if not orig_o.is_loc_modified then + -- Setting generate_ui to this sentinel value + -- makes vanilla localization code run instead of SMODS's code + orig_o.generate_ui = 0 + else + -- reset the value if otherwise, in case when the object was taken over before and this value was already set to 0 + if orig_o.generate_ui == 0 then + orig_o.generate_ui = nil + end + end + -- TODO + -- it's unclear how much we should modify `obj` on a failed take_ownership call. + -- do we make sure the metatable is set early, or wait until the end? + setmetatable(orig_o, self) + if orig_o.mod then + orig_o.dependencies = orig_o.dependencies or {} + if not silent then table.insert(orig_o.dependencies, SMODS.current_mod.id) end + else + if not silent then orig_o.mod = SMODS.current_mod end + orig_o.rarity_original = orig_o.rarity + end + if orig_o._saved_d_u then + orig_o.discovered, orig_o.unlocked = orig_o._d, orig_o._u + orig_o._saved_d_u = false + orig_o._discovered_unlocked_overwritten = false + end + for k, v in pairs(obj) do orig_o[k] = v end + SMODS._save_d_u(orig_o) + orig_o.taken_ownership = true + orig_o:register() + return orig_o + end + + -- Inject all SMODS Objects that are part of this class or a subclass. + function SMODS.injectObjects(class) + if class.obj_table and class.obj_buffer then + class:inject_class() + else + for _, subclass in ipairs(class.subclasses) do SMODS.injectObjects(subclass) end + end + end + + -- Internal function + -- Creates a list of objects from a list of keys. + -- Currently used for a special case when selecting a random suit/rank. + function SMODS.GameObject:obj_list(reversed) + local lb, ub, step = 1, #self.obj_buffer, 1 + if reversed then lb, ub, step = ub, lb, -1 end + local res = {} + for i = lb, ub, step do + res[#res+1] = self.obj_table[self.obj_buffer[i]] + end + return res + end + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Language + ------------------------------------------------------------------------------------------------- + + SMODS.Languages = {} + SMODS.Language = SMODS.GameObject:extend { + obj_table = SMODS.Languages, + set = 'Language', + obj_buffer = {}, + required_params = { + 'key', + 'label', + }, + prefix_config = { key = false }, + process_loc_text = function() end, + inject = function(self) + self.font = self.font or 1 + if type(self.font) == 'table' and not self.font.FONT and self.font.file and self.font.render_scale then + local data = assert(NFS.newFileData(self.mod.path .. 'assets/fonts/' .. self.font.file), ('Failed to collect file data for font of language %s'):format(self.key)) + self.font.FONT = love.graphics.newFont(data, self.font.render_scale) + elseif type(self.font) ~= 'table' then + self.font = G.FONTS[type(self.font) == 'number' and self.font or 1] or G.FONTS[1] + end + G.LANGUAGES[self.key] = self + if self.key == (G.SETTINGS.real_language or G.SETTINGS.language) then G.LANG = self end + end, + } + + ------------------------------------------------------------------------------------------------- + ----- INTERNAL API CODE GameObject._Loc_Pre + ------------------------------------------------------------------------------------------------- + + SMODS._Loc_Pre = SMODS.GameObject:extend { + obj_table = {}, + obj_buffer = {}, + silent = true, + set = '[INTERNAL]', + register = function() error('INTERNAL CLASS, DO NOT CALL') end, + pre_inject_class = function() + SMODS.handle_loc_file(SMODS.path) + if SMODS.dump_loc then SMODS.dump_loc.pre_inject = copy_table(G.localization) end + for _, mod in ipairs(SMODS.mod_list) do + if mod.process_loc_text and type(mod.process_loc_text) == 'function' then + mod.process_loc_text() + end + end + end + } + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Atlas + ------------------------------------------------------------------------------------------------- + + SMODS.Atlases = {} + SMODS.Atlas = SMODS.GameObject:extend { + obj_table = SMODS.Atlases, + obj_buffer = {}, + disable_mipmap = false, + required_params = { + 'key', + 'path', + 'px', + 'py' + }, + atlas_table = 'ASSET_ATLAS', + set = 'Atlas', + register = function(self) + if self.registered then + sendWarnMessage(('Detected duplicate register call on object %s'):format(self.key), self.set) + return + end + if self.language then + self.key_noloc = self.key + self.key = ('%s_%s'):format(self.key, self.language) + end + -- needed for changing high contrast settings, apparently + self.name = self.key + SMODS.Atlas.super.register(self) + end, + inject = function(self) + local file_path = type(self.path) == 'table' and + ((G.SETTINGS.real_language and self.path[G.SETTINGS.real_language]) or self.path[G.SETTINGS.language] or self.path['default'] or self.path['en-us']) or self.path + if file_path == 'DEFAULT' then return end + -- language specific sprites override fully defined sprites only if that language is set + if self.language and G.SETTINGS.language ~= self.language and G.SETTINGS.real_language ~= self.language then return end + if not self.language and (self.obj_table[('%s_%s'):format(self.key, G.SETTINGS.language)] or self.obj_table[('%s_%s'):format(self.key, G.SETTINGS.real_language)]) then return end + self.full_path = (self.mod and self.mod.path or SMODS.path) .. + 'assets/' .. G.SETTINGS.GRAPHICS.texture_scaling .. 'x/' .. file_path + local file_data = assert(NFS.newFileData(self.full_path), + ('Failed to collect file data for Atlas %s'):format(self.key)) + self.image_data = assert(love.image.newImageData(file_data), + ('Failed to initialize image data for Atlas %s'):format(self.key)) + self.image = love.graphics.newImage(self.image_data, + { mipmaps = true, dpiscale = G.SETTINGS.GRAPHICS.texture_scaling }) + G[self.atlas_table][self.key_noloc or self.key] = self + + local mipmap_level = SMODS.config.graphics_mipmap_level_options[SMODS.config.graphics_mipmap_level] + if not self.disable_mipmap and mipmap_level and mipmap_level > 0 then + self.image:setMipmapFilter('linear', mipmap_level) + end + end, + process_loc_text = function() end, + pre_inject_class = function(self) + G:set_render_settings() -- restore originals first in case a texture pack was disabled + end + } + + SMODS.Atlas { + key = 'mod_tags', + path = 'mod_tags.png', + px = 34, + py = 34, + } + SMODS.Atlas { + key = 'achievements', + path = 'default_achievements.png', + px = 66, + py = 66, + } + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Sound + ------------------------------------------------------------------------------------------------- + + SMODS.Sounds = {} + SMODS.Sound = SMODS.GameObject:extend { + obj_buffer = {}, + set = 'Sound', + obj_table = SMODS.Sounds, + stop_sounds = {}, + replace_sounds = {}, + required_params = { + 'key', + 'path' + }, + process_loc_text = function() end, + register = function(self) + if self.registered then + sendWarnMessage(('Detected duplicate register call on object %s'):format(self.key), self.set) + return + end + self.sound_code = self.key + if self.replace then + local replace, times, args + if type(self.replace) == 'table' then + replace, times, args = self.replace.key, self.replace.times or -1, self.replace.args + else + replace, times = self.replace, -1 + end + self.replace_sounds[replace] = { key = self.key, times = times, args = args } + end + -- TODO detect music state based on if select_music_track exists + assert(not self.select_music_track or self.key:find('music')) + SMODS.Sound.super.register(self) + end, + inject = function(self) + local file_path = type(self.path) == 'table' and + ((G.SETTINGS.real_language and self.path[G.SETTINGS.real_language]) or self.path[G.SETTINGS.language] or self.path['default'] or self.path['en-us']) or self.path + if file_path == 'DEFAULT' then return end + local prev_path = self.full_path + self.full_path = (self.mod and self.mod.path or SMODS.path) .. + 'assets/sounds/' .. file_path + if prev_path == self.full_path then return end + self.data = NFS.read('data', self.full_path) + --self.decoder = love.sound.newDecoder(self.data) + self.should_stream = string.find(self.key, 'music') or string.find(self.key, 'stream') or string.find(self.key, 'ambient') + --self.sound = love.audio.newSource(self.decoder, self.should_stream and 'stream' or 'static') + if prev_path then G.SOUND_MANAGER.channel:push({ type = 'stop' }) end + G.SOUND_MANAGER.channel:push({ type = 'sound_source', sound_code = self.sound_code, data = self.data, should_stream = self.should_stream, per = self.pitch, vol = self.volume }) + end, + register_global = function(self) + local mod = SMODS.current_mod + if not mod then return end + for _, filename in ipairs(NFS.getDirectoryItems(mod.path .. 'assets/sounds/')) do + local extension = string.sub(filename, -4) + if extension == '.ogg' or extension == '.mp3' or extension == '.wav' then -- please use .ogg or .wav files + local sound_code = string.sub(filename, 1, -5) + self { + key = sound_code, + path = filename, + } + end + end + end, + -- retaining this function for mod compat + play = function(self, pitch, volume, stop_previous_instance, key) + return play_sound(key or self.sound_code, pitch, volume) + end, + create_stop_sound = function(self, key, times) + times = times or -1 + self.stop_sounds[key] = times + end, + create_replace_sound = function(self, replace_sound) + self.replace = replace_sound + local replace, times, args + if type(self.replace) == 'table' then + replace, times, args = self.replace.key, self.replace.times or -1, self.replace.args + else + replace, times = self.replace, -1 + end + self.replace_sounds[replace] = { key = self.key, times = times, args = args } + end, + get_current_music = function(self) + local track + local maxp = -math.huge + for _, v in ipairs(self.obj_buffer) do + local s = self.obj_table[v] + if type(s.select_music_track) == 'function' then + local res = s:select_music_track() + if res then + if type(res) ~= 'number' then res = 0 end + if res > maxp then track, maxp = v, res end + end + end + end + return track + end + } + + local play_sound_ref = play_sound + function play_sound(sound_code, per, vol) + local replace_sound = SMODS.Sound.replace_sounds[sound_code] + if replace_sound then + local sound = SMODS.Sounds[replace_sound.key] + local rt + if replace_sound.args then + local args = replace_sound.args + if type(args) == 'function' then args = args(sound, { pitch = per, volume = vol }) end + play_sound(sound.sound_code, args.pitch, args.volume) + if not args.continue_base_sound then rt = true end + else + play_sound(sound.sound_code, per, vol) + rt = true + end + if replace_sound.times > 0 then replace_sound.times = replace_sound.times - 1 end + if replace_sound.times == 0 then SMODS.Sound.replace_sounds[sound_code] = nil end + if rt then return end + end + local stop_sound = SMODS.Sound.stop_sounds[sound_code] + if stop_sound then + if stop_sound > 0 then + SMODS.Sound.stop_sounds[sound_code] = stop_sound - 1 + end + return + end + + return play_sound_ref(sound_code, per, vol) + end + + SMODS.Sound{ key = 'xchips', path = 'xchips.ogg'} + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Stake + ------------------------------------------------------------------------------------------------- + + SMODS.Stakes = {} + SMODS.Stake = SMODS.GameObject:extend { + obj_table = SMODS.Stakes, + obj_buffer = {}, + class_prefix = 'stake', + unlocked = false, + set = 'Stake', + atlas = 'chips', + pos = { x = 0, y = 0 }, + injected = false, + required_params = { + 'key', + 'pos', + 'applied_stakes' + }, + pre_inject_class = function(self) + G.P_CENTER_POOLS[self.set] = {} + G.P_STAKES = {} + end, + inject = function(self) + if not self.injected then + -- Inject stake in the correct spot + self.count = #G.P_CENTER_POOLS[self.set] + 1 + self.order = self.count + if self.above_stake and G.P_STAKES[self.above_stake] then + self.order = G.P_STAKES[self.above_stake].order + 1 + end + for _, v in pairs(G.P_STAKES) do + if v.order >= self.order then + v.order = v.order + 1 + end + end + G.P_STAKES[self.key] = self + table.insert(G.P_CENTER_POOLS.Stake, self) + -- Sticker sprites (stake_ prefix is removed for vanilla compatiblity) + if self.sticker_pos ~= nil then + G.shared_stickers[self.key:sub(7)] = Sprite(0, 0, G.CARD_W, G.CARD_H, + G.ASSET_ATLAS[self.sticker_atlas] or G.ASSET_ATLAS["stickers"], self.sticker_pos) + G.sticker_map[self.key] = self.key:sub(7) + else + G.sticker_map[self.key] = nil + end + else + G.P_STAKES[self.key] = self + SMODS.insert_pool(G.P_CENTER_POOLS.Stake, self) + end + self.injected = true + -- should only need to do this once per injection routine + end, + post_inject_class = function(self) + table.sort(G.P_CENTER_POOLS[self.set], function(a, b) return a.order < b.order end) + for _,stake in pairs(G.P_CENTER_POOLS.Stake) do + local applied = SMODS.build_stake_chain(stake) + stake.stake_level = 0 + for i,_ in ipairs(G.P_CENTER_POOLS.Stake) do + if applied[i] then stake.stake_level = stake.stake_level+1 end + end + end + G.C.STAKES = {} + for i = 1, #G.P_CENTER_POOLS[self.set] do + G.C.STAKES[i] = G.P_CENTER_POOLS[self.set][i].colour or G.C.WHITE + end + end, + process_loc_text = function(self) + -- empty loc_txt indicates there are existing values that shouldn't be changed or it isn't necessary + if not self.loc_txt or not next(self.loc_txt) then return end + local target = (G.SETTINGS.real_language and self.loc_txt[G.SETTINGS.real_language]) or self.loc_txt[G.SETTINGS.language] or self.loc_txt['default'] or self.loc_txt['en-us'] or + self.loc_txt + local applied_text = "{s:0.8}" .. localize('b_applies_stakes_1') + local any_applied + for _, v in pairs(self.applied_stakes) do + any_applied = true + applied_text = applied_text .. + localize { set = self.set, key = v, type = 'name_text' } .. ', ' + end + applied_text = applied_text:sub(1, -3) + if not any_applied then + applied_text = "{s:0.8}" + else + applied_text = applied_text .. localize('b_applies_stakes_2') + end + local desc_target = copy_table(target) + table.insert(desc_target.text, applied_text) + G.localization.descriptions[self.set][self.key] = desc_target + SMODS.process_loc_text(G.localization.descriptions["Other"], self.key:sub(7) .. "_sticker", self.loc_txt, + 'sticker') + end, + get_obj = function(self, key) return G.P_STAKES[key] end + } + + function SMODS.build_stake_chain(stake, applied) + if not applied then applied = {} end + if not stake or applied[stake.order] then return end + applied[stake.order] = stake.order + if not stake.applied_stakes then + return applied + end + for _, s in pairs(stake.applied_stakes) do + SMODS.build_stake_chain(G.P_STAKES[s], applied) + end + return applied + end + + function SMODS.setup_stake(i) + local applied_stakes = SMODS.build_stake_chain(G.P_CENTER_POOLS.Stake[i]) + for stake, _ in pairs(applied_stakes) do + if G.P_CENTER_POOLS['Stake'][stake].modifiers then + G.P_CENTER_POOLS['Stake'][stake].modifiers() + end + end + end + + --Register vanilla stakes + G.P_STAKES = {} + SMODS.Stake { + name = "White Stake", + key = "white", + unlocked_stake = "red", + unlocked = true, + applied_stakes = {}, + pos = { x = 0, y = 0 }, + sticker_pos = { x = 1, y = 0 }, + colour = G.C.WHITE, + loc_txt = {} + } + SMODS.Stake { + name = "Red Stake", + key = "red", + unlocked_stake = "green", + applied_stakes = { "white" }, + pos = { x = 1, y = 0 }, + sticker_pos = { x = 2, y = 0 }, + modifiers = function() + G.GAME.modifiers.no_blind_reward = G.GAME.modifiers.no_blind_reward or {} + G.GAME.modifiers.no_blind_reward.Small = true + end, + colour = G.C.RED, + loc_txt = {} + } + SMODS.Stake { + name = "Green Stake", + key = "green", + unlocked_stake = "black", + applied_stakes = { "red" }, + pos = { x = 2, y = 0 }, + sticker_pos = { x = 3, y = 0 }, + modifiers = function() + G.GAME.modifiers.scaling = (G.GAME.modifiers.scaling or 1) + 1 + end, + colour = G.C.GREEN, + loc_txt = {} + } + SMODS.Stake { + name = "Black Stake", + key = "black", + unlocked_stake = "blue", + applied_stakes = { "green" }, + pos = { x = 4, y = 0 }, + sticker_pos = { x = 0, y = 1 }, + modifiers = function() + G.GAME.modifiers.enable_eternals_in_shop = true + end, + colour = G.C.BLACK, + loc_txt = {} + } + SMODS.Stake { + name = "Blue Stake", + key = "blue", + unlocked_stake = "purple", + applied_stakes = { "black" }, + pos = { x = 3, y = 0 }, + sticker_pos = { x = 4, y = 0 }, + modifiers = function() + G.GAME.starting_params.discards = G.GAME.starting_params.discards - 1 + end, + colour = G.C.BLUE, + loc_txt = {} + } + SMODS.Stake { + name = "Purple Stake", + key = "purple", + unlocked_stake = "orange", + applied_stakes = { "blue" }, + pos = { x = 0, y = 1 }, + sticker_pos = { x = 1, y = 1 }, + modifiers = function() + G.GAME.modifiers.scaling = (G.GAME.modifiers.scaling or 1) + 1 + end, + colour = G.C.PURPLE, + loc_txt = {} + } + SMODS.Stake { + name = "Orange Stake", + key = "orange", + unlocked_stake = "gold", + applied_stakes = { "purple" }, + pos = { x = 1, y = 1 }, + sticker_pos = { x = 2, y = 1 }, + modifiers = function() + G.GAME.modifiers.enable_perishables_in_shop = true + end, + colour = G.C.ORANGE, + loc_txt = {} + } + SMODS.Stake { + name = "Gold Stake", + key = "gold", + applied_stakes = { "orange" }, + pos = { x = 2, y = 1 }, + sticker_pos = { x = 3, y = 1 }, + modifiers = function() + G.GAME.modifiers.enable_rentals_in_shop = true + end, + colour = G.C.GOLD, + shiny = true, + loc_txt = {} + } + + ------------------------------------------------------------------------------------------------- + ------- API CODE GameObject.Rarity + ------------------------------------------------------------------------------------------------- + + SMODS.Rarities = {} + SMODS.Rarity = SMODS.GameObject:extend { + obj_table = SMODS.Rarities, + obj_buffer = {}, + set = 'Rarity', + required_params = { + 'key', + }, + badge_colour = HEX 'FFFFFF', + default_weight = 0, + inject = function(self) + G.P_JOKER_RARITY_POOLS[self.key] = {} + G.C.RARITY[self.key] = self.badge_colour + end, + process_loc_text = function(self) + SMODS.process_loc_text(G.localization.misc.labels, "k_"..self.key:lower(), self.loc_txt, 'name') + SMODS.process_loc_text(G.localization.misc.dictionary, "k_"..self.key:lower(), self.loc_txt, 'name') + end, + get_rarity_badge = function(self, rarity) + local vanilla_rarity_keys = {localize('k_common'), localize('k_uncommon'), localize('k_rare'), localize('k_legendary')} + if (vanilla_rarity_keys)[rarity] then + return vanilla_rarity_keys[rarity] --compat layer in case function gets the int of the rarity + else + return localize("k_"..rarity:lower()) + end + end, + } + + function SMODS.inject_rarity(object_type, rarity) + if not object_type.rarities then + object_type.rarities = {} + object_type.rarity_pools = {} + end + object_type.rarities[#object_type.rarities+1] = { + key = rarity.key, + weight = type(rarity.pools[object_type.key]) == "table" and rarity.pools[object_type.key].weight or rarity.default_weight + } + for _, vv in ipairs(object_type.rarities) do + local default_rarity_check = {["Common"] = 1, ["Uncommon"] = 2, ["Rare"] = 3, ["Legendary"] = 4} + if default_rarity_check[vv.key] then + object_type.rarity_pools[default_rarity_check[vv.key]] = {} + else + object_type.rarity_pools[vv.key] = {} + end + end + end + + local game_init_game_object_ref = Game.init_game_object + function Game:init_game_object() + local t = game_init_game_object_ref(self) + for _, v in pairs(SMODS.Rarities) do + local key = v.key:lower() .. '_mod' + t[key] = t[key] or 1 + end + return t + end + + SMODS.Rarity{ + key = "Common", + loc_txt = {}, + default_weight = 0.7, + badge_colour = HEX('009dff'), + get_weight = function(self, weight, object_type) + return weight + end, + } + + SMODS.Rarity{ + key = "Uncommon", + loc_txt = {}, + default_weight = 0.25, + badge_colour = HEX("4BC292"), + get_weight = function(self, weight, object_type) + return weight + end, + } + + SMODS.Rarity{ + key = "Rare", + loc_txt = {}, + default_weight = 0.05, + badge_colour = HEX('fe5f55'), + get_weight = function(self, weight, object_type) + return weight + end, + } + + SMODS.Rarity{ + key = "Legendary", + loc_txt = {}, + default_weight = 0, + badge_colour = HEX("b26cbb"), + get_weight = function(self, weight, object_type) + return weight + end, + } + + ------------------------------------------------------------------------------------------------- + ------- API CODE GameObject.ObjectType + ------------------------------------------------------------------------------------------------- + + SMODS.ObjectTypes = {} + SMODS.ObjectType = SMODS.GameObject:extend { + obj_table = SMODS.ObjectTypes, + obj_buffer = {}, + set = 'ObjectType', + required_params = { + 'key', + }, + prefix_config = { key = false }, + inject = function(self) + G.P_CENTER_POOLS[self.key] = G.P_CENTER_POOLS[self.key] or {} + local injected_rarities = {} + if self.rarities then + self.rarity_pools = {} + for _, v in ipairs(self.rarities) do + if not v.weight then v.weight = SMODS.Rarities[v.key].default_weight end + local default_rarity_check = {["Common"] = 1, ["Uncommon"] = 2, ["Rare"] = 3, ["Legendary"] = 4} + if default_rarity_check[v.key] then + self.rarity_pools[default_rarity_check[v.key]] = {} + else + self.rarity_pools[v.key] = {} + end + injected_rarities[v.key] = true + end + end + for _, v in pairs(SMODS.Rarities) do + if v.pools and v.pools[self.key] and not injected_rarities[v.key] then SMODS.inject_rarity(self, v) end + end + end, + inject_card = function(self, center) + if center.set ~= self.key then SMODS.insert_pool(G.P_CENTER_POOLS[self.key], center) end + local default_rarity_check = {["Common"] = 1, ["Uncommon"] = 2, ["Rare"] = 3, ["Legendary"] = 4} + if self.rarities and center.rarity and self.rarity_pools[default_rarity_check[center.rarity] or center.rarity] then + SMODS.insert_pool(self.rarity_pools[default_rarity_check[center.rarity] or center.rarity], center) + end + end, + delete_card = function(self, center) + if center.set ~= self.key then SMODS.remove_pool(G.P_CENTER_POOLS[self.key], center.key) end + local default_rarity_check = {["Common"] = 1, ["Uncommon"] = 2, ["Rare"] = 3, ["Legendary"] = 4} + if self.rarities and center.rarity and self.rarity_pools[default_rarity_check[center.rarity] or center.rarity] then + SMODS.remove_pool(self.rarity_pools[default_rarity_check[center.rarity] or center.rarity], center.key) + end + end, + } + + SMODS.ObjectType{ + key = "Joker", + rarities = { + { key = "Common" }, + { key = "Uncommon" }, + { key = "Rare" }, + }, + } + + ------------------------------------------------------------------------------------------------- + ------- API CODE GameObject.ConsumableType + ------------------------------------------------------------------------------------------------- + + SMODS.ConsumableTypes = {} + SMODS.ConsumableType = SMODS.ObjectType:extend { + ctype_buffer = {}, + set = 'ConsumableType', + required_params = { + 'key', + 'primary_colour', + 'secondary_colour', + }, + prefix_config = { key = false }, + collection_rows = { 6, 6 }, + create_UIBox_your_collection = function(self) + local type_buf = {} + for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do + if not v.no_collection and (not G.ACTIVE_MOD_UI or modsCollectionTally(G.P_CENTER_POOLS[v]).of > 0) then type_buf[#type_buf + 1] = v end + end + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS[self.key], self.collection_rows, { back_func = #type_buf>3 and 'your_collection_consumables' or nil }) + end, + register = function(self) + SMODS.ConsumableType.super.register(self) + if self:check_dependencies() then + SMODS.ConsumableType.ctype_buffer[#SMODS.ConsumableType.ctype_buffer+1] = self.key + end + end, + inject = function(self) + SMODS.ObjectType.inject(self) + SMODS.ConsumableTypes[self.key] = self + G.localization.descriptions[self.key] = G.localization.descriptions[self.key] or {} + G.C.SET[self.key] = self.primary_colour + G.C.SECONDARY_SET[self.key] = self.secondary_colour + G.FUNCS['your_collection_' .. string.lower(self.key) .. 's'] = function(e) + G.SETTINGS.paused = true + G.FUNCS.overlay_menu { + definition = self:create_UIBox_your_collection(), + } + end + end, + process_loc_text = function(self) + SMODS.process_loc_text(G.localization.misc.dictionary, 'k_' .. string.lower(self.key), self.loc_txt, 'name') + SMODS.process_loc_text(G.localization.misc.dictionary, 'b_' .. string.lower(self.key) .. '_cards', + self.loc_txt, 'collection') + SMODS.process_loc_text(G.localization.descriptions.Other, 'undiscovered_' .. string.lower(self.key), + self.loc_txt, 'undiscovered') + end, + } + + SMODS.ConsumableType { + key = 'Tarot', + collection_rows = { 5, 6 }, + primary_colour = G.C.SET.Tarot, + secondary_colour = G.C.SECONDARY_SET.Tarot, + inject_card = function(self, center) + SMODS.ObjectType.inject_card(self, center) + SMODS.insert_pool(G.P_CENTER_POOLS['Tarot_Planet'], center) + end, + delete_card = function(self, center) + SMODS.ObjectType.delete_card(self, center) + SMODS.remove_pool(G.P_CENTER_POOLS['Tarot_Planet'], center.key) + end, + loc_txt = {}, + } + SMODS.ConsumableType { + key = 'Planet', + collection_rows = { 6, 6 }, + primary_colour = G.C.SET.Planet, + secondary_colour = G.C.SECONDARY_SET.Planet, + inject_card = function(self, center) + SMODS.ObjectType.inject_card(self, center) + SMODS.insert_pool(G.P_CENTER_POOLS['Tarot_Planet'], center) + end, + delete_card = function(self, center) + SMODS.ObjectType.delete_card(self, center) + SMODS.remove_pool(G.P_CENTER_POOLS['Tarot_Planet'], center.key) + end, + loc_txt = {}, + } + SMODS.ConsumableType { + key = 'Spectral', + collection_rows = { 4, 5 }, + primary_colour = G.C.SET.Spectral, + secondary_colour = G.C.SECONDARY_SET.Spectral, + loc_txt = {}, + } + + local game_init_game_object_ref = Game.init_game_object + function Game:init_game_object() + local t = game_init_game_object_ref(self) + for _, v in pairs(SMODS.ConsumableTypes) do + local key = v.key:lower() .. '_rate' + t[key] = v.shop_rate or t[key] or 0 + end + return t + end + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Center + ------------------------------------------------------------------------------------------------- + + SMODS.Centers = {} + --- Shared class for center objects. Holds no default values; only register an object directly using this if it doesn't fit any subclass, creating one isn't justified and you know what you're doing. + SMODS.Center = SMODS.GameObject:extend { + obj_table = SMODS.Centers, + obj_buffer = {}, + set = 'Center', -- For logging purposes | Subclasses should change this + get_obj = function(self, key) return G.P_CENTERS[key] end, + register = function(self) + -- 0.9.8 defense + self.name = self.name or self.key + SMODS.Center.super.register(self) + end, + inject = function(self) + G.P_CENTERS[self.key] = self + if not self.omit then SMODS.insert_pool(G.P_CENTER_POOLS[self.set], self) end + for k, v in pairs(SMODS.ObjectTypes) do + -- Should "cards" be formatted as `{[
    ] = true}` or {
    }? + -- Changing "cards" and "pools" wouldn't be hard to do, just depends on preferred format + if ((self.pools and self.pools[k]) or (v.cards and v.cards[self.key])) then + SMODS.ObjectTypes[k]:inject_card(self) + end + end + end, + delete = function(self) + G.P_CENTERS[self.key] = nil + SMODS.remove_pool(G.P_CENTER_POOLS[self.set], self.key) + for k, v in pairs(SMODS.ObjectTypes) do + if ((self.pools and self.pools[k]) or (v.cards and v.cards[self.key])) then + SMODS.ObjectTypes[k]:remove_card(self) + end + end + local j + for i, v in ipairs(self.obj_buffer) do + if v == self.key then j = i end + end + if j then table.remove(self.obj_buffer, j) end + self = nil + return true + end, + create_fake_card = function(self) + return { ability = copy_table(self.config), fake_card = true } + end, + generate_ui = function(self, info_queue, card, desc_nodes, specific_vars, full_UI_table) + if not card then + card = self:create_fake_card() + end + local target = { + type = 'descriptions', + key = self.key, + set = self.set, + nodes = desc_nodes, + vars = + specific_vars or {} + } + local res = {} + if self.loc_vars and type(self.loc_vars) == 'function' then + res = self:loc_vars(info_queue, card) or {} + target.vars = res.vars or target.vars + target.key = res.key or target.key + target.set = res.set or target.set + target.scale = res.scale + target.text_colour = res.text_colour + end + if desc_nodes == full_UI_table.main and not full_UI_table.name then + full_UI_table.name = self.set == 'Enhanced' and 'temp_value' or localize { type = 'name', set = target.set, key = res.name_key or target.key, nodes = full_UI_table.name, vars = res.name_vars or target.vars or {} } + elseif desc_nodes ~= full_UI_table.main and not desc_nodes.name and self.set ~= 'Enhanced' then + desc_nodes.name = localize{type = 'name_text', key = res.name_key or target.key, set = target.set } + end + if specific_vars and specific_vars.debuffed and not res.replace_debuff then + target = { type = 'other', key = 'debuffed_' .. + (specific_vars.playing_card and 'playing_card' or 'default'), nodes = desc_nodes } + end + if res.main_start then + desc_nodes[#desc_nodes + 1] = res.main_start + end + localize(target) + if res.main_end then + desc_nodes[#desc_nodes + 1] = res.main_end + end + desc_nodes.background_colour = res.background_colour + end + } + + ------------------------------------------------------------------------------------------------- + ------- API CODE GameObject.Center.Joker + ------------------------------------------------------------------------------------------------- + + SMODS.Joker = SMODS.Center:extend { + rarity = 1, + unlocked = true, + discovered = false, + blueprint_compat = false, + perishable_compat = true, + eternal_compat = true, + pos = { x = 0, y = 0 }, + cost = 3, + config = {}, + set = 'Joker', + atlas = 'Joker', + class_prefix = 'j', + required_params = { + 'key', + }, + inject = function(self) + -- call the parent function to ensure all pools are set + SMODS.Center.inject(self) + if self.taken_ownership and self.rarity_original == self.rarity then + SMODS.remove_pool(G.P_JOKER_RARITY_POOLS[self.rarity_original], self.key) + SMODS.insert_pool(G.P_JOKER_RARITY_POOLS[self.rarity], self, false) + else + SMODS.insert_pool(G.P_JOKER_RARITY_POOLS[self.rarity], self) + local vanilla_rarities = {["Common"] = 1, ["Uncommon"] = 2, ["Rare"] = 3, ["Legendary"] = 4} + if vanilla_rarities[self.rarity] then + SMODS.insert_pool(G.P_JOKER_RARITY_POOLS[vanilla_rarities[self.rarity]], self) + end + end + end + } + + ------------------------------------------------------------------------------------------------- + ------- API CODE GameObject.Center.Consumable + ------------------------------------------------------------------------------------------------- + + SMODS.Consumable = SMODS.Center:extend { + unlocked = true, + discovered = false, + consumeable = true, + pos = { x = 0, y = 0 }, + atlas = 'Tarot', + legendaries = {}, + cost = 3, + config = {}, + class_prefix = 'c', + required_params = { + 'set', + 'key', + }, + inject = function(self) + SMODS.Center.inject(self) + SMODS.insert_pool(G.P_CENTER_POOLS['Consumeables'], self) + self.type = SMODS.ConsumableTypes[self.set] + if self.hidden then + self.soul_set = self.soul_set or 'Spectral' + self.soul_rate = self.soul_rate or 0.003 + table.insert(self.legendaries, self) + end + if self.type and self.type.inject_card and type(self.type.inject_card) == 'function' then + self.type:inject_card(self) + end + end, + delete = function(self) + if self.type and self.type.delete_card and type(self.type.delete_card) == 'function' then + self.type:delete_card(self) + end + SMODS.remove_pool(G.P_CENTER_POOLS['Consumeables'], self.key) + SMODS.Consumable.super.delete(self) + end, + create_fake_card = function(self) + local ret = SMODS.Center.create_fake_card(self) + ret.ability.consumeable = copy_table(self.config) + return ret + end, + loc_vars = function(self, info_queue) + return {} + end + } + + SMODS.Tarot = SMODS.Consumable:extend { + set = 'Tarot', + } + SMODS.Planet = SMODS.Consumable:extend { + set = 'Planet', + atlas = 'Planet', + } + SMODS.Spectral = SMODS.Consumable:extend { + set = 'Spectral', + atlas = 'Spectral', + cost = 4, + } + + + ------------------------------------------------------------------------------------------------- + ------- API CODE GameObject.Center.Voucher + ------------------------------------------------------------------------------------------------- + + SMODS.Voucher = SMODS.Center:extend { + set = 'Voucher', + cost = 10, + atlas = 'Voucher', + discovered = false, + unlocked = true, + available = true, + pos = { x = 0, y = 0 }, + config = {}, + class_prefix = 'v', + required_params = { + 'key', + } + } + + SMODS.Voucher:take_ownership('observatory', { + calculate = function(self, card, context) + if + context.other_consumeable and + context.other_consumeable.ability.set == 'Planet' and + context.other_consumeable.ability.consumeable.hand_type == context.scoring_name + then + return { + x_mult = card.ability.extra + } + end + end, + }) + + ------------------------------------------------------------------------------------------------- + ------- API CODE GameObject.Center.Back + ------------------------------------------------------------------------------------------------- + + SMODS.Back = SMODS.Center:extend { + set = 'Back', + discovered = false, + unlocked = true, + atlas = 'centers', + pos = { x = 0, y = 0 }, + config = {}, + omit = false, + unlock_condition = {}, + stake = 1, + class_prefix = 'b', + required_params = { + 'key', + }, + register = function(self) + -- game expects a name, so ensure it's set + self.name = self.name or self.key + SMODS.Back.super.register(self) + end + } + + -- set the correct stake level for unlocks when injected (spares me from completely overwriting the unlock checks) + local function stake_mod(stake) + return { + inject = function(self) + self.unlock_condition.stake = SMODS.Stakes[stake].order + SMODS.Back.inject(self) + end + } + end + SMODS.Back:take_ownership('zodiac', stake_mod('stake_red')) + SMODS.Back:take_ownership('painted', stake_mod('stake_green')) + SMODS.Back:take_ownership('anaglyph', stake_mod('stake_black')) + SMODS.Back:take_ownership('plasma', stake_mod('stake_blue')) + SMODS.Back:take_ownership('erratic', stake_mod('stake_orange')) + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Center.Booster + ------------------------------------------------------------------------------------------------- + + SMODS.OPENED_BOOSTER = nil + SMODS.Booster = SMODS.Center:extend { + required_params = { + 'key', + }, + class_prefix = 'p', + set = "Booster", + atlas = "Booster", + pos = {x = 0, y = 0}, + loc_txt = {}, + discovered = false, + weight = 1, + cost = 4, + config = {extra = 3, choose = 1}, + process_loc_text = function(self) + SMODS.process_loc_text(G.localization.descriptions.Other, self.key, self.loc_txt) + SMODS.process_loc_text(G.localization.misc.dictionary, 'k_booster_group_'..self.key, self.loc_txt, 'group_name') + end, + loc_vars = function(self, info_queue, card) + return { vars = {card.ability.choose, card.ability.extra} } + end, + generate_ui = function(self, info_queue, card, desc_nodes, specific_vars, full_UI_table) + if not card then + card = self:create_fake_card() + end + local target = { + type = 'other', + key = self.key, + nodes = desc_nodes, + vars = {} + } + local res = {} + if self.loc_vars and type(self.loc_vars) == 'function' then + res = self:loc_vars(info_queue, card) or {} + target.vars = res.vars or target.vars + target.key = res.key or target.key + target.scale = res.scale + target.text_colour = res.text_colour + end + if desc_nodes == full_UI_table.main and not full_UI_table.name then + full_UI_table.name = localize{type = 'name', set = 'Other', key = res.name_key or target.key, nodes = full_UI_table.name, vars = res.name_vars or target.vars or {}} + elseif desc_nodes ~= full_UI_table.main and not desc_nodes.name then + desc_nodes.name = localize{type = 'name_text', key = res.name_key or target.key, set = 'Other' } + end + localize(target) + desc_nodes.background_colour = res.background_colour + end, + --[[ + create_card = function(self, card) + -- Example + -- return {set = "Joker", area = G.pack_cards, skip_materialize = true, soulable = true, key_append = "buf"} + end, + --]] + update_pack = function(self, dt) + if G.buttons then G.buttons:remove(); G.buttons = nil end + if G.shop then G.shop.alignment.offset.y = G.ROOM.T.y+11 end + + if not G.STATE_COMPLETE then + G.STATE_COMPLETE = true + G.CONTROLLER.interrupt.focus = true + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = function() + if self.particles and type(self.particles) == "function" then self:particles() end + G.booster_pack = UIBox{ + definition = self:create_UIBox(), + config = {align="tmi", offset = {x=0,y=G.ROOM.T.y + 9}, major = G.hand, bond = 'Weak'} + } + G.booster_pack.alignment.offset.y = -2.2 + G.ROOM.jiggle = G.ROOM.jiggle + 3 + self:ease_background_colour() + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = function() + if self.draw_hand == true then G.FUNCS.draw_from_deck_to_hand() end + + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.5, + func = function() + G.CONTROLLER:recall_cardarea_focus('pack_cards') + return true + end})) + return true + end + })) + return true + end + })) + end + end, + ease_background_colour = function(self) + ease_colour(G.C.DYN_UI.MAIN, G.C.FILTER) + ease_background_colour{new_colour = G.C.FILTER, special_colour = G.C.BLACK, contrast = 2} + end, + create_UIBox = function(self) + local _size = SMODS.OPENED_BOOSTER.ability.extra + G.pack_cards = CardArea( + G.ROOM.T.x + 9 + G.hand.T.x, G.hand.T.y, + math.max(1,math.min(_size,5))*G.CARD_W*1.1, + 1.05*G.CARD_H, + {card_limit = _size, type = 'consumeable', highlight_limit = 1}) + + local t = {n=G.UIT.ROOT, config = {align = 'tm', r = 0.15, colour = G.C.CLEAR, padding = 0.15}, nodes={ + {n=G.UIT.R, config={align = "cl", colour = G.C.CLEAR,r=0.15, padding = 0.1, minh = 2, shadow = true}, nodes={ + {n=G.UIT.R, config={align = "cm"}, nodes={ + {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={ + {n=G.UIT.C, config={align = "cm", r=0.2, colour = G.C.CLEAR, shadow = true}, nodes={ + {n=G.UIT.O, config={object = G.pack_cards}},}}}}}}, + {n=G.UIT.R, config={align = "cm"}, nodes={}}, + {n=G.UIT.R, config={align = "tm"}, nodes={ + {n=G.UIT.C,config={align = "tm", padding = 0.05, minw = 2.4}, nodes={}}, + {n=G.UIT.C,config={align = "tm", padding = 0.05}, nodes={ + UIBox_dyn_container({ + {n=G.UIT.C, config={align = "cm", padding = 0.05, minw = 4}, nodes={ + {n=G.UIT.R,config={align = "bm", padding = 0.05}, nodes={ + {n=G.UIT.O, config={object = DynaText({string = localize(self.group_key or ('k_booster_group_'..self.key)), colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.7, maxw = 4, pop_in = 0.5})}}}}, + {n=G.UIT.R,config={align = "bm", padding = 0.05}, nodes={ + {n=G.UIT.O, config={object = DynaText({string = {localize('k_choose')..' '}, colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.5, pop_in = 0.7})}}, + {n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME, ref_value = 'pack_choices'}}, colours = {G.C.WHITE},shadow = true, rotate = true, bump = true, spacing =2, scale = 0.5, pop_in = 0.7})}}}},}} + }),}}, + {n=G.UIT.C,config={align = "tm", padding = 0.05, minw = 2.4}, nodes={ + {n=G.UIT.R,config={minh =0.2}, nodes={}}, + {n=G.UIT.R,config={align = "tm",padding = 0.2, minh = 1.2, minw = 1.8, r=0.15,colour = G.C.GREY, one_press = true, button = 'skip_booster', hover = true,shadow = true, func = 'can_skip_booster'}, nodes = { + {n=G.UIT.T, config={text = localize('b_skip'), scale = 0.5, colour = G.C.WHITE, shadow = true, focus_args = {button = 'y', orientation = 'bm'}, func = 'set_button_pip'}}}}}}}}}}}} + return t + end, + take_ownership_by_kind = function(self, kind, obj, silent) + for k, v in ipairs(G.P_CENTER_POOLS.Booster) do + if v.set == self.set and v.kind and v.kind == kind then + self:take_ownership(v.key, obj, silent) + end + end + end + } + + local pack_loc_vars = function(self, info_queue, card) + local cfg = (card and card.ability) or self.config + return { + vars = { cfg.choose, cfg.extra }, + key = self.key:sub(1, -3), + } + end + SMODS.Booster:take_ownership_by_kind('Arcana', { + group_key = "k_arcana_pack", + draw_hand = true, + update_pack = SMODS.Booster.update_pack, + ease_background_colour = function(self) ease_background_colour_blind(G.STATES.TAROT_PACK) end, + create_UIBox = function(self) return create_UIBox_arcana_pack() end, + particles = function(self) + G.booster_pack_sparkles = Particles(1, 1, 0,0, { + timer = 0.015, + scale = 0.2, + initialize = true, + lifespan = 1, + speed = 1.1, + padding = -1, + attach = G.ROOM_ATTACH, + colours = {G.C.WHITE, lighten(G.C.PURPLE, 0.4), lighten(G.C.PURPLE, 0.2), lighten(G.C.GOLD, 0.2)}, + fill = true + }) + G.booster_pack_sparkles.fade_alpha = 1 + G.booster_pack_sparkles:fade(1, 0) + end, + create_card = function(self, card, i) + local _card + if G.GAME.used_vouchers.v_omen_globe and pseudorandom('omen_globe') > 0.8 then + _card = {set = "Spectral", area = G.pack_cards, skip_materialize = true, soulable = true, key_append = "ar2"} + else + _card = {set = "Tarot", area = G.pack_cards, skip_materialize = true, soulable = true, key_append = "ar1"} + end + return _card + end, + loc_vars = pack_loc_vars, + }) + + SMODS.Booster:take_ownership_by_kind('Celestial', { + group_key = "k_celestial_pack", + update_pack = SMODS.Booster.update_pack, + ease_background_colour = function(self) ease_background_colour_blind(G.STATES.PLANET_PACK) end, + create_UIBox = function(self) return create_UIBox_celestial_pack() end, + particles = function(self) + G.booster_pack_stars = Particles(1, 1, 0,0, { + timer = 0.07, + scale = 0.1, + initialize = true, + lifespan = 15, + speed = 0.1, + padding = -4, + attach = G.ROOM_ATTACH, + colours = {G.C.WHITE, HEX('a7d6e0'), HEX('fddca0')}, + fill = true + }) + G.booster_pack_meteors = Particles(1, 1, 0,0, { + timer = 2, + scale = 0.05, + lifespan = 1.5, + speed = 4, + attach = G.ROOM_ATTACH, + colours = {G.C.WHITE}, + fill = true + }) + end, + create_card = function(self, card, i) + local _card + if G.GAME.used_vouchers.v_telescope and i == 1 then + local _planet, _hand, _tally = nil, nil, 0 + for k, v in ipairs(G.handlist) do + if G.GAME.hands[v].visible and G.GAME.hands[v].played > _tally then + _hand = v + _tally = G.GAME.hands[v].played + end + end + if _hand then + for k, v in pairs(G.P_CENTER_POOLS.Planet) do + if v.config.hand_type == _hand then + _planet = v.key + end + end + end + _card = {set = "Planet", area = G.pack_cards, skip_materialize = true, soulable = true, key = _planet, key_append = "pl1"} + else + _card = {set = "Planet", area = G.pack_cards, skip_materialize = true, soulable = true, key_append = "pl1"} + end + return _card + end, + loc_vars = pack_loc_vars, + }) + + SMODS.Booster:take_ownership_by_kind('Spectral', { + group_key = "k_spectral_pack", + draw_hand = true, + update_pack = SMODS.Booster.update_pack, + ease_background_colour = function(self) ease_background_colour_blind(G.STATES.SPECTRAL_PACK) end, + create_UIBox = function(self) return create_UIBox_spectral_pack() end, + particles = function(self) + G.booster_pack_sparkles = Particles(1, 1, 0,0, { + timer = 0.015, + scale = 0.1, + initialize = true, + lifespan = 3, + speed = 0.2, + padding = -1, + attach = G.ROOM_ATTACH, + colours = {G.C.WHITE, lighten(G.C.GOLD, 0.2)}, + fill = true + }) + G.booster_pack_sparkles.fade_alpha = 1 + G.booster_pack_sparkles:fade(1, 0) + end, + create_card = function(self, card, i) + return {set = "Spectral", area = G.pack_cards, skip_materialize = true, soulable = true, key_append = "spe"} + end, + loc_vars = pack_loc_vars, + }) + + SMODS.Booster:take_ownership_by_kind('Standard', { + group_key = "k_standard_pack", + update_pack = SMODS.Booster.update_pack, + ease_background_colour = function(self) ease_background_colour_blind(G.STATES.STANDARD_PACK) end, + create_UIBox = function(self) return create_UIBox_standard_pack() end, + particles = function(self) + G.booster_pack_sparkles = Particles(1, 1, 0,0, { + timer = 0.015, + scale = 0.3, + initialize = true, + lifespan = 3, + speed = 0.2, + padding = -1, + attach = G.ROOM_ATTACH, + colours = {G.C.BLACK, G.C.RED}, + fill = true + }) + G.booster_pack_sparkles.fade_alpha = 1 + G.booster_pack_sparkles:fade(1, 0) + end, + create_card = function(self, card, i) + local _edition = poll_edition('standard_edition'..G.GAME.round_resets.ante, 2, true) + local _seal = SMODS.poll_seal({mod = 10}) + return {set = (pseudorandom(pseudoseed('stdset'..G.GAME.round_resets.ante)) > 0.6) and "Enhanced" or "Base", edition = _edition, seal = _seal, area = G.pack_cards, skip_materialize = true, soulable = true, key_append = "sta"} + end, + loc_vars = pack_loc_vars, + }) + + SMODS.Booster:take_ownership_by_kind('Buffoon', { + group_key = "k_buffoon_pack", + update_pack = SMODS.Booster.update_pack, + ease_background_colour = function(self) ease_background_colour_blind(G.STATES.BUFFOON_PACK) end, + create_UIBox = function(self) return create_UIBox_buffoon_pack() end, + create_card = function(self, card) + return {set = "Joker", area = G.pack_cards, skip_materialize = true, soulable = true, key_append = "buf"} + end, + loc_vars = pack_loc_vars, + }) + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.UndiscoveredSprite + ------------------------------------------------------------------------------------------------- + + SMODS.UndiscoveredSprites = {} + SMODS.UndiscoveredSprite = SMODS.GameObject:extend { + obj_buffer = {}, + obj_table = SMODS.UndiscoveredSprites, + set = 'Undiscovered Sprite', + -- this is more consistent and allows for extension + process_loc_text = function() end, + inject = function(self) + if self.overlay_pos then + self.overlay_sprite = Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS[self.atlas], self.overlay_pos) + self.no_overlay = true + end + end, + prefix_config = { key = false }, + required_params = { + 'key', + 'atlas', + 'pos', + } + } + SMODS.UndiscoveredSprite { key = 'Joker', atlas = 'Joker', pos = G.j_undiscovered.pos } + SMODS.UndiscoveredSprite { key = 'Edition', atlas = 'Joker', pos = G.j_undiscovered.pos } + SMODS.UndiscoveredSprite { key = 'Tarot', atlas = 'Tarot', pos = G.t_undiscovered.pos } + SMODS.UndiscoveredSprite { key = 'Planet', atlas = 'Tarot', pos = G.p_undiscovered.pos } + SMODS.UndiscoveredSprite { key = 'Spectral', atlas = 'Tarot', pos = G.s_undiscovered.pos } + SMODS.UndiscoveredSprite { key = 'Voucher', atlas = 'Voucher', pos = G.v_undiscovered.pos } + SMODS.UndiscoveredSprite { key = 'Booster', atlas = 'Booster', pos = G.booster_undiscovered.pos } + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Blind + ------------------------------------------------------------------------------------------------- + + SMODS.Blinds = {} + SMODS.Blind = SMODS.GameObject:extend { + obj_table = SMODS.Blinds, + obj_buffer = {}, + class_prefix = 'bl', + debuff = {}, + vars = {}, + dollars = 5, + mult = 2, + atlas = 'blind_chips', + discovered = false, + pos = { x = 0, y = 0 }, + required_params = { + 'key', + }, + set = 'Blind', + get_obj = function(self, key) return G.P_BLINDS[key] end, + register = function(self) + self.name = self.name or self.key + SMODS.Blind.super.register(self) + end, + inject = function(self, i) + -- no pools to query length of, so we assign order manually + if not self.taken_ownership then + self.order = 30 + i + end + G.P_BLINDS[self.key] = self + end + } + SMODS.Blind:take_ownership('eye', { + set_blind = function(self, reset, silent) + if not reset then + G.GAME.blind.hands = {} + for _, v in ipairs(G.handlist) do + G.GAME.blind.hands[v] = false + end + end + end + }) + SMODS.Blind:take_ownership('wheel', { + loc_vars = function(self) + return { vars = { G.GAME.probabilities.normal } } + end, + collection_loc_vars = function(self) + return { vars = { '1' }} + end, + process_loc_text = function(self) + local text = G.localization.descriptions.Blind[self.key].text[1] + if string.sub(text, 1, 3) ~= '#1#' then + G.localization.descriptions.Blind[self.key].text[1] = "#1#"..text + end + SMODS.Blind.process_loc_text(self) + end, + get_loc_debuff_text = function() return G.GAME.blind.loc_debuff_text end, + }) + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Seal + ------------------------------------------------------------------------------------------------- + + SMODS.Seals = {} + SMODS.Seal = SMODS.GameObject:extend { + obj_table = SMODS.Seals, + obj_buffer = {}, + rng_buffer = { 'Purple', 'Gold', 'Blue', 'Red' }, + badge_to_key = {}, + set = 'Seal', + atlas = 'centers', + pos = { x = 0, y = 0 }, + discovered = false, + badge_colour = HEX('FFFFFF'), + required_params = { + 'key', + 'pos', + }, + inject = function(self) + G.P_SEALS[self.key] = self + G.shared_seals[self.key] = Sprite(0, 0, G.CARD_W, G.CARD_H, + G.ASSET_ATLAS[self.atlas] or G.ASSET_ATLAS['centers'], self.pos) + self.badge_to_key[self.key:lower() .. '_seal'] = self.key + SMODS.insert_pool(G.P_CENTER_POOLS[self.set], self) + self.rng_buffer[#self.rng_buffer + 1] = self.key + end, + process_loc_text = function(self) + SMODS.process_loc_text(G.localization.descriptions.Other, self.key:lower() .. '_seal', self.loc_txt) + SMODS.process_loc_text(G.localization.misc.labels, self.key:lower() .. '_seal', self.loc_txt, 'label') + end, + get_obj = function(self, key) return G.P_SEALS[key] end, + generate_ui = function(self, info_queue, card, desc_nodes, specific_vars, full_UI_table) + local target = { + type = 'other', + set = 'Other', + key = self.key:lower()..'_seal', + nodes = desc_nodes, + vars = specific_vars or {}, + } + local res = {} + if self.loc_vars and type(self.loc_vars) == 'function' then + res = self:loc_vars(info_queue, card) or {} + target.vars = res.vars or target.vars + target.key = res.key or target.key + if res.set then + target.type = 'descriptions' + target.set = res.set + end + target.scale = res.scale + target.text_colour = res.text_colour + end + if desc_nodes == full_UI_table.main and not full_UI_table.name then + full_UI_table.name = localize { type = 'name', set = target.set, key = res.name_key or target.key, nodes = full_UI_table.name, vars = res.name_vars or target.vars or {} } + elseif desc_nodes ~= full_UI_table.main and not desc_nodes.name then + desc_nodes.name = localize{type = 'name_text', key = res.name_key or target.key, set = target.set } + end + if res.main_start then + desc_nodes[#desc_nodes + 1] = res.main_start + end + localize(target) + if res.main_end then + desc_nodes[#desc_nodes + 1] = res.main_end + end + desc_nodes.background_colour = res.background_colour + end, + } + for _,v in ipairs { 'Purple', 'Gold', 'Blue', 'Red' } do + SMODS.Seal:take_ownership(v, { badge_colour = G.C[v:upper()], pos = G.shared_seals[v].sprite_pos, generate_ui = SMODS.Seal.generate_ui }) + end + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Suit + ------------------------------------------------------------------------------------------------- + + SMODS.inject_p_card = function(suit, rank) + G.P_CARDS[suit.card_key .. '_' .. rank.card_key] = { + name = rank.key .. ' of ' .. suit.key, + value = rank.key, + suit = suit.key, + pos = { x = rank.pos.x, y = rank.suit_map[suit.key] or suit.pos.y }, + lc_atlas = rank.suit_map[suit.key] and rank.lc_atlas or suit.lc_atlas, + hc_atlas = rank.suit_map[suit.key] and rank.hc_atlas or suit.hc_atlas, + } + end + SMODS.remove_p_card = function(suit, rank) + G.P_CARDS[suit.card_key .. '_' .. rank.card_key] = nil + end + + SMODS.Suits = {} + SMODS.Suit = SMODS.GameObject:extend { + obj_table = SMODS.Suits, + obj_buffer = {}, + used_card_keys = {}, + set = 'Suit', + required_params = { + 'key', + 'card_key', + 'pos', + 'ui_pos', + }, + hc_atlas = 'cards_2', + lc_atlas = 'cards_1', + hc_ui_atlas = 'ui_2', + lc_ui_atlas = 'ui_1', + hc_colour = HEX '000000', + lc_colour = HEX '000000', + max_nominal = { + value = 0, + }, + register = function(self) + -- 0.9.8 compat + self.name = self.name or self.key + if self.used_card_keys[self.card_key] then + sendWarnMessage(('Tried to use duplicate card key %s, aborting registration'):format(self.card_key), self.set) + return + end + self.used_card_keys[self.card_key] = true + self.max_nominal.value = self.max_nominal.value + 0.01 + self.suit_nominal = self.max_nominal.value + local def = 'default_'..self.key + if G.COLLABS.options[self.key] == nil then + G.COLLABS.options[self.key] = {def} + end + SMODS.Suit.super.register(self) + self:create_default_deck_skin() + end, + inject = function(self) + for _, rank in pairs(SMODS.Ranks) do + SMODS.inject_p_card(self, rank) + end + end, + create_default_deck_skin = function(self) + if self.key ~= "Hearts" and self.key ~= "Diamonds" and self.key ~= "Clubs" and self.key ~= "Spades" then + local contrast = self.lc_atlas ~= self.hc_atlas or not rawget(self, 'hc_atlas') + SMODS.DeckSkin{ + key = 'default_'..self.key, + prefix_config = { key = false }, + suit = self.key, + palettes = { + { + key = contrast and 'lc' or 'def', + ranks = {'Ace', 'King', 'Queen', 'Jack', '10', '9', '8', '7', '6', '5', '4', '3', '2'}, + display_ranks = {'King', 'Queen', 'Jack'}, + atlas = self.lc_atlas, + pos_style = 'deck' + }, + contrast and { + key = 'hc', + ranks = {'Ace', 'King', 'Queen', 'Jack', '10', '9', '8', '7', '6', '5', '4', '3', '2'}, + display_ranks = {'King', 'Queen', 'Jack'}, + atlas = self.hc_atlas, + pos_style = 'deck' + } or nil, + } + } + end + end, + delete = function(self) + local i + for j, v in ipairs(self.obj_buffer) do + if v == self.key then i = j end + end + for _, rank in pairs(SMODS.Ranks) do + SMODS.remove_p_card(self, rank) + end + self.used_card_keys[self.card_key] = nil + table.remove(self.obj_buffer, i) + end, + process_loc_text = function(self) + -- empty loc_txt indicates there are existing values that shouldn't be changed + SMODS.process_loc_text(G.localization.misc.suits_plural, self.key, self.loc_txt, 'plural') + SMODS.process_loc_text(G.localization.misc.suits_singular, self.key, self.loc_txt, 'singular') + if not self.keep_base_colours then + if type(self.lc_colour) == 'string' then self.lc_colour = HEX(self.lc_colour) end + if type(self.hc_colour) == 'string' then self.hc_colour = HEX(self.hc_colour) end + G.C.SO_1[self.key] = self.lc_colour + G.C.SO_2[self.key] = self.hc_colour + G.C.SUITS[self.key] = G.C["SO_" .. (G.SETTINGS.colourblind_option and 2 or 1)][self.key] + end + end, + } + SMODS.Suit { + key = 'Diamonds', + card_key = 'D', + pos = { y = 2 }, + ui_pos = { x = 1, y = 1 }, + keep_base_colours = true, + } + SMODS.Suit { + key = 'Clubs', + card_key = 'C', + pos = { y = 1 }, + ui_pos = { x = 2, y = 1 }, + keep_base_colours = true, + } + SMODS.Suit { + key = 'Hearts', + card_key = 'H', + pos = { y = 0 }, + ui_pos = { x = 0, y = 1 }, + keep_base_colours = true, + } + SMODS.Suit { + key = 'Spades', + card_key = 'S', + pos = { y = 3 }, + ui_pos = { x = 3, y = 1 }, + keep_base_colours = true, + } + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Rank + ------------------------------------------------------------------------------------------------- + + SMODS.Ranks = {} + SMODS.Rank = SMODS.GameObject:extend { + obj_table = SMODS.Ranks, + obj_buffer = {}, + used_card_keys = {}, + set = 'Rank', + required_params = { + 'key', + 'pos', + 'nominal', + }, + hc_atlas = 'cards_2', + lc_atlas = 'cards_1', + strength_effect = { + fixed = 1, + random = false, + ignore = false + }, + next = {}, + straight_edge = false, + -- TODO we need a better system for what this is doing. + -- We should allow setting a playing card's atlas and position to any values, + -- and we should also ensure that it's easy to create an atlas with a standard + -- arrangement: x and y set according to rank and suit. + + -- Currently suit_map does the following: + -- suit_map forces a playing card's atlas to be rank.hc_atlas/lc_atlas, + -- and not the atlas defined on the suit of the playing card; + -- additionally pos.y is set according to the corresponding value in the + -- suit_map + suit_map = { + Hearts = 0, + Clubs = 1, + Diamonds = 2, + Spades = 3, + }, + max_id = { + value = 1, + }, + register = function(self) + if self.used_card_keys[self.card_key] then + sendWarnMessage(('Tried to use duplicate card key %s, aborting registration'):format(self.card_key), self.set) + return + end + self.used_card_keys[self.card_key] = true + self.max_id.value = self.max_id.value + 1 + self.id = self.max_id.value + self.shorthand = self.shorthand or self.key + self.sort_nominal = self.nominal + (self.face_nominal or 0) + if self:check_dependencies() and not self.obj_table[self.key] then + self.obj_table[self.key] = self + local j + -- keep buffer sorted in ascending nominal order + for i = 1, #self.obj_buffer - 1 do + if self.obj_table[self.obj_buffer[i]].sort_nominal > self.sort_nominal then + j = i + break + end + end + if j then + table.insert(self.obj_buffer, j, self.key) + else + table.insert(self.obj_buffer, self.key) + end + end + end, + process_loc_text = function(self) + SMODS.process_loc_text(G.localization.misc.ranks, self.key, self.loc_txt, 'name') + end, + inject = function(self) + for _, suit in pairs(SMODS.Suits) do + SMODS.inject_p_card(suit, self) + end + end, + delete = function(self) + local i + for j, v in ipairs(self.obj_buffer) do + if v == self.key then i = j end + end + for _, suit in pairs(SMODS.Suits) do + SMODS.remove_p_card(suit, self) + end + self.used_card_keys[self.card_key] = nil + table.remove(self.obj_buffer, i) + end + } + for _, v in ipairs({ 2, 3, 4, 5, 6, 7, 8, 9 }) do + SMODS.Rank { + key = v .. '', + card_key = v .. '', + pos = { x = v - 2 }, + nominal = v, + next = { (v + 1) .. '' }, + } + end + SMODS.Rank { + key = '10', + card_key = 'T', + pos = { x = 8 }, + nominal = 10, + next = { 'Jack' }, + } + SMODS.Rank { + key = 'Jack', + card_key = 'J', + pos = { x = 9 }, + nominal = 10, + face_nominal = 0.1, + face = true, + shorthand = 'J', + next = { 'Queen' }, + } + SMODS.Rank { + key = 'Queen', + card_key = 'Q', + pos = { x = 10 }, + nominal = 10, + face_nominal = 0.2, + face = true, + shorthand = 'Q', + next = { 'King' }, + } + SMODS.Rank { + key = 'King', + card_key = 'K', + pos = { x = 11 }, + nominal = 10, + face_nominal = 0.3, + face = true, + shorthand = 'K', + next = { 'Ace' }, + } + SMODS.Rank { + key = 'Ace', + card_key = 'A', + pos = { x = 12 }, + nominal = 11, + face_nominal = 0.4, + shorthand = 'A', + straight_edge = true, + next = { '2' }, + } + -- make consumable effects compatible with added suits + -- TODO put this in utils.lua + local function juice_flip(used_tarot) + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.4, + func = function() + play_sound('tarot1') + used_tarot:juice_up(0.3, 0.5) + return true + end + })) + for i = 1, #G.hand.cards do + local percent = 1.15 - (i - 0.999) / (#G.hand.cards - 0.998) * 0.3 + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.15, + func = function() + G.hand.cards[i]:flip(); play_sound('card1', percent); G.hand.cards[i]:juice_up(0.3, 0.3); return true + end + })) + end + end + SMODS.Consumable:take_ownership('strength', { + use = function(self, card, area, copier) + local used_tarot = copier or card + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.4, + func = function() + play_sound('tarot1') + used_tarot:juice_up(0.3, 0.5) + return true + end + })) + for i = 1, #G.hand.highlighted do + local percent = 1.15 - (i - 0.999) / (#G.hand.highlighted - 0.998) * 0.3 + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.15, + func = function() + G.hand.highlighted[i]:flip(); play_sound('card1', percent); G.hand.highlighted[i]:juice_up(0.3, + 0.3); return true + end + })) + end + delay(0.2) + for i = 1, #G.hand.highlighted do + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.1, + func = function() + local _card = G.hand.highlighted[i] + local rank_data = SMODS.Ranks[_card.base.value] + local behavior = rank_data.strength_effect or { fixed = 1, ignore = false, random = false } + local new_rank + if behavior.ignore or not next(rank_data.next) then + return true + elseif behavior.random then + -- TODO doesn't respect in_pool + new_rank = pseudorandom_element(rank_data.next, pseudoseed('strength')) + else + local ii = (behavior.fixed and rank_data.next[behavior.fixed]) and behavior.fixed or 1 + new_rank = rank_data.next[ii] + end + assert(SMODS.change_base(_card, nil, new_rank)) + return true + end + })) + end + for i = 1, #G.hand.highlighted do + local percent = 0.85 + (i - 0.999) / (#G.hand.highlighted - 0.998) * 0.3 + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.15, + func = function() + G.hand.highlighted[i]:flip(); play_sound('tarot2', percent, 0.6); G.hand.highlighted[i] + :juice_up( + 0.3, 0.3); return true + end + })) + end + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.2, + func = function() + G.hand:unhighlight_all(); return true + end + })) + delay(0.5) + end, + }) + SMODS.Consumable:take_ownership('sigil', { + use = function(self, card, area, copier) + local used_tarot = copier or card + juice_flip(used_tarot) + local _suit = pseudorandom_element(SMODS.Suits, pseudoseed('sigil')) + for i = 1, #G.hand.cards do + G.E_MANAGER:add_event(Event({ + func = function() + local _card = G.hand.cards[i] + assert(SMODS.change_base(_card, _suit.key)) + return true + end + })) + end + for i = 1, #G.hand.cards do + local percent = 0.85 + (i - 0.999) / (#G.hand.cards - 0.998) * 0.3 + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.15, + func = function() + G.hand.cards[i]:flip(); play_sound('tarot2', percent, 0.6); G.hand.cards[i]:juice_up(0.3, 0.3); return true + end + })) + end + delay(0.5) + end, + }) + SMODS.Consumable:take_ownership('ouija', { + use = function(self, card, area, copier) + local used_tarot = copier or card + juice_flip(used_tarot) + local _rank = pseudorandom_element(SMODS.Ranks, pseudoseed('ouija')) + for i = 1, #G.hand.cards do + G.E_MANAGER:add_event(Event({ + func = function() + local _card = G.hand.cards[i] + assert(SMODS.change_base(_card, nil, _rank.key)) + return true + end + })) + end + G.hand:change_size(-1) + for i = 1, #G.hand.cards do + local percent = 0.85 + (i - 0.999) / (#G.hand.cards - 0.998) * 0.3 + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.15, + func = function() + G.hand.cards[i]:flip(); play_sound('tarot2', percent, 0.6); G.hand.cards[i]:juice_up(0.3, 0.3); return true + end + })) + end + delay(0.5) + end, + }) + local function random_destroy(used_tarot) + local destroyed_cards = {} + destroyed_cards[#destroyed_cards + 1] = pseudorandom_element(G.hand.cards, pseudoseed('random_destroy')) + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.4, + func = function() + play_sound('tarot1') + used_tarot:juice_up(0.3, 0.5) + return true + end + })) + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.1, + func = function() + for i = #destroyed_cards, 1, -1 do + local card = destroyed_cards[i] + if card.ability.name == 'Glass Card' then + card:shatter() + else + card:start_dissolve(nil, i ~= #destroyed_cards) + end + end + return true + end + })) + return destroyed_cards + end + SMODS.Consumable:take_ownership('grim', { + use = function(self, card, area, copier) + local used_tarot = copier or card + local destroyed_cards = random_destroy(used_tarot) + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.7, + func = function() + local cards = {} + for i = 1, card.ability.extra do + cards[i] = true + -- TODO preserve suit vanilla RNG + local _suit, _rank = + pseudorandom_element(SMODS.Suits, pseudoseed('grim_create')).card_key, 'A' + local cen_pool = {} + for k, v in pairs(G.P_CENTER_POOLS["Enhanced"]) do + if v.key ~= 'm_stone' and not v.overrides_base_rank then + cen_pool[#cen_pool + 1] = v + end + end + create_playing_card({ + front = G.P_CARDS[_suit .. '_' .. _rank], + center = pseudorandom_element(cen_pool, pseudoseed('spe_card')) + }, G.hand, nil, i ~= 1, { G.C.SECONDARY_SET.Spectral }) + end + playing_card_joker_effects(cards) + return true + end + })) + delay(0.3) + SMODS.calculate_context({ remove_playing_cards = true, removed = destroyed_cards }) + end, + }) + SMODS.Consumable:take_ownership('familiar', { + use = function(self, card, area, copier) + local used_tarot = copier or card + local destroyed_cards = random_destroy(used_tarot) + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.7, + func = function() + local cards = {} + for i = 1, card.ability.extra do + cards[i] = true + -- TODO preserve suit vanilla RNG + local faces = {} + for _, v in ipairs(SMODS.Rank.obj_buffer) do + local r = SMODS.Ranks[v] + if r.face then table.insert(faces, r) end + end + local _suit, _rank = + pseudorandom_element(SMODS.Suits, pseudoseed('familiar_create')).card_key, + pseudorandom_element(faces, pseudoseed('familiar_create')).card_key + local cen_pool = {} + for k, v in pairs(G.P_CENTER_POOLS["Enhanced"]) do + if v.key ~= 'm_stone' and not v.overrides_base_rank then + cen_pool[#cen_pool + 1] = v + end + end + create_playing_card({ + front = G.P_CARDS[_suit .. '_' .. _rank], + center = pseudorandom_element(cen_pool, pseudoseed('spe_card')) + }, G.hand, nil, i ~= 1, { G.C.SECONDARY_SET.Spectral }) + end + playing_card_joker_effects(cards) + return true + end + })) + delay(0.3) + SMODS.calculate_context({ remove_playing_cards = true, removed = destroyed_cards }) + end, + }) + SMODS.Consumable:take_ownership('incantation', { + use = function(self, card, area, copier) + local used_tarot = copier or card + local destroyed_cards = random_destroy(used_tarot) + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.7, + func = function() + local cards = {} + for i = 1, card.ability.extra do + cards[i] = true + -- TODO preserve suit vanilla RNG + local numbers = {} + for _, v in ipairs(SMODS.Rank.obj_buffer) do + local r = SMODS.Ranks[v] + if v ~= 'Ace' and not r.face then table.insert(numbers, r) end + end + local _suit, _rank = + pseudorandom_element(SMODS.Suits, pseudoseed('incantation_create')).card_key, + pseudorandom_element(numbers, pseudoseed('incantation_create')).card_key + local cen_pool = {} + for k, v in pairs(G.P_CENTER_POOLS["Enhanced"]) do + if v.key ~= 'm_stone' and not v.overrides_base_rank then + cen_pool[#cen_pool + 1] = v + end + end + create_playing_card({ + front = G.P_CARDS[_suit .. '_' .. _rank], + center = pseudorandom_element(cen_pool, pseudoseed('spe_card')) + }, G.hand, nil, i ~= 1, { G.C.SECONDARY_SET.Spectral }) + end + playing_card_joker_effects(cards) + return true + end + })) + delay(0.3) + SMODS.calculate_context({ remove_playing_cards = true, removed = destroyed_cards }) + + end, + }) + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.DeckSkin + ------------------------------------------------------------------------------------------------- + + SMODS.DeckSkins = {} + SMODS.DeckSkin = SMODS.GameObject:extend { + obj_table = SMODS.DeckSkins, + obj_buffer = {}, + required_params = { + 'key', + 'suit', + }, + pos_style = 'deck', + set = 'DeckSkin', + count_by_suit = {}, + process_loc_text = function(self) + G.localization.misc.collabs[self.suit] = G.localization.misc.collabs[self.suit] or {["1"] = 'Default'} + G.localization.misc.collab_palettes = G.localization.misc.collab_palettes or {} + G.localization.misc.collab_palettes[self.key] = G.localization.misc.collab_palettes[self.key] or {} + if not self.outdated then + for i, p in ipairs(self.palettes) do + if p.loc_txt then + SMODS.process_loc_text(G.localization.misc.collab_palettes[self.key], i..'', p.loc_txt) + elseif G.localization.misc.collab_palettes[self.key][i..''] then + else + G.localization.misc.collab_palettes[self.key][i..''] = ({ lc = true, hc = true, def = true })[p.key] and localize('b_deckskins_'..p.key) or p.key + end + end + else + if self.lc_atlas == self.hc_atlas then + G.localization.misc.collab_palettes[self.key]['1'] = localize('b_deckskins_def') + else + G.localization.misc.collab_palettes[self.key]['1'] = localize('b_deckskins_lc') + G.localization.misc.collab_palettes[self.key]['2'] = localize('b_deckskins_hc') + end + end + + if not self.loc_txt then + G.localization.misc.collabs[self.suit][self.suit_index .. ''] = G.localization.misc.collabs[self.suit][self.suit_index .. ''] or self.key + return + end + + SMODS.process_loc_text(G.localization.misc.collabs[self.suit], self.suit_index..'', self.loc_txt) + end, + register = function(self) + if self.registered then + sendWarnMessage(('Detected duplicate register call on DeckSkin %s'):format(self.key), self.set) + return + end + if self:check_dependencies() then + assert(not self.palettes ~= not (self.ranks and self.lc_atlas), + ('Error loading DeckSkin %s! Please define your palettes or use the old formatting'):format(self.key)) + -- for compat with old format + self.pos_style = self.posStyle or self.pos_style + if self.palettes and not (self.ranks and self.lc_atlas) then + local temp_palettes = self.palettes + self.palettes = {} + -- ensure all palettes are valid + for _,v in ipairs(temp_palettes) do assert(self:add_palette(v)) end + + elseif not self.palettes and (self.ranks and self.lc_atlas) then + sendWarnMessage(('Old DeckSkin formatting detected on DeckSkin %s!'):format(self.key), self.set) + self.outdated = true + + self.hc_atlas = self.hc_atlas or self.lc_atlas + local valid_pos_styles = { ranks = true, collab = true, suit = true, deck = true} + assert(valid_pos_styles[self.pos_style], + ('%s is not a valid pos_style on DeckSkin %s. Supported pos_style values are \'ranks\', \'collab\', \'suit\' and \'deck\'') + :format(self.pos_style, self.key), self.set) + end + + self.count_by_suit[self.suit] = (self.count_by_suit[self.suit] or 0) + 1 + self.suit_index = self.count_by_suit[self.suit] + self.obj_buffer[#self.obj_buffer + 1] = self.key + self.obj_table[self.key] = self + self.registered = true + end + end, + pre_inject_class = function(self) + G.COLLABS.options = {} + end, + inject = function(self) + local def = 'default_'..self.suit + G.COLLABS.options[self.suit] = G.COLLABS.options[self.suit] or {def} + G.COLLABS.colour_palettes = G.COLLABS.colour_palettes or {} + G.COLLABS.colour_palettes[self.key] = {} + if self.palettes then + for _,v in ipairs(self.palettes) do + table.insert(G.COLLABS.colour_palettes[self.key], v.key) + end + else + if self.lc_atlas == self.hc_atlas then + table.insert(G.COLLABS.colour_palettes[self.key], 'lc') + else + table.insert(G.COLLABS.colour_palettes[self.key], 'lc') + table.insert(G.COLLABS.colour_palettes[self.key], 'hc') + end + end + G.COLLABS.options[self.suit] = G.COLLABS.options[self.suit] or {} + local options = G.COLLABS.options[self.suit] + if self.key ~= def then + options[#options + 1] = self.key + end + end, + add_palette = function(self, palette) + if not (self and self.key) then return false, 'Invalid DeckSkin object' end + local required_values = { 'key', 'ranks', 'atlas' } + -- for compat with old format + palette.pos_style = palette.pos_style or palette.posStyle or 'deck' + for _,v in ipairs(required_values) do + if not palette[v] then + return false, ('Missing required value "%s" in Palette "%s" on DeckSkin "%s"'):format(v, palette.key or '(unknown)', self.key) + end + end + table.insert(self.palettes, palette) + self.palette_map = self.palette_map or {} + self.palette_map[palette.key] = palette + return true + end, + get_palette_loc_options = function(key, suit) + if type(key) == "number" then + key = G.COLLABS.options[suit][key] + end + + local conv_palette_loc_options = {} + for k, v in pairs(G.localization.misc.collab_palettes[key]) do + conv_palette_loc_options[tonumber(k)] = v + end + + return conv_palette_loc_options + end, + post_inject_class = function(self) + for _, k in ipairs(SMODS.Suit.obj_buffer) do + local val = G.SETTINGS.CUSTOM_DECK.Collabs[k] or '' + if not self.obj_table[val] then + G.SETTINGS.CUSTOM_DECK.Collabs[k] = 'default_'..k + end + local skin = self.obj_table[G.SETTINGS.CUSTOM_DECK.Collabs[k]] + local pal = G.SETTINGS.colour_palettes[k] + if not skin.outdated and skin.palette_map and not skin.palette_map[pal] then + G.SETTINGS.colour_palettes[k] = skin.palettes[1].key + end + end + + end + } + + for suitName, options in pairs(G.COLLABS.options) do + SMODS.DeckSkin{ + key = options[1]..'_'..suitName, + suit = suitName, + palettes = { + { + key = 'lc', + ranks = {'2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', "King", "Ace",}, + display_ranks = {'King', 'Queen', 'Jack'}, + atlas = 'cards_1', + pos_style = 'deck' + }, + { + key = 'hc', + ranks = {'2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', "King", "Ace",}, + display_ranks = {'King', 'Queen', 'Jack'}, + atlas = 'cards_2', + pos_style = 'deck', + hc_default = true, + }, + } + } + end + for suitName, options in pairs(G.COLLABS.options) do + for i = 2, #options do + SMODS.DeckSkin{ + key = options[i], + suit = suitName, + palettes = { + { + key = 'lc', + ranks = {'King', 'Queen', 'Jack'}, + atlas = options[i] .. '_1', + pos_style = 'collab' + }, + { + key = 'hc', + ranks = {'King', 'Queen', 'Jack'}, + atlas = options[i] .. '_2', + pos_style = 'collab', + hc_default = true, + }, + }, + } + end + end + + if not G.SETTINGS.colour_palettes then + local val = G.SETTINGS.colourblind_option and 'hc' or 'lc' + G.SETTINGS.colour_palettes = { + Spades = val, + Hearts = val, + Clubs = val, + Diamonds = val, + } + G:save_settings() + end + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.PokerHand + ------------------------------------------------------------------------------------------------- + + SMODS.PokerHandParts = {} + SMODS.PokerHandPart = SMODS.GameObject:extend { + obj_table = SMODS.PokerHandParts, + obj_buffer = {}, + required_params = { + 'key', + 'func', + }, + inject_class = function() end, + } + local handlist = G.handlist + G.handlist = {} + SMODS.PokerHands = {} + SMODS.PokerHand = SMODS.GameObject:extend { + obj_table = SMODS.PokerHands, + obj_buffer = G.handlist, + required_params = { + 'key', + 'mult', + 'chips', + 'l_mult', + 'l_chips', + 'example', + 'evaluate' + }, + visible = true, + played = 0, + played_this_round = 0, + level = 1, + set = 'PokerHand', + process_loc_text = function(self) + SMODS.process_loc_text(G.localization.misc.poker_hands, self.key, self.loc_txt, 'name') + SMODS.process_loc_text(G.localization.misc.poker_hand_descriptions, self.key, self.loc_txt, 'description') + end, + register = function(self) + if self:check_dependencies() and not self.obj_table[self.key] then + self.s_mult = self.mult + self.s_chips = self.chips + self.visible = self.visible + self.level = self.level + self.played = self.played + self.played_this_round = self.played_this_round + self.obj_table[self.key] = self + self.obj_buffer[#self.obj_buffer + 1] = self.key + end + end, + inject = function(self) end, + post_inject_class = function(self) + table.sort( + self.obj_buffer, + function(a, b) + local x, y = self.obj_table[a], self.obj_table[b] + local x_above = self.obj_table[x.above_hand or {}] + local y_above = self.obj_table[y.above_hand or {}] + local function eval(h) return h.mult*h.chips + (h.order_offset or 0) end + return (x_above and (1e-6*eval(x) + eval(x_above)) or eval(x)) > (y_above and (1e-6*eval(y) + eval(y_above)) or eval(y)) + end + ) + for i, v in ipairs(self.obj_buffer) do self.obj_table[v].order = i end + end + } + + SMODS.PokerHandPart { + key = '_highest', + func = function(hand) return get_highest(hand) end + } + SMODS.PokerHandPart { + key = '_straight', + func = function(hand) return get_straight(hand) end + } + SMODS.PokerHandPart { + key = '_flush', + func = function(hand) return get_flush(hand) end, + } + -- all sets of 2 or more cards of same rank + SMODS.PokerHandPart { + key = '_all_pairs', + func = function(hand) + local _2 = get_X_same(2, hand, true) + if not next(_2) then return {} end + return {SMODS.merge_lists(_2)} + end + } + for i = 2, 5 do + SMODS.PokerHandPart { + key = '_'..i, + func = function(hand) return get_X_same(i, hand, true) end + } + end + + local hands = G:init_game_object().hands + local eval_functions = { + ['Flush Five'] = function(parts) + if not next(parts._5) or not next(parts._flush) then return {} end + return { SMODS.merge_lists(parts._5, parts._flush) } + end, + ['Flush House'] = function(parts) + if #parts._3 < 1 or #parts._2 < 2 or not next(parts._flush) then return {} end + return { SMODS.merge_lists(parts._all_pairs, parts._flush) } + end, + ['Five of a Kind'] = function(parts) return parts._5 end, + ['Straight Flush'] = function(parts) + if not next(parts._straight) or not next(parts._flush) then return end + return { SMODS.merge_lists(parts._straight, parts._flush) } + end, + ['Four of a Kind'] = function(parts) return parts._4 end, + ['Full House'] = function(parts) + if #parts._3 < 1 or #parts._2 < 2 then return {} end + return parts._all_pairs + end, + ['Flush'] = function(parts) return parts._flush end, + ['Straight'] = function(parts) return parts._straight end, + ['Three of a Kind'] = function(parts) return parts._3 end, + ['Two Pair'] = function(parts) + if #parts._2 < 2 then return {} end + return parts._all_pairs + end, + ['Pair'] = function(parts) return parts._2 end, + ['High Card'] = function(parts) return parts._highest end, + } + for _, v in ipairs(handlist) do + local hand = copy_table(hands[v]) + hand.key = v + hand.evaluate = eval_functions[v] + SMODS.PokerHand(hand) + end + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Challenge + ------------------------------------------------------------------------------------------------- + + SMODS.Challenges = {} + SMODS.Challenge = SMODS.GameObject:extend { + obj_table = SMODS.Challenges, + obj_buffer = {}, + get_obj = function(self, key) + for _, v in ipairs(G.CHALLENGES) do + if v.id == key then return v end + end + end, + set = "Challenge", + required_params = { + 'key', + }, + deck = { type = "Challenge Deck" }, + rules = { custom = {}, modifiers = {} }, + jokers = {}, + consumeables = {}, + vouchers = {}, + restrictions = { banned_cards = {}, banned_tags = {}, banned_other = {} }, + unlocked = function(self) return true end, + class_prefix = 'c', + process_loc_text = function(self) + SMODS.process_loc_text(G.localization.misc.challenge_names, self.key, self.loc_txt, 'name') + end, + register = function(self) + if self.registered then + sendWarnMessage(('Detected duplicate register call on object %s'):format(self.key), self.set) + return + end + self.id = self.key + -- only needs to be called once + SMODS.insert_pool(G.CHALLENGES, self) + SMODS.Challenge.super.register(self) + end, + inject = function(self) end, + } + for k, v in ipairs { + 'omelette_1', + 'city_1', + 'rich_1', + 'knife_1', + 'xray_1', + 'mad_world_1', + 'luxury_1', + 'non_perishable_1', + 'medusa_1', + 'double_nothing_1', + 'typecast_1', + 'inflation_1', + 'bram_poker_1', + 'fragile_1', + 'monolith_1', + 'blast_off_1', + 'five_card_1', + 'golden_needle_1', + 'cruelty_1', + 'jokerless_1', + } do + SMODS.Challenge:take_ownership(v, { + unlocked = function(self) + return G.PROFILES[G.SETTINGS.profile].challenges_unlocked and + (G.PROFILES[G.SETTINGS.profile].challenges_unlocked >= k) + end, + }) + end + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Tag + ------------------------------------------------------------------------------------------------- + + SMODS.Tags = {} + SMODS.Tag = SMODS.GameObject:extend { + obj_table = SMODS.Tags, + obj_buffer = {}, + required_params = { + 'key', + }, + discovered = false, + min_ante = nil, + atlas = 'tags', + class_prefix = 'tag', + set = 'Tag', + pos = { x = 0, y = 0 }, + config = {}, + get_obj = function(self, key) return G.P_TAGS[key] end, + process_loc_text = function(self) + SMODS.process_loc_text(G.localization.descriptions.Tag, self.key, self.loc_txt) + end, + inject = function(self) + G.P_TAGS[self.key] = self + SMODS.insert_pool(G.P_CENTER_POOLS[self.set], self) + end, + generate_ui = function(self, info_queue, card, desc_nodes, specific_vars, full_UI_table) + if not card then + card = { config = copy_table(self.config), fake_tag = true} + end + local target = { + type = 'descriptions', + key = self.key, + set = self.set, + nodes = desc_nodes, + vars = specific_vars + } + local res = {} + if self.loc_vars and type(self.loc_vars) == 'function' then + -- card is actually a `Tag` here + res = self:loc_vars(info_queue, card) or {} + target.vars = res.vars or target.vars + target.key = res.key or target.key + target.set = res.set or target.set + target.scale = res.scale + target.text_colour = res.text_colour + end + if desc_nodes == full_UI_table.main and not full_UI_table.name then + full_UI_table.name = localize { type = 'name', set = target.set, key = res.name_key or target.key, nodes = full_UI_table.name, vars = res.name_vars or res.vars or {} } + elseif desc_nodes ~= full_UI_table.main and not desc_nodes.name then + desc_nodes.name = localize{type = 'name_text', key = res.name_key or target.key, set = target.set } + end + if res.main_start then + desc_nodes[#desc_nodes + 1] = res.main_start + end + localize(target) + if res.main_end then + desc_nodes[#desc_nodes + 1] = res.main_end + end + desc_nodes.background_colour = res.background_colour + end + } + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Sticker + ------------------------------------------------------------------------------------------------- + + SMODS.Stickers = {} + SMODS.Sticker = SMODS.GameObject:extend { + obj_table = SMODS.Stickers, + obj_buffer = {}, + set = 'Sticker', + required_params = { + 'key', + }, + rate = 0.3, + atlas = 'stickers', + pos = { x = 0, y = 0 }, + badge_colour = HEX 'FFFFFF', + default_compat = true, + compat_exceptions = {}, + sets = { Joker = true }, + needs_enable_flag = true, + process_loc_text = function(self) + SMODS.process_loc_text(G.localization.descriptions.Other, self.key, self.loc_txt) + SMODS.process_loc_text(G.localization.misc.labels, self.key, self.loc_txt, 'label') + end, + register = function(self) + if self.registered then + sendWarnMessage(('Detected duplicate register call on object %s'):format(self.key), self.set) + return + end + SMODS.Sticker.super.register(self) + self.order = #self.obj_buffer + end, + inject = function(self) + self.sticker_sprite = Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS[self.atlas], self.pos) + G.shared_stickers[self.key] = self.sticker_sprite + end, + -- relocating sticker checks to here, so if the sticker has different checks than default + -- they can be handled without hooking/injecting into create_card + -- or handling it in apply + -- TODO: rename + should_apply = function(self, card, center, area, bypass_roll) + if + ( not self.sets or self.sets[center.set or {}]) and + ( + center[self.key..'_compat'] or -- explicit marker + (self.default_compat and not self.compat_exceptions[center.key]) or -- default yes with no exception + (not self.default_compat and self.compat_exceptions[center.key]) -- default no with exception + ) and + (not self.needs_enable_flag or G.GAME.modifiers['enable_'..self.key]) + then + self.last_roll = pseudorandom((area == G.pack_cards and 'packssj' or 'shopssj')..self.key..G.GAME.round_resets.ante) + return (bypass_roll ~= nil) and bypass_roll or self.last_roll > (1-self.rate) + end + end, + apply = function(self, card, val) + card.ability[self.key] = val + end + } + + -- Create base game stickers + -- eternal and perishable follow shared checks for sticker application, therefore omitted + SMODS.Sticker{ + key = "eternal", + badge_colour = HEX 'c75985', + prefix_config = {key = false}, + pos = { x = 0, y = 0 }, + hide_badge = true, + order = 1, + should_apply = false, + inject = function(self) + SMODS.Sticker.inject(self) + G.shared_sticker_eternal = self.sticker_sprite + end, + } + + SMODS.Sticker{ + key = "perishable", + badge_colour = HEX '4f5da1', + prefix_config = {key = false}, + pos = { x = 0, y = 2 }, + hide_badge = true, + order = 2, + should_apply = false, + apply = function(self, card, val) + card.ability[self.key] = val + if card.ability[self.key] then card.ability.perish_tally = G.GAME.perishable_rounds end + end, + loc_vars = function(self, info_queue, card) + return {vars = {card.ability.perishable_rounds or 5, card.ability.perish_tally or G.GAME.perishable_rounds}} + end, + inject = function(self) + SMODS.Sticker.inject(self) + G.shared_sticker_perishable = self.sticker_sprite + end, + calculate = function(self, card, context) + if context.end_of_round and not context.repetition and not context.individual then + card:calculate_perishable() + end + end + } + + SMODS.Sticker{ + key = "rental", + badge_colour = HEX 'b18f43', + prefix_config = {key = false}, + pos = { x = 1, y = 2 }, + hide_badge = true, + order = 3, + should_apply = false, + apply = function(self, card, val) + card.ability[self.key] = val + if card.ability[self.key] then card:set_cost() end + end, + loc_vars = function(self, info_queue, card) + return {vars = {G.GAME.rental_rate or 1}} + end, + inject = function(self) + SMODS.Sticker.inject(self) + G.shared_sticker_rental = self.sticker_sprite + end, + calculate = function(self, card, context) + if context.end_of_round and not context.repetition and not context.individual then + card:calculate_rental() + end + end + } + + SMODS.Sticker{ + key = "pinned", + badge_colour = HEX 'fda200', + prefix_config = {key = false}, + pos = { x = 10, y = 10 }, -- Base game has no art, and I haven't made any yet to represent Pinned with + rate = 0, + should_apply = false, + order = 4, + apply = function(self, card, val) + card[self.key] = val + end + } + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Enhancement + ------------------------------------------------------------------------------------------------- + + SMODS.Enhancement = SMODS.Center:extend { + set = 'Enhanced', + class_prefix = 'm', + atlas = 'centers', + pos = { x = 0, y = 0 }, + required_params = { + 'key', + -- table with keys `name` and `text` + }, + -- other fields: + -- replace_base_card + -- if true, don't draw base card sprite and don't give base card's chips + -- no_suit + -- if true, enhanced card has no suit + -- no_rank + -- if true, enhanced card has no rank + -- overrides_base_rank + -- Set to true if your enhancement overrides the base card's rank. + -- This prevents rank generators like Familiar creating cards + -- whose rank is overridden. + -- any_suit + -- if true, enhanced card is any suit + -- always_scores + -- if true, card always scores + -- loc_subtract_extra_chips + -- During tooltip generation, number of chips to subtract from displayed extra chips. + -- Use if enhancement already displays its own chips. + -- Future work: use ranks() and suits() for better control + register = function(self) + self.config = self.config or {} + assert(not (self.no_suit and self.any_suit)) + if self.no_rank then self.overrides_base_rank = true end + SMODS.Enhancement.super.register(self) + end, + -- Produces the description of the whole playing card + -- (including chips from the rank of the card and permanent bonus chips). + -- You will probably want to override this if your enhancement interacts with + -- those parts of the base card. + generate_ui = function(self, info_queue, card, desc_nodes, specific_vars, full_UI_table) + if specific_vars and specific_vars.nominal_chips and not self.replace_base_card then + localize { type = 'other', key = 'card_chips', nodes = desc_nodes, vars = { specific_vars.nominal_chips } } + end + SMODS.Enhancement.super.generate_ui(self, info_queue, card, desc_nodes, specific_vars, full_UI_table) + if specific_vars and specific_vars.bonus_chips then + local remaining_bonus_chips = specific_vars.bonus_chips - (self.config.bonus or 0) + if remaining_bonus_chips > 0 then + localize { type = 'other', key = 'card_extra_chips', nodes = desc_nodes, vars = { specific_vars.bonus_chips - (self.config.bonus or 0) } } + end + end + end, + -- other methods: + -- calculate(self, context, effect) + } + -- Note: `name`, `effect`, and `label` all serve the same purpose as + -- the name of the enhancement. In theory, `effect` serves to allow reusing + -- similar effects (ex. the Sinful jokers). But Balatro just uses them all + -- indiscriminately for enhancements. + -- `name` and `effect` are technically different for Bonus and Mult + -- cards but this never matters in practice; also `label` is a red herring, + -- I can't even find a single use of `label`. + + -- It would be nice if the relevant functions for modding each class of object + -- would be documented. + -- For example, Card:set_ability sets the card's enhancement, which is not immediately + -- obvious. + + -- local stone_card = SMODS.Enhancement:take_ownership('m_stone', { + -- replace_base_card = true, + -- no_suit = true, + -- no_rank = true, + -- always_scores = true, + -- loc_txt = { + -- name = "Stone Card", + -- text = { + -- "{C:chips}+#1#{} Chips", + -- "no rank or suit" + -- } + -- }, + -- loc_vars = function(self) + -- return { + -- vars = { self.config.bonus } + -- } + -- end + -- }) + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Shader + ------------------------------------------------------------------------------------------------- + + SMODS.Shaders = {} + SMODS.Shader = SMODS.GameObject:extend { + obj_table = SMODS.Shaders, + obj_buffer = {}, + required_params = { + 'key', + 'path', + }, + set = 'Shader', + send_vars = nil, -- function (sprite) - get custom externs to send to shader. + inject = function(self) + self.full_path = (self.mod and self.mod.path or SMODS.path) .. + 'assets/shaders/' .. self.path + local file = NFS.read(self.full_path) + love.filesystem.write(self.key .. "-temp.fs", file) + G.SHADERS[self.key] = love.graphics.newShader(self.key .. "-temp.fs") + love.filesystem.remove(self.key .. "-temp.fs") + -- G.SHADERS[self.key] = love.graphics.newShader(self.full_path) + end, + process_loc_text = function() end + } + + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Edition + ------------------------------------------------------------------------------------------------- + + SMODS.Edition = SMODS.Center:extend { + set = 'Edition', + -- atlas only matters for displaying editions in the collection + atlas = 'Joker', + pos = { x = 0, y = 0 }, + class_prefix = 'e', + discovered = false, + unlocked = true, + apply_to_float = false, + in_shop = false, + weight = 0, + badge_colour = G.C.DARK_EDITION, + -- default sound is foil sound + sound = { sound = "foil1", per = 1.2, vol = 0.4 }, + required_params = { + 'key', + 'shader' -- can be set to `false` for shaderless edition + }, + -- optional fields: + extra_cost = nil, + + -- TODO badge colours. need to check how Steamodded already does badge colors + -- other methods: + calculate = nil, -- function (self) + on_apply = nil, -- function (card) - modify card when edition is applied + on_remove = nil, -- function (card) - modify card when edition is removed + on_load = nil, -- function (card) - modify card when it is loaded from the save file + register = function(self) + self.config = self.config or {} + SMODS.Edition.super.register(self) + end, + process_loc_text = function(self) + SMODS.process_loc_text(G.localization.misc.labels, self.key:sub(3), self.loc_txt, 'label') + SMODS.Edition.super.process_loc_text(self) + end, + -- apply_modifier = true when G.GAME.edition_rate is to be applied + get_weight = function(self, apply_modifier) + return self.weight + end + } + + -- TODO also, this should probably be a utility method in core + -- card_area = pass the card area + -- edition = boolean value + function SMODS.Edition:get_edition_cards(card_area, edition) + local cards = {} + for _, v in ipairs(card_area.cards) do + if (not v.edition and edition) or (v.edition and not edition) then + table.insert(cards, v) + end + end + return cards + end + + SMODS.Edition:take_ownership('foil', { + shader = 'foil', + config = setmetatable({ chips = 50 }, { + __index = function(t, k) + if k == 'extra' then return t.chips end + return rawget(t, k) + end, + __newindex = function(t, k, v) + if k == 'extra' then + t.chips = v; return + end + rawset(t, k, v) + end, + }), + sound = { sound = "foil1", per = 1.2, vol = 0.4 }, + weight = 20, + extra_cost = 2, + get_weight = function(self) + return G.GAME.edition_rate * self.weight + end, + loc_vars = function(self) + return { vars = { self.config.chips } } + end, + calculate = function(self, card, context) + if context.pre_joker or (context.main_scoring and context.cardarea == G.play) then + return { + chips = card.edition.chips + } + end + end + }) + SMODS.Edition:take_ownership('holo', { + shader = 'holo', + config = setmetatable({ mult = 10 }, { + __index = function(t, k) + if k == 'extra' then return t.mult end + return rawget(t, k) + end, + __newindex = function(t, k, v) + if k == 'extra' then + t.mult = v; return + end + rawset(t, k, v) + end, + }), + sound = { sound = "holo1", per = 1.2 * 1.58, vol = 0.4 }, + weight = 14, + extra_cost = 3, + get_weight = function(self) + return G.GAME.edition_rate * self.weight + end, + loc_vars = function(self) + return { vars = { self.config.mult } } + end, + calculate = function(self, card, context) + if context.pre_joker or (context.main_scoring and context.cardarea == G.play) then + return { + mult = card.edition.mult + } + end + end + }) + SMODS.Edition:take_ownership('polychrome', { + shader = 'polychrome', + config = setmetatable({ x_mult = 1.5 }, { + __index = function(t, k) + if k == 'extra' then return t.x_mult end + return rawget(t, k) + end, + __newindex = function(t, k, v) + if k == 'extra' then + t.x_mult = v; return + end + rawset(t, k, v) + end, + }), + sound = { sound = "polychrome1", per = 1.2, vol = 0.7 }, + weight = 3, + extra_cost = 5, + get_weight = function(self) + return (G.GAME.edition_rate - 1) * G.P_CENTERS["e_negative"].weight + G.GAME.edition_rate * self.weight + end, + loc_vars = function(self) + return { vars = { self.config.x_mult } } + end, + calculate = function(self, card, context) + if context.post_joker or (context.main_scoring and context.cardarea == G.play) then + return { + x_mult = card.edition.x_mult + } + end + end + }) + SMODS.Edition:take_ownership('negative', { + shader = 'negative', + config = setmetatable({ card_limit = 1 }, { + __index = function(t, k) + if k == 'extra' then return t.card_limit end + return rawget(t, k) + end, + __newindex = function(t, k, v) + if k == 'extra' then + t.card_limit = v; return + end + rawset(t, k, v) + end, + }), + sound = { sound = "negative", per = 1.5, vol = 0.4 }, + weight = 3, + extra_cost = 5, + get_weight = function(self) + return self.weight + end, + loc_vars = function(self) + return { vars = { self.config.card_limit } } + end, + }) + + ------------------------------------------------------------------------------------------------- + ------- API CODE GameObject.Keybind + ------------------------------------------------------------------------------------------------- + SMODS.Keybinds = {} + SMODS.Keybind = SMODS.GameObject:extend { + obj_table = SMODS.Keybinds, + obj_buffer = {}, + + -- key_pressed = 'x', + held_keys = {}, -- other key(s) that need to be held + -- action = function(controller) + -- print("Keybind pressed") + -- end, + + event = 'pressed', + held_duration = 1, + + required_params = { + 'key_pressed', + 'action', + }, + set = 'Keybind', + class_prefix = 'keybind', + register = function(self) + self.key = self.key or (#self.obj_buffer..'') + SMODS.Keybind.super.register(self) + end, + inject = function(_) end + } + + SMODS.Keybind { + key_pressed = 'm', + event = 'held', + held_duration = 1.1, + action = function(self) + SMODS.save_all_config() + SMODS.restart_game() + end + } + + ------------------------------------------------------------------------------------------------- + ------- API CODE GameObject.Achievements + ------------------------------------------------------------------------------------------------- + + SMODS.Achievements = {} + SMODS.Achievement = SMODS.GameObject:extend{ + obj_table = SMODS.Achievements, + obj_buffer = {}, + required_params = { + 'key', + 'unlock_condition', + }, + set = 'Achievement', + class_prefix = "ach", + atlas = "achievements", + pos = {x=1, y=0}, + hidden_pos = {x=0, y=0}, + bypass_all_unlocked = false, + hidden_name = true, + steamid = "STEAMODDED", + pre_inject_class = fetch_achievements, + inject = function(self) + G.ACHIEVEMENTS[self.key] = self + if self.reset_on_startup then + if G.SETTINGS.ACHIEVEMENTS_EARNED[self.key] then G.SETTINGS.ACHIEVEMENTS_EARNED[self.key] = nil end + if G.ACHIEVEMENTS[self.key].earned then G.ACHIEVEMENTS[self.key].earned = nil end + end + end, + process_loc_text = function(self) + SMODS.process_loc_text(G.localization.misc.achievement_names, self.key, self.loc_txt, "name") + SMODS.process_loc_text(G.localization.misc.achievement_descriptions, self.key, self.loc_txt, "description") + end, + } + + ------------------------------------------------------------------------------------------------- + ----- INTERNAL API CODE GameObject._Loc_Post + ------------------------------------------------------------------------------------------------- + + SMODS._Loc_Post = SMODS.GameObject:extend { + obj_table = {}, + obj_buffer = {}, + set = '[INTERNAL]', + silent = true, + register = function() error('INTERNAL CLASS, DO NOT CALL') end, + pre_inject_class = function() + for _, mod in ipairs(SMODS.mod_list) do + if mod.can_load then + SMODS.handle_loc_file(mod.path) + end + end + end + } +end diff --git a/smods-main/src/index.lua b/smods-main/src/index.lua new file mode 100644 index 0000000..699ac1c --- /dev/null +++ b/smods-main/src/index.lua @@ -0,0 +1,32 @@ +SMODS.fetch_index = function() + SMODS.index = {} + local https = require"https" + local status, contents = https.request("https://github.com/Aurelius7309/Steamodded.index/archive/refs/heads/main.zip") + if status ~= 200 then return false end + love.filesystem.write('index.zip', contents) + if not love.filesystem.mount('index.zip', 'index') then return false end + local path = 'index/Steamodded.index-main/mods/' + for _, filename in ipairs(love.filesystem.getDirectoryItems(path)) do + local key, ext = filename:sub(1, -6), filename:sub(-5) + if ext:lower() == '.json' then + local success, data = pcall(function() return JSON.decode(love.filesystem.read(path..filename)) end) + if success and data.id == key then SMODS.index[key] = data end + end + end + love.filesystem.unmount('index.zip') + return true +end + +SMODS.update_mod_files = function(id) + local mod = SMODS.Mods[id] + if not mod then return false end + local use_git = os.execute('git -v') == 0 + if false and use_git and os.execute(('cd %s & git pull'):format(mod.path)) == 0 then + return true + end + local https = require"https" + local url = mod.github or (SMODS.index[id] or {}).github + local status, contents = https.request(url) -- TODO account for branches + local hash = contents:match('"currentOid":"([^"]*)"') + sendWarnMessage(hash, "Index") +end diff --git a/smods-main/src/loader.lua b/smods-main/src/loader.lua new file mode 100644 index 0000000..fb429d1 --- /dev/null +++ b/smods-main/src/loader.lua @@ -0,0 +1,728 @@ +--- STEAMODDED CORE +--- MODULE MODLOADER + +function loadMods(modsDirectory) + SMODS.Mods = {} + SMODS.Mods[SMODS.id] = SMODS + SMODS.Mods['Lovely'] = { + id = 'Lovely', + can_load = true, + version = require'lovely'.version, + meta_mod = true, + } + SMODS.Mods['Balatro'] = { + id = 'Balatro', + can_load = true, + version = G.VERSION, + meta_mod = true, + } + SMODS.mod_priorities = {} + SMODS.mod_list = {} + SMODS.provided_mods = {} + -- for legacy header support + local header_components = { + name = { pattern = '%-%-%- MOD_NAME: ([^\n]+)\n', required = true }, + id = { pattern = '%-%-%- MOD_ID: ([^ \n]+)\n', required = true }, + author = { pattern = '%-%-%- MOD_AUTHOR: %[(.-)%]\n', required = true, parse_array = true }, + description = { pattern = '%-%-%- MOD_DESCRIPTION: (.-)\n', required = true }, + priority = { pattern = '%-%-%- PRIORITY: (%-?%d+)\n', handle = function(x) return x and x + 0 or 0 end }, + badge_colour = { pattern = '%-%-%- BADGE_COLO[U]?R: (%x-)\n', handle = function(x) return HEX(x or '666666FF') end }, + badge_text_colour = { pattern = '%-%-%- BADGE_TEXT_COLO[U]?R: (%x-)\n', handle = function(x) return HEX(x or 'FFFFFF') end }, + display_name = { pattern = '%-%-%- DISPLAY_NAME: (.-)\n' }, + dependencies = { + pattern = { + '%-%-%- DEPENDENCIES: %[(.-)%]\n', + '%-%-%- DEPENDS: %[(.-)%]\n', + '%-%-%- DEPS: %[(.-)%]\n', + }, + parse_array = true, + handle = function(x) + local t = {} + for _, v in ipairs(x) do + table.insert(t, { + id = v:match '(.-)[<>]' or v, + min_version = v:match '>=([^<>]+)', + max_version = v:match '<=([^<>]+)', + }) + end + return t + end, + }, + conflicts = { + pattern = '%-%-%- CONFLICTS: %[(.-)%]\n', + parse_array = true, + handle = function(x) + local t = {} + for _, v in ipairs(x) do + table.insert(t, { + id = v:match '(.-)[<>]', + min_version = v:match '>=([^<>]+)', + max_version = v:match '<=([^<>]+)', + }) + if t.min_version and not V(t[#t].min_version):is_valid() then t[#t].min_version = nil end + if t.max_version and not V(t[#t].max_version):is_valid() then t[#t].max_version = nil end + end + + return t + end + }, + prefix = { pattern = '%-%-%- PREFIX: (.-)\n' }, + version = { pattern = '%-%-%- VERSION: (.-)\n', handle = function(x) return x and V(x):is_valid() and x or '0.0.0' end }, + outdated = { pattern = { 'SMODS%.INIT', 'SMODS%.Deck[:.]new' } }, + dump_loc = { pattern = { '%-%-%- DUMP_LOCALIZATION\n'}} + } + + + local json_spec = { + id = { type = 'string', required = true }, + author = { type = 'table', required = true, check = function(mod, t) + for k, v in pairs(t) do + if type(k) ~= 'number' or type(v) ~= 'string' then t[k] = nil end + end + return t + end }, + name = { type = 'string', required = true }, + display_name = { type = 'string', check = function(mod, s) mod.display_name = s or mod.name end }, + description = { type = 'string', required = true }, + priority = { type = 'number', default = 0 }, + badge_colour = { type = 'string', check = function(mod, s) local success, hex = pcall(HEX, s); mod.badge_colour = success and hex or HEX('666665FF') end }, + badge_text_colour = { type = 'string', check = function(mod, s) local success, hex = pcall(HEX, s); mod.badge_text_colour = success and hex or HEX('FFFFFFFF') end}, + prefix = { type = 'string', required = true }, + version = { type = 'string', check = function(mod, x) return x and V(x):is_valid() and x or '0.0.0' end }, + dump_loc = { type = 'boolean' }, + dependencies = { type = 'table', check = function(mod, t) + local ops = { + ['<<'] = function(a,b) return a>'] = function(a,b) return a>b end, + ['<='] = function(a,b) return a<=b end, + ['>='] = function(a,b) return a>=b end, + ['=='] = function(a,b) return a==b end + } + for i,v in ipairs(t or {}) do + local parts = {} + parts.str = v + for part in v:gmatch('([^|]+)') do + local x = {} + x.id = part:match '^([^(%s]+)' + local j = 1 + for version_string in string.gmatch(part, '%((.-)%)') do + local operator, version = string.match(version_string, '^(..)(.*)$') + local op = ops[operator] + local ver = V(version) + -- if operator == '<<' and not ver.rev then + -- ver.beta = -1 + -- ver.rev = '~' + -- end + if op and ver:is_valid(true) then + x[j] = { op = op, ver = ver } + j = j+1 + end + end + parts[#parts+1] = x + end + t[i] = parts + end + end}, + conflicts = { type = 'table', check = function(mod, t) + local ops = { + ['<<'] = function(a,b) return a>'] = function(a,b) return a>b end, + ['<='] = function(a,b) return a<=b end, + ['>='] = function(a,b) return a>=b end, + ['=='] = function(a,b) return a==b end + } + for i,v in ipairs(t or {}) do + v = v:gsub('%s', '') + local x = {} + x.str = v + v = v:gsub('%s', '') + x.id = v:match '^([^(%s]+)' + local j = 1 + for version_string in string.gmatch(v, '%((.-)%)') do + local operator, version = string.match(version_string, '^(..)(.*)$') + local op = ops[operator] + local ver = V(version) + -- if operator == '<<' and not ver.rev then + -- ver.beta = -1 + -- ver.rev = '~' + -- end + if op and ver:is_valid(true) then + x[j] = { op = op, ver = ver, str = '('..version_string..')' } + j = j+1 + end + end + t[i] = x + end + end}, + main_file = { type = 'string', required = true }, + config_file = {type = 'string', default = 'config.lua' }, + __ = { check = function(mod) + if SMODS.Mods[mod.id] then error('dupe') end + end}, + provides = { type = 'table', check = function(mod, t) + t = t or {} + for _,v in pairs(t) do + v = v:gsub('%s', '') + local id = v:match '^([^(%s]+)' + local ver = v:match '%((.-)%)' + ver = (ver and V(ver):is_valid()) and ver or mod.version + if id and ver then + SMODS.provided_mods[id] = SMODS.provided_mods[id] or {} + table.insert(SMODS.provided_mods[id], { version = ver, mod = mod }) + end + end + end} + + } + + + local used_prefixes = {} + local lovely_directories = {} + + -- Function to process each directory (including subdirectories) with depth tracking + local function processDirectory(directory, depth) + if depth > 3 or directory..'/' == SMODS.path then + return + end + + local isDirLovely = false + + for _, filename in ipairs(NFS.getDirectoryItems(directory)) do + local file_path = directory .. "/" .. filename + + -- Check if the current file is a directory + local file_type = NFS.getInfo(file_path).type + if file_type == 'directory' or file_type == 'symlink' then + -- Lovely patches + if depth == 2 and filename == "lovely" and not isDirLovely then + isDirLovely = true + table.insert(lovely_directories, directory .. "/") + end + -- If it's a directory and depth is within limit, recursively process it + if depth < 2 or (filename:lower() ~= 'localization' and filename:lower() ~= 'assets') then + processDirectory(file_path, depth + 1) + end + elseif depth == 2 and filename == "lovely.toml" and not isDirLovely then + isDirLovely = true + table.insert(lovely_directories, directory .. "/") + elseif filename:lower():match('%.json') and depth > 1 then + local json_str = NFS.read(file_path) + local parsed, mod = pcall(JSON.decode, json_str) + local valid = true + local err + if not parsed then + valid = false + err = mod + else + mod.json = true + mod.path = directory .. '/' + mod.optional_dependencies = {} + local success, e = pcall(function() + -- remove invalid fields and check required ones first + for k, v in pairs(json_spec) do + if v.type and type(mod[k]) ~= v.type then mod[k] = nil end + if v.required and mod[k] == nil then error(k) end + end + -- perform additional checks and fill in defaults + for k, v in pairs(json_spec) do + if v.default then mod[k] = mod[k] or v.default end + if v.check then v.check(mod, mod[k]) end + end + end) + if not success then + valid = false + err = e + end + end + if not valid then + sendErrorMessage(('Found invalid metadata JSON file at %s, ignoring: %s'):format(file_path, err), 'Loader') + else + sendInfoMessage('Valid JSON file found') + if NFS.getInfo(directory..'/.lovelyignore') then + mod.disabled = true + end + if mod.prefix and used_prefixes[mod.prefix] then + mod.can_load = false + mod.load_issues = { + prefix_conflict = used_prefixes[mod.prefix], + dependencies = {}, + conflicts = {}, + } + sendWarnMessage(('Duplicate Mod prefix %s used by %s, %s'):format(mod.prefix, mod.id, used_prefixes[mod.prefix]), 'Loader') + end + if not NFS.getInfo(mod.path..mod.main_file) then + mod.can_load = false + mod.load_issues = { + main_file_not_found = true, + dependencies = {}, + conflicts = {}, + } + sendWarnMessage(('Unable to load Mod %s: cannot find main file'):format(mod.id), 'Loader') + end + if mod.dump_loc then + SMODS.dump_loc = { + path = mod.path, + } + end + SMODS.Mods[mod.id] = mod + SMODS.mod_priorities[mod.priority] = SMODS.mod_priorities[mod.priority] or {} + table.insert(SMODS.mod_priorities[mod.priority], mod) + end + elseif filename:lower():match("%.lua$") then -- Check for legacy headers + if depth == 1 then + sendWarnMessage(('Found lone Lua file %s in Mods directory :: Please place the files for each mod in its own subdirectory.'):format(filename), 'Loader') + end + local file_content = NFS.read(file_path) + + -- Convert CRLF in LF + file_content = file_content:gsub("\r\n", "\n") + + -- Check the header lines using string.match + local headerLine = file_content:match("^(.-)\n") + if headerLine == "--- STEAMODDED HEADER" then + sendTraceMessage('Processing Mod file (Legacy header): ' .. filename, "Loader") + local mod = {} + local sane = true + for k, v in pairs(header_components) do + local component = nil + if type(v.pattern) == "table" then + for _, pattern in ipairs(v.pattern) do + component = file_content:match(pattern) or component + if component then break end + end + else + component = file_content:match(v.pattern) + end + if v.required and not component then + sane = false + sendWarnMessage(string.format('Mod file %s is missing required header component: %s', + filename, k), 'Loader') + break + end + if v.parse_array then + local list = {} + component = component or '' + for val in string.gmatch(component, "([^,]+)") do + table.insert(list, val:match("^%s*(.-)%s*$")) -- Trim spaces + end + component = list + end + if v.handle and type(v.handle) == 'function' then + component = v.handle(component) + end + mod[k] = component + end + if NFS.getInfo(directory..'/.lovelyignore') then + mod.disabled = true + end + if SMODS.Mods[mod.id] then + sane = false + sendWarnMessage("Duplicate Mod ID: " .. mod.id, 'Loader') + end + + if mod.outdated then + mod.prefix_config = { key = { mod = false }, atlas = false } + else + mod.prefix = mod.prefix or (mod.id or ''):lower():sub(1, 4) + end + if mod.prefix and used_prefixes[mod.prefix] then + mod.can_load = false + mod.load_issues = { + prefix_conflict = used_prefixes[mod.prefix], + dependencies = {}, + conflicts = {}, + } + sendWarnMessage(('Duplicate Mod prefix %s used by %s, %s'):format(mod.prefix, mod.id, used_prefixes[mod.prefix]), 'Loader') + end + + if sane then + sendTraceMessage('Saving Mod Info: ' .. mod.id, 'Loader') + mod.path = directory .. '/' + mod.main_file = filename + mod.display_name = mod.display_name or mod.name + if mod.prefix then + used_prefixes[mod.prefix] = mod.id + end + mod.optional_dependencies = {} + if mod.dump_loc then + SMODS.dump_loc = { + path = mod.path, + } + end + SMODS.Mods[mod.id] = mod + SMODS.mod_priorities[mod.priority] = SMODS.mod_priorities[mod.priority] or {} + table.insert(SMODS.mod_priorities[mod.priority], mod) + end + end + end + end + end + + + boot_print_stage('Processing Mod Files') + -- Start processing with the initial directory at depth 1 + processDirectory(modsDirectory, 1) + for _, path in ipairs(lovely_directories) do + local hasSMOD = false + for _, mod in pairs(SMODS.Mods) do + if mod.path == path then + mod.lovely = true + hasSMOD = true + end + end + if not hasSMOD then + local name = string.match(path, "[/\\]([^/\\]+)[/\\]?$") + local disabled = not not NFS.getInfo(path .. '/.lovelyignore') + local mod = { + name = name, + id = "lovely-compat-" .. name, + author = {"???"}, + description = "A lovely mod.", + prefix_config = { key = { mod = false }, atlas = false }, + priority = 0, + badge_colour = HEX("666666FF"), + badge_text_colour = HEX('FFFFFF'), + path = path, + main_file = "", + display_name = name, + dependencies = {}, + optional_dependencies = {}, + conflicts = {}, + version = "0.0.0", + can_load = not disabled, + lovely = true, + lovely_only = true, + meta_mod = true, + disabled = disabled, + load_issues = { + dependencies = {}, + conflicts = {}, + disabled = disabled + } + + } + SMODS.mod_priorities[mod.priority] = SMODS.mod_priorities[mod.priority] or {} + table.insert(SMODS.mod_priorities[mod.priority], mod) + SMODS.Mods[mod.id] = mod + end + end + + -- sort by priority + local keyset = {} + for k, _ in pairs(SMODS.mod_priorities) do + keyset[#keyset + 1] = k + end + table.sort(keyset) + + local function check_dependencies(mod, seen) + if not (mod.can_load == nil) then return mod.can_load end + seen = seen or {} + local can_load = true + if seen[mod.id] then return true end + seen[mod.id] = true + local load_issues = { + dependencies = {}, + conflicts = {}, + } + if not mod.json then + for _, v in ipairs(mod.conflicts or {}) do + -- block load even if the conflict is also blocked + if + SMODS.Mods[v.id] and + (not v.max_version or V(SMODS.Mods[v.id].version) <= V(v.max_version)) and + (not v.min_version or V(SMODS.Mods[v.id].version) >= V(v.min_version)) + then + can_load = false + table.insert(load_issues.conflicts, v.id..(v.max_version and '<='..v.max_version or '')..(v.min_version and '>='..v.min_version or '')) + end + end + for _, v in ipairs(mod.dependencies or {}) do + -- recursively check dependencies of dependencies to make sure they are actually fulfilled + if + not SMODS.Mods[v.id] or + not check_dependencies(SMODS.Mods[v.id], seen) or + (v.max_version and V(SMODS.Mods[v.id].version) > V(v.max_version)) or + (v.min_version and V(SMODS.Mods[v.id].version) < V(v.min_version)) + then + can_load = false + table.insert(load_issues.dependencies, + v.id .. (v.min_version and '>=' .. v.min_version or '') .. (v.max_version and '<=' .. v.max_version or '')) + if v.id == 'Steamodded' then + load_issues.version_mismatch = ''..(v.min_version and '>='..v.min_version or '')..(v.max_version and '<='..v.max_version or '') + end + end + end + else + for _, x in ipairs(mod.dependencies or {}) do + local fulfilled + for _, y in ipairs(x) do + if fulfilled then break end + local id = y.id + if SMODS.Mods[id] and check_dependencies(SMODS.Mods[id], seen) then + fulfilled = true + local dep_ver = V(SMODS.Mods[id].version) + for _, v in ipairs(y) do + if not v.op(dep_ver, v.ver) then + fulfilled = false + end + end + if fulfilled then y.fulfilled = true end + else + for _, provided in ipairs(SMODS.provided_mods[id] or {}) do + if provided.mod ~= mod and check_dependencies(provided.mod, seen) then + fulfilled = true + local dep_ver = V(provided.version) + for _, v in ipairs(y) do + if not v.op(dep_ver, v.ver) then + fulfilled = false + end + end + if fulfilled then y.fulfilled = true; y.provided = provided end + end + end + end + end + if not fulfilled then + can_load = false + table.insert(load_issues.dependencies, x.str) + end + end + for _, y in ipairs(mod.conflicts or {}) do + local id = y.id + local conflict = false + if SMODS.Mods[id] and check_dependencies(SMODS.Mods[id], seen) then + conflict = true + local dep_ver = V(SMODS.Mods[id].version) + for _, v in ipairs(y) do + if not v.op(dep_ver, v.ver) then + conflict = false + break + end + end + else + for _, provided in ipairs(SMODS.provided_mods[id] or {}) do + if provided.mod ~= mod and check_dependencies(provided.mod, seen) then + conflict = true + local dep_ver = V(provided.version) + for _, v in ipairs(y) do + if not v.op(dep_ver, v.ver) then + conflict = false + break + end + end + end + end + end + if conflict then + can_load = false + table.insert(load_issues.conflicts, y.str) + end + end + end + if mod.disabled then + can_load = false + load_issues.disabled = true + end + if not can_load then + mod.load_issues = load_issues + return false + end + for _, x in ipairs(mod.dependencies or {}) do + for _, y in ipairs(x) do + if y.fulfilled then + if y.provided then + y.provided.mod.can_load = true + else + SMODS.Mods[y.id].can_load = true + end + end + end + end + return true + end + + -- check dependencies first (for object dependencies) + for _, mod in pairs(SMODS.Mods) do mod.can_load = check_dependencies(mod) end + + boot_print_stage('Loading Mods') + -- load the mod files + for _, priority in ipairs(keyset) do + table.sort(SMODS.mod_priorities[priority], + function(mod_a, mod_b) + return mod_a.id < mod_b.id + end) + for _, mod in ipairs(SMODS.mod_priorities[priority]) do + SMODS.mod_list[#SMODS.mod_list + 1] = mod -- keep mod list in prioritized load order + if mod.can_load and not mod.lovely_only then + SMODS.current_mod = mod + if mod.outdated then + SMODS.compat_0_9_8.with_compat(function() + mod.config = {} + assert(load(NFS.read(mod.path..mod.main_file), ('=[SMODS %s "%s"]'):format(mod.id, mod.main_file)))() + for k, v in pairs(SMODS.compat_0_9_8.init_queue) do + v() + SMODS.compat_0_9_8.init_queue[k] = nil + end + end) + else + SMODS.load_mod_config(mod) + assert(load(NFS.read(mod.path..mod.main_file), ('=[SMODS %s "%s"]'):format(mod.id, mod.main_file)))() + end + SMODS.current_mod = nil + elseif not mod.lovely_only then + sendTraceMessage(string.format("Mod %s was unable to load: %s%s%s%s", mod.id, + mod.load_issues.outdated and + 'Outdated: Steamodded versions 0.9.8 and below are no longer supported!\n' or '', + mod.load_issues.main_file_not_found and "The main file could not be found.\n" or '', + next(mod.load_issues.dependencies) and + ('Missing Dependencies: ' .. inspect(mod.load_issues.dependencies) .. '\n') or '', + next(mod.load_issues.conflicts) and + ('Unresolved Conflicts: ' .. inspect(mod.load_issues.conflicts) .. '\n') or '' + ), 'Loader') + end + end + end + SMODS.get_optional_features() + -- compat after loading mods + if SMODS.compat_0_9_8.load_done then + -- Invasive change to Card:generate_UIBox_ability_table() + local Card_generate_UIBox_ability_table_ref = Card.generate_UIBox_ability_table + function Card:generate_UIBox_ability_table(...) + SMODS.compat_0_9_8.generate_UIBox_ability_table_card = self + local ret = Card_generate_UIBox_ability_table_ref(self, ...) + SMODS.compat_0_9_8.generate_UIBox_ability_table_card = nil + return ret + end + end +end + +function SMODS.injectItems() + -- Set .key for vanilla undiscovered, locked objects + for k, v in pairs(G) do + if type(k) == 'string' and (k:sub(-12, -1) == 'undiscovered' or k:sub(-6, -1) == 'locked') then + v.key = k + end + end + SMODS.injectObjects(SMODS.GameObject) + if SMODS.dump_loc then + boot_print_stage('Dumping Localization') + SMODS.create_loc_dump() + end + boot_print_stage('Initializing Localization') + init_localization() + SMODS.SAVE_UNLOCKS() + table.sort(G.P_CENTER_POOLS["Back"], function (a, b) return (a.order - (a.unlocked and 100 or 0)) < (b.order - (b.unlocked and 100 or 0)) end) + for _, t in ipairs{ + G.P_CENTERS, + G.P_BLINDS, + G.P_TAGS, + G.P_SEALS, + } do + for k, v in pairs(t) do + assert(v._discovered_unlocked_overwritten) + end + end +end + +local function initializeModUIFunctions() + for id, modInfo in pairs(SMODS.mod_list) do + G.FUNCS["openModUI_" .. modInfo.id] = function(e) + G.ACTIVE_MOD_UI = modInfo + G.FUNCS.overlay_menu({ + definition = create_UIBox_mods(e) + }) + end + end +end + +local function checkForLoadFailure() + SMODS.mod_button_alert = false + for k,v in pairs(SMODS.Mods) do + if v and not v.can_load and not v.disabled then + SMODS.mod_button_alert = true + return + end + end +end + +function initSteamodded() + initGlobals() + boot_print_stage("Loading APIs") + loadAPIs() + loadMods(SMODS.MODS_DIR) + checkForLoadFailure() + initializeModUIFunctions() + boot_print_stage("Injecting Items") + SMODS.injectItems() + SMODS.booted = true +end + +-- re-inject on reload +local init_item_prototypes_ref = Game.init_item_prototypes +function Game:init_item_prototypes() + init_item_prototypes_ref(self) + convert_save_data() + if SMODS.booted then + SMODS.injectItems() + end +end + +SMODS.booted = false +function boot_print_stage(stage) + if not SMODS.booted then + boot_timer(nil, "STEAMODDED - " .. stage, 0.95) + end +end + +function boot_timer(_label, _next, progress) + progress = progress or 0 + G.LOADING = G.LOADING or { + font = love.graphics.setNewFont("resources/fonts/m6x11plus.ttf", 20), + love.graphics.dis + } + local realw, realh = love.window.getMode() + love.graphics.setCanvas() + love.graphics.push() + love.graphics.setShader() + love.graphics.clear(0, 0, 0, 1) + love.graphics.setColor(0.6, 0.8, 0.9, 1) + if progress > 0 then love.graphics.rectangle('fill', realw / 2 - 150, realh / 2 - 15, progress * 300, 30, 5) end + love.graphics.setColor(1, 1, 1, 1) + love.graphics.setLineWidth(3) + love.graphics.rectangle('line', realw / 2 - 150, realh / 2 - 15, 300, 30, 5) + love.graphics.print("LOADING: " .. _next, realw / 2 - 150, realh / 2 + 40) + love.graphics.pop() + love.graphics.present() + + G.ARGS.bt = G.ARGS.bt or love.timer.getTime() + G.ARGS.bt = love.timer.getTime() +end + +function SMODS.load_file(path, id) + if not path or path == "" then + error("No path was provided to load.") + end + local mod + if not id then + if not SMODS.current_mod then + error("No ID was provided! Usage without an ID is only available when file is first loaded.") + end + mod = SMODS.current_mod + else + mod = SMODS.Mods[id] + end + if not mod then + error("Mod not found. Ensure you are passing the correct ID.") + end + local file_path = mod.path .. path + local file_content, err = NFS.read(file_path) + if not file_content then return nil, "Error reading file '" .. path .. "' for mod with ID '" .. mod.id .. "': " .. err end + local chunk, err = load(file_content, "=[SMODS " .. mod.id .. ' "' .. path .. '"]') + if not chunk then return nil, "Error processing file '" .. path .. "' for mod with ID '" .. mod.id .. "': " .. err end + return chunk +end + +---------------------------------------------- +------------MOD LOADER END-------------------- diff --git a/smods-main/src/logging.lua b/smods-main/src/logging.lua new file mode 100644 index 0000000..001ed9c --- /dev/null +++ b/smods-main/src/logging.lua @@ -0,0 +1,58 @@ +--- STEAMODDED CORE +--- MODULE LOGGING + +function initializeSocketConnection() + local socket = require("socket") + client = socket.connect("localhost", 53153) + if not client then + print("Failed to connect to the debug server") + end +end + +-- message, logger in this order to preserve backward compatibility +function sendTraceMessage(message, logger) + sendMessageToConsole("TRACE", logger, message) +end + +function sendDebugMessage(message, logger) + sendMessageToConsole("DEBUG", logger, message) +end + +function sendInfoMessage(message, logger) + -- space in info string to align the logs in console + sendMessageToConsole("INFO ", logger, message) +end + +function sendWarnMessage(message, logger) + -- space in warn string to align the logs in console + sendMessageToConsole("WARN ", logger, message) +end + +function sendErrorMessage(message, logger) + sendMessageToConsole("ERROR", logger, message) +end + +function sendFatalMessage(message, logger) + sendMessageToConsole("FATAL", logger, message) +end + +function sendMessageToConsole(level, logger, message) + level = level or "DEBUG" + logger = logger or "DefaultLogger" + message = message or "Default log message" + date = os.date('%Y-%m-%d %H:%M:%S') + print(date .. " :: " .. level .. " :: " .. logger .. " :: " .. message) + if client then + -- naive way to separate the logs if the console receive multiple logs at the same time + client:send(date .. " :: " .. level .. " :: " .. logger .. " :: " .. message .. "ENDOFLOG") + end +end + +initializeSocketConnection() + +-- Use the function to send messages +sendDebugMessage("Steamodded Debug Socket started !", "DebugConsole") + + +----------------------------------------------- +---------------MOD LOGGING END----------------- diff --git a/smods-main/src/overrides.lua b/smods-main/src/overrides.lua new file mode 100644 index 0000000..139a35d --- /dev/null +++ b/smods-main/src/overrides.lua @@ -0,0 +1,1753 @@ +--- STEAMODDED CORE +--- OVERRIDES + +--#region blind UI +-- Recreate all lines of the blind description. +-- This callback is called each frame. +---@param e {} +--**e** Is the UIE that called this function +G.FUNCS.HUD_blind_debuff = function(e) + local scale = 0.4 + local num_lines = #G.GAME.blind.loc_debuff_lines + while G.GAME.blind.loc_debuff_lines[num_lines] == '' do + num_lines = num_lines - 1 + end + local padding = 0.05 + if num_lines > 5 then + local excess_height = (0.3 + padding)*(num_lines - 5) + padding = padding - excess_height / (num_lines + 1) + end + e.config.padding = padding + if num_lines > #e.children then + for i = #e.children+1, num_lines do + local node_def = {n = G.UIT.R, config = {align = "cm", minh = 0.3, maxw = 4.2}, nodes = { + {n = G.UIT.T, config = {ref_table = G.GAME.blind.loc_debuff_lines, ref_value = i, scale = scale * 0.9, colour = G.C.UI.TEXT_LIGHT}}}} + e.UIBox:set_parent_child(node_def, e) + end + elseif num_lines < #e.children then + for i = num_lines+1, #e.children do + e.children[i]:remove() + e.children[i] = nil + end + end + e.UIBox:recalculate() + assert(G.HUD_blind == e.UIBox) +end + +function create_UIBox_your_collection_blinds(exit) + local min_ante = 1 + local max_ante = 16 + local spacing = 1 - 15*0.06 + if G.GAME and G.GAME.round_resets and G.GAME.round_resets.ante then + local current_ante = G.GAME.round_resets.ante + + if current_ante > 8 then + min_ante = current_ante - 8 + 1 + max_ante = current_ante + 8 + end + end + local ante_amounts = {} + for i = min_ante, max_ante do + if i > 1 then + ante_amounts[#ante_amounts + 1] = { n = G.UIT.R, config = { minh = spacing }, nodes = {} } + end + local blind_chip = Sprite(0, 0, 0.2, 0.2, G.ASSET_ATLAS["ui_" .. (G.SETTINGS.colourblind_option and 2 or 1)], + { x = 0, y = 0 }) + blind_chip.states.drag.can = false + ante_amounts[#ante_amounts + 1] = { + n = G.UIT.R, + config = { align = "cm", padding = 0.03 }, + nodes = { + { + n = G.UIT.C, + config = { align = "cm", minw = 0.7 }, + nodes = { + { n = G.UIT.T, config = { text = i, scale = 0.4, colour = G.C.FILTER, shadow = true } }, + } + }, + { + n = G.UIT.C, + config = { align = "cr", minw = 2.8 }, + nodes = { + { n = G.UIT.O, config = { object = blind_chip } }, + { n = G.UIT.C, config = { align = "cm", minw = 0.03, minh = 0.01 }, nodes = {} }, + { n = G.UIT.T, config = { text = number_format(get_blind_amount(i)), scale = 0.4, colour = i <= G.PROFILES[G.SETTINGS.profile].high_scores.furthest_ante.amt and G.C.RED or G.C.JOKER_GREY, shadow = true } }, + } + } + } + } + end + + local rows = 6 + local cols = 5 + local page = 1 + local deck_tables = {} + + G.your_collection = {} + for j = 1, rows do + G.your_collection[j] = CardArea( + G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2, G.ROOM.T.h, + cols * 1.55, + 0.95 * 1.33, + { card_limit = cols, type = 'title_2', highlight_limit = 0, collection = true }) + table.insert(deck_tables, + { + n = G.UIT.R, + config = { align = "cm", padding = 0, no_fill = true }, + nodes = { + j%2 == 0 and { n = G.UIT.B, config = { h = 0.2, w = 0.5 } } or nil, + { n = G.UIT.O, config = { object = G.your_collection[j] } }, + j%2 == 1 and { n = G.UIT.B, config = { h = 0.2, w = 0.5 } } or nil, + } + } + ) + end + + local blind_tab = SMODS.collection_pool(G.P_BLINDS) + local blinds_amt = #blind_tab + + local this_page = {} + for i, v in ipairs(blind_tab) do + if i > rows*cols*(page-1) and i <= rows*cols*page then + table.insert(this_page, v) + elseif i > rows*cols*page then + break + end + end + blind_tab = this_page + + local blinds_to_be_alerted = {} + local row, col = 1, 1 + for k, v in ipairs(blind_tab) do + local temp_blind = AnimatedSprite(G.your_collection[row].T.x + G.your_collection[row].T.w/2, G.your_collection[row].T.y, 1.3, 1.3, G.ANIMATION_ATLAS[v.discovered and v.atlas or 'blind_chips'], + v.discovered and v.pos or G.b_undiscovered.pos) + temp_blind.states.click.can = false + temp_blind.states.drag.can = false + temp_blind.states.hover.can = true + local card = Card(G.your_collection[row].T.x + G.your_collection[row].T.w/2, G.your_collection[row].T.y, 1.3, 1.3, G.P_CARDS.empty, G.P_CENTERS.c_base) + temp_blind.states.click.can = false + card.states.drag.can = false + card.states.hover.can = true + card.children.center = temp_blind + temp_blind:set_role({major = card, role_type = 'Glued', draw_major = card}) + card.set_sprites = function(...) + local args = {...} + if not args[1].animation then return end -- fix for debug unlock + local c = card.children.center + Card.set_sprites(...) + card.children.center = c + end + temp_blind:define_draw_steps({ + { shader = 'dissolve', shadow_height = 0.05 }, + { shader = 'dissolve' } + }) + temp_blind.float = true + card.states.collide.can = true + card.config.blind = v + card.config.force_focus = true + if v.discovered and not v.alerted then + blinds_to_be_alerted[#blinds_to_be_alerted + 1] = card + end + card.hover = function() + if not G.CONTROLLER.dragging.target or G.CONTROLLER.using_touch then + if not card.hovering and card.states.visible then + card.hovering = true + card.hover_tilt = 3 + card:juice_up(0.05, 0.02) + play_sound('chips1', math.random() * 0.1 + 0.55, 0.12) + card.config.h_popup = create_UIBox_blind_popup(v, card.config.blind.discovered) + card.config.h_popup_config = card:align_h_popup() + Node.hover(card) + if card.children.alert then + card.children.alert:remove() + card.children.alert = nil + card.config.blind.alerted = true + G:save_progress() + end + end + end + card.stop_hover = function() + card.hovering = false; Node.stop_hover(card); card.hover_tilt = 0 + end + end + G.your_collection[row]:emplace(card) + col = col + 1 + if col > cols then col = 1; row = row + 1 end + end + + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = (function() + for _, v in ipairs(blinds_to_be_alerted) do + v.children.alert = UIBox { + definition = create_UIBox_card_alert(), + config = { align = "tri", offset = { x = 0.1, y = 0.1 }, parent = v } + } + v.children.alert.states.collide.can = false + end + return true + end) + })) + + local page_options = {} + for i = 1, math.ceil(blinds_amt/(rows*cols)) do + table.insert(page_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(blinds_amt/(rows*cols)))) + end + + local extras = nil + local t = create_UIBox_generic_options({ + back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or exit or 'your_collection', + contents = { + { + n = G.UIT.C, + config = { align = "cm", r = 0.1, colour = G.C.BLACK, padding = 0.1, emboss = 0.05 }, + nodes = { + { + n = G.UIT.C, + config = { align = "cm", r = 0.1, colour = G.C.L_BLACK, padding = 0.1, force_focus = true, focus_args = { nav = 'tall' } }, + nodes = { + { + n = G.UIT.R, + config = { align = "cm", padding = 0.05 }, + nodes = { + { + n = G.UIT.C, + config = { align = "cm", minw = 0.7 }, + nodes = { + { n = G.UIT.T, config = { text = localize('k_ante_cap'), scale = 0.4, colour = lighten(G.C.FILTER, 0.2), shadow = true } }, + } + }, + { + n = G.UIT.C, + config = { align = "cr", minw = 2.8 }, + nodes = { + { n = G.UIT.T, config = { text = localize('k_base_cap'), scale = 0.4, colour = lighten(G.C.RED, 0.2), shadow = true } }, + } + } + } + }, + { n = G.UIT.R, config = { align = "cm" }, nodes = ante_amounts } + } + }, + { + n = G.UIT.C, + config = { align = 'cm' }, + nodes = { + { + n = G.UIT.R, + config = { align = 'cm', padding = 0.15 }, + nodes = {} + }, + { + n= G.UIT.R, + config = {align = 'cm' }, + nodes = { + { + n = G.UIT.C, + config = { + align = 'cm', + }, + nodes = deck_tables, + } + } + }, + { + n = G.UIT.R, + config = { align = 'cm', padding = 0.1 }, + nodes = {} + }, + create_option_cycle({ + options = page_options, + w = 4.5, + cycle_shoulders = true, + opt_callback = 'your_collection_blinds_page', + focus_args = {snap_to = true, nav = 'wide'}, + current_option = page, + colour = G.C.RED, + no_pips = true + }) + }, + }, + } + } + } + }) + return t +end + +function G.FUNCS.your_collection_blinds_page(args) + if not args or not args.cycle_config then return end + for j = 1, #G.your_collection do + for i = #G.your_collection[j].cards, 1, -1 do + local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) + c:remove() + c = nil + end + end + + local cols = 5 + local rows = 6 + local page = args.cycle_config.current_option + local blind_tab = SMODS.collection_pool(G.P_BLINDS) + + local this_page = {} + for i, v in ipairs(blind_tab) do + if i > rows*cols*(page-1) and i <= rows*cols*page then + table.insert(this_page, v) + elseif i > rows*cols*page then + break + end + end + blind_tab = this_page + + local blinds_to_be_alerted = {} + local row, col = 1, 1 + for k, v in ipairs(blind_tab) do + local temp_blind = AnimatedSprite(G.your_collection[row].T.x + G.your_collection[row].T.w/2, G.your_collection[row].T.y, 1.3, 1.3, G.ANIMATION_ATLAS[v.discovered and v.atlas or 'blind_chips'], + v.discovered and v.pos or G.b_undiscovered.pos) + temp_blind.states.click.can = false + temp_blind.states.drag.can = false + temp_blind.states.hover.can = true + local card = Card(G.your_collection[row].T.x + G.your_collection[row].T.w/2, G.your_collection[row].T.y, 1.3, 1.3, G.P_CARDS.empty, G.P_CENTERS.c_base) + temp_blind.states.click.can = false + card.states.drag.can = false + card.states.hover.can = true + card.children.center = temp_blind + temp_blind:set_role({major = card, role_type = 'Glued', draw_major = card}) + card.set_sprites = function(...) + local args = {...} + if not args[1].animation then return end -- fix for debug unlock + local c = card.children.center + Card.set_sprites(...) + card.children.center = c + end + temp_blind:define_draw_steps({ + { shader = 'dissolve', shadow_height = 0.05 }, + { shader = 'dissolve' } + }) + temp_blind.float = true + card.states.collide.can = true + card.config.blind = v + card.config.force_focus = true + if v.discovered and not v.alerted then + blinds_to_be_alerted[#blinds_to_be_alerted + 1] = card + end + card.hover = function() + if not G.CONTROLLER.dragging.target or G.CONTROLLER.using_touch then + if not card.hovering and card.states.visible then + card.hovering = true + card.hover_tilt = 3 + card:juice_up(0.05, 0.02) + play_sound('chips1', math.random() * 0.1 + 0.55, 0.12) + card.config.h_popup = create_UIBox_blind_popup(v, card.config.blind.discovered) + card.config.h_popup_config = card:align_h_popup() + Node.hover(card) + if card.children.alert then + card.children.alert:remove() + card.children.alert = nil + card.config.blind.alerted = true + G:save_progress() + end + end + end + card.stop_hover = function() + card.hovering = false; Node.stop_hover(card); card.hover_tilt = 0 + end + end + G.your_collection[row]:emplace(card) + col = col + 1 + if col > cols then col = 1; row = row + 1 end + end + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = (function() + for _, v in ipairs(blinds_to_be_alerted) do + v.children.alert = UIBox{ + definition = create_UIBox_card_alert(), + config = { align="tri", offset = {x = 0.1, y = 0.1}, parent = v} + } + v.children.alert.states.collide.can = false + end + return true + end) + })) +end +--#endregion +--#region tag collections +function create_UIBox_your_collection_tags() + G.E_MANAGER:add_event(Event({ + func = function() + G.FUNCS.your_collection_tags_page({ cycle_config = {}}) + return true + end + })) + return { + n = G.UIT.O, + config = { object = UIBox{ + definition = create_UIBox_your_collection_tags_content(), + config = { offset = {x=0, y=0}, align = 'cm' } + }, id = 'your_collection_tags_contents', align = 'cm' }, + } +end + +function create_UIBox_your_collection_tags_content(page) + page = page or 1 + local tag_matrix = {} + local rows = 4 + local cols = 6 + local tag_tab = SMODS.collection_pool(G.P_TAGS) + for i = 1, math.ceil(rows) do + table.insert(tag_matrix, {}) + end + + local tags_to_be_alerted = {} + local row, col = 1, 1 + for k, v in ipairs(tag_tab) do + if k <= cols*rows*(page-1) then elseif k > cols*rows*page then break else + local discovered = v.discovered + local temp_tag = Tag(v.key, true) + if not v.discovered then temp_tag.hide_ability = true end + local temp_tag_ui, temp_tag_sprite = temp_tag:generate_UI() + tag_matrix[row][col] = { + n = G.UIT.C, + config = { align = "cm", padding = 0.1 }, + nodes = { + temp_tag_ui, + } + } + col = col + 1 + if col > cols then col = 1; row = row + 1 end + if discovered and not v.alerted then + tags_to_be_alerted[#tags_to_be_alerted + 1] = temp_tag_sprite + end + end + end + + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = (function() + for _, v in ipairs(tags_to_be_alerted) do + v.children.alert = UIBox { + definition = create_UIBox_card_alert(), + config = { align = "tri", offset = { x = 0.1, y = 0.1 }, parent = v } + } + v.children.alert.states.collide.can = false + end + return true + end) + })) + + + local table_nodes = {} + for i = 1, rows do + table.insert(table_nodes, { n = G.UIT.R, config = { align = "cm", minh = 1 }, nodes = tag_matrix[i] }) + end + local page_options = {} + for i = 1, math.ceil(#tag_tab/(rows*cols)) do + table.insert(page_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#tag_tab/(rows*cols)))) + end + local t = create_UIBox_generic_options({ + back_func = G.ACTIVE_MOD_UI and "openModUI_" .. G.ACTIVE_MOD_UI.id or 'your_collection', + contents = { + { + n = G.UIT.R, + config = { align = "cm", r = 0.1, colour = G.C.BLACK, padding = 0.1, emboss = 0.05 }, + nodes = { + { + n = G.UIT.C, + config = { align = "cm" }, + nodes = { + { n = G.UIT.R, config = { align = "cm" }, nodes = table_nodes }, + } + }, + } + }, + { + n = G.UIT.R, + config = { align = 'cm' }, + nodes = { + create_option_cycle({ + options = page_options, + w = 4.5, + cycle_shoulders = true, + opt_callback = 'your_collection_tags_page', + focus_args = { snap_to = true, nav = 'wide' }, + current_option = page, + colour = G.C.RED, + no_pips = true + }) + } + } + } + }) + return t +end + +G.FUNCS.your_collection_tags_page = function(args) + local page = args.cycle_config.current_option or 1 + local t = create_UIBox_your_collection_tags_content(page) + local e = G.OVERLAY_MENU:get_UIE_by_ID('your_collection_tags_contents') + if e.config.object then e.config.object:remove() end + e.config.object = UIBox{ + definition = t, + config = {offset = {x=0,y=0}, align = 'cm', parent = e} + } +end +--#endregion +--#region stakes UI +function SMODS.applied_stakes_UI(i, stake_desc_rows, num_added) + if num_added == nil then num_added = { val = 0 } end + if G.P_CENTER_POOLS['Stake'][i].applied_stakes then + for _, v in pairs(G.P_CENTER_POOLS['Stake'][i].applied_stakes) do + if v ~= "white" then + --todo: manage this with pages + if num_added.val < 8 then + local i = G.P_STAKES[v].stake_level + local _stake_desc = {} + local _stake_center = G.P_CENTER_POOLS.Stake[i] + localize { type = 'descriptions', key = _stake_center.key, set = _stake_center.set, nodes = _stake_desc } + local _full_desc = {} + for k, v in ipairs(_stake_desc) do + _full_desc[#_full_desc + 1] = {n = G.UIT.R, config = {align = "cm"}, nodes = v} + end + _full_desc[#_full_desc] = nil + stake_desc_rows[#stake_desc_rows + 1] = {n = G.UIT.R, config = {align = "cm" }, nodes = { + {n = G.UIT.C, config = {align = 'cm'}, nodes = { + {n = G.UIT.C, config = {align = "cm", colour = get_stake_col(i), r = 0.1, minh = 0.35, minw = 0.35, emboss = 0.05 }, nodes = {}}, + {n = G.UIT.B, config = {w = 0.1, h = 0.1}}}}, + {n = G.UIT.C, config = {align = "cm", padding = 0.03, colour = G.C.WHITE, r = 0.1, minh = 0.7, minw = 4.8 }, nodes = + _full_desc},}} + end + num_added.val = num_added.val + 1 + num_added.val = SMODS.applied_stakes_UI(G.P_STAKES[v].stake_level, stake_desc_rows, + num_added) + end + end + end +end + +-- We're overwriting so much that it's better to just remake this +function G.UIDEF.deck_stake_column(_deck_key) + local deck_usage = G.PROFILES[G.SETTINGS.profile].deck_usage[_deck_key] + local stake_col = {} + local valid_option = nil + local num_stakes = #G.P_CENTER_POOLS['Stake'] + for i = #G.P_CENTER_POOLS['Stake'], 1, -1 do + local _wins = deck_usage and deck_usage.wins[i] or 0 + if (deck_usage and deck_usage.wins[i - 1]) or i == 1 or G.PROFILES[G.SETTINGS.profile].all_unlocked then valid_option = true end + stake_col[#stake_col + 1] = {n = G.UIT.R, config = {id = i, align = "cm", colour = _wins > 0 and G.C.GREY or G.C.CLEAR, outline = 0, outline_colour = G.C.WHITE, r = 0.1, minh = 2 / num_stakes, minw = valid_option and 0.45 or 0.25, func = 'RUN_SETUP_check_back_stake_highlight'}, nodes = { + {n = G.UIT.R, config = {align = "cm", minh = valid_option and 1.36 / num_stakes or 1.04 / num_stakes, minw = valid_option and 0.37 or 0.13, colour = _wins > 0 and get_stake_col(i) or G.C.UI.TRANSPARENT_LIGHT, r = 0.1}, nodes = {}}}} + if i > 1 then stake_col[#stake_col + 1] = {n = G.UIT.R, config = {align = "cm", minh = 0.8 / num_stakes, minw = 0.04 }, nodes = {} } end + end + return {n = G.UIT.ROOT, config = {align = 'cm', colour = G.C.CLEAR}, nodes = stake_col} +end + +--#endregion +--#region straights and view deck UI +function get_straight(hand) + local ret = {} + local four_fingers = next(SMODS.find_card('j_four_fingers')) + local can_skip = next(SMODS.find_card('j_shortcut')) + if #hand < (5 - (four_fingers and 1 or 0)) then return ret end + local t = {} + local RANKS = {} + for i = 1, #hand do + if hand[i]:get_id() > 0 then + local rank = hand[i].base.value + RANKS[rank] = RANKS[rank] or {} + RANKS[rank][#RANKS[rank] + 1] = hand[i] + end + end + local straight_length = 0 + local straight = false + local skipped_rank = false + local vals = {} + for k, v in pairs(SMODS.Ranks) do + if v.straight_edge then + table.insert(vals, k) + end + end + local init_vals = {} + for _, v in ipairs(vals) do + init_vals[v] = true + end + if not next(vals) then table.insert(vals, 'Ace') end + local initial = true + local br = false + local end_iter = false + local i = 0 + while 1 do + end_iter = false + if straight_length >= (5 - (four_fingers and 1 or 0)) then + straight = true + end + i = i + 1 + if br or (i > #SMODS.Rank.obj_buffer + 1) then break end + if not next(vals) then break end + for _, val in ipairs(vals) do + if init_vals[val] and not initial then br = true end + if RANKS[val] then + straight_length = straight_length + 1 + skipped_rank = false + for _, vv in ipairs(RANKS[val]) do + t[#t + 1] = vv + end + vals = SMODS.Ranks[val].next + initial = false + end_iter = true + break + end + end + if not end_iter then + local new_vals = {} + for _, val in ipairs(vals) do + for _, r in ipairs(SMODS.Ranks[val].next) do + table.insert(new_vals, r) + end + end + vals = new_vals + if can_skip and not skipped_rank then + skipped_rank = true + else + straight_length = 0 + skipped_rank = false + if not straight then t = {} end + if straight then break end + end + end + end + if not straight then return ret end + table.insert(ret, t) + return ret +end + +function G.UIDEF.deck_preview(args) + local _minh, _minw = 0.35, 0.5 + local suit_labels = {} + local suit_counts = {} + local mod_suit_counts = {} + for _, v in ipairs(SMODS.Suit.obj_buffer) do + suit_counts[v] = 0 + mod_suit_counts[v] = 0 + end + local mod_suit_diff = false + local wheel_flipped, wheel_flipped_text = 0, nil + local flip_col = G.C.WHITE + local rank_counts = {} + local deck_tables = {} + remove_nils(G.playing_cards) + table.sort(G.playing_cards, function(a, b) return a:get_nominal('suit') > b:get_nominal('suit') end) + local SUITS = {} + for _, suit in ipairs(SMODS.Suit.obj_buffer) do + SUITS[suit] = {} + for _, rank in ipairs(SMODS.Rank.obj_buffer) do + SUITS[suit][rank] = {} + end + end + local stones = nil + local suit_map = {} + for i = #SMODS.Suit.obj_buffer, 1, -1 do + suit_map[#suit_map + 1] = SMODS.Suit.obj_buffer[i] + end + local rank_name_mapping = {} + for i = #SMODS.Rank.obj_buffer, 1, -1 do + rank_name_mapping[#rank_name_mapping + 1] = SMODS.Rank.obj_buffer[i] + end + for k, v in ipairs(G.playing_cards) do + if v.ability.effect == 'Stone Card' then + stones = stones or 0 + end + if (v.area and v.area == G.deck) or v.ability.wheel_flipped then + if v.ability.wheel_flipped and not (v.area and v.area == G.deck) then wheel_flipped = wheel_flipped + 1 end + if v.ability.effect == 'Stone Card' then + stones = stones + 1 + else + for kk, vv in pairs(suit_counts) do + if v.base.suit == kk then suit_counts[kk] = suit_counts[kk] + 1 end + if v:is_suit(kk) then mod_suit_counts[kk] = mod_suit_counts[kk] + 1 end + end + if SUITS[v.base.suit][v.base.value] then + table.insert(SUITS[v.base.suit][v.base.value], v) + end + rank_counts[v.base.value] = (rank_counts[v.base.value] or 0) + 1 + end + end + end + + wheel_flipped_text = (wheel_flipped > 0) and + {n = G.UIT.T, config = {text = '?', colour = G.C.FILTER, scale = 0.25, shadow = true}} + or nil + flip_col = wheel_flipped_text and mix_colours(G.C.FILTER, G.C.WHITE, 0.7) or G.C.WHITE + + suit_labels[#suit_labels + 1] = {n = G.UIT.R, config = {align = "cm", r = 0.1, padding = 0.04, minw = _minw, minh = 2 * _minh + 0.25}, nodes = { + stones and {n = G.UIT.T, config = {text = localize('ph_deck_preview_stones') .. ': ', colour = G.C.WHITE, scale = 0.25, shadow = true}} + or nil, + stones and {n = G.UIT.T, config = {text = '' .. stones, colour = (stones > 0 and G.C.WHITE or G.C.UI.TRANSPARENT_LIGHT), scale = 0.4, shadow = true}} + or nil,}} + local hidden_ranks = {} + for _, rank in ipairs(rank_name_mapping) do + local count = 0 + for _, suit in ipairs(suit_map) do + count = count + #SUITS[suit][rank] + end + if count == 0 and SMODS.Ranks[rank].in_pool and not SMODS.Ranks[rank]:in_pool({suit=''}) then + hidden_ranks[rank] = true + end + end + local hidden_suits = {} + for _, suit in ipairs(suit_map) do + if suit_counts[suit] == 0 and SMODS.Suits[suit].in_pool and not SMODS.Suits[suit]:in_pool({rank=''}) then + hidden_suits[suit] = true + end + end + local _row = {} + local _bg_col = G.C.JOKER_GREY + for k, v in ipairs(rank_name_mapping) do + local _tscale = 0.3 + local _colour = G.C.BLACK + local rank_col = SMODS.Ranks[v].face and G.C.WHITE or _bg_col + rank_col = mix_colours(rank_col, _bg_col, 0.8) + + local _col = {n = G.UIT.C, config = {align = "cm" }, nodes = { + {n = G.UIT.C, config = {align = "cm", r = 0.1, minw = _minw, minh = _minh, colour = rank_col, emboss = 0.04, padding = 0.03 }, nodes = { + {n = G.UIT.R, config = {align = "cm" }, nodes = { + {n = G.UIT.T, config = {text = '' .. SMODS.Ranks[v].shorthand, colour = _colour, scale = 1.6 * _tscale } },}}, + {n = G.UIT.R, config = {align = "cm", minw = _minw + 0.04, minh = _minh, colour = G.C.L_BLACK, r = 0.1 }, nodes = { + {n = G.UIT.T, config = {text = '' .. (rank_counts[v] or 0), colour = flip_col, scale = _tscale, shadow = true } }}}}}}} + if not hidden_ranks[v] then table.insert(_row, _col) end + end + table.insert(deck_tables, {n = G.UIT.R, config = {align = "cm", padding = 0.04 }, nodes = _row }) + + for _, suit in ipairs(suit_map) do + if not hidden_suits[suit] then + _row = {} + _bg_col = mix_colours(G.C.SUITS[suit], G.C.L_BLACK, 0.7) + for _, rank in ipairs(rank_name_mapping) do + local _tscale = #SUITS[suit][rank] > 0 and 0.3 or 0.25 + local _colour = #SUITS[suit][rank] > 0 and flip_col or G.C.UI.TRANSPARENT_LIGHT + + local _col = {n = G.UIT.C, config = {align = "cm", padding = 0.05, minw = _minw + 0.098, minh = _minh }, nodes = { + {n = G.UIT.T, config = {text = '' .. #SUITS[suit][rank], colour = _colour, scale = _tscale, shadow = true, lang = G.LANGUAGES['en-us'] } },}} + if not hidden_ranks[rank] then table.insert(_row, _col) end + end + table.insert(deck_tables, + {n = G.UIT.R, config = {align = "cm", r = 0.1, padding = 0.04, minh = 0.4, colour = _bg_col }, nodes = + _row}) + end + end + + for k, v in ipairs(suit_map) do + if not hidden_suits[v] then + local deckskin = SMODS.DeckSkins[G.SETTINGS.CUSTOM_DECK.Collabs[v]] + local palette = deckskin.palette_map and deckskin.palette_map[G.SETTINGS.colour_palettes[v] or ''] or (deckskin.palettes or {})[1] + local t_s + if palette and palette.suit_icon and palette.suit_icon.atlas then + local _x = (v == 'Spades' and 3) or (v == 'Hearts' and 0) or (v == 'Clubs' and 2) or (v == 'Diamonds' and 1) + t_s = Sprite(0,0,0.3,0.3,G.ASSET_ATLAS[palette.suit_icon.atlas or 'ui_1'], (type(palette.suit_icon.pos) == "number" and {x=_x, y=palette.suit_icon.pos}) or palette.suit_icon.pos or {x=_x, y=0}) + elseif G.SETTINGS.colour_palettes[v] == 'lc' or G.SETTINGS.colour_palettes[v] == 'hc' then + t_s = Sprite(0, 0, 0.3, 0.3, + G.ASSET_ATLAS[SMODS.Suits[v][G.SETTINGS.colour_palettes[v] == 'hc' and "hc_ui_atlas" or G.SETTINGS.colour_palettes[v] == 'lc' and "lc_ui_atlas"]] or + G.ASSET_ATLAS[("ui_" .. (G.SETTINGS.colourblind_option and "2" or "1"))], SMODS.Suits[v].ui_pos) + else + t_s = Sprite(0, 0, 0.3, 0.3, G.ASSET_ATLAS[("ui_" .. (G.SETTINGS.colourblind_option and "2" or "1"))], SMODS.Suits[v].ui_pos) + end + + t_s.states.drag.can = false + t_s.states.hover.can = false + t_s.states.collide.can = false + + if mod_suit_counts[v] ~= suit_counts[v] then mod_suit_diff = true end + + suit_labels[#suit_labels + 1] = + {n = G.UIT.R, config = {align = "cm", r = 0.1, padding = 0.03, colour = G.C.JOKER_GREY }, nodes = { + {n = G.UIT.C, config = {align = "cm", minw = _minw, minh = _minh }, nodes = { + {n = G.UIT.O, config = {can_collide = false, object = t_s } }}}, + {n = G.UIT.C, config = {align = "cm", minw = _minw * 2.4, minh = _minh, colour = G.C.L_BLACK, r = 0.1 }, nodes = { + {n = G.UIT.T, config = {text = '' .. suit_counts[v], colour = flip_col, scale = 0.3, shadow = true, lang = G.LANGUAGES['en-us'] } }, + mod_suit_counts[v] ~= suit_counts[v] and {n = G.UIT.T, config = {text = ' (' .. mod_suit_counts[v] .. ')', colour = mix_colours(G.C.BLUE, G.C.WHITE, 0.7), scale = 0.28, shadow = true, lang = G.LANGUAGES['en-us'] } } + or nil,}}}} + end + end + + + local t = {n = G.UIT.ROOT, config = {align = "cm", colour = G.C.JOKER_GREY, r = 0.1, emboss = 0.05, padding = 0.07}, nodes = { + {n = G.UIT.R, config = {align = "cm", r = 0.1, emboss = 0.05, colour = G.C.BLACK, padding = 0.1}, nodes = { + {n = G.UIT.R, config = {align = "cm"}, nodes = { + {n = G.UIT.C, config = {align = "cm", padding = 0.04}, nodes = suit_labels }, + {n = G.UIT.C, config = {align = "cm", padding = 0.02}, nodes = deck_tables }}}, + mod_suit_diff and {n = G.UIT.R, config = {align = "cm" }, nodes = { + {n = G.UIT.C, config = {padding = 0.3, r = 0.1, colour = mix_colours(G.C.BLUE, G.C.WHITE, 0.7) }, nodes = {} }, + {n = G.UIT.T, config = {text = ' ' .. localize('ph_deck_preview_effective'), colour = G.C.WHITE, scale = 0.3 } },}} + or nil, + wheel_flipped_text and {n = G.UIT.R, config = {align = "cm" }, nodes = { + {n = G.UIT.C, config = {padding = 0.3, r = 0.1, colour = flip_col }, nodes = {} }, + {n = G.UIT.T, config = { + text = ' ' .. (wheel_flipped > 1 and + localize { type = 'variable', key = 'deck_preview_wheel_plural', vars = { wheel_flipped } } or + localize { type = 'variable', key = 'deck_preview_wheel_singular', vars = { wheel_flipped } }), + colour = G.C.WHITE, + scale = 0.3}},}} + or nil,}}}} + return t +end + +function tally_sprite(pos, value, tooltip, suit) + local text_colour = G.C.BLACK + if type(value) == "table" and value[1].string==value[2].string then + text_colour = value[1].colour or G.C.WHITE + value = value[1].string + end + local deckskin = suit and SMODS.DeckSkins[G.SETTINGS.CUSTOM_DECK.Collabs[suit]] + local palette = deckskin and (deckskin.palette_map and deckskin.palette_map[G.SETTINGS.colour_palettes[suit] or ''] or (deckskin.palettes or {})[1]) + local t_s + if palette and palette.suit_icon and palette.suit_icon.atlas then + local _x = (suit == 'Spades' and 3) or (suit == 'Hearts' and 0) or (suit == 'Clubs' and 2) or (suit == 'Diamonds' and 1) + t_s = Sprite(0,0,0.3,0.3,G.ASSET_ATLAS[palette.suit_icon.atlas or 'ui_1'], (type(palette.suit_icon.pos) == "number" and {x=_x, y=palette.suit_icon.pos}) or palette.suit_icon.pos or {x=_x, y=0}) + elseif suit and (G.SETTINGS.colour_palettes[suit] == 'lc' or G.SETTINGS.colour_palettes[suit] == 'hc') then + t_s = Sprite(0, 0, 0.3, 0.3, + G.ASSET_ATLAS[SMODS.Suits[suit][G.SETTINGS.colour_palettes[suit] == 'hc' and "hc_ui_atlas" or G.SETTINGS.colour_palettes[suit] == 'lc' and "lc_ui_atlas"]] or + G.ASSET_ATLAS[("ui_" .. (G.SETTINGS.colourblind_option and "2" or "1"))], SMODS.Suits[suit].ui_pos) + else + t_s = Sprite(0,0,0.5,0.5, suit and G.ASSET_ATLAS[SMODS.Suits[suit][G.SETTINGS.colourblind_option and "hc_ui_atlas" or "lc_ui_atlas"]] or G.ASSET_ATLAS[("ui_"..(G.SETTINGS.colourblind_option and "2" or "1"))], {x=pos.x or 0, y=pos.y or 0}) + end + t_s.states.drag.can = false + t_s.states.hover.can = false + t_s.states.collide.can = false + return + {n=G.UIT.C, config={align = "cm", padding = 0.07,force_focus = true, focus_args = {type = 'tally_sprite'}, tooltip = {text = tooltip}}, nodes={ + {n=G.UIT.R, config={align = "cm", r = 0.1, padding = 0.04, emboss = 0.05, colour = G.C.JOKER_GREY}, nodes={ + {n=G.UIT.O, config={w=0.5,h=0.5 ,can_collide = false, object = t_s, tooltip = {text = tooltip}}} + }}, + {n=G.UIT.R, config={align = "cm"}, nodes={ + type(value) == "table" and {n=G.UIT.O, config={object = DynaText({string = value, colours = {G.C.RED}, scale = 0.4, silent = true, shadow = true, pop_in_rate = 10, pop_delay = 4})}} or + {n=G.UIT.T, config={text = value or 'NIL',colour = text_colour, scale = 0.4, shadow = true}}, + }}, + }} +end + +function G.UIDEF.view_deck(unplayed_only) + local deck_tables = {} + remove_nils(G.playing_cards) + G.VIEWING_DECK = true + table.sort(G.playing_cards, function(a, b) return a:get_nominal('suit') > b:get_nominal('suit') end) + local SUITS = {} + local suit_map = {} + for i = #SMODS.Suit.obj_buffer, 1, -1 do + SUITS[SMODS.Suit.obj_buffer[i]] = {} + suit_map[#suit_map + 1] = SMODS.Suit.obj_buffer[i] + end + for k, v in ipairs(G.playing_cards) do + if v.base.suit then table.insert(SUITS[v.base.suit], v) end + end + local num_suits = 0 + for j = 1, #suit_map do + if SUITS[suit_map[j]][1] then num_suits = num_suits + 1 end + end + for j = 1, #suit_map do + if SUITS[suit_map[j]][1] then + local view_deck = CardArea( + G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2, G.ROOM.T.h, + 6.5 * G.CARD_W, + ((num_suits > 8) and 0.2 or (num_suits > 4) and (1 - 0.1 * num_suits) or 0.6) * G.CARD_H, + { + card_limit = #SUITS[suit_map[j]], + type = 'title', + view_deck = true, + highlight_limit = 0, + card_w = G + .CARD_W * 0.7, + draw_layers = { 'card' } + }) + table.insert(deck_tables, + {n = G.UIT.R, config = {align = "cm", padding = 0}, nodes = { + {n = G.UIT.O, config = {object = view_deck}}}} + ) + + for i = 1, #SUITS[suit_map[j]] do + if SUITS[suit_map[j]][i] then + local greyed, _scale = nil, 0.7 + if unplayed_only and not ((SUITS[suit_map[j]][i].area and SUITS[suit_map[j]][i].area == G.deck) or SUITS[suit_map[j]][i].ability.wheel_flipped) then + greyed = true + end + local copy = copy_card(SUITS[suit_map[j]][i], nil, _scale) + copy.greyed = greyed + copy.T.x = view_deck.T.x + view_deck.T.w / 2 + copy.T.y = view_deck.T.y + + copy:hard_set_T() + view_deck:emplace(copy) + end + end + end + end + + local flip_col = G.C.WHITE + + local suit_tallies = {} + local mod_suit_tallies = {} + for _, v in ipairs(suit_map) do + suit_tallies[v] = 0 + mod_suit_tallies[v] = 0 + end + local rank_tallies = {} + local mod_rank_tallies = {} + local rank_name_mapping = SMODS.Rank.obj_buffer + for _, v in ipairs(rank_name_mapping) do + rank_tallies[v] = 0 + mod_rank_tallies[v] = 0 + end + local face_tally = 0 + local mod_face_tally = 0 + local num_tally = 0 + local mod_num_tally = 0 + local ace_tally = 0 + local mod_ace_tally = 0 + local wheel_flipped = 0 + + for k, v in ipairs(G.playing_cards) do + if v.ability.name ~= 'Stone Card' and (not unplayed_only or ((v.area and v.area == G.deck) or v.ability.wheel_flipped)) then + if v.ability.wheel_flipped and not (v.area and v.area == G.deck) and unplayed_only then wheel_flipped = wheel_flipped + 1 end + --For the suits + if v.base.suit then suit_tallies[v.base.suit] = (suit_tallies[v.base.suit] or 0) + 1 end + for kk, vv in pairs(mod_suit_tallies) do + mod_suit_tallies[kk] = (vv or 0) + (v:is_suit(kk) and 1 or 0) + end + + --for face cards/numbered cards/aces + local card_id = v:get_id() + if v.base.value then face_tally = face_tally + ((SMODS.Ranks[v.base.value].face) and 1 or 0) end + mod_face_tally = mod_face_tally + (v:is_face() and 1 or 0) + if v.base.value and not SMODS.Ranks[v.base.value].face and card_id ~= 14 then + num_tally = num_tally + 1 + if not v.debuff then mod_num_tally = mod_num_tally + 1 end + end + if card_id == 14 then + ace_tally = ace_tally + 1 + if not v.debuff then mod_ace_tally = mod_ace_tally + 1 end + end + + --ranks + if v.base.value then rank_tallies[v.base.value] = rank_tallies[v.base.value] + 1 end + if v.base.value and not v.debuff then mod_rank_tallies[v.base.value] = mod_rank_tallies[v.base.value] + 1 end + end + end + local modded = face_tally ~= mod_face_tally + for kk, vv in pairs(mod_suit_tallies) do + modded = modded or (vv ~= suit_tallies[kk]) + if modded then break end + end + + if wheel_flipped > 0 then flip_col = mix_colours(G.C.FILTER, G.C.WHITE, 0.7) end + + local rank_cols = {} + for i = #rank_name_mapping, 1, -1 do + if rank_tallies[rank_name_mapping[i]] ~= 0 or not SMODS.Ranks[rank_name_mapping[i]].in_pool or SMODS.Ranks[rank_name_mapping[i]]:in_pool({suit=''}) then + local mod_delta = mod_rank_tallies[rank_name_mapping[i]] ~= rank_tallies[rank_name_mapping[i]] + rank_cols[#rank_cols + 1] = {n = G.UIT.R, config = {align = "cm", padding = 0.07}, nodes = { + {n = G.UIT.C, config = {align = "cm", r = 0.1, padding = 0.04, emboss = 0.04, minw = 0.5, colour = G.C.L_BLACK}, nodes = { + {n = G.UIT.T, config = {text = SMODS.Ranks[rank_name_mapping[i]].shorthand, colour = G.C.JOKER_GREY, scale = 0.35, shadow = true}},}}, + {n = G.UIT.C, config = {align = "cr", minw = 0.4}, nodes = { + mod_delta and {n = G.UIT.O, config = { + object = DynaText({ + string = { { string = '' .. rank_tallies[rank_name_mapping[i]], colour = flip_col }, { string = '' .. mod_rank_tallies[rank_name_mapping[i]], colour = G.C.BLUE } }, + colours = { G.C.RED }, scale = 0.4, y_offset = -2, silent = true, shadow = true, pop_in_rate = 10, pop_delay = 4 + })}} + or {n = G.UIT.T, config = {text = rank_tallies[rank_name_mapping[i]], colour = flip_col, scale = 0.45, shadow = true } },}}}} + end + end + + local tally_ui = { + -- base cards + {n = G.UIT.R, config = {align = "cm", minh = 0.05, padding = 0.07}, nodes = { + {n = G.UIT.O, config = { + object = DynaText({ + string = { + { string = localize('k_base_cards'), colour = G.C.RED }, + modded and { string = localize('k_effective'), colour = G.C.BLUE } or nil + }, + colours = { G.C.RED }, silent = true, scale = 0.4, pop_in_rate = 10, pop_delay = 4 + }) + }}}}, + -- aces, faces and numbered cards + {n = G.UIT.R, config = {align = "cm", minh = 0.05, padding = 0.1}, nodes = { + tally_sprite( + { x = 1, y = 0 }, + { { string = '' .. ace_tally, colour = flip_col }, { string = '' .. mod_ace_tally, colour = G.C.BLUE } }, + { localize('k_aces') } + ), --Aces + tally_sprite( + { x = 2, y = 0 }, + { { string = '' .. face_tally, colour = flip_col }, { string = '' .. mod_face_tally, colour = G.C.BLUE } }, + { localize('k_face_cards') } + ), --Face + tally_sprite( + { x = 3, y = 0 }, + { { string = '' .. num_tally, colour = flip_col }, { string = '' .. mod_num_tally, colour = G.C.BLUE } }, + { localize('k_numbered_cards') } + ), --Numbers + }}, + } + -- add suit tallies + local hidden_suits = {} + for _, suit in ipairs(suit_map) do + if suit_tallies[suit] == 0 and SMODS.Suits[suit].in_pool and not SMODS.Suits[suit]:in_pool({rank=''}) then + hidden_suits[suit] = true + end + end + local i = 1 + local num_suits_shown = 0 + for i = 1, #suit_map do + if not hidden_suits[suit_map[i]] then + num_suits_shown = num_suits_shown+1 + end + end + local suits_per_row = num_suits_shown > 6 and 4 or num_suits_shown > 4 and 3 or 2 + local n_nodes = {} + while i <= #suit_map do + while #n_nodes < suits_per_row and i <= #suit_map do + if not hidden_suits[suit_map[i]] then + table.insert(n_nodes, tally_sprite( + SMODS.Suits[suit_map[i]].ui_pos, + { + { string = '' .. suit_tallies[suit_map[i]], colour = flip_col }, + { string = '' .. mod_suit_tallies[suit_map[i]], colour = G.C.BLUE } + }, + { localize(suit_map[i], 'suits_plural') }, + suit_map[i] + )) + end + i = i + 1 + end + if #n_nodes > 0 then + local n = {n = G.UIT.R, config = {align = "cm", minh = 0.05, padding = 0.1}, nodes = n_nodes} + table.insert(tally_ui, n) + n_nodes = {} + end + end + local t = {n = G.UIT.ROOT, config = {align = "cm", colour = G.C.CLEAR}, nodes = { + {n = G.UIT.R, config = {align = "cm", padding = 0.05}, nodes = {}}, + {n = G.UIT.R, config = {align = "cm"}, nodes = { + {n = G.UIT.C, config = {align = "cm", minw = 1.5, minh = 2, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = { + {n = G.UIT.C, config = {align = "cm", padding = 0.1}, nodes = { + {n = G.UIT.R, config = {align = "cm", r = 0.1, colour = G.C.L_BLACK, emboss = 0.05, padding = 0.15}, nodes = { + {n = G.UIT.R, config = {align = "cm"}, nodes = { + {n = G.UIT.O, config = { + object = DynaText({ string = G.GAME.selected_back.loc_name, colours = {G.C.WHITE}, bump = true, rotate = true, shadow = true, scale = 0.6 - string.len(G.GAME.selected_back.loc_name) * 0.01 }) + }},}}, + {n = G.UIT.R, config = {align = "cm", r = 0.1, padding = 0.1, minw = 2.5, minh = 1.3, colour = G.C.WHITE, emboss = 0.05}, nodes = { + {n = G.UIT.O, config = { + object = UIBox { + definition = G.GAME.selected_back:generate_UI(nil, 0.7, 0.5, G.GAME.challenge), config = {offset = { x = 0, y = 0 } } + } + }}}}}}, + {n = G.UIT.R, config = {align = "cm", r = 0.1, outline_colour = G.C.L_BLACK, line_emboss = 0.05, outline = 1.5}, nodes = + tally_ui}}}, + {n = G.UIT.C, config = {align = "cm"}, nodes = rank_cols}, + {n = G.UIT.B, config = {w = 0.1, h = 0.1}},}}, + {n = G.UIT.B, config = {w = 0.2, h = 0.1}}, + {n = G.UIT.C, config = {align = "cm", padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = + deck_tables}}}, + {n = G.UIT.R, config = {align = "cm", minh = 0.8, padding = 0.05}, nodes = { + modded and {n = G.UIT.R, config = {align = "cm"}, nodes = { + {n = G.UIT.C, config = {padding = 0.3, r = 0.1, colour = mix_colours(G.C.BLUE, G.C.WHITE, 0.7)}, nodes = {}}, + {n = G.UIT.T, config = {text = ' ' .. localize('ph_deck_preview_effective'), colour = G.C.WHITE, scale = 0.3}},}} + or nil, + wheel_flipped > 0 and {n = G.UIT.R, config = {align = "cm"}, nodes = { + {n = G.UIT.C, config = {padding = 0.3, r = 0.1, colour = flip_col}, nodes = {}}, + {n = G.UIT.T, config = { + text = ' ' .. (wheel_flipped > 1 and + localize { type = 'variable', key = 'deck_preview_wheel_plural', vars = { wheel_flipped } } or + localize { type = 'variable', key = 'deck_preview_wheel_singular', vars = { wheel_flipped } }), + colour = G.C.WHITE, scale = 0.3 + }},}} + or nil,}}}} + return t +end + +--#endregion +--#region poker hands +local init_game_object_ref = Game.init_game_object +function Game:init_game_object() + local t = init_game_object_ref(self) + for _, key in ipairs(SMODS.PokerHand.obj_buffer) do + t.hands[key] = {} + for k, v in pairs(SMODS.PokerHands[key]) do + -- G.GAME needs to be able to be serialized + -- TODO this is too specific; ex. nested tables with simple keys + -- are fine. + -- In fact, the check should just warn you if you have a key that + -- can't be serialized. + if type(v) == 'number' or type(v) == 'boolean' or k == 'example' then + t.hands[key][k] = v + end + end + end + return t +end + +-- why bother patching when i basically change everything +function G.FUNCS.get_poker_hand_info(_cards) + local poker_hands = evaluate_poker_hand(_cards) + local scoring_hand = {} + local text, disp_text, loc_disp_text = 'NULL', 'NULL', 'NULL' + for _, v in ipairs(G.handlist) do + if next(poker_hands[v]) then + text = v + scoring_hand = poker_hands[v][1] + break + end + end + disp_text = text + local _hand = SMODS.PokerHands[text] + if text == 'Straight Flush' then + local royal = true + for j = 1, #scoring_hand do + local rank = SMODS.Ranks[scoring_hand[j].base.value] + royal = royal and (rank.key == 'Ace' or rank.key == '10' or rank.face) + end + if royal then + disp_text = 'Royal Flush' + end + elseif _hand and _hand.modify_display_text and type(_hand.modify_display_text) == 'function' then + disp_text = _hand:modify_display_text(_cards, scoring_hand) or disp_text + end + loc_disp_text = localize(disp_text, 'poker_hands') + return text, loc_disp_text, poker_hands, scoring_hand, disp_text +end + +function create_UIBox_current_hands(simple) + G.current_hands = {} + local index = 0 + for _, v in ipairs(G.handlist) do + local ui_element = create_UIBox_current_hand_row(v, simple) + G.current_hands[index + 1] = ui_element + if ui_element then + index = index + 1 + end + if index >= 10 then + break + end + end + + local visible_hands = {} + for _, v in ipairs(G.handlist) do + if G.GAME.hands[v].visible then + table.insert(visible_hands, v) + end + end + + local hand_options = {} + for i = 1, math.ceil(#visible_hands / 10) do + table.insert(hand_options, + localize('k_page') .. ' ' .. tostring(i) .. '/' .. tostring(math.ceil(#visible_hands / 10))) + end + + local object = {n = G.UIT.ROOT, config = {align = "cm", colour = G.C.CLEAR}, nodes = { + {n = G.UIT.R, config = {align = "cm", padding = 0.04}, nodes = + G.current_hands}, + {n = G.UIT.R, config = {align = "cm", padding = 0}, nodes = { + create_option_cycle({ + options = hand_options, + w = 4.5, + cycle_shoulders = true, + opt_callback = 'your_hands_page', + focus_args = { snap_to = true, nav = 'wide' }, + current_option = 1, + colour = G.C.RED, + no_pips = true + })}}}} + + local t = {n = G.UIT.ROOT, config = {align = "cm", minw = 3, padding = 0.1, r = 0.1, colour = G.C.CLEAR}, nodes = { + {n = G.UIT.O, config = { + id = 'hand_list', + object = UIBox { + definition = object, config = {offset = { x = 0, y = 0 }, align = 'cm'} + } + }}}} + return t +end + +G.FUNCS.your_hands_page = function(args) + if not args or not args.cycle_config then return end + G.current_hands = {} + + + local index = 0 + for _, v in ipairs(G.handlist) do + local ui_element = create_UIBox_current_hand_row(v, simple) + if index >= (0 + 10 * (args.cycle_config.current_option - 1)) and index < 10 * args.cycle_config.current_option then + G.current_hands[index - (10 * (args.cycle_config.current_option - 1)) + 1] = ui_element + end + + if ui_element then + index = index + 1 + end + + if index >= 10 * args.cycle_config.current_option then + break + end + end + + local visible_hands = {} + for _, v in ipairs(G.handlist) do + if G.GAME.hands[v].visible then + table.insert(visible_hands, v) + end + end + + local hand_options = {} + for i = 1, math.ceil(#visible_hands / 10) do + table.insert(hand_options, + localize('k_page') .. ' ' .. tostring(i) .. '/' .. tostring(math.ceil(#visible_hands / 10))) + end + + local object = {n = G.UIT.ROOT, config = {align = "cm", colour = G.C.CLEAR }, nodes = { + {n = G.UIT.R, config = {align = "cm", padding = 0.04 }, nodes = G.current_hands + }, + {n = G.UIT.R, config = {align = "cm", padding = 0 }, nodes = { + create_option_cycle({ + options = hand_options, + w = 4.5, + cycle_shoulders = true, + opt_callback = + 'your_hands_page', + focus_args = { snap_to = true, nav = 'wide' }, + current_option = args.cycle_config.current_option, + colour = G + .C.RED, + no_pips = true + }) + } + } + } + } + + local hand_list = G.OVERLAY_MENU:get_UIE_by_ID('hand_list') + if hand_list then + if hand_list.config.object then + hand_list.config.object:remove() + end + hand_list.config.object = UIBox { + definition = object, config = {offset = { x = 0, y = 0 }, align = 'cm', parent = hand_list } + } + end +end + +function evaluate_poker_hand(hand) + local results = {} + local parts = {} + for _, v in ipairs(SMODS.PokerHandPart.obj_buffer) do + parts[v] = SMODS.PokerHandParts[v].func(hand) or {} + end + for k, _hand in pairs(SMODS.PokerHands) do + results[k] = _hand.evaluate(parts, hand) or {} + end + for _, v in ipairs(G.handlist) do + if not results.top and results[v] then + results.top = results[v] + break + end + end + return results +end +--#endregion + +-- Init custom card parameters. +local card_init = Card.init +function Card:init(X, Y, W, H, card, center, params) + card_init(self, X, Y, W, H, card, center, params) + + -- This table contains object keys for layers (e.g. edition) + -- that dont want base layer to be drawn. + -- When layer is removed, layer's value should be set to nil. + self.ignore_base_shader = self.ignore_base_shader or {} + -- This table contains object keys for layers (e.g. edition) + -- that dont want shadow to be drawn. + -- When layer is removed, layer's value should be set to nil. + self.ignore_shadow = self.ignore_shadow or {} +end + +function Card:should_draw_base_shader() + return not next(self.ignore_base_shader or {}) +end + +function Card:should_draw_shadow() + return not next(self.ignore_shadow or {}) +end + +local smods_card_load = Card.load +-- +function Card:load(cardTable, other_card) + local ret = smods_card_load(self, cardTable, other_card) + local on_edition_loaded = self.edition and self.edition.key and G.P_CENTERS[self.edition.key].on_load + if type(on_edition_loaded) == "function" then + on_edition_loaded(self) + end + + return ret +end + +-- self = pass the card +-- edition = +-- nil (removes edition) +-- OR key as string +-- OR { name_of_edition = true } (key without e_). This is from the base game, prefer using a string. +-- OR another card's self.edition table +-- immediate = boolean value +-- silent = boolean value +function Card:set_edition(edition, immediate, silent) + -- Check to see if negative is being removed and reduce card_limit accordingly + if (self.added_to_deck or self.joker_added_to_deck_but_debuffed or (self.area == G.hand and not self.debuff)) and self.edition and self.edition.card_limit then + if self.ability.consumeable and self.area == G.consumeables then + G.consumeables.config.card_limit = G.consumeables.config.card_limit - self.edition.card_limit + elseif self.ability.set == 'Joker' and self.area == G.jokers then + G.jokers.config.card_limit = G.jokers.config.card_limit - self.edition.card_limit + elseif self.area == G.hand then + G.hand.config.card_limit = G.hand.config.card_limit - self.edition.card_limit + end + end + + local old_edition = self.edition and self.edition.key + if old_edition then + self.ignore_base_shader[old_edition] = nil + self.ignore_shadow[old_edition] = nil + + local on_old_edition_removed = G.P_CENTERS[old_edition] and G.P_CENTERS[old_edition].on_remove + if type(on_old_edition_removed) == "function" then + on_old_edition_removed(self) + end + end + + local edition_type = nil + if type(edition) == 'string' then + assert(string.sub(edition, 1, 2) == 'e_') + edition_type = string.sub(edition, 3) + elseif type(edition) == 'table' then + if edition.type then + edition_type = edition.type + else + for k, v in pairs(edition) do + if v then + assert(not edition_type) + edition_type = k + end + end + end + end + + if not edition_type or edition_type == 'base' then + if self.edition == nil then -- early exit + return + end + self.edition = nil -- remove edition from card + self:set_cost() + if not silent then + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = not immediate and 0.2 or 0, + blockable = not immediate, + func = function() + self:juice_up(1, 0.5) + play_sound('whoosh2', 1.2, 0.6) + return true + end + })) + end + return + end + + self.edition = {} + self.edition[edition_type] = true + self.edition.type = edition_type + self.edition.key = 'e_' .. edition_type + + local p_edition = G.P_CENTERS['e_' .. edition_type] + + if p_edition.override_base_shader or p_edition.disable_base_shader then + self.ignore_base_shader[self.edition.key] = true + end + if p_edition.no_shadow or p_edition.disable_shadow then + self.ignore_shadow[self.edition.key] = true + end + + local on_edition_applied = p_edition.on_apply + if type(on_edition_applied) == "function" then + on_edition_applied(self) + end + + for k, v in pairs(p_edition.config) do + if type(v) == 'table' then + self.edition[k] = copy_table(v) + else + self.edition[k] = v + end + if k == 'card_limit' and (self.added_to_deck or self.joker_added_to_deck_but_debuffed or (self.area == G.hand and not self.debuff)) and G.jokers and G.consumeables then + if self.ability.consumeable then + G.consumeables.config.card_limit = G.consumeables.config.card_limit + v + elseif self.ability.set == 'Joker' then + G.jokers.config.card_limit = G.jokers.config.card_limit + v + elseif self.area == G.hand then + local is_in_pack = (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or (G.STATE == G.STATES.SMODS_BOOSTER_OPENED and SMODS.OPENED_BOOSTER.config.center.draw_hand)) + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = function() + if G.hand.config.real_card_limit then + G.hand.config.real_card_limit = G.hand.config.real_card_limit + v + end + G.hand.config.card_limit = G.hand.config.card_limit + v + if not is_in_pack then + G.FUNCS.draw_from_deck_to_hand(v) + end + return true + end + })) + end + end + end + + if self.area and self.area == G.jokers then + if self.edition then + if not G.P_CENTERS['e_' .. (self.edition.type)].discovered then + discover_card(G.P_CENTERS['e_' .. (self.edition.type)]) + end + else + if not G.P_CENTERS['e_base'].discovered then + discover_card(G.P_CENTERS['e_base']) + end + end + end + + if self.edition and not silent then + local ed = G.P_CENTERS['e_' .. (self.edition.type)] + G.CONTROLLER.locks.edition = true + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = not immediate and 0.2 or 0, + blockable = not immediate, + func = function() + if self.edition then + self:juice_up(1, 0.5) + play_sound(ed.sound.sound, ed.sound.per, ed.sound.vol) + end + return true + end + })) + G.E_MANAGER:add_event(Event({ + trigger = 'after', + delay = 0.1, + func = function() + G.CONTROLLER.locks.edition = false + return true + end + })) + end + + if G.jokers and self.area == G.jokers then + check_for_unlock({ type = 'modify_jokers' }) + end + + self:set_cost() +end + +-- _key = key value for random seed +-- _mod = scale of chance against base card (does not change guaranteed weights) +-- _no_neg = boolean value to disable negative edition +-- _guaranteed = boolean value to determine whether an edition is guaranteed +-- _options = list of keys of editions to include in the poll +-- OR list of tables { name = key, weight = number } +function poll_edition(_key, _mod, _no_neg, _guaranteed, _options) + local _modifier = 1 + local edition_poll = pseudorandom(pseudoseed(_key or 'edition_generic')) -- Generate the poll value + local available_editions = {} -- Table containing a list of editions and their weights + + if not _options then + _options = { 'e_negative', 'e_polychrome', 'e_holo', 'e_foil' } + if _key == "wheel_of_fortune" or _key == "aura" then -- set base game edition polling + else + for _, v in ipairs(G.P_CENTER_POOLS.Edition) do + if v.in_shop then + table.insert(_options, v.key) + end + end + end + end + for _, v in ipairs(_options) do + local edition_option = {} + if type(v) == 'string' then + assert(string.sub(v, 1, 2) == 'e_') + edition_option = { name = v, weight = G.P_CENTERS[v].weight } + elseif type(v) == 'table' then + assert(string.sub(v.name, 1, 2) == 'e_') + edition_option = { name = v.name, weight = v.weight } + end + table.insert(available_editions, edition_option) + end + + -- Calculate total weight of editions + local total_weight = 0 + for _, v in ipairs(available_editions) do + total_weight = total_weight + (v.weight) -- total all the weights of the polled editions + end + -- sendDebugMessage("Edition weights: "..total_weight, "EditionAPI") + -- If not guaranteed, calculate the base card rate to maintain base 4% chance of editions + if not _guaranteed then + _modifier = _mod or 1 + total_weight = total_weight + (total_weight / 4 * 96) -- Find total weight with base_card_rate as 96% + for _, v in ipairs(available_editions) do + v.weight = G.P_CENTERS[v.name]:get_weight() -- Apply game modifiers where appropriate (defined in edition declaration) + end + end + -- sendDebugMessage("Total weight: "..total_weight, "EditionAPI") + -- sendDebugMessage("Editions: "..#available_editions, "EditionAPI") + -- sendDebugMessage("Poll: "..edition_poll, "EditionAPI") + + -- Calculate whether edition is selected + local weight_i = 0 + for _, v in ipairs(available_editions) do + weight_i = weight_i + v.weight * _modifier + -- sendDebugMessage(v.name.." weight is "..v.weight*_modifier) + -- sendDebugMessage("Checking for "..v.name.." at "..(1 - (weight_i)/total_weight), "EditionAPI") + if edition_poll > 1 - (weight_i) / total_weight then + if not (v.name == 'e_negative' and _no_neg) then -- skip return if negative is selected and _no_neg is true + -- sendDebugMessage("Matched edition: "..v.name, "EditionAPI") + return v.name + end + end + end + + return nil +end + +-- local cge = Card.get_edition +-- function Card:get_edition() +-- if self.ability.extra_enhancement then return end +-- local ret = cge(self) +-- if self.edition and self.edition.key then +-- local ed = SMODS.Centers[self.edition.key] +-- if ed.calculate and type(ed.calculate) == 'function' then +-- ed:calculate(self, {edition_main = true, edition_val = ret}) +-- end +-- end +-- return ret +-- end + +function get_joker_win_sticker(_center, index) + local joker_usage = G.PROFILES[G.SETTINGS.profile].joker_usage[_center.key] or {} + if joker_usage.wins then + local applied = {} + local _count = 0 + local _stake = nil + for k, v in pairs(joker_usage.wins_by_key) do + SMODS.build_stake_chain(G.P_STAKES[k], applied) + end + for i, v in ipairs(G.P_CENTER_POOLS.Stake) do + if applied[v.order] then + _count = _count+1 + if (v.stake_level or 0) > (_stake and G.P_STAKES[_stake].stake_level or 0) then + _stake = v.key + end + end + end + if index then return _count end + if _count > 0 then return G.sticker_map[_stake] end + end + if index then return 0 end +end + +function get_deck_win_stake(_deck_key) + if not _deck_key then + local _stake, _stake_low = nil, nil + local deck_count = 0 + for _, deck in pairs(G.PROFILES[G.SETTINGS.profile].deck_usage) do + local deck_won_with = false + for key, _ in pairs(deck.wins_by_key or {}) do + deck_won_with = true + if (G.P_STAKES[key] and G.P_STAKES[key].stake_level or 0) > (_stake and G.P_STAKES[_stake].stake_level or 0) then + _stake = key + end + end + if deck_won_with then deck_count = deck_count + 1 end + if not _stake_low then _stake_low = _stake end + if (_stake and G.P_STAKES[_stake] and G.P_STAKES[_stake].stake_level or 0) < (_stake_low and G.P_STAKES[_stake_low].stake_level or 0) then + _stake_low = _stake + end + end + return _stake and G.P_STAKES[_stake].order or 0, (deck_count >= #G.P_CENTER_POOLS.Back and G.P_STAKES[_stake_low].order or 0) + end + if G.PROFILES[G.SETTINGS.profile].deck_usage[_deck_key] and G.PROFILES[G.SETTINGS.profile].deck_usage[_deck_key].wins_by_key then + local _stake = nil + for key, _ in pairs(G.PROFILES[G.SETTINGS.profile].deck_usage[_deck_key].wins_by_key) do + if (G.P_STAKES[key] and G.P_STAKES[key].stake_level or 0) > (_stake and G.P_STAKES[_stake].stake_level or 0) then + _stake = key + end + end + if _stake then return G.P_STAKES[_stake].order end + end + return 0 +end + +function get_deck_win_sticker(_center) + if G.PROFILES[G.SETTINGS.profile].deck_usage[_center.key] and + G.PROFILES[G.SETTINGS.profile].deck_usage[_center.key].wins_by_key then + local _stake = nil + for key, _ in pairs(G.PROFILES[G.SETTINGS.profile].deck_usage[_center.key].wins_by_key) do + if (G.P_STAKES[key] and G.P_STAKES[key].stake_level or 0) > (_stake and G.P_STAKES[_stake].stake_level or 0) then + _stake = key + end + end + if _stake then return G.sticker_map[_stake] end + end +end + +function set_deck_win() + if G.GAME.selected_back and G.GAME.selected_back.effect and G.GAME.selected_back.effect.center and G.GAME.selected_back.effect.center.key then + local deck_key = G.GAME.selected_back.effect.center.key + local deck_usage = G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] + if not deck_usage then deck_usage = { count = 1, order = + G.GAME.selected_back.effect.center.order, wins = {}, losses = {}, wins_by_key = {}, losses_by_key = {} } end + if deck_usage then + deck_usage.wins[G.GAME.stake] = (deck_usage.wins[G.GAME.stake] or 0) + 1 + deck_usage.wins_by_key[SMODS.stake_from_index(G.GAME.stake)] = (deck_usage.wins_by_key[SMODS.stake_from_index(G.GAME.stake)] or 0) + 1 + local applied = SMODS.build_stake_chain(G.P_STAKES[SMODS.stake_from_index(G.GAME.stake)]) or {} + for i, v in ipairs(G.P_CENTER_POOLS.Stake) do + if applied[i] then + deck_usage.wins[i] = math.max(deck_usage.wins[i] or 0, 1) + deck_usage.wins_by_key[SMODS.stake_from_index(i)] = math.max(deck_usage.wins_by_key[SMODS.stake_from_index(i)] or 0, 1) + end + end + end + set_challenge_unlock() + G:save_settings() + G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] = deck_usage + end +end + +function Card:align_h_popup() + local focused_ui = self.children.focused_ui and true or false + local popup_direction = (self.children.buy_button or (self.area and self.area.config.view_deck) or (self.area and self.area.config.type == 'shop')) and 'cl' or + (self.T.y < G.CARD_H*0.8) and 'bm' or + 'tm' + local sign = 1 + if popup_direction == 'cl' and self.T.x <= G.ROOM.T.w*0.4 then + popup_direction = 'cr' + sign = -1 + end + return { + major = self.children.focused_ui or self, + parent = self, + xy_bond = 'Strong', + r_bond = 'Weak', + wh_bond = 'Weak', + offset = { + x = popup_direction ~= 'cl' and popup_direction ~= 'cr' and 0 or + focused_ui and sign*-0.05 or + (self.ability.consumeable and 0.0) or + (self.ability.set == 'Voucher' and 0.0) or + sign*-0.05, + y = focused_ui and ( + popup_direction == 'tm' and (self.area and self.area == G.hand and -0.08 or-0.15) or + popup_direction == 'bm' and 0.12 or + 0 + ) or + popup_direction == 'tm' and -0.13 or + popup_direction == 'bm' and 0.1 or + 0 + }, + type = popup_direction, + --lr_clamp = true + } +end + +function get_pack(_key, _type) + if not G.GAME.first_shop_buffoon and not G.GAME.banned_keys['p_buffoon_normal_1'] then + G.GAME.first_shop_buffoon = true + return G.P_CENTERS['p_buffoon_normal_'..(math.random(1, 2))] + end + local cume, it, center = 0, 0, nil + local temp_in_pool = {} + for k, v in ipairs(G.P_CENTER_POOLS['Booster']) do + local add + v.current_weight = v.get_weight and v:get_weight() or v.weight or 1 + if (not _type or _type == v.kind) then add = true end + if v.in_pool and type(v.in_pool) == 'function' then + local res, pool_opts = v:in_pool() + pool_opts = pool_opts or {} + add = res and (add or pool_opts.override_base_checks) + end + if add and not G.GAME.banned_keys[v.key] then cume = cume + (v.current_weight or 1); temp_in_pool[v.key] = true end + end + local poll = pseudorandom(pseudoseed((_key or 'pack_generic')..G.GAME.round_resets.ante))*cume + for k, v in ipairs(G.P_CENTER_POOLS['Booster']) do + if temp_in_pool[v.key] then + it = it + (v.current_weight or 1) + if it >= poll and it - (v.current_weight or 1) <= poll then center = v; break end + end + end + if not center then center = G.P_CENTERS['p_buffoon_normal_1'] end return center +end + +--#region quantum enhancements API +-- prevent base chips from applying with extra enhancements +local gcb = Card.get_chip_bonus +function Card:get_chip_bonus() + if not self.ability.extra_enhancement then + return gcb(self) + end + if self.debuff then return 0 end + return self.ability.bonus + (self.ability.perma_bonus or 0) +end + +-- prevent quantum enhacements from applying seal effects +local ccs = Card.calculate_seal +function Card:calculate_seal(context) + if self.ability.extra_enhancement then return end + return ccs(self, context) +end +--#endregion + +function playing_card_joker_effects(cards) + SMODS.calculate_context({playing_card_added = true, cards = cards}) +end + +G.FUNCS.change_collab = function(args) + G.SETTINGS.CUSTOM_DECK.Collabs[args.cycle_config.curr_suit] = G.COLLABS.options[args.cycle_config.curr_suit][args.to_key] or 'default' + local deckskin_key = G.COLLABS.options[args.cycle_config.curr_suit][args.to_key] + local palette_loc_options = SMODS.DeckSkin.get_palette_loc_options(args.to_key, args.cycle_config.curr_suit) + local swap_node = G.OVERLAY_MENU:get_UIE_by_ID('palette_selector') + local selected_palette = 1 + for i, v in ipairs(G.COLLABS.colour_palettes[deckskin_key]) do + if G.SETTINGS.colour_palettes[args.cycle_config.curr_suit] == v then + selected_palette = i + end + end + G.FUNCS.update_suit_colours(args.cycle_config.curr_suit, deckskin_key, selected_palette) + G.FUNCS.update_collab_cards(args.to_key, args.cycle_config.curr_suit) + if swap_node then + for i=1, #swap_node.children do + swap_node.children[i]:remove() + swap_node.children[i] = nil + end + local new_palette_selector = {n=G.UIT.R, config={align = "cm", id = 'palette_selector'}, nodes={ + create_option_cycle({options = palette_loc_options, w = 5.5, cycle_shoulders = false, curr_suit = args.cycle_config.curr_suit, curr_skin = deckskin_key, opt_callback = 'change_colour_palette', current_option = selected_palette, colour = G.C.ORANGE, focus_args = {snap_to = true, nav = 'wide'}}), + }} + swap_node.UIBox:add_child(new_palette_selector, swap_node) + end + for k, v in pairs(G.I.CARD) do + if v.config and v.config.card and v.children.front and v.ability.effect ~= 'Stone Card' then + v:set_sprites(nil, v.config.card) + end + end + G:save_settings() +end + +G.FUNCS.change_colour_palette = function(args) + G.SETTINGS.colour_palettes[args.cycle_config.curr_suit] = G.COLLABS.colour_palettes[args.cycle_config.curr_skin][args.to_key] + G.FUNCS.update_suit_colours(args.cycle_config.curr_suit, args.cycle_config.curr_skin) + G.FUNCS.update_collab_cards(args.cycle_config.curr_skin, args.cycle_config.curr_suit) + for k, v in pairs(G.I.CARD) do + if v.config and v.config.card and v.children.front and v.ability.effect ~= 'Stone Card' then + v:set_sprites(nil, v.config.card) + end + end + G:save_settings() +end \ No newline at end of file diff --git a/smods-main/src/ui.lua b/smods-main/src/ui.lua new file mode 100644 index 0000000..0490272 --- /dev/null +++ b/smods-main/src/ui.lua @@ -0,0 +1,1821 @@ +SMODS.GUI = {} +SMODS.GUI.DynamicUIManager = {} + +function STR_UNPACK(str) + local chunk, err = loadstring(str) + if chunk then + setfenv(chunk, {}) -- Use an empty environment to prevent access to potentially harmful functions + local success, result = pcall(chunk) + if success then + return result + else + print("Error unpacking string: " .. result) + return nil + end + else + print("Error loading string: " .. err) + return nil + end +end + + +local gameMainMenuRef = Game.main_menu +function Game:main_menu(change_context) + for k, v in pairs(G.C.SUITS) do + G.FUNCS.update_suit_colours(k, G.SETTINGS.CUSTOM_DECK.Collabs[k]) + end + gameMainMenuRef(self, change_context) + UIBox({ + definition = { + n = G.UIT.ROOT, + config = { + align = "cm", + colour = G.C.UI.TRANSPARENT_DARK + }, + nodes = { + { + n = G.UIT.T, + config = { + scale = 0.3, + text = MODDED_VERSION, + colour = G.C.UI.TEXT_LIGHT + } + } + } + }, + config = { + align = "tri", + bond = "Weak", + offset = { + x = 0, + y = 0.3 + }, + major = G.ROOM_ATTACH + } + }) +end + +local gameUpdateRef = Game.update +function Game:update(dt) + if G.STATE ~= G.STATES.SPLASH and G.MAIN_MENU_UI then + local node = G.MAIN_MENU_UI:get_UIE_by_ID("main_menu_play") + + if node and not node.children.alert then + node.children.alert = UIBox({ + definition = create_UIBox_card_alert({ + text = localize('b_modded_version'), + no_bg = true, + scale = 0.4, + text_rot = -0.2 + }), + config = { + align = "tli", + offset = { + x = -0.1, + y = 0 + }, + major = node, + parent = node + } + }) + node.children.alert.states.collide.can = false + end + end + gameUpdateRef(self, dt) +end + +local function wrapText(text, maxChars) + local wrappedText = "" + local currentLineLength = 0 + + for word in text:gmatch("%S+") do + if currentLineLength + #word <= maxChars then + wrappedText = wrappedText .. word .. ' ' + currentLineLength = currentLineLength + #word + 1 + else + wrappedText = wrappedText .. '\n' .. word .. ' ' + currentLineLength = #word + 1 + end + end + + return wrappedText +end + +-- Helper function to concatenate author names +local function concatAuthors(authors) + if type(authors) == "table" then + return table.concat(authors, ", ") + end + return authors or localize('b_unknown') +end + + +SMODS.LAST_SELECTED_MOD_TAB = "mod_desc" +function create_UIBox_mods(args) + local mod = G.ACTIVE_MOD_UI + if not SMODS.LAST_SELECTED_MOD_TAB then SMODS.LAST_SELECTED_MOD_TAB = "mod_desc" end + + local mod_tabs = {} + table.insert(mod_tabs, buildModDescTab(mod)) + local additions_tab = buildAdditionsTab(mod) + if additions_tab then table.insert(mod_tabs, additions_tab) end + local credits_func = mod.credits_tab + if credits_func and type(credits_func) == 'function' then + table.insert(mod_tabs, { + label = localize("b_credits"), + chosen = SMODS.LAST_SELECTED_MOD_TAB == "credits" or false, + tab_definition_function = function(...) + SMODS.LAST_SELECTED_MOD_TAB = "credits" + return credits_func(...) + end + }) + end + local config_func = mod.config_tab + if config_func and type(config_func) == 'function' then + table.insert(mod_tabs, { + label = localize("b_config"), + chosen = SMODS.LAST_SELECTED_MOD_TAB == "config" or false, + tab_definition_function = function(...) + SMODS.LAST_SELECTED_MOD_TAB = "config" + return config_func(...) + end + }) + end + + local mod_has_achievement + for _, v in pairs(SMODS.Achievements) do + if v.mod.id == mod.id then mod_has_achievement = true end + end + if mod_has_achievement then table.insert(mod_tabs, + { + label = localize("b_achievements"), + chosen = SMODS.LAST_SELECTED_MOD_TAB == "achievements" or false, + tab_definition_function = function() + SMODS.LAST_SELECTED_MOD_TAB = "achievements" + return buildAchievementsTab(mod) + end + }) + end + + local custom_ui_func = mod.extra_tabs + if custom_ui_func and type(custom_ui_func) == 'function' then + local custom_tabs = custom_ui_func() + if next(custom_tabs) and #custom_tabs == 0 then custom_tabs = { custom_tabs } end + for i, v in ipairs(custom_tabs) do + local id = mod.id..'_'..i + v.chosen = (SMODS.LAST_SELECTED_MOD_TAB == id) or false + v.label = v.label or '' + local def = v.tab_definition_function + assert(def, ('Custom defined mod tab with label "%s" from mod with id %s is missing definition function'):format(v.label, mod.id)) + v.tab_definition_function = function(...) + SMODS.LAST_SELECTED_MOD_TAB = id + return def(...) + end + table.insert(mod_tabs, v) + end + end + + return (create_UIBox_generic_options({ + back_func = "mods_button", + contents = { + { + n = G.UIT.R, + config = { + padding = 0, + align = "tm" + }, + nodes = { + create_tabs({ + snap_to_nav = true, + colour = G.C.BOOSTER, + tabs = mod_tabs + }) + } + } + } + })) +end + +function buildModDescTab(mod) + G.E_MANAGER:add_event(Event({ + blockable = false, + func = function() + G.REFRESH_ALERTS = nil + return true + end + })) + local label = mod.name + if (G.localization.descriptions.Mod or {})[mod.id] then + label = localize { type = 'name_text', set = 'Mod', key = mod.id } + end + return { + label = label, + chosen = SMODS.LAST_SELECTED_MOD_TAB == "mod_desc" or false, + tab_definition_function = function() + local modNodes = {} + local scale = 0.75 -- Scale factor for text + local maxCharsPerLine = 50 + + local wrappedDescription = wrapText(mod.description or '', maxCharsPerLine) + + local authors = localize('b_author' .. (#mod.author > 1 and 's' or '')) .. ': ' .. concatAuthors(mod.author) + + -- Authors names in blue + table.insert(modNodes, { + n = G.UIT.R, + config = { + padding = 0, + align = "cm", + r = 0.1, + emboss = 0.1, + outline = 1, + padding = 0.07 + }, + nodes = { + { + n = G.UIT.T, + config = { + text = authors, + shadow = true, + scale = scale * 0.65, + colour = G.C.BLUE, + } + } + } + }) + + -- Mod description + if (G.localization.descriptions.Mod or {})[mod.id] then + modNodes[#modNodes + 1] = {} + local loc_vars = mod.description_loc_vars and mod:description_loc_vars() or {} + localize { type = 'descriptions', key = loc_vars.key or mod.id, set = 'Mod', nodes = modNodes[#modNodes], vars = loc_vars.vars, scale = loc_vars.scale, text_colour = loc_vars.text_colour, shadow = loc_vars.shadow } + modNodes[#modNodes] = desc_from_rows(modNodes[#modNodes]) + modNodes[#modNodes].config.colour = loc_vars.background_colour or modNodes[#modNodes].config.colour + else + table.insert(modNodes, { + n = G.UIT.R, + config = { + padding = 0.2, + align = "cm" + }, + nodes = { + { + n = G.UIT.T, + config = { + text = wrappedDescription, + shadow = true, + scale = scale * 0.5, + colour = G.C.UI.TEXT_LIGHT + } + } + } + }) + end + + local custom_ui_func = mod.custom_ui + if custom_ui_func and type(custom_ui_func) == 'function' then + custom_ui_func(modNodes) + end + + return { + n = G.UIT.ROOT, + config = { + emboss = 0.05, + minh = 6, + r = 0.1, + minw = 6, + align = "tm", + padding = 0.2, + colour = G.C.BLACK + }, + nodes = modNodes + } + end + } +end + +function buildAdditionsTab(mod) + local consumable_nodes = {} + for _, key in ipairs(SMODS.ConsumableType.ctype_buffer) do + local id = 'your_collection_'..key:lower()..'s' + local tally = modsCollectionTally(G.P_CENTER_POOLS[key]) + if tally.of > 0 then + consumable_nodes[#consumable_nodes+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = tally, minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) + end + end + if #consumable_nodes > 3 then + consumable_nodes = { UIBox_button({ button = 'your_collection_consumables', label = {localize('b_stat_consumables'), localize{ type = 'variable', key = 'c_types', vars = {#consumable_nodes} } }, count = modsCollectionTally(G.P_CENTER_POOLS.Consumeables), minw = 4, minh = 4, id = 'your_collection_consumables', colour = G.C.FILTER }) } + end + + local leftside_nodes = {} + for _, v in ipairs { { k = 'Joker', minh = 1.7, scale = 0.6 }, { k = 'Back', b = 'decks' }, { k = 'Voucher' } } do + v.b = v.b or v.k:lower()..'s' + v.l = v.l or v.b + local tally = modsCollectionTally(G.P_CENTER_POOLS[v.k]) + if tally.of > 0 then + leftside_nodes[#leftside_nodes+1] = UIBox_button({button = 'your_collection_'..v.b, label = {localize('b_'..v.l)}, count = modsCollectionTally(G.P_CENTER_POOLS[v.k]), minw = 5, minh = v.minh, scale = v.scale, id = 'your_collection_'..v.b}) + end + end + if #consumable_nodes > 0 then + leftside_nodes[#leftside_nodes + 1] = { + n = G.UIT.R, + config = { align = "cm", padding = 0.1, r = 0.2, colour = G.C.BLACK }, + nodes = { + { + n = G.UIT.C, + config = { align = "cm", maxh = 2.9 }, + nodes = { + { n = G.UIT.T, config = { text = localize('k_cap_consumables'), scale = 0.45, colour = G.C.L_BLACK, vert = true, maxh = 2.2 } }, + } + }, + { n = G.UIT.C, config = { align = "cm", padding = 0.15 }, nodes = consumable_nodes } + } + } + end + + local rightside_nodes = {} + for _, v in ipairs { { k = 'Enhanced', b = 'enhancements', l = 'enhanced_cards'}, { k = 'Seal' }, { k = 'Edition' }, { k = 'Booster', l = 'booster_packs' }, { b = 'tags', p = G.P_TAGS }, { b = 'blinds', p = G.P_BLINDS, minh = 2.0 }, } do + v.b = v.b or v.k:lower()..'s' + v.l = v.l or v.b + v.p = v.p or G.P_CENTER_POOLS[v.k] + local tally = modsCollectionTally(v.p) + if tally.of > 0 then + rightside_nodes[#rightside_nodes+1] = UIBox_button({button = 'your_collection_'..v.b, label = {localize('b_'..v.l)}, count = modsCollectionTally(v.p), minw = 5, minh = v.minh, id = 'your_collection_'..v.b}) + end + end + local has_other_gameobjects = create_UIBox_Other_GameObjects() + if has_other_gameobjects then + rightside_nodes[#rightside_nodes+1] = UIBox_button({button = 'your_collection_other_gameobjects', label = {localize('k_other')}, minw = 5, id = 'your_collection_other_gameobjects', focus_args = {snap_to = true}}) + end + + local t = {n=G.UIT.R, config={align = "cm",padding = 0.2, minw = 7}, nodes={ + {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes = leftside_nodes }, + {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes = rightside_nodes } + }} + + local modNodes = {} + table.insert(modNodes, t) + return (#leftside_nodes > 0 or #rightside_nodes > 0 ) and { + label = localize("b_additions"), + chosen = SMODS.LAST_SELECTED_MOD_TAB == "additions" or false, + tab_definition_function = function() + SMODS.LAST_SELECTED_MOD_TAB = "additions" + return { + n = G.UIT.ROOT, + config = { + emboss = 0.05, + minh = 6, + r = 0.1, + minw = 6, + align = "tm", + padding = 0.2, + colour = G.C.BLACK + }, + nodes = modNodes + } + end + } or nil +end + +-- Disable alerts when in Additions tab +local set_alerts_ref = set_alerts +function set_alerts() + if G.ACTIVE_MOD_UI then + else + set_alerts_ref() + end +end + +G.FUNCS.your_collection_other_gameobjects = function(e) + G.SETTINGS.paused = true + G.FUNCS.overlay_menu{ + definition = create_UIBox_Other_GameObjects(), + } +end + +function create_UIBox_Other_GameObjects() + local custom_gameobject_tabs = {{}} + local curr_height = 0 + local curr_col = 1 + local other_collections_tabs = {} + local smods_uibox_buttons = { + { + count = G.ACTIVE_MOD_UI and modsCollectionTally(SMODS.Stickers), --Returns nil outside of G.ACTIVE_MOD_UI but we don't use it anyways + button = UIBox_button({button = 'your_collection_stickers', label = {localize('b_stickers')}, count = G.ACTIVE_MOD_UI and modsCollectionTally(SMODS.Stickers), minw = 5, id = 'your_collection_stickers'}) + } + } + + if G.ACTIVE_MOD_UI then + for _, tab in pairs(smods_uibox_buttons) do + if tab.count.of > 0 then other_collections_tabs[#other_collections_tabs+1] = tab.button end + end + if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.custom_collection_tabs then + object_tabs = G.ACTIVE_MOD_UI.custom_collection_tabs() + for _, tab in ipairs(object_tabs) do + other_collections_tabs[#other_collections_tabs+1] = tab + end + end + else + for _, tab in pairs(smods_uibox_buttons) do + other_collections_tabs[#other_collections_tabs+1] = tab.button + end + for _, mod in pairs(SMODS.Mods) do + if mod.custom_collection_tabs and type(mod.custom_collection_tabs) == "function" then + object_tabs = mod.custom_collection_tabs() + for _, tab in ipairs(object_tabs) do + other_collections_tabs[#other_collections_tabs+1] = tab + end + end + end + end + + local custom_gameobject_rows = {} + if #other_collections_tabs > 0 then + for _, gameobject_tabs in ipairs(other_collections_tabs) do + table.insert(custom_gameobject_tabs[curr_col], gameobject_tabs) + curr_height = curr_height + gameobject_tabs.nodes[1].config.minh + if curr_height > 6 then --TODO: Verify that this is the ideal number + curr_height = 0 + curr_col = curr_col + 1 + custom_gameobject_tabs[curr_col] = {} + end + end + for _, v in ipairs(custom_gameobject_tabs) do + table.insert(custom_gameobject_rows, {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes = v}) + end + + local t = {n=G.UIT.C, config={align = "cm", r = 0.1, colour = G.C.BLACK, padding = 0.1, emboss = 0.05, minw = 7}, nodes={ + {n=G.UIT.R, config={align = "cm", padding = 0.15}, nodes = custom_gameobject_rows} + }} + + return create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = {t}}) + else + return nil + end +end + +G.FUNCS.your_collection_consumables = function(e) + G.SETTINGS.paused = true + G.FUNCS.overlay_menu{ + definition = create_UIBox_your_collection_consumables(), + } +end + +function create_UIBox_your_collection_consumables() + local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = { + { n = G.UIT.C, config = { align = 'cm', minw = 11.5, minh = 6 }, nodes = { + { n = G.UIT.O, config = { id = 'consumable_collection', object = Moveable() },} + }}, + }}) + G.E_MANAGER:add_event(Event({func = function() + G.FUNCS.your_collection_consumables_page({ cycle_config = { current_option = 1 }}) + return true + end})) + return t +end + +G.FUNCS.your_collection_consumables_page = function(args) + if not args or not args.cycle_config then return end + if G.OVERLAY_MENU then + local uie = G.OVERLAY_MENU:get_UIE_by_ID('consumable_collection') + if uie then + if uie.config.object then + uie.config.object:remove() + end + uie.config.object = UIBox{ + definition = G.UIDEF.consumable_collection_page(args.cycle_config.current_option), + config = { align = 'cm', parent = uie} + } + end + end +end + +G.UIDEF.consumable_collection_page = function(page) + local nodes_per_page = 10 + local page_offset = nodes_per_page * ((page or 1) - 1) + local type_buf = {} + if G.ACTIVE_MOD_UI then + for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do + if modsCollectionTally(G.P_CENTER_POOLS[v]).of > 0 then type_buf[#type_buf + 1] = v end + end + else + type_buf = SMODS.ConsumableType.ctype_buffer + end + local center_options = {} + for i = 1, math.ceil(#type_buf / nodes_per_page) do + table.insert(center_options, + localize('k_page') .. + ' ' .. tostring(i) .. '/' .. tostring(math.ceil(#type_buf / nodes_per_page))) + end + local option_nodes = { create_option_cycle({ + options = center_options, + w = 4.5, + cycle_shoulders = true, + opt_callback = 'your_collection_consumables_page', + focus_args = { snap_to = true, nav = 'wide' }, + current_option = page or 1, + colour = G.C.RED, + no_pips = true + }) } + local function create_consumable_nodes(_start, _end) + local t = {} + for i = _start, _end do + local key = type_buf[i] + if not key then + if i == _start then break end + t[#t+1] = { n = G.UIT.R, config = { align ='cm', minh = 0.81 }, nodes = {}} + else + local id = 'your_collection_'..key:lower()..'s' + t[#t+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = G.ACTIVE_MOD_UI and modsCollectionTally(G.P_CENTER_POOLS[key]) or G.DISCOVER_TALLIES[key:lower()..'s'], minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) + end + end + return t + end + + local t = { n = G.UIT.C, config = { align = 'cm' }, nodes = { + {n=G.UIT.R, config = {align="cm"}, nodes = { + {n=G.UIT.C, config={align = "tm", padding = 0.15}, nodes= create_consumable_nodes(page_offset + 1, page_offset + math.ceil(nodes_per_page/2))}, + {n=G.UIT.C, config={align = "tm", padding = 0.15}, nodes= create_consumable_nodes(page_offset+1+math.ceil(nodes_per_page/2), page_offset + nodes_per_page)}, + }}, + {n=G.UIT.R, config = {align="cm"}, nodes = option_nodes}, + }} + return t +end + +function buildAchievementsTab(mod, current_page) + current_page = current_page or 1 + fetch_achievements() + local achievement_matrix = {{},{}} + local achievements_per_row = 3 + local achievements_pool = {} + for k, v in pairs(G.ACHIEVEMENTS) do + if v.mod and v.mod.id == mod.id then achievements_pool[#achievements_pool+1] = v end + end + + local achievement_tab = {} + for k, v in pairs(achievements_pool) do + achievement_tab[#achievement_tab+1] = v + end + + table.sort(achievement_tab, function(a, b) return (a.order or 1) < (b.order or 1) end) + + local row = 1 + local max_lines = 2 + for i = 1, achievements_per_row*2 do + local v = achievement_tab[i+((achievements_per_row*2)*(current_page-1))] + if not v then break end + local temp_achievement = Sprite(0,0,1.1,1.1,G.ASSET_ATLAS[v.atlas or "achievements"], v.earned and v.pos or {x=0, y=0}) + temp_achievement:define_draw_steps({ + {shader = 'dissolve', shadow_height = 0.05}, + {shader = 'dissolve'} + }) + if i == 1 then + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = (function() + G.CONTROLLER:snap_to{node = temp_achievement} + return true + end) + })) + end + temp_achievement.float = true + temp_achievement.states.hover.can = true + temp_achievement.states.drag.can = false + temp_achievement.states.collide.can = true + --temp_achievement.config = {blind = v, force_focus = true} + temp_achievement.hover = function() + if not G.CONTROLLER.dragging.target or G.CONTROLLER.using_touch then + if not temp_achievement.hovering and temp_achievement.states.visible then + temp_achievement.hovering = true + temp_achievement.hover_tilt = 3 + temp_achievement:juice_up(0.05, 0.02) + play_sound('chips1', math.random()*0.1 + 0.55, 0.12) + Node.hover(temp_achievement) + if temp_achievement.children.alert then + temp_achievement.children.alert:remove() + temp_achievement.children.alert = nil + v.alerted = true + G:save_progress() + end + end + end + temp_achievement.stop_hover = function() temp_achievement.hovering = false; Node.stop_hover(temp_achievement); temp_achievement.hover_tilt = 0 end + end + + -- Description + local achievement_text = {} + local maxCharsPerLine = 30 + local function wrapText(text, maxChars) + local wrappedText = {""} + local curr_line = 1 + local currentLineLength = 0 + + for word in text:gmatch("%S+") do + if currentLineLength + #word <= maxChars then + wrappedText[curr_line] = wrappedText[curr_line] .. word .. ' ' + currentLineLength = currentLineLength + #word + 1 + else + wrappedText[curr_line] = string.sub(wrappedText[curr_line], 0, -2) + curr_line = curr_line + 1 + wrappedText[curr_line] = "" + wrappedText[curr_line] = wrappedText[curr_line] .. word .. ' ' + currentLineLength = #word + 1 + end + end + + wrappedText[curr_line] = string.sub(wrappedText[curr_line], 0, -2) + return wrappedText + end + + local loc_target = (v.hidden_text and not v.earned) and {localize("hidden_achievement", 'achievement_descriptions')} or wrapText(localize(v.key, 'achievement_descriptions'), maxCharsPerLine) + local loc_name = (v.hidden_name and not v.earned) and localize("hidden_achievement", 'achievement_names') or localize(v.key, 'achievement_names') + + local ability_text = {} + if loc_target then + for k, v in ipairs(loc_target) do + ability_text[#ability_text + 1] = {n=G.UIT.R, config={align = "cm"}, nodes={{n=G.UIT.T, config={text = v, scale = 0.35, shadow = true, colour = G.C.WHITE}}}} + end + end + max_lines = math.max(max_lines, #ability_text) + achievement_text[#achievement_text + 1] = + {n=G.UIT.R, config={align = "cm", emboss = 0.05, r = 0.1, minw = 4, maxw = 4, padding = 0.05, colour = G.C.WHITE, minh = 0.4*max_lines+0.1}, nodes={ + ability_text[1] and {n=G.UIT.R, config={align = "cm", padding = 0.08, colour = G.C.GREY, r = 0.1, emboss = 0.05, minw = 3.9, maxw = 3.9, minh = 0.4*max_lines}, nodes=ability_text} or nil + }} + + table.insert(achievement_matrix[row], { + n = G.UIT.C, + config = { align = "cm", padding = 0.1 }, + nodes = { + {n=G.UIT.R, config = {align = "cm"}, nodes = { + {n=G.UIT.R, config = {align = "cm", padding = 0.1}, nodes = {{ n = G.UIT.O, config = { object = temp_achievement, focus_with_object = true }}}}, + { + n=G.UIT.R, config = {align = "cm", minw = 4, maxw = 4, padding = 0.05}, nodes = { + {n=G.UIT.R, config={align = "cm", emboss = 0.05, r = 0.1, padding = 0.1, minh = 0.6, colour = G.C.GREY}, nodes={ + {n=G.UIT.O, config={align = "cm", maxw = 3.8, object = DynaText({string = loc_name, maxw = 3.8, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, spacing = 1, bump = true, scale = 0.4})}}, + }}, + {n=G.UIT.R, config={align = "cm"}, nodes=achievement_text}, + }, + }, + }}, + }, + }) + if #achievement_matrix[row] == achievements_per_row then + row = row + 1 + achievement_matrix[row] = {} + max_lines = 2 + end + end + + local achievements_options = {} + for i = 1, math.ceil(#achievements_pool/(2*achievements_per_row)) do + table.insert(achievements_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#achievements_pool/(2*achievements_per_row)))) + end + + local t = { + {n=G.UIT.C, config={}, nodes={ + {n=G.UIT.C, config={align = "cm"}, nodes={ + {n=G.UIT.R, config={align = "cm"}, nodes={ + {n=G.UIT.R, config={align = "cm", padding = 0.1 }, nodes=achievement_matrix[1]}, + {n=G.UIT.R, config={align = "cm", padding = 0.1 }, nodes=achievement_matrix[2]}, + create_option_cycle({options = achievements_options, w = 4.5, cycle_shoulders = true, opt_callback = 'achievments_tab_page', focus_args = {snap_to = true, nav = 'wide'},current_option = current_page, colour = G.C.RED, no_pips = true}) + }} + }} + }}} + return { + n = G.UIT.ROOT, + config = { + emboss = 0.05, + minh = 6, + r = 0.1, + minw = 6, + align = "tm", + padding = 0.2, + colour = G.C.BLACK + }, + nodes = t + } +end + +G.FUNCS.achievments_tab_page = function(args) + if not args or not args.cycle_config then return end + achievement_matrix = {{},{}} + + local tab_contents = G.OVERLAY_MENU:get_UIE_by_ID('tab_contents') + tab_contents.config.object:remove() + tab_contents.config.object = UIBox{ + definition = buildAchievementsTab(G.ACTIVE_MOD_UI, args.cycle_config.current_option), + config = {offset = {x=0,y=0}, parent = tab_contents, type = 'cm'} + } + tab_contents.UIBox:recalculate() +end + +-- TODO: Optimize this. +function modsCollectionTally(pool, set) + local set = set or nil + local obj_tally = {tally = 0, of = 0} + + for _, v in pairs(pool) do + if v.mod and G.ACTIVE_MOD_UI.id == v.mod.id and not v.no_collection then + if set then + if v.set and v.set == set then + obj_tally.of = obj_tally.of+1 + if v.discovered then + obj_tally.tally = obj_tally.tally+1 + end + end + else + obj_tally.of = obj_tally.of+1 + if v.discovered then + obj_tally.tally = obj_tally.tally+1 + end + end + end + end + + return obj_tally +end + +-- TODO: Make better solution +local UIBox_button_ref = UIBox_button +function UIBox_button(args) + local button = UIBox_button_ref(args) + button.nodes[1].config.count = args.count + return button +end + +function buildModtag(mod) + local tag_pos, tag_message, tag_atlas = { x = 0, y = 0 }, "load_success", mod.prefix and mod.prefix .. '_modicon' or 'modicon' + local specific_vars = {} + + if not mod.can_load then + tag_message = "load_failure" + tag_atlas = "mod_tags" + specific_vars = {} + if next(mod.load_issues.dependencies) then + tag_message = tag_message..'_d' + table.insert(specific_vars, concatAuthors(mod.load_issues.dependencies)) + end + if next(mod.load_issues.conflicts) then + tag_message = tag_message .. '_c' + table.insert(specific_vars, concatAuthors(mod.load_issues.conflicts)) + end + if mod.load_issues.outdated then tag_message = 'load_failure_o' end + if mod.load_issues.version_mismatch then + tag_message = 'load_failure_i' + specific_vars = {mod.load_issues.version_mismatch, MODDED_VERSION:gsub('-STEAMODDED', '')} + end + if mod.load_issues.main_file_not_found then + tag_message = 'load_failure_m' + specific_vars = {mod.main_file} + end + if mod.load_issues.prefix_conflict then + tag_message = 'load_failure_p' + local name = mod.load_issues.prefix_conflict + for _, m in ipairs(SMODS.mod_list) do + if m.id == mod.load_issues.prefix_conflict then + name = m.name or name + end + end + specific_vars = {name} + end + if mod.disabled then + tag_pos = {x = 1, y = 0} + tag_message = 'load_disabled' + end + end + + + local tag_sprite_tab = nil + + local tag_sprite = Sprite(0, 0, 0.8*1, 0.8*1, G.ASSET_ATLAS[tag_atlas] or G.ASSET_ATLAS['tags'], tag_pos) + tag_sprite.T.scale = 1 + tag_sprite_tab = {n= G.UIT.C, config={align = "cm", padding = 0}, nodes={ + {n=G.UIT.O, config={w=0.8*1, h=0.8*1, colour = G.C.BLUE, object = tag_sprite, focus_with_object = true}}, + }} + tag_sprite:define_draw_steps({ + {shader = 'dissolve', shadow_height = 0.05}, + {shader = 'dissolve'}, + }) + tag_sprite.float = true + tag_sprite.states.hover.can = true + tag_sprite.states.drag.can = false + tag_sprite.states.collide.can = true + + tag_sprite.hover = function(_self) + if not G.CONTROLLER.dragging.target or G.CONTROLLER.using_touch then + if not _self.hovering and _self.states.visible then + _self.hovering = true + if _self == tag_sprite then + _self.hover_tilt = 3 + _self:juice_up(0.05, 0.02) + play_sound('paper1', math.random()*0.1 + 0.55, 0.42) + play_sound('tarot2', math.random()*0.1 + 0.55, 0.09) + end + tag_sprite.ability_UIBox_table = generate_card_ui({set = "Other", discovered = false, key = tag_message}, nil, specific_vars, 'Other', nil, false) + _self.config.h_popup = G.UIDEF.card_h_popup(_self) + _self.config.h_popup_config ={align = 'cl', offset = {x=-0.1,y=0},parent = _self} + Node.hover(_self) + if _self.children.alert then + _self.children.alert:remove() + _self.children.alert = nil + G:save_progress() + end + end + end + end + tag_sprite.stop_hover = function(_self) _self.hovering = false; Node.stop_hover(_self); _self.hover_tilt = 0 end + + tag_sprite:juice_up() + + return tag_sprite_tab +end + +-- Helper function to create a clickable mod box +local function createClickableModBox(modInfo, scale) + local function invert(c) + return {1-c[1], 1-c[2], 1-c[3], c[4]} + end + local col, text_col + if modInfo.should_enable == nil then + modInfo.should_enable = not modInfo.disabled + end + if SMODS.full_restart == nil then + SMODS.full_restart = 0 + end + if modInfo.can_load then + col = G.C.BOOSTER + elseif modInfo.disabled then + col = G.C.UI.BACKGROUND_INACTIVE + else + col = mix_colours(G.C.RED, G.C.UI.BACKGROUND_INACTIVE, 0.7) + text_col = G.C.TEXT_DARK + end + local label = { " " .. modInfo.name .. " " } + if modInfo.lovely_only then + label[2] = localize('b_lovely_mod') + else + label[2] = localize('b_by') .. concatAuthors(modInfo.author) .. " " + end + local but = UIBox_button { + label = label, + shadow = true, + scale = scale, + colour = col, + text_colour = text_col, + button = "openModUI_" .. modInfo.id, + minh = 0.8, + minw = 7 + } + if modInfo.lovely_only then + local config = but.nodes[1].nodes[2].nodes[1].config + config.colour = mix_colours(invert(col), G.C.UI.TEXT_INACTIVE, 0.8) + config.scale = scale * .8 + end + if modInfo.version and modInfo.version ~= '0.0.0' then + table.insert(but.nodes[1].nodes[1].nodes, { + n = G.UIT.T, + config = { + text = ('(%s) '):format(modInfo.version), + scale = scale*0.8, + colour = mix_colours(invert(col), G.C.UI.TEXT_INACTIVE, 0.8), + shadow = true, + }, + }) + end + if modInfo.config_tab then + table.insert(but.nodes[1].nodes[1].nodes, { + n = G.UIT.O, + config = { + object = Sprite(0,0,0.4,0.4, G.ASSET_ATLAS['mod_tags'], {x=2,y=0}) + } + }) + end + return { + n = G.UIT.R, + config = { padding = 0, align = "cm" }, + nodes = { + { + n = G.UIT.C, + config = { align = "cm" }, + nodes = { + buildModtag(modInfo) + } + }, + { + n = G.UIT.C, + config = { align = "cm", padding = 0.1 }, + nodes = {}, + }, + { n = G.UIT.C, config = { padding = 0, align = "cm" }, nodes = { but } }, + create_toggle({ + label = '', + ref_table = modInfo, + ref_value = 'should_enable', + col = true, + w = 0, + h = 0.5, + callback = ( + function(_set_toggle) + if not modInfo.should_enable then + NFS.write(modInfo.path .. '.lovelyignore', '') + else + NFS.remove(modInfo.path .. '.lovelyignore') + end + local toChange = 1 + if modInfo.should_enable == not modInfo.disabled then + toChange = -1 + end + SMODS.full_restart = SMODS.full_restart + toChange + end + ) + }), + }} + +end + +function G.FUNCS.openModsDirectory(options) + love.system.openURL(SMODS.MODS_DIR) +end + +function G.FUNCS.mods_buttons_page(options) + if not options or not options.cycle_config then + return + end +end + +function SMODS.load_mod_config(mod) + local s1, config = pcall(function() + return load(NFS.read(('config/%s.jkr'):format(mod.id)), ('=[SMODS %s "config"]'):format(mod.id))() + end) + local s2, default_config = pcall(function() + return load(NFS.read(mod.path..(mod.config_file or 'config.lua')), ('=[SMODS %s "default_config"]'):format(mod.id))() + end) + if not s1 or type(config) ~= 'table' then config = {} end + if not s2 or type(default_config) ~= 'table' then default_config = {} end + mod.config = default_config + + local function insert_saved_config(savedCfg, defaultCfg) + for savedKey, savedVal in pairs(savedCfg) do + local savedValType = type(savedVal) + local defaultValType = type(defaultCfg[savedKey]) + if not defaultCfg[savedKey] then + defaultCfg[savedKey] = savedVal + elseif savedValType ~= defaultValType then + elseif savedValType == "table" and defaultValType == "table" then + insert_saved_config(savedVal, defaultCfg[savedKey]) + elseif savedVal ~= defaultCfg[savedKey] then + defaultCfg[savedKey] = savedVal + end + + end + end + + insert_saved_config(config, mod.config) + + return mod.config +end +SMODS:load_mod_config() +function SMODS.save_mod_config(mod) + local success = pcall(function() + NFS.createDirectory('config') + assert(mod.config and next(mod.config)) + local serialized = 'return '..serialize(mod.config) + NFS.write(('config/%s.jkr'):format(mod.id), serialized) + end) + return success +end +function SMODS.save_all_config() + SMODS:save_mod_config() + for _, v in ipairs(SMODS.mod_list) do + if v.can_load then + local save_func = type(v.save_mod_config) == 'function' and v.save_mod_config or SMODS.save_mod_config + save_func(v) + end + end +end + +function G.FUNCS.exit_mods(e) + G.ACTIVE_MOD_UI = nil + SMODS.save_all_config() + if SMODS.full_restart and SMODS.full_restart ~= 0 then + -- launch a new instance of the game and quit the current one + SMODS.restart_game() + end + SMODS.IN_MODS_TAB = nil + if e then + -- This is only needed when back button is pressed + G.FUNCS.exit_overlay_menu(e) + end +end + +function create_UIBox_mods_button() + local scale = 0.75 + SMODS.browse_search = SMODS.browse_search or '' + return (create_UIBox_generic_options({ + back_func = 'exit_mods', + contents = { + { + n = G.UIT.R, + config = { + padding = 0, + align = "cm" + }, + nodes = { + create_tabs({ + snap_to_nav = true, + colour = G.C.BOOSTER, + tabs = { + { + label = localize('b_mods'), + chosen = true, + tab_definition_function = function() + return SMODS.GUI.DynamicUIManager.initTab({ + updateFunctions = { + modsList = G.FUNCS.update_mod_list, + }, + staticPageDefinition = SMODS.GUI.staticModListContent() + }) + end + }, + -- { + -- label = localize('b_browse'), + -- tab_definition_function = function() + -- return { + -- n = G.UIT.ROOT, + -- config = { + -- align = "cm", + -- padding = 0.05, + -- colour = G.C.CLEAR, + -- }, + -- nodes = { + -- { + -- n = G.UIT.C, + -- config = { align = 'cm' }, + -- nodes = { + -- { + -- n = G.UIT.R, + -- config = { align = 'cl' }, + -- nodes = { + -- create_text_input{ + -- prompt_text = localize('b_search_prompt'), + -- max_length = 50, + -- text_scale = 0.6, + -- w = 6, + -- h = 1, + -- ref_table = SMODS, + -- ref_value = "browse_search", + -- extended_corpus = true, + -- }, + -- UIBox_button{ + -- button = 'browse_search', + -- label = {localize('b_search_button')}, + -- minw = 3, + -- colour = G.C.RED + -- } + -- } + -- }, + -- { + -- n = G.UIT.R, + -- config = { align = 'cm', emboss = 0.05, colour = G.C.BLACK, minh=5, minw=10.5}, + -- nodes = { + -- { + -- n = G.UIT.O, + -- config = { align = 'cm', object = Moveable(), id = 'browse_mods'} + -- } + -- } + -- } + -- } + -- } + -- } + -- } + -- end, + -- }, + { + + label = localize('b_credits'), + tab_definition_function = function() + return { + n = G.UIT.ROOT, + config = { + emboss = 0.05, + minh = 6, + r = 0.1, + minw = 6, + align = "cm", + padding = 0.2, + colour = G.C.BLACK + }, + nodes = { + { + n = G.UIT.R, + config = { + padding = 0, + align = "cm" + }, + nodes = { + { + n = G.UIT.T, + config = { + text = localize('b_mod_loader'), + shadow = true, + scale = scale * 0.8, + colour = G.C.UI.TEXT_LIGHT + } + } + } + }, + { + n = G.UIT.R, + config = { + padding = 0, + align = "cm" + }, + nodes = { + { + n = G.UIT.T, + config = { + text = localize('b_developed_by'), + shadow = true, + scale = scale * 0.8, + colour = G.C.UI.TEXT_LIGHT + } + }, + { + n = G.UIT.T, + config = { + text = "Steamo", + shadow = true, + scale = scale * 0.8, + colour = G.C.BLUE + } + } + } + }, + { + n = G.UIT.R, + config = { + padding = 0, + align = "cm" + }, + nodes = { + { + n = G.UIT.T, + config = { + text = localize('b_rewrite_by'), + shadow = true, + scale = scale * 0.8, + colour = G.C.UI.TEXT_LIGHT + } + }, + { + n = G.UIT.T, + config = { + text = "Aure", + shadow = true, + scale = scale * 0.8, + colour = G.C.BLUE + } + } + } + }, + { + n = G.UIT.R, + config = { + padding = 0.2, + align = "cm", + }, + nodes = { + UIBox_button({ + minw = 3.85, + button = "steamodded_github", + label = {localize('b_github_project')} + }) + } + }, + { + n = G.UIT.R, + config = { + padding = 0.2, + align = "cm" + }, + nodes = { + { + n = G.UIT.T, + config = { + text = localize('b_github_bugs_1')..'\n'..localize('b_github_bugs_2'), + shadow = true, + scale = scale * 0.5, + colour = G.C.UI.TEXT_LIGHT + } + }, + + } + }, + } + } + end + }, + { + label = localize('b_config'), + tab_definition_function = function() + return { + n = G.UIT.ROOT, + config = { + align = "cm", + padding = 0.05, + colour = G.C.CLEAR, + }, + nodes = { + create_toggle { + label = localize('b_disable_mod_badges'), + ref_table = SMODS.config, + ref_value = 'no_mod_badges', + }, + create_toggle { + label = localize('b_seeded_unlocks'), + info = {localize('b_seeded_unlocks_info')}, + ref_table = SMODS.config, + ref_value = 'seeded_unlocks', + }, + create_option_cycle { + w = 4.5, + scale = 0.8, + label = localize('b_achievements'), + options = localize('ml_achievement_settings'), + opt_callback = 'update_achievement_settings', + current_option = SMODS.config.achievements, + cycle_shoulders = true, + } + } + } + end + } + } + }) + } + } + } + })) +end + +G.FUNCS.update_achievement_settings = function(e) + local opt = (e.cycle_config or {}).current_option or 1 + SMODS.config.achievements = opt + G.F_NO_ACHIEVEMENTS = opt == 1 +end + +G.FUNCS.browse_search = function(e) + SMODS.fetch_index() + +end + +G.FUNCS.browse_mods_page = function(args) + local page = args.cycle_config and args.cycle_config.current_option or 1 +end + +function G.FUNCS.steamodded_github(e) + love.system.openURL("https://github.com/Steamopollys/Steamodded") +end + +function G.FUNCS.mods_button(e) + G.SETTINGS.paused = true + SMODS.LAST_SELECTED_MOD_TAB = nil + SMODS.IN_MODS_TAB = true + + G.FUNCS.overlay_menu({ + definition = create_UIBox_mods_button() + }) +end + +local create_UIBox_main_menu_buttonsRef = create_UIBox_main_menu_buttons +function create_UIBox_main_menu_buttons() + local modsButton = UIBox_button({ + id = "mods_button", + minh = 1.55, + minw = 1.85, + col = true, + button = "mods_button", + colour = G.C.BOOSTER, + label = {localize('b_mods_cap')}, + scale = 0.45 * 1.2 + }) + local menu = create_UIBox_main_menu_buttonsRef() + table.insert(menu.nodes[1].nodes[1].nodes, modsButton) + menu.nodes[1].nodes[1].config = {align = "cm", padding = 0.15, r = 0.1, emboss = 0.1, colour = G.C.L_BLACK, mid = true} + if SMODS.mod_button_alert then + G.E_MANAGER:add_event(Event({ + func = function() + if G.MAIN_MENU_UI then -- Wait until the ui is rendered before spawning the alert + UIBox{definition = create_UIBox_card_alert(), config = {align="tri", offset = {x = 0.05, y = -0.05}, major = G.MAIN_MENU_UI:get_UIE_by_ID('mods_button'), can_collide = false}} + return true + end + end, + blocking = false, + blockable = false + })) + end + return menu +end + +local create_UIBox_profile_buttonRef = create_UIBox_profile_button +function create_UIBox_profile_button() + local profile_menu = create_UIBox_profile_buttonRef() + profile_menu.nodes[1].config = {align = "cm", padding = 0.11, r = 0.1, emboss = 0.1, colour = G.C.L_BLACK} + return(profile_menu) +end + +-- Disable achievments and crash report upload +function initGlobals() + G.F_NO_ACHIEVEMENTS = SMODS.config.achievements == 1 + G.F_CRASH_REPORTS = false +end + +function G.FUNCS.update_mod_list(args) + if not args or not args.cycle_config then return end + SMODS.GUI.DynamicUIManager.updateDynamicAreas({ + ["modsList"] = SMODS.GUI.dynamicModListContent(args.cycle_config.current_option) + }) +end + +-- Same as Balatro base game code, but accepts a value to match against (rather than the index in the option list) +-- e.g. create_option_cycle({ current_option = 1 }) vs. SMODS.GUID.createOptionSelector({ current_option = "Page 1/2" }) +function SMODS.GUI.createOptionSelector(args) + args = args or {} + args.colour = args.colour or G.C.RED + args.options = args.options or { + 'Option 1', + 'Option 2' + } + + local current_option_index = 1 + for i, option in ipairs(args.options) do + if option == args.current_option then + current_option_index = i + break + end + end + args.current_option_val = args.options[current_option_index] + args.current_option = current_option_index + args.opt_callback = args.opt_callback or nil + args.scale = args.scale or 1 + args.ref_table = args.ref_table or nil + args.ref_value = args.ref_value or nil + args.w = (args.w or 2.5)*args.scale + args.h = (args.h or 0.8)*args.scale + args.text_scale = (args.text_scale or 0.5)*args.scale + args.l = '<' + args.r = '>' + args.focus_args = args.focus_args or {} + args.focus_args.type = 'cycle' + + local info = nil + if args.info then + info = {} + for k, v in ipairs(args.info) do + table.insert(info, {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ + {n=G.UIT.T, config={text = v, scale = 0.3*args.scale, colour = G.C.UI.TEXT_LIGHT}} + }}) + end + info = {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes=info} + end + + local disabled = #args.options < 2 + local pips = {} + for i = 1, #args.options do + pips[#pips+1] = {n=G.UIT.B, config={w = 0.1*args.scale, h = 0.1*args.scale, r = 0.05, id = 'pip_'..i, colour = args.current_option == i and G.C.WHITE or G.C.BLACK}} + end + + local choice_pips = not args.no_pips and {n=G.UIT.R, config={align = "cm", padding = (0.05 - (#args.options > 15 and 0.03 or 0))*args.scale}, nodes=pips} or nil + + local t = + {n=G.UIT.C, config={align = "cm", padding = 0.1, r = 0.1, colour = G.C.CLEAR, id = args.id and (not args.label and args.id or nil) or nil, focus_args = args.focus_args}, nodes={ + {n=G.UIT.C, config={align = "cm",r = 0.1, minw = 0.6*args.scale, hover = not disabled, colour = not disabled and args.colour or G.C.BLACK,shadow = not disabled, button = not disabled and 'option_cycle' or nil, ref_table = args, ref_value = 'l', focus_args = {type = 'none'}}, nodes={ + {n=G.UIT.T, config={ref_table = args, ref_value = 'l', scale = args.text_scale, colour = not disabled and G.C.UI.TEXT_LIGHT or G.C.UI.TEXT_INACTIVE}} + }}, + args.mid and + {n=G.UIT.C, config={id = 'cycle_main'}, nodes={ + {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ + args.mid + }}, + not disabled and choice_pips or nil + }} + or {n=G.UIT.C, config={id = 'cycle_main', align = "cm", minw = args.w, minh = args.h, r = 0.1, padding = 0.05, colour = args.colour,emboss = 0.1, hover = true, can_collide = true, on_demand_tooltip = args.on_demand_tooltip}, nodes={ + {n=G.UIT.R, config={align = "cm"}, nodes={ + {n=G.UIT.R, config={align = "cm"}, nodes={ + {n=G.UIT.O, config={object = DynaText({string = {{ref_table = args, ref_value = "current_option_val"}}, colours = {G.C.UI.TEXT_LIGHT},pop_in = 0, pop_in_rate = 8, reset_pop_in = true,shadow = true, float = true, silent = true, bump = true, scale = args.text_scale, non_recalc = true})}}, + }}, + {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ + }}, + not disabled and choice_pips or nil + }} + }}, + {n=G.UIT.C, config={align = "cm",r = 0.1, minw = 0.6*args.scale, hover = not disabled, colour = not disabled and args.colour or G.C.BLACK,shadow = not disabled, button = not disabled and 'option_cycle' or nil, ref_table = args, ref_value = 'r', focus_args = {type = 'none'}}, nodes={ + {n=G.UIT.T, config={ref_table = args, ref_value = 'r', scale = args.text_scale, colour = not disabled and G.C.UI.TEXT_LIGHT or G.C.UI.TEXT_INACTIVE}} + }}, + }} + + if args.cycle_shoulders then + t = + {n=G.UIT.R, config={align = "cm", colour = G.C.CLEAR}, nodes = { + {n=G.UIT.C, config={minw = 0.7,align = "cm", colour = G.C.CLEAR,func = 'set_button_pip', focus_args = {button = 'leftshoulder', type = 'none', orientation = 'cm', scale = 0.7, offset = {x = -0.1, y = 0}}}, nodes = {}}, + {n=G.UIT.C, config={id = 'cycle_shoulders', padding = 0.1}, nodes={t}}, + {n=G.UIT.C, config={minw = 0.7,align = "cm", colour = G.C.CLEAR,func = 'set_button_pip', focus_args = {button = 'rightshoulder', type = 'none', orientation = 'cm', scale = 0.7, offset = {x = 0.1, y = 0}}}, nodes = {}}, + }} + else + t = + {n=G.UIT.R, config={align = "cm", colour = G.C.CLEAR, padding = 0.0}, nodes = { + t + }} + end + if args.label or args.info then + t = {n=G.UIT.R, config={align = "cm", padding = 0.05, id = args.id or nil}, nodes={ + args.label and {n=G.UIT.R, config={align = "cm"}, nodes={ + {n=G.UIT.T, config={text = args.label, scale = 0.5*args.scale, colour = G.C.UI.TEXT_LIGHT}} + }} or nil, + t, + info, + }} + end + return t +end + +local function generateBaseNode(staticPageDefinition) + return { + n = G.UIT.ROOT, + config = { + emboss = 0.05, + minh = 6, + r = 0.1, + minw = 8, + align = "cm", + padding = 0.2, + colour = G.C.BLACK + }, + nodes = { + staticPageDefinition + } + } +end + +-- Initialize a tab with sections that can be updated dynamically (e.g. modifying text labels, showing additional UI elements after toggling buttons, etc.) +function SMODS.GUI.DynamicUIManager.initTab(args) + local updateFunctions = args.updateFunctions + local staticPageDefinition = args.staticPageDefinition + + for _, updateFunction in pairs(updateFunctions) do + G.E_MANAGER:add_event(Event({func = function() + updateFunction{cycle_config = {}} + return true + end})) + end + return generateBaseNode(staticPageDefinition) +end + +-- Call this to trigger an update for a list of dynamic content areas +function SMODS.GUI.DynamicUIManager.updateDynamicAreas(uiDefinitions) + for id, uiDefinition in pairs(uiDefinitions) do + local dynamicArea = G.OVERLAY_MENU:get_UIE_by_ID(id) + if dynamicArea and dynamicArea.config.object then + dynamicArea.config.object:remove() + dynamicArea.config.object = UIBox{ + definition = uiDefinition, + config = {offset = {x=0, y=0}, align = 'cm', parent = dynamicArea} + } + end + end +end + +local function recalculateModsList(page) + page = page or SMODS.LAST_VIEWED_MODS_PAGE or 1 + SMODS.LAST_VIEWED_MODS_PAGE = page + local modsPerPage = 4 + local startIndex = (page - 1) * modsPerPage + 1 + local endIndex = startIndex + modsPerPage - 1 + local totalPages = math.ceil(#SMODS.mod_list / modsPerPage) + local currentPage = localize('k_page') .. ' ' .. page .. "/" .. totalPages + local pageOptions = {} + for i = 1, totalPages do + table.insert(pageOptions, (localize('k_page') .. ' ' .. tostring(i) .. "/" .. totalPages)) + end + local showingList = #SMODS.mod_list > 0 + + return currentPage, pageOptions, showingList, startIndex, endIndex, modsPerPage +end + +-- Define the content in the pane that does not need to update +-- Should include OBJECT nodes that indicate where the dynamic content sections will be populated +-- EX: in this pane the 'modsList' node will contain the dynamic content which is defined in the function below +function SMODS.GUI.staticModListContent() + local scale = 0.75 + local currentPage, pageOptions, showingList = recalculateModsList() + return { + n = G.UIT.ROOT, + config = { + minh = 6, + r = 0.1, + minw = 10, + align = "tm", + padding = 0.2, + colour = G.C.BLACK + }, + nodes = { + -- row container + { + n = G.UIT.R, + config = { align = "cm", padding = 0.05 }, + nodes = { + -- column container + { + n = G.UIT.C, + config = { align = "cm", minw = 3, padding = 0.2, r = 0.1, colour = G.C.CLEAR }, + nodes = { + -- title row + { + n = G.UIT.R, + config = { + padding = 0.05, + align = "cm" + }, + nodes = { + UIBox_button({ + label = { localize('b_mod_list') }, + shadow = true, + scale = scale*0.85, + colour = G.C.BOOSTER, + button = "openModsDirectory", + minh = scale, + minw = 9 + }), + } + }, + + -- add some empty rows for spacing + { + n = G.UIT.R, + config = { align = "cm", padding = 0.05 }, + nodes = {} + }, + { + n = G.UIT.R, + config = { align = "cm", padding = 0.05 }, + nodes = {} + }, + { + n = G.UIT.R, + config = { align = "cm", padding = 0.05 }, + nodes = {} + }, + { + n = G.UIT.R, + config = { align = "cm", padding = 0.05 }, + nodes = {} + }, + + -- dynamic content rendered in this row container + -- list of 4 mods on the current page + { + n = G.UIT.R, + config = { + padding = 0.05, + align = "cm", + minh = 2, + minw = 4 + }, + nodes = { + {n=G.UIT.O, config={id = 'modsList', object = Moveable()}}, + } + }, + + -- another empty row for spacing + { + n = G.UIT.R, + config = { align = "cm", padding = 0.3 }, + nodes = {} + }, + + -- page selector + -- does not appear when list of mods is empty + showingList and SMODS.GUI.createOptionSelector({label = "", scale = 0.8, options = pageOptions, opt_callback = 'update_mod_list', no_pips = true, current_option = ( + currentPage + )}) or nil + } + }, + } + }, + } + } +end + +function SMODS.GUI.dynamicModListContent(page) + local scale = 0.75 + local _, __, showingList, startIndex, endIndex, modsPerPage = recalculateModsList(page) + + local modNodes = {} + + -- If no mods are loaded, show a default message + if showingList == false then + table.insert(modNodes, { + n = G.UIT.R, + config = { + padding = 0, + align = "cm" + }, + nodes = { + { + n = G.UIT.T, + config = { + text = localize('b_no_mods'), + shadow = true, + scale = scale * 0.5, + colour = G.C.UI.TEXT_DARK + } + } + } + }) + else + local modCount = 0 + local id = 0 + + for _, condition in ipairs({ + function(m) return not m.can_load and not m.disabled end, + function(m) return m.can_load and m.config_tab end, + function(m) return m.can_load and not m.config_tab end, + function(m) return m.disabled end, + }) do + for _, modInfo in ipairs(SMODS.mod_list) do + if modCount >= modsPerPage then break end + if condition(modInfo) then + id = id + 1 + if id >= startIndex and id <= endIndex then + table.insert(modNodes, createClickableModBox(modInfo, scale * 0.5)) + modCount = modCount + 1 + end + end + end + end + end + + return { + n = G.UIT.C, + config = { + r = 0.1, + align = "cm", + padding = 0.2, + }, + nodes = modNodes + } +end + +G.FUNCS.SMODS_change_mipmap = function(args) + SMODS.config.graphics_mipmap_level = args.to_key + G:set_render_settings() + SMODS:save_mod_config() +end + +SMODS.card_collection_UIBox = function(_pool, rows, args) + args = args or {} + args.w_mod = args.w_mod or 1 + args.h_mod = args.h_mod or 1 + args.card_scale = args.card_scale or 1 + local deck_tables = {} + local pool = SMODS.collection_pool(_pool) + + G.your_collection = {} + local cards_per_page = 0 + local row_totals = {} + for j = 1, #rows do + if cards_per_page >= #pool and args.collapse_single_page then + rows[j] = nil + else + row_totals[j] = cards_per_page + cards_per_page = cards_per_page + rows[j] + G.your_collection[j] = CardArea( + G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, + (args.w_mod*rows[j]+0.25)*G.CARD_W, + args.h_mod*G.CARD_H, + {card_limit = rows[j], type = args.area_type or 'title', highlight_limit = 0, collection = true} + ) + table.insert(deck_tables, + {n=G.UIT.R, config={align = "cm", padding = 0.07, no_fill = true}, nodes={ + {n=G.UIT.O, config={object = G.your_collection[j]}} + }}) + end + end + + local options = {} + for i = 1, math.ceil(#pool/cards_per_page) do + table.insert(options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#pool/cards_per_page))) + end + + G.FUNCS.SMODS_card_collection_page = function(e) + if not e or not e.cycle_config then return end + for j = 1, #G.your_collection do + for i = #G.your_collection[j].cards, 1, -1 do + local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) + c:remove() + c = nil + end + end + for j = 1, #rows do + for i = 1, rows[j] do + local center = pool[i+row_totals[j] + (cards_per_page*(e.cycle_config.current_option - 1))] + if not center then break end + local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W*args.card_scale, G.CARD_H*args.card_scale, G.P_CARDS.empty, (args.center and G.P_CENTERS[args.center]) or center) + if args.modify_card then args.modify_card(card, center, i, j) end + if not args.no_materialize then card:start_materialize(nil, i>1 or j>1) end + G.your_collection[j]:emplace(card) + end + end + INIT_COLLECTION_CARD_ALERTS() + end + + G.FUNCS.SMODS_card_collection_page{ cycle_config = { current_option = 1 }} + + local t = create_UIBox_generic_options({ back_func = (args and args.back_func) or G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', snap_back = args.snap_back, infotip = args.infotip, contents = { + {n=G.UIT.R, config={align = "cm", r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables}, + (not args.hide_single_page or cards_per_page < #pool) and {n=G.UIT.R, config={align = "cm"}, nodes={ + create_option_cycle({options = options, w = 4.5, cycle_shoulders = true, opt_callback = 'SMODS_card_collection_page', current_option = 1, colour = G.C.RED, no_pips = true, focus_args = {snap_to = true, nav = 'wide'}}) + }} or nil, + }}) + return t +end + +create_UIBox_your_collection_jokers = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Joker, {5,5,5}, { + no_materialize = true, + modify_card = function(card, center) card.sticker = get_joker_win_sticker(center) end, + h_mod = 0.95, + }) +end +create_UIBox_your_collection_boosters = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Booster, {4,4}, { + h_mod = 1.3, + w_mod = 1.25, + card_scale = 1.27, + }) +end +create_UIBox_your_collection_vouchers = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Voucher, {4,4}, { + area_type = 'voucher', + modify_card = function(card, center, i, j) + card.ability.order = i+(j-1)*4 + end, + }) +end +create_UIBox_your_collection_enhancements = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Enhanced, {4,4}, { + no_materialize = true, + snap_back = true, + h_mod = 1.03, + infotip = localize('ml_edition_seal_enhancement_explanation'), + hide_single_page = true, + }) +end +create_UIBox_your_collection_editions = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Edition, {5,5}, { + snap_back = true, + h_mod = 1.03, + infotip = localize('ml_edition_seal_enhancement_explanation'), + hide_single_page = true, + collapse_single_page = true, + modify_card = function(card, center) + if center.discovered then card:set_edition(center.key, true, true) end + end, + }) +end + +create_UIBox_your_collection_seals = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Seal, {5,5}, { + snap_back = true, + infotip = localize('ml_edition_seal_enhancement_explanation'), + hide_single_page = true, + collapse_single_page = true, + center = 'c_base', + h_mod = 1.03, + modify_card = function(card, center) + card:set_seal(center.key, true) + end, + }) +end + +G.FUNCS.your_collection_stickers = function(e) + G.SETTINGS.paused = true + G.FUNCS.overlay_menu{ + definition = create_UIBox_your_collection_stickers(), + } +end + +create_UIBox_your_collection_stickers = function() + return SMODS.card_collection_UIBox(SMODS.Stickers, {5,5}, { + snap_back = true, + hide_single_page = true, + collapse_single_page = true, + center = 'c_base', + h_mod = 1.03, + back_func = 'your_collection_other_gameobjects', + modify_card = function(card, center) + card.ignore_pinned = true + center:apply(card, true) + end, + }) +end diff --git a/smods-main/src/utils.lua b/smods-main/src/utils.lua new file mode 100644 index 0000000..6f9c09d --- /dev/null +++ b/smods-main/src/utils.lua @@ -0,0 +1,1796 @@ +--- STEAMODDED CORE +--- UTILITY FUNCTIONS +function inspect(table) + if type(table) ~= 'table' then + return "Not a table" + end + + local str = "" + for k, v in pairs(table) do + local valueStr = type(v) == "table" and "table" or tostring(v) + str = str .. tostring(k) .. ": " .. valueStr .. "\n" + end + + return str +end + +function inspectDepth(table, indent, depth) + if depth and depth > 5 then -- Limit the depth to avoid deep nesting + return "Depth limit reached" + end + + if type(table) ~= 'table' then -- Ensure the object is a table + return "Not a table" + end + + local str = "" + if not indent then indent = 0 end + + for k, v in pairs(table) do + local formatting = string.rep(" ", indent) .. tostring(k) .. ": " + if type(v) == "table" then + str = str .. formatting .. "\n" + str = str .. inspectDepth(v, indent + 1, (depth or 0) + 1) + elseif type(v) == 'function' then + str = str .. formatting .. "function\n" + elseif type(v) == 'boolean' then + str = str .. formatting .. tostring(v) .. "\n" + else + str = str .. formatting .. tostring(v) .. "\n" + end + end + + return str +end + +function inspectFunction(func) + if type(func) ~= 'function' then + return "Not a function" + end + + local info = debug.getinfo(func) + local result = "Function Details:\n" + + if info.what == "Lua" then + result = result .. "Defined in Lua\n" + else + result = result .. "Defined in C or precompiled\n" + end + + result = result .. "Name: " .. (info.name or "anonymous") .. "\n" + result = result .. "Source: " .. info.source .. "\n" + result = result .. "Line Defined: " .. info.linedefined .. "\n" + result = result .. "Last Line Defined: " .. info.lastlinedefined .. "\n" + result = result .. "Number of Upvalues: " .. info.nups .. "\n" + + return result +end + +function SMODS._save_d_u(o) + assert(not o._discovered_unlocked_overwritten) + o._d, o._u = o.discovered, o.unlocked + o._saved_d_u = true +end + +function SMODS.SAVE_UNLOCKS() + boot_print_stage("Saving Unlocks") + G:save_progress() + ------------------------------------- + local TESTHELPER_unlocks = false and not _RELEASE_MODE + ------------------------------------- + if not love.filesystem.getInfo(G.SETTINGS.profile .. '') then + love.filesystem.createDirectory(G.SETTINGS.profile .. + '') + end + if not love.filesystem.getInfo(G.SETTINGS.profile .. '/' .. 'meta.jkr') then + love.filesystem.append( + G.SETTINGS.profile .. '/' .. 'meta.jkr', 'return {}') + end + + convert_save_to_meta() + + local meta = STR_UNPACK(get_compressed(G.SETTINGS.profile .. '/' .. 'meta.jkr') or 'return {}') + meta.unlocked = meta.unlocked or {} + meta.discovered = meta.discovered or {} + meta.alerted = meta.alerted or {} + + G.P_LOCKED = {} + for k, v in pairs(G.P_CENTERS) do + if not v.wip and not v.demo then + if TESTHELPER_unlocks then + v.unlocked = true; v.discovered = true; v.alerted = true + end --REMOVE THIS + if not v.unlocked and meta.unlocked[k] then + v.unlocked = true + end + if not v.unlocked then + G.P_LOCKED[#G.P_LOCKED + 1] = v + end + if not v.discovered and meta.discovered[k] then + v.discovered = true + end + if v.discovered and meta.alerted[k] or v.set == 'Back' or v.start_alerted then + v.alerted = true + elseif v.discovered then + v.alerted = false + end + end + end + + table.sort(G.P_LOCKED, function (a, b) return a.order and b.order and a.order < b.order end) + + for k, v in pairs(G.P_BLINDS) do + v.key = k + if not v.wip and not v.demo then + if TESTHELPER_unlocks then v.discovered = true; v.alerted = true end --REMOVE THIS + if not v.discovered and meta.discovered[k] then + v.discovered = true + end + if v.discovered and meta.alerted[k] then + v.alerted = true + elseif v.discovered then + v.alerted = false + end + end + end + for k, v in pairs(G.P_TAGS) do + v.key = k + if not v.wip and not v.demo then + if TESTHELPER_unlocks then v.discovered = true; v.alerted = true end --REMOVE THIS + if not v.discovered and meta.discovered[k] then + v.discovered = true + end + if v.discovered and meta.alerted[k] then + v.alerted = true + elseif v.discovered then + v.alerted = false + end + end + end + for k, v in pairs(G.P_SEALS) do + v.key = k + if not v.wip and not v.demo then + if TESTHELPER_unlocks then + v.discovered = true; v.alerted = true + end --REMOVE THIS + if not v.discovered and meta.discovered[k] then + v.discovered = true + end + if v.discovered and meta.alerted[k] then + v.alerted = true + elseif v.discovered then + v.alerted = false + end + end + end + for _, t in ipairs{ + G.P_CENTERS, + G.P_BLINDS, + G.P_TAGS, + G.P_SEALS, + } do + for k, v in pairs(t) do + v._discovered_unlocked_overwritten = true + end + end +end + +function SMODS.process_loc_text(ref_table, ref_value, loc_txt, key) + local target = (type(loc_txt) == 'table') and + ((G.SETTINGS.real_language and loc_txt[G.SETTINGS.real_language]) or loc_txt[G.SETTINGS.language] or loc_txt['default'] or loc_txt['en-us']) or loc_txt + if key and (type(target) == 'table') then target = target[key] end + if not (type(target) == 'string' or target and next(target)) then return end + ref_table[ref_value] = target +end + +local function parse_loc_file(file_name, force) + local loc_table = nil + if file_name:lower():match("%.json$") then + loc_table = assert(JSON.decode(NFS.read(file_name))) + else + loc_table = assert(loadstring(NFS.read(file_name)))() + end + local function recurse(target, ref_table) + if type(target) ~= 'table' then return end --this shouldn't happen unless there's a bad return value + for k, v in pairs(target) do + -- If the value doesn't exist *or* + -- force mode is on and the value is not a table, + -- change/add the thing + -- brings back compatibility with language patching mods + if (not ref_table[k] and type(k) ~= 'number') or (force and ((type(v) ~= 'table') or type(v[1]) == 'string')) then + ref_table[k] = v + else + recurse(v, ref_table[k]) + end + end + end + recurse(loc_table, G.localization) +end + +local function handle_loc_file(dir, language, force) + for k, v in ipairs({ dir .. language .. '.lua', dir .. language .. '.json' }) do + if NFS.getInfo(v) then + parse_loc_file(v, force) + break + end + end +end + +function SMODS.handle_loc_file(path) + local dir = path .. 'localization/' + handle_loc_file(dir, 'en-us', true) + handle_loc_file(dir, 'default', true) + handle_loc_file(dir, G.SETTINGS.language, true) + if G.SETTINGS.real_language then handle_loc_file(dir, G.SETTINGS.real_language, true) end +end + +function SMODS.insert_pool(pool, center, replace) + if replace == nil then replace = center.taken_ownership end + if replace then + for k, v in ipairs(pool) do + if v.key == center.key then + pool[k] = center + end + end + else + local prev_order = (pool[#pool] and pool[#pool].order) or 0 + if prev_order ~= nil then + center.order = prev_order + 1 + end + table.insert(pool, center) + end +end + +function SMODS.remove_pool(pool, key) + local j + for i, v in ipairs(pool) do + if v.key == key then j = i end + end + if j then return table.remove(pool, j) end +end + +function SMODS.juice_up_blind() + local ui_elem = G.HUD_blind:get_UIE_by_ID('HUD_blind_debuff') + for _, v in ipairs(ui_elem.children) do + v.children[1]:juice_up(0.3, 0) + end + G.GAME.blind:juice_up() +end + +-- @deprecated +function SMODS.eval_this(_card, effects) + sendWarnMessage('SMODS.eval_this is deprecated. All calculation stages now support returning effects directly. Effects evaluated using this function are out of order and may not use the correct sound pitch.', 'Util') + if effects then + local extras = { mult = false, hand_chips = false } + if effects.mult_mod then + mult = mod_mult(mult + effects.mult_mod); extras.mult = true + end + if effects.chip_mod then + hand_chips = mod_chips(hand_chips + effects.chip_mod); extras.hand_chips = true + end + if effects.Xmult_mod then + mult = mod_mult(mult * effects.Xmult_mod); extras.mult = true + end + update_hand_text({ delay = 0 }, { chips = extras.hand_chips and hand_chips, mult = extras.mult and mult }) + if effects.message then + card_eval_status_text(_card, 'jokers', nil, percent, nil, effects) + end + percent = (percent or 0) + (percent_delta or 0.08) + end +end + +-- Change a card's suit, rank, or both. +-- Accepts keys for both objects instead of needing to build a card key yourself. +function SMODS.change_base(card, suit, rank) + if not card then return false end + local _suit = SMODS.Suits[suit or card.base.suit] + local _rank = SMODS.Ranks[rank or card.base.value] + if not _suit or not _rank then + sendWarnMessage(('Tried to call SMODS.change_base with invalid arguments: suit="%s", rank="%s"'):format(suit, rank), 'Util') + return false + end + card:set_base(G.P_CARDS[('%s_%s'):format(_suit.card_key, _rank.card_key)]) + return card +end + +-- Return an array of all (non-debuffed) jokers or consumables with key `key`. +-- Debuffed jokers count if `count_debuffed` is true. +-- This function replaces find_joker(); please use SMODS.find_card() instead +-- to avoid name conflicts with other mods. +function SMODS.find_card(key, count_debuffed) + local results = {} + if not G.jokers or not G.jokers.cards then return {} end + for _, area in ipairs(SMODS.get_card_areas('jokers')) do + for _, v in pairs(area.cards) do + if v and type(v) == 'table' and v.config.center.key == key and (count_debuffed or not v.debuff) then + table.insert(results, v) + end + end + end + return results +end + +function SMODS.create_card(t) + if not t.area and t.key and G.P_CENTERS[t.key] then + t.area = G.P_CENTERS[t.key].consumeable and G.consumeables or G.P_CENTERS[t.key].set == 'Joker' and G.jokers + end + if not t.area and not t.key and t.set and SMODS.ConsumableTypes[t.set] then + t.area = G.consumeables + end + SMODS.bypass_create_card_edition = t.no_edition + local _card = create_card(t.set, t.area, t.legendary, t.rarity, t.skip_materialize, t.soulable, t.key, t.key_append) + SMODS.bypass_create_card_edition = nil + + -- Should this be restricted to only cards able to handle these + -- or should that be left to the person calling SMODS.create_card to use it correctly? + if t.edition then _card:set_edition(t.edition) end + if t.enhancement then _card:set_ability(G.P_CENTERS[t.enhancement]) end + if t.seal then _card:set_seal(t.seal) end + if t.stickers then + for i, v in ipairs(t.stickers) do + local s = SMODS.Stickers[v] + if not s or type(s.should_apply) ~= 'function' or s:should_apply(_card, t.area, true) then + SMODS.Stickers[v]:apply(_card, true) + end + end + end + + return _card +end + +function SMODS.add_card(t) + local card = SMODS.create_card(t) + card:add_to_deck() + local area = t.area or G.jokers + area:emplace(card) + return card +end + +function SMODS.debuff_card(card, debuff, source) + debuff = debuff or nil + source = source and tostring(source) or nil + if debuff == 'reset' then card.ability.debuff_sources = {}; return end + card.ability.debuff_sources = card.ability.debuff_sources or {} + card.ability.debuff_sources[source] = debuff + card:set_debuff() +end + +-- Recalculate whether a card should be debuffed +function SMODS.recalc_debuff(card) + G.GAME.blind:debuff_card(card) +end + +function SMODS.restart_game() + if ((G or {}).SOUND_MANAGER or {}).channel then + G.SOUND_MANAGER.channel:push({ + type = "kill", + }) + end + if ((G or {}).SAVE_MANAGER or {}).channel then + G.SAVE_MANAGER.channel:push({ + type = "kill", + }) + end + if ((G or {}).HTTP_MANAGER or {}).channel then + G.HTTP_MANAGER.channel:push({ + type = "kill", + }) + end + if love.system.getOS() ~= 'OS X' then + love.thread.newThread("os.execute(...)\n"):start('"' .. arg[-2] .. '" ' .. table.concat(arg, " ")) + else + os.execute('sh "/Users/$USER/Library/Application Support/Steam/steamapps/common/Balatro/run_lovely.sh" &') + end + + love.event.quit() +end + +function SMODS.create_mod_badges(obj, badges) + if not SMODS.config.no_mod_badges and obj and obj.mod and obj.mod.display_name and not obj.no_mod_badges then + local mods = {} + badges.mod_set = badges.mod_set or {} + if not badges.mod_set[obj.mod.id] and not obj.no_main_mod_badge then table.insert(mods, obj.mod) end + badges.mod_set[obj.mod.id] = true + if obj.dependencies then + for _, v in ipairs(obj.dependencies) do + local m = assert(SMODS.find_mod(v)[1]) + if not badges.mod_set[m.id] then + table.insert(mods, m) + badges.mod_set[m.id] = true + end + end + end + for i, mod in ipairs(mods) do + local mod_name = string.sub(mod.display_name, 1, 20) + local size = 0.9 + local font = G.LANG.font + local max_text_width = 2 - 2*0.05 - 4*0.03*size - 2*0.03 + local calced_text_width = 0 + -- Math reproduced from DynaText:update_text + for _, c in utf8.chars(mod_name) do + local tx = font.FONT:getWidth(c)*(0.33*size)*G.TILESCALE*font.FONTSCALE + 2.7*1*G.TILESCALE*font.FONTSCALE + calced_text_width = calced_text_width + tx/(G.TILESIZE*G.TILESCALE) + end + local scale_fac = + calced_text_width > max_text_width and max_text_width/calced_text_width + or 1 + badges[#badges + 1] = {n=G.UIT.R, config={align = "cm"}, nodes={ + {n=G.UIT.R, config={align = "cm", colour = mod.badge_colour or G.C.GREEN, r = 0.1, minw = 2, minh = 0.36, emboss = 0.05, padding = 0.03*size}, nodes={ + {n=G.UIT.B, config={h=0.1,w=0.03}}, + {n=G.UIT.O, config={object = DynaText({string = mod_name or 'ERROR', colours = {mod.badge_text_colour or G.C.WHITE},float = true, shadow = true, offset_y = -0.05, silent = true, spacing = 1*scale_fac, scale = 0.33*size*scale_fac})}}, + {n=G.UIT.B, config={h=0.1,w=0.03}}, + }} + }} + end + end +end + +function SMODS.create_loc_dump() + local _old, _new = SMODS.dump_loc.pre_inject, G.localization + local _dump = {} + local function recurse(old, new, dump) + for k, _ in pairs(new) do + if type(new[k]) == 'table' then + dump[k] = {} + if not old[k] then + dump[k] = new[k] + else + recurse(old[k], new[k], dump[k]) + end + elseif old[k] ~= new[k] then + dump[k] = new[k] + end + end + end + recurse(_old, _new, _dump) + local function cleanup(dump) + for k, v in pairs(dump) do + if type(v) == 'table' then + cleanup(v) + if not next(v) then dump[k] = nil end + end + end + end + cleanup(_dump) + local str = 'return ' .. serialize(_dump) + NFS.createDirectory(SMODS.dump_loc.path..'localization/') + NFS.write(SMODS.dump_loc.path..'localization/dump.lua', str) +end + +-- Serializes an input table in valid Lua syntax +-- Keys must be of type number or string +-- Values must be of type number, boolean, string or table +function serialize(t, indent) + indent = indent or '' + local str = '{\n' + for k, v in ipairs(t) do + str = str .. indent .. '\t' + if type(v) == 'number' then + str = str .. v + elseif type(v) == 'boolean' then + str = str .. (v and 'true' or 'false') + elseif type(v) == 'string' then + str = str .. serialize_string(v) + elseif type(v) == 'table' then + str = str .. serialize(v, indent .. '\t') + else + -- not serializable + str = str .. 'nil' + end + str = str .. ',\n' + end + for k, v in pairs(t) do + if type(k) == 'string' then + str = str .. indent .. '\t' .. '[' .. serialize_string(k) .. '] = ' + + if type(v) == 'number' then + str = str .. v + elseif type(v) == 'boolean' then + str = str .. (v and 'true' or 'false') + elseif type(v) == 'string' then + str = str .. serialize_string(v) + elseif type(v) == 'table' then + str = str .. serialize(v, indent .. '\t') + else + -- not serializable + str = str .. 'nil' + end + str = str .. ',\n' + end + end + str = str .. indent .. '}' + return str +end + +function serialize_string(s) + return string.format("%q", s) +end + +-- Starting with `t`, insert any key-value pairs from `defaults` that don't already +-- exist in `t` into `t`. Modifies `t`. +-- Returns `t`, the result of the merge. +-- +-- `nil` inputs count as {}; `false` inputs count as a table where +-- every possible key maps to `false`. Therefore, +-- * `t == nil` is weak and falls back to `defaults` +-- * `t == false` explicitly ignores `defaults` +-- (This function might not return a table, due to the above) +function SMODS.merge_defaults(t, defaults) + if t == false then return false end + if defaults == false then return false end + + -- Add in the keys from `defaults`, returning a table + if defaults == nil then return t end + if t == nil then t = {} end + for k, v in pairs(defaults) do + if t[k] == nil then + t[k] = v + end + end + return t +end +V_MT = { + __eq = function(a, b) + local minorWildcard = a.minor == -2 or b.minor == -2 + local patchWildcard = a.patch == -2 or b.patch == -2 + local betaWildcard = a.rev == '~' or b.rev == '~' + return a.major == b.major and + (a.minor == b.minor or minorWildcard) and + (a.patch == b.patch or minorWildcard or patchWildcard) and + (a.rev == b.rev or minorWildcard or patchWildcard or betaWildcard) and + (betaWildcard or a.beta == b.beta) + end, + __le = function(a, b) + local b = { + major = b.major + (b.minor == -2 and 1 or 0), + minor = b.minor == -2 and 0 or (b.minor + (b.patch == -2 and 1 or 0)), + patch = b.patch == -2 and 0 or b.patch, + beta = b.beta, + rev = b.rev, + } + if a.major ~= b.major then return a.major < b.major end + if a.minor ~= b.minor then return a.minor < b.minor end + if a.patch ~= b.patch then return a.patch < b.patch end + if a.beta ~= b.beta then return a.beta < b.beta end + return a.rev <= b.rev + end, + __lt = function(a, b) + return a <= b and not (a == b) + end, + __call = function(_, str) + str = str or '0.0.0' + local _, _, major, minorFull, minor, patchFull, patch, rev = string.find(str, '^(%d+)(%.?([%d%*]*))(%.?([%d%*]*))(.*)$') + local minorWildcard = string.match(minor, '%*') + local patchWildcard = string.match(patch, '%*') + if (minorFull ~= "" and minor == "") or (patchFull ~= "" and patch == "") then + sendWarnMessage('Trailing dot found in version "' .. str .. '".') + major, minor, patch = -1, 0, 0 + end + local t = { + major = tonumber(major), + minor = minorWildcard and -2 or tonumber(minor) or 0, + patch = patchWildcard and -2 or tonumber(patch) or 0, + rev = rev or '', + beta = rev and rev:sub(1,1) == '~' and -1 or 0 + } + return setmetatable(t, V_MT) + end +} +V = setmetatable({}, V_MT) +V_MT.__index = V +function V.is_valid(v, allow_wildcard) + if getmetatable(v) ~= V_MT then return false end + return(pcall(function() return V() <= v and (allow_wildcard or (v.minor ~= -2 and v.patch ~= -2 and v.rev ~= '~')) end)) +end + +-- Flatten the given arrays of arrays into one, then +-- add elements of each table to a new table in order, +-- skipping any duplicates. +function SMODS.merge_lists(...) + local t = {} + for _, v in ipairs({...}) do + for _, vv in ipairs(v) do + table.insert(t, vv) + end + end + local ret = {} + local seen = {} + for _, li in ipairs(t) do + assert(type(li) == 'table') + for _, v in ipairs(li) do + if not seen[v] then + ret[#ret+1] = v + seen[v] = true + end + end + end + return ret +end + +--#region Number formatting + +function round_number(num, precision) + precision = 10^(precision or 0) + + return math.floor(num * precision + 0.4999999999999994) / precision +end + +-- Formatting util for UI elements (look number_formatting.toml) +function format_ui_value(value) + if type(value) ~= "number" then + return tostring(value) + end + + return number_format(value, 1000000) +end + +--#endregion + + +function SMODS.poll_seal(args) + args = args or {} + local key = args.key or 'stdseal' + local mod = args.mod or 1 + local guaranteed = args.guaranteed or false + local options = args.options or get_current_pool("Seal") + local type_key = args.type_key or key.."type"..G.GAME.round_resets.ante + key = key..G.GAME.round_resets.ante + + local available_seals = {} + local total_weight = 0 + for _, v in ipairs(options) do + if v ~= "UNAVAILABLE" then + local seal_option = {} + if type(v) == 'string' then + assert(G.P_SEALS[v]) + seal_option = { key = v, weight = G.P_SEALS[v].weight or 5 } -- default weight set to 5 to replicate base game weighting + elseif type(v) == 'table' then + assert(G.P_SEALS[v.key]) + seal_option = { key = v.key, weight = v.weight } + end + if seal_option.weight > 0 then + table.insert(available_seals, seal_option) + total_weight = total_weight + seal_option.weight + end + end + end + total_weight = total_weight + (total_weight / 2 * 98) -- set base rate to 2% + + local type_weight = 0 -- modified weight total + for _,v in ipairs(available_seals) do + v.weight = G.P_SEALS[v.key].get_weight and G.P_SEALS[v.key]:get_weight() or v.weight + type_weight = type_weight + v.weight + end + + local seal_poll = pseudorandom(pseudoseed(key or 'stdseal'..G.GAME.round_resets.ante)) + if seal_poll > 1 - (type_weight*mod / total_weight) or guaranteed then -- is a seal generated + local seal_type_poll = pseudorandom(pseudoseed(type_key)) -- which seal is generated + local weight_i = 0 + for k, v in ipairs(available_seals) do + weight_i = weight_i + v.weight + if seal_type_poll > 1 - (weight_i / type_weight) then + return v.key + end + end + end +end + +function SMODS.get_blind_amount(ante) + local scale = G.GAME.modifiers.scaling + local amounts = { + 300, + 700 + 100*scale, + 1400 + 600*scale, + 2100 + 2900*scale, + 15000 + 5000*scale*math.log(scale), + 12000 + 8000*(scale+1)*(0.4*scale), + 10000 + 25000*(scale+1)*((scale/4)^2), + 50000 * (scale+1)^2 * (scale/7)^2 + } + + if ante < 1 then return 100 end + if ante <= 8 then return amounts[ante] - amounts[ante]%(10^math.floor(math.log10(amounts[ante])-1)) end + local a, b, c, d = amounts[8], amounts[8]/amounts[7], ante-8, 1 + 0.2*(ante-8) + local amount = math.floor(a*(b + (b*0.75*c)^d)^c) + amount = amount - amount%(10^math.floor(math.log10(amount)-1)) + return amount +end + +function SMODS.stake_from_index(index) + local stake = G.P_CENTER_POOLS.Stake[index] or nil + if not stake then return "error" end + return stake.key +end + +function convert_save_data() + for k, v in pairs(G.PROFILES[G.SETTINGS.profile].deck_usage) do + local first_pass = not v.wins_by_key and not v.losses_by_key + v.wins_by_key = v.wins_by_key or {} + for index, number in pairs(v.wins or {}) do + if index > 8 and not first_pass then break end + v.wins_by_key[SMODS.stake_from_index(index)] = number + end + v.losses_by_key = v.losses_by_key or {} + for index, number in pairs(v.losses or {}) do + if index > 8 and not first_pass then break end + v.losses_by_key[SMODS.stake_from_index(index)] = number + end + end + for k, v in pairs(G.PROFILES[G.SETTINGS.profile].joker_usage) do + local first_pass = not v.wins_by_key and not v.losses_by_key + v.wins_by_key = v.wins_by_key or {} + for index, number in pairs(v.wins or {}) do + if index > 8 and not first_pass then break end + v.wins_by_key[SMODS.stake_from_index(index)] = number + end + v.losses_by_key = v.losses_by_key or {} + for index, number in pairs(v.losses or {}) do + if index > 8 and not first_pass then break end + v.losses_by_key[SMODS.stake_from_index(index)] = number + end + end + G:save_settings() +end + + +function SMODS.poll_rarity(_pool_key, _rand_key) + local rarity_poll = pseudorandom(pseudoseed(_rand_key or ('rarity'..G.GAME.round_resets.ante))) -- Generate the poll value + local available_rarities = copy_table(SMODS.ObjectTypes[_pool_key].rarities) -- Table containing a list of rarities and their rates + local vanilla_rarities = {["Common"] = 1, ["Uncommon"] = 2, ["Rare"] = 3, ["Legendary"] = 4} + + -- Calculate total rates of rarities + local total_weight = 0 + for _, v in ipairs(available_rarities) do + v.mod = G.GAME[tostring(v.key):lower().."_mod"] or 1 + -- Should this fully override the v.weight calcs? + if SMODS.Rarities[v.key] and SMODS.Rarities[v.key].get_weight and type(SMODS.Rarities[v.key].get_weight) == "function" then + v.weight = SMODS.Rarities[v.key]:get_weight(v.weight, SMODS.ObjectTypes[_pool_key]) + end + v.weight = v.weight*v.mod + total_weight = total_weight + v.weight + end + -- recalculate rarities to account for v.mod + for _, v in ipairs(available_rarities) do + v.weight = v.weight / total_weight + end + + -- Calculate selected rarity + local weight_i = 0 + for _, v in ipairs(available_rarities) do + weight_i = weight_i + v.weight + if rarity_poll < weight_i then + if vanilla_rarities[v.key] then + return vanilla_rarities[v.key] + else + return v.key + end + end + end + return nil +end + +function SMODS.poll_enhancement(args) + args = args or {} + local key = args.key or 'std_enhance' + local mod = args.mod or 1 + local guaranteed = args.guaranteed or false + local options = args.options or get_current_pool("Enhanced") + if args.no_replace then + for i, k in pairs(options) do + if G.P_CENTERS[k] and G.P_CENTERS[k].replace_base_card then + options[i] = 'UNAVAILABLE' + end + end + end + local type_key = args.type_key or key.."type"..G.GAME.round_resets.ante + key = key..G.GAME.round_resets.ante + + local available_enhancements = {} + local total_weight = 0 + for _, v in ipairs(options) do + if v ~= "UNAVAILABLE" then + local enhance_option = {} + if type(v) == 'string' then + assert(G.P_CENTERS[v]) + enhance_option = { key = v, weight = G.P_CENTERS[v].weight or 5 } -- default weight set to 5 to replicate base game weighting + elseif type(v) == 'table' then + assert(G.P_CENTERS[v.key]) + enhance_option = { key = v.key, weight = v.weight } + end + if enhance_option.weight > 0 then + table.insert(available_enhancements, enhance_option) + total_weight = total_weight + enhance_option.weight + end + end + end + total_weight = total_weight + (total_weight / 40 * 60) -- set base rate to 40% + + local type_weight = 0 -- modified weight total + for _,v in ipairs(available_enhancements) do + v.weight = G.P_CENTERS[v.key].get_weight and G.P_CENTERS[v.key]:get_weight() or v.weight + type_weight = type_weight + v.weight + end + + local enhance_poll = pseudorandom(pseudoseed(key)) + if enhance_poll > 1 - (type_weight*mod / total_weight) or guaranteed then -- is an enhancement selected + local seal_type_poll = pseudorandom(pseudoseed(type_key)) -- which enhancement is selected + local weight_i = 0 + for k, v in ipairs(available_enhancements) do + weight_i = weight_i + v.weight + if seal_type_poll > 1 - (weight_i / type_weight) then + return v.key + end + end + end +end + +function time(func, ...) + local start_time = love.timer.getTime() + func(...) + local end_time = love.timer.getTime() + return 1000*(end_time-start_time) +end + +function Card:add_sticker(sticker, bypass_check) + local sticker = SMODS.Stickers[sticker] + if bypass_check or (sticker and sticker.should_apply and type(sticker.should_apply) == 'function' and sticker:should_apply(self, self.config.center, self.area, true)) then + sticker:apply(self, true) + end +end + +function Card:remove_sticker(sticker) + if self.ability[sticker] then + SMODS.Stickers[sticker]:apply(self, false) + end +end + + +function Card:calculate_sticker(context, key) + local sticker = SMODS.Stickers[key] + if self.ability[key] and type(sticker.calculate) == 'function' then + local o = sticker:calculate(self, context) + if o then + if not o.card then o.card = self end + return o + end + end +end + +function Card:calculate_enhancement(context) + if self.debuff or self.ability.set ~= 'Enhanced' then return nil end + local center = self.config.center + if center.calculate and type(center.calculate) == 'function' then + local o = center:calculate(self, context) + if o then + if not o.card then o.card = self end + return o + end + end +end + +function SMODS.get_enhancements(card, extra_only) + if not SMODS.optional_features.quantum_enhancements or not G.hand then + return not extra_only and card.ability.set == 'Enhanced' and { [card.config.center.key] = true } or {} + end + if card.extra_enhancements and next(card.extra_enhancements) then + if extra_only then + local extras = copy_table(card.extra_enhancements) + extras[card.config.center.key] = nil + return extras + end + return card.extra_enhancements + end + local enhancements = {} + if card.config.center.key ~= "c_base" and not extra_only then + enhancements[card.config.center.key] = true + end + local calc_return = {} + SMODS.calculate_context({other_card = card, check_enhancement = true, no_blueprint = true}, calc_return) + for _, eval in pairs(calc_return) do + for key, eval2 in pairs(eval) do + if type(eval2) == 'table' then + for key2, _ in pairs(eval2) do + if G.P_CENTERS[key2] then enhancements[key2] = true end + end + else + if G.P_CENTERS[key] then enhancements[key] = true end + end + end + end + + if extra_only and enhancements[card.config.center.key] then + enhancements[card.config.center.key] = nil + end + if next(enhancements) then card.extra_enhancements = enhancements end + return enhancements +end + +function SMODS.has_enhancement(card, key) + if card.config.center.key == key then return true end + card.extra_enhancements = nil + local enhancements = SMODS.get_enhancements(card) + if enhancements[key] then return true end + return false +end + +function SMODS.shatters(card) + card.extra_enhancements = nil + local enhancements = SMODS.get_enhancements(card) + for key, _ in pairs(enhancements) do + if G.P_CENTERS[key].shatters or key == 'm_glass' then return true end + end +end + +function SMODS.calculate_quantum_enhancements(card, effects, context) + if not SMODS.optional_features.quantum_enhancements then return end + context.extra_enhancement = true + local extra_enhancements = SMODS.get_enhancements(card, true) + local old_ability = copy_table(card.ability) + local old_center = card.config.center + local old_center_key = card.config.center_key + for k, _ in pairs(extra_enhancements) do + if G.P_CENTERS[k] then + card:set_ability(G.P_CENTERS[k]) + card.ability.extra_enhancement = k + local eval = eval_card(card, context) + table.insert(effects, 1, eval) + end + end + card.ability = old_ability + card.config.center = old_center + card.config.center_key = old_center_key + card:set_sprites(old_center) + context.extra_enhancement = nil +end + +function SMODS.has_no_suit(card) + local is_stone = false + local is_wild = false + card.extra_enhancements = nil + for k, _ in pairs(SMODS.get_enhancements(card)) do + if k == 'm_stone' or G.P_CENTERS[k].no_suit then is_stone = true end + if k == 'm_wild' or G.P_CENTERS[k].any_suit then is_wild = true end + end + return is_stone and not is_wild +end +function SMODS.has_any_suit(card) + card.extra_enhancements = nil + for k, _ in pairs(SMODS.get_enhancements(card)) do + if k == 'm_wild' or G.P_CENTERS[k].any_suit then return true end + end +end +function SMODS.has_no_rank(card) + card.extra_enhancements = nil + for k, _ in pairs(SMODS.get_enhancements(card)) do + if k == 'm_stone' or G.P_CENTERS[k].no_rank then return true end + end +end +function SMODS.always_scores(card) + card.extra_enhancements = nil + for k, _ in pairs(SMODS.get_enhancements(card)) do + if k == 'm_stone' or G.P_CENTERS[k].always_scores then return true end + end + if (G.P_CENTERS[(card.edition or {}).key] or {}).always_scores then return true end + if (G.P_SEALS[card.seal or {}] or {}).always_scores then return true end + for k, v in pairs(SMODS.Stickers) do + if v.always_scores and card.ability[k] then return true end + end +end + +SMODS.collection_pool = function(_base_pool) + local pool = {} + if type(_base_pool) ~= 'table' then return pool end + local is_array = _base_pool[1] + local ipairs = is_array and ipairs or pairs + for _, v in ipairs(_base_pool) do + if (not G.ACTIVE_MOD_UI or v.mod == G.ACTIVE_MOD_UI) and not v.no_collection then + pool[#pool+1] = v + end + end + if not is_array then table.sort(pool, function(a,b) return a.order < b.order end) end + return pool +end + +SMODS.find_mod = function(id) + local ret = {} + local mod = SMODS.Mods[id] or {} + if mod.can_load then ret[#ret+1] = mod end + for _,v in ipairs(SMODS.provided_mods[id] or {}) do + if v.mod.can_load then ret[#ret+1] = v.mod end + end + return ret +end + +local function bufferCardLimitForSmallDS(cards, scaleFactor) + local cardCount = #cards + if type(scaleFactor) ~= "number" or scaleFactor <= 0 then + sendWarnMessage("scaleFactor must be a positive number") + return cardCount + end + -- Ensure card_limit is always at least the number of cards + G.cdds_cards.config.card_limit = math.max(G.cdds_cards.config.card_limit, cardCount) + -- Calculate the buffer size dynamically based on the scale factor + local buffer = 0 + if cardCount < G.cdds_cards.rankCount then + -- Buffer decreases as cardCount approaches G.cdds_cards.rankCount, modulated by scaleFactor + buffer = math.ceil(((G.cdds_cards.rankCount - cardCount) / scaleFactor)) + end + G.cdds_cards.config.card_limit = math.max(cardCount, cardCount + buffer) + + return G.cdds_cards.config.card_limit +end + +G.FUNCS.update_collab_cards = function(key, suit, silent) + if type(key) == "number" then + key = G.COLLABS.options[suit][key] + end + if not G.cdds_cards then return end + local cards = {} + local cards_order = {} + local deckskin = SMODS.DeckSkins[key] + local palette = deckskin.palette_map and deckskin.palette_map[G.SETTINGS.colour_palettes[suit] or ''] or (deckskin.palettes or {})[1] + local suit_data = SMODS.Suits[suit] + local d_ranks = (palette and (palette.display_ranks or palette.ranks)) or deckskin.display_ranks or deckskin.ranks + if deckskin.outdated then + local reversed = {} + for i = #d_ranks, 1, -1 do + table.insert(reversed, d_ranks[i]) + end + d_ranks = reversed + end + + local diff_order + if #G.cdds_cards.cards ~= #d_ranks then + diff_order = true + else + for i,v in ipairs(G.cdds_cards.cards) do + if v.config.card_key ~= suit_data.card_key..'_'..SMODS.Ranks[d_ranks[i]].card_key then + diff_order = true + break + end + end + end + + if diff_order then + for i = #G.cdds_cards.cards, 1, -1 do + G.cdds_cards:remove_card(G.cdds_cards.cards[i]):remove() + end + for i, r in ipairs(d_ranks) do + local rank = SMODS.Ranks[r] + local card_code = suit_data.card_key .. '_' .. rank.card_key + cards_order[#cards_order+1] = card_code + local card = Card(G.cdds_cards.T.x+G.cdds_cards.T.w/2, G.cdds_cards.T.y+G.cdds_cards.T.h/2, G.CARD_W*1.2, G.CARD_H*1.2, G.P_CARDS[card_code], G.P_CENTERS.c_base) + -- Instead of no ui it would be nice to pass info queue to this so that artist credits can be done? + card.no_ui = true + + G.cdds_cards:emplace(card) + end + end + G.cdds_cards.config.card_limit = bufferCardLimitForSmallDS(cards, 2.5) +end + +G.FUNCS.update_suit_colours = function(suit, skin, palette_num) + skin = skin and SMODS.DeckSkins[skin] or nil + local new_colour_proto = G.C.SO_1[suit] + if G.SETTINGS.colour_palettes[suit] == 'lc' or G.SETTINGS.colour_palettes[suit] == 'hc' then + new_colour_proto = G.C["SO_"..((G.SETTINGS.colour_palettes[suit] == 'hc' and 2) or (G.SETTINGS.colour_palettes[suit] == 'lc' and 1))][suit] + end + if skin and not skin.outdated then + local palette = (palette_num and skin.palettes[palette_num]) or skin.palette_map and skin.palette_map[G.SETTINGS.colour_palettes[suit] or ''] + new_colour_proto = palette and palette.colour or new_colour_proto + end + G.C.SUITS[suit] = new_colour_proto +end + +-- This function handles the calculation of each effect returned to evaluate play. +-- Can easily be hooked to add more calculation effects ala Talisman +SMODS.calculate_individual_effect = function(effect, scored_card, key, amount, from_edition) + if effect.card and effect.card ~= scored_card then juice_card(effect.card) end + if (key == 'chips' or key == 'h_chips' or key == 'chip_mod') and amount then + hand_chips = mod_chips(hand_chips + amount) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = localize{type = 'variable', key = amount > 0 and 'a_chips' or 'a_chips_minus', vars = {amount}}, chip_mod = amount, colour = G.C.EDITION, edition = true}) + else + if key ~= 'chip_mod' then + if effect.chip_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.chip_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'chips', amount, percent) + end + end + end + end + return true + end + + if (key == 'mult' or key == 'h_mult' or key == 'mult_mod') and amount then + mult = mod_mult(mult + amount) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = localize{type = 'variable', key = amount > 0 and 'a_mult' or 'a_mult_minus', vars = {amount}}, mult_mod = amount, colour = G.C.DARK_EDITION, edition = true}) + else + if key ~= 'mult_mod' then + if effect.mult_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.mult_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'mult', amount, percent) + end + end + end + end + return true + end + + if (key == 'p_dollars' or key == 'dollars' or key == 'h_dollars') and amount then + ease_dollars(amount) + if not effect.remove_default_message then + if effect.dollar_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.dollar_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'dollars', amount, percent) + end + end + return true + end + + if (key == 'x_chips' or key == 'xchips' or key == 'Xchip_mod') and amount ~= 1 then + hand_chips = mod_chips(hand_chips * amount) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = localize{type='variable',key= amount > 0 and 'a_xchips' or 'a_xchips_minus',vars={amount}}, Xchips_mod = amount, colour = G.C.EDITION, edition = true}) + else + if key ~= 'Xchip_mod' then + if effect.xchip_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.xchip_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'x_chips', amount, percent) + end + end + end + end + return true + end + + if (key == 'x_mult' or key == 'xmult' or key == 'Xmult' or key == 'x_mult_mod' or key == 'Xmult_mod') and amount ~= 1 then + mult = mod_mult(mult * amount) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = localize{type='variable',key= amount > 0 and 'a_xmult' or 'a_xmult_minus',vars={amount}}, Xmult_mod = amount, colour = G.C.EDITION, edition = true}) + else + if key ~= 'Xmult_mod' then + if effect.xmult_message then + card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.xmult_message) + else + card_eval_status_text(scored_card or effect.card or effect.focus, 'x_mult', amount, percent) + end + end + end + end + return true + end + + if key == 'message' then + card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect) + return true + end + + if key == 'func' then + effect.func() + return true + end + + if key == 'swap' then + local old_mult = mult + mult = mod_mult(hand_chips) + hand_chips = mod_chips(old_mult) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + return true + end + + if key == 'level_up' then + level_up_hand(scored_card, G.GAME.last_hand_played, effect.instant, type(amount) == 'number' and amount or 1) + return true + end + + if key == 'extra' then + return SMODS.calculate_effect(amount, scored_card) + end + + if key == 'saved' then + SMODS.saved = amount + return true + end +end + +-- Used to calculate a table of effects generated in evaluate_play +SMODS.trigger_effects = function(effects, card) + for i, effect_table in ipairs(effects) do + for key, effect in pairs(effect_table) do + if key ~= 'smods' then + if type(effect) == 'table' then + local calc = SMODS.calculate_effect(effect, card, key == 'edition') + if calc then effects.calculated = true end + end + end + end + end +end + +SMODS.calculate_effect = function(effect, scored_card, from_edition, pre_jokers) + local calculated = false + for _, key in ipairs(SMODS.calculation_keys) do + if effect[key] then + if effect.juice_card then G.E_MANAGER:add_event(Event({trigger = 'immediate', func = function () effect.juice_card:juice_up(0.1); scored_card:juice_up(0.1); return true end})) end + calculated = SMODS.calculate_individual_effect(effect, scored_card, key, effect[key], from_edition, pre_jokers) + percent = (percent or 0) + (percent_delta or 0.08) + end + end + if effect.effect then calculated = true end + if effect.remove then calculated = true end + return calculated +end + +SMODS.calculation_keys = { + 'chips', 'h_chips', 'chip_mod', + 'mult', 'h_mult', 'mult_mod', + 'x_chips', 'xchips', 'Xchip_mod', + 'x_mult', 'Xmult', 'xmult', 'x_mult_mod', 'Xmult_mod', + 'p_dollars', 'dollars', 'h_dollars', + 'swap', + 'message', + 'level_up', 'func', 'extra', + 'saved' +} + +SMODS.calculate_repetitions = function(card, context, reps) + -- From the card + context.repetition_only = true + local eval = eval_card(card, context) + for key, value in pairs(eval) do + if value.repetitions then + for h=1, value.repetitions do + value.card = value.card or card + value.message = value.message or (not value.remove_default_message and localize('k_again_ex')) + reps[#reps+1] = {key = value} + end + end + end + context.repetition_only = false + --From jokers + for _, area in ipairs(SMODS.get_card_areas('jokers')) do + for _, _card in ipairs(area.cards) do + --calculate the joker effects + local eval, post = eval_card(_card, context) + if next(post) then SMODS.trigger_effects({post}, card) end + local rt = eval and eval.retriggers and #eval.retriggers or 0 + for key, value in pairs(eval) do + if value.repetitions and key ~= 'retriggers' then + + for h=1, value.repetitions do + value.card = value.card or _card + value.message = value.message or (not value.remove_default_message and localize('k_again_ex')) + reps[#reps+1] = {key = value} + for i=1, rt do + local rt_eval, rt_post = eval_card(_card, context) + rt_eval.card = rt_eval.card or _card + reps[#reps+1] = {key = value} + if next(rt_post) then SMODS.trigger_effects({rt_post}, card) end + end + end + end + end + end + end + local effect = G.GAME.selected_back:trigger_effect(context) + if effect and effect.repetitions then + for h=1, effect.repetitions do + effect.card = effect.card or G.deck.cards[1] or G.deck + reps[#reps+1] = {key = effect} + end + end + return reps +end + +SMODS.calculate_retriggers = function(card, context, _ret) + local retriggers = {} + if not SMODS.optional_features.retrigger_joker then return retriggers end + for _, area in ipairs(SMODS.get_card_areas('jokers')) do + for _, _card in ipairs(area.cards) do + local eval, post = eval_card(_card, {retrigger_joker_check = true, other_card = card, other_context = context, other_ret = _ret}) + if next(post) then SMODS.trigger_effects({post}, _card) end + for key, value in pairs(eval) do + if value.repetitions then + for h=1, value.repetitions do + value.retrigger_card = _card + value.message = value.message or (not value.remove_default_message and localize('k_again_ex')) + retriggers[#retriggers + 1] = value + end + end + end + end + end + return retriggers +end + +function Card:calculate_edition(context) + if self.debuff then return end + if self.edition then + local edition = G.P_CENTERS[self.edition.key] + if edition.calculate and type(edition.calculate) == 'function' then + local o = edition:calculate(self, context) + if o then + if not o.card then o.card = self end + return o + end + end + end +end + +-- Used to calculate contexts across G.jokers, scoring_hand (if present), G.play and G.GAME.selected_back +-- Hook this function to add different areas to MOST calculations +function SMODS.calculate_context(context, return_table) + context.cardarea = G.jokers + context.main_eval = true + for _, area in ipairs(SMODS.get_card_areas('jokers')) do + for _, _card in ipairs(area.cards) do + --calculate the joker effects + local eval, post = eval_card(_card, context) + local effects = {eval} + for _,v in ipairs(post) do effects[#effects+1] = v end + + if context.other_joker then + for k, v in pairs(effects[1]) do + v.other_card = _card + end + end + if effects[1].retriggers then + context.retrigger_joker = true + for rt = 1, #effects[1].retriggers do + context.retrigger_joker = effects[1].retriggers[rt].retrigger_card + local rt_eval, rt_post = eval_card(_card, context) + table.insert(effects, {effects[1].retriggers[rt]}) + table.insert(effects, rt_eval) + for _,v in ipairs(rt_post) do effects[#effects+1] = v end + end + context.retrigger_joker = false + end + if return_table then + for _,v in ipairs(effects) do + if v.jokers and not v.jokers.card then v.jokers.card = _card end + return_table[#return_table+1] = v + end + else + SMODS.trigger_effects(effects, _card) + end + end + end + context.main_eval = nil + if context.scoring_hand then + context.cardarea = G.play + for i=1, #context.scoring_hand do + --calculate the played card effects + if return_table then + return_table[#return_table+1] = eval_card(context.scoring_hand[i], context) + SMODS.calculate_quantum_enhancements(context.scoring_hand[i], return_table, context) + else + local effects = {eval_card(context.scoring_hand[i], context)} + SMODS.calculate_quantum_enhancements(context.scoring_hand[i], effects, context) + SMODS.trigger_effects(effects, context.scoring_hand[i]) + end + end + end + context.cardarea = G.hand + for i=1, #G.hand.cards do + --calculate the held card effects + if return_table then + return_table[#return_table+1] = eval_card(G.hand.cards[i], context) + else + local effects = {eval_card(G.hand.cards[i], context)} + SMODS.calculate_quantum_enhancements(G.hand.cards[i], effects, context) + SMODS.trigger_effects(effects, G.hand.cards[i]) + end + end + if SMODS.optional_features.cardareas.deck then + context.cardarea = G.deck + for i=1, #G.deck.cards do + --calculate the held card effects + if return_table then + return_table[#return_table+1] = eval_card(G.deck.cards[i], context) + else + local effects = {eval_card(G.deck.cards[i], context)} + SMODS.calculate_quantum_enhancements(G.deck.cards[i], effects, context) + SMODS.trigger_effects(effects, G.deck.cards[i]) + end + end + end + if SMODS.optional_features.cardareas.discard then + context.cardarea = G.discard + for i=1, #G.discard.cards do + --calculate the held card effects + if return_table then + return_table[#return_table+1] = eval_card(G.discard.cards[i], context) + else + local effects = {eval_card(G.discard.cards[i], context)} + SMODS.calculate_quantum_enhancements(G.discard.cards[i], effects, context) + SMODS.trigger_effects(effects, G.discard.cards[i]) + end + end + end + local effect = G.GAME.selected_back:trigger_effect(context) + if effect then SMODS.calculate_effect(effect, G.deck.cards[1] or G.deck) end +end + +function SMODS.score_card(card, context) + local reps = { 1 } + local j = 1 + while j <= #reps do + if reps[j] ~= 1 then + local _, eff = next(reps[j]) + SMODS.calculate_effect(eff, eff.card) + percent = percent + percent_delta + end + + context.main_scoring = true + local effects = { eval_card(card, context) } + SMODS.calculate_quantum_enhancements(card, effects, context) + context.main_scoring = nil + context.individual = true + context.other_card = card + + if next(effects) then + for _, area in ipairs(SMODS.get_card_areas('jokers')) do + for _, _card in ipairs(area.cards) do + --calculate the joker individual card effects + local eval, post = eval_card(_card, context) + if next(eval) then + if eval.jokers then eval.jokers.juice_card = eval.jokers.juice_card or eval.jokers.card or _card end + table.insert(effects, eval) + for _, v in ipairs(post) do effects[#effects+1] = v end + if eval.retriggers then + context.retrigger_joker = true + for rt = 1, #eval.retriggers do + local rt_eval, rt_post = eval_card(_card, context) + table.insert(effects, { eval.retriggers[rt] }) + table.insert(effects, rt_eval) + for _, v in ipairs(rt_post) do effects[#effects+1] = v end + end + context.retrigger_joker = nil + end + end + end + end + end + + SMODS.trigger_effects(effects, card) + local deck_effect = G.GAME.selected_back:trigger_effect(context) + if deck_effect then SMODS.calculate_effect(deck_effect, G.deck.cards[1] or G.deck) end + + context.individual = nil + if reps[j] == 1 and effects.calculated then + context.repetition = true + context.card_effects = effects + SMODS.calculate_repetitions(card, context, reps) + context.repetition = nil + context.card_effects = nil + end + j = j + (effects.calculated and 1 or #reps) + context.other_card = nil + card.lucky_trigger = nil + end + card.extra_enhancements = nil +end + +function SMODS.calculate_main_scoring(context, scoring_hand) + for _, card in ipairs(scoring_hand or context.cardarea.cards) do + --add cards played to list + if scoring_hand and not SMODS.has_no_rank(card) then + G.GAME.cards_played[card.base.value].total = G.GAME.cards_played[card.base.value].total + 1 + if not SMODS.has_no_suit(card) then + G.GAME.cards_played[card.base.value].suits[card.base.suit] = true + end + end + --if card is debuffed + if scoring_hand and card.debuff then + G.GAME.blind.triggered = true + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = (function() SMODS.juice_up_blind();return true end) + })) + card_eval_status_text(card, 'debuff') + else + SMODS.score_card(card, context) + end + end +end + +function SMODS.calculate_end_of_round_effects(context) + for i, card in ipairs(context.cardarea.cards) do + local reps = {1} + local j = 1 + while j <= #reps do + percent = (i-0.999)/(#context.cardarea.cards-0.998) + (j-1)*0.1 + if reps[j] ~= 1 then + local _, eff = next(reps[j]) + SMODS.calculate_effect(eff, eff.card) + percent = percent + 0.08 + end + + context.playing_card_end_of_round = true + --calculate the hand effects + local effects = {eval_card(card, context)} + local extra_enhancements = SMODS.get_enhancements(card, true) + local old_ability = copy_table(card.ability) + local old_center = card.config.center + local old_center_key = card.config.center_key + for k, _ in pairs(extra_enhancements) do + if G.P_CENTERS[k] then + card:set_ability(G.P_CENTERS[k]) + card.ability.extra_enhancement = k + effects[#effects+1] = eval_card(card, context) + end + end + card.ability = old_ability + card.config.center = old_center + card.config.center_key = old_center_key + card:set_sprites(old_center) + + context.playing_card_end_of_round = nil + context.individual = true + context.other_card = card + -- context.end_of_round individual calculations + for _, area in ipairs(SMODS.get_card_areas('jokers')) do + for _, _card in ipairs(area.cards) do + + local eval, post = eval_card(_card, context) + eval.juice_card = eval.card + if next(eval) then + table.insert(effects, eval) + end + for _, v in ipairs(post) do effects[#effects+1] = v end + end + end + + local deck_effect = G.GAME.selected_back:trigger_effect(context) + if deck_effect then SMODS.calculate_effect(deck_effect, G.deck.cards[1] or G.deck) end + SMODS.trigger_effects(effects, card) + + context.individual = nil + context.repetition = true + context.card_effects = effects + if reps[j] == 1 then + SMODS.calculate_repetitions(card, context, reps) + end + + context.repetition = nil + context.card_effects = nil + j = j + (effects.calculated and 1 or #reps) + + -- TARGET: effects after end of round evaluation + end + end +end + +function SMODS.calculate_destroying_cards(context, cards_destroyed, scoring_hand) + for i,card in ipairs(scoring_hand or context.cardarea.cards) do + local destroyed = nil + --un-highlight all cards + if scoring_hand then highlight_card(card,(i-0.999)/(#scoring_hand-0.998),'down') end + + -- context.destroying_card calculations + context.destroy_card = card + context.destroying_card = scoring_hand and card + for _, area in ipairs(SMODS.get_card_areas('jokers')) do + local should_break + for _, _card in ipairs(area.cards) do + local eval, post = eval_card(_card, context) + local self_destroy = false + for key, effect in pairs(eval) do + if type(effect) == 'table' then + self_destroy = SMODS.calculate_effect(effect, card) + else + self_destroy = effect + end + end + SMODS.trigger_effects({post}, card) + if self_destroy then + destroyed = true + should_break = true + break + end + end + if should_break then break end + end + + if scoring_hand and SMODS.has_enhancement(card, 'm_glass') and not card.debuff and pseudorandom('glass') < G.GAME.probabilities.normal/(card.ability.name == 'Glass Card' and card.ability.extra or G.P_CENTERS.m_glass.config.extra) then + destroyed = true + end + + local eval, post = eval_card(card, context) + local self_destroy = false + for key, effect in pairs(eval) do + self_destroy = SMODS.calculate_effect(effect, card) + end + SMODS.trigger_effects({post}, card) + if self_destroy then destroyed = true end + + -- TARGET: card destroyed + + if destroyed then + if SMODS.shatters(card) then + card.shattered = true + else + card.destroyed = true + end + cards_destroyed[#cards_destroyed+1] = card + end + end +end + +function SMODS.get_card_areas(_type, _context) + if _type == 'playing_cards' then + local t = {} + if _context ~= 'end_of_round' then t[#t+1] = G.play end + t[#t+1] = G.hand + if SMODS.optional_features.cardareas.deck then t[#t+1] = G.deck end + if SMODS.optional_features.cardareas.discard then t[#t+1] = G.discard end + -- TARGET: add your own CardAreas for playing card evaluation + return t + end + if _type == 'jokers' then + local t = {G.jokers, G.consumeables, G.vouchers} + -- TARGET: add your own CardAreas for joker evaluation + return t + end + return {} +end + +local flat_copy_table = function(tbl) + local new = {} + for i, v in pairs(tbl) do + new[i] = v + end + return new +end + +---Seatch for val anywhere deep in tbl. Return a table of finds, or the first found if immediate is provided. +SMODS.deepfind = function(tbl, val, immediate) + local seen = {[tbl] = true} + local collector = {} + local stack = { {tbl = tbl, path = {}, objpath = {}} } + + --while there are any elements to traverse + while #stack > 0 do + --pull the top off of the stack and start traversing it (by default this will be the last element of the last traversed table found in pairs) + local current = table.remove(stack) + --the current table we wish to traverse + local currentTbl = current.tbl + --the current path + local currentPath = current.path + --the current object path + local currentObjPath = current.objpath + + --for every table that we have + for i, v in pairs(currentTbl) do + --if the value matches + if v == val then + --copy our values and store it in the collector + local newPath = flat_copy_table(currentPath) + local newObjPath = flat_copy_table(currentObjPath) + table.insert(newPath, i) + table.insert(newObjPath, v) + table.insert(collector, {table = currentTbl, index = i, tree = newPath, objtree = newObjPath}) + if immediate then + return collector + end + --otherwise, if its a traversable table we havent seen yet + elseif type(v) == "table" and not seen[v] then + --make sure we dont see it again + seen[v] = true + --and then place it on the top of the stack + local newPath = flat_copy_table(currentPath) + local newObjPath = flat_copy_table(currentObjPath) + table.insert(newPath, i) + table.insert(newObjPath, v) + table.insert(stack, {tbl = v, path = newPath, objpath = newObjPath}) + end + end + end + + return collector +end + +--Seatch for val as an index anywhere deep in tbl. Return a table of finds, or the first found if immediate is provided. +SMODS.deepfindbyindex = function(tbl, val, immediate) + local seen = {[tbl] = true} + local collector = {} + local stack = { {tbl = tbl, path = {}, objpath = {}} } + + --while there are any elements to traverse + while #stack > 0 do + --pull the top off of the stack and start traversing it (by default this will be the last element of the last traversed table found in pairs) + local current = table.remove(stack) + --the current table we wish to traverse + local currentTbl = current.tbl + --the current path + local currentPath = current.path + --the current object path + local currentObjPath = current.objpath + + --for every table that we have + for i, v in pairs(currentTbl) do + --if the value matches + if i == val then + --copy our values and store it in the collector + local newPath = flat_copy_table(currentPath) + local newObjPath = flat_copy_table(currentObjPath) + table.insert(newPath, i) + table.insert(newObjPath, v) + table.insert(collector, {table = currentTbl, index = i, tree = newPath, objtree = newObjPath}) + if immediate then + return collector + end + --otherwise, if its a traversable table we havent seen yet + elseif type(v) == "table" and not seen[v] then + --make sure we dont see it again + seen[v] = true + --and then place it on the top of the stack + local newPath = flat_copy_table(currentPath) + local newObjPath = flat_copy_table(currentObjPath) + table.insert(newPath, i) + table.insert(newObjPath, v) + table.insert(stack, {tbl = v, path = newPath, objpath = newObjPath}) + end + end + end + + return collector +end + +-- this is for debugging +SMODS.debug_calculation = function() + G.contexts = {} + local cj = Card.calculate_joker + function Card:calculate_joker(context) + for k,v in pairs(context) do G.contexts[k] = (G.contexts[k] or 0) + 1 end + return cj(self, context) + end +end + +local function insert(t, res) + for k,v in pairs(res) do + if type(v) == 'table' and type(t[k]) == 'table' then + insert(t[k], v) + else + t[k] = v + end + end +end +SMODS.optional_features = { + cardareas = {}, +} +SMODS.get_optional_features = function() + for _,mod in ipairs(SMODS.mod_list) do + if mod.can_load and mod.optional_features then + local opt_features = type(mod.optional_features) == 'function' and mod.optional_features() or mod.optional_features + if type(opt_features) == 'table' then + insert(SMODS.optional_features, opt_features) + end + end + end +end + +G.FUNCS.can_select_from_booster = function(e) + local area = booster_obj and booster_obj.select_card and (type(booster_obj.select_card) == 'table' and (booster_obj.select_card[e.config.ref_table.ability.set] or nil) or booster_obj.select_card) or nil + if area and #G[area].cards < G[area].config.card_limit then + e.config.colour = G.C.GREEN + e.config.button = 'use_card' + else + e.config.colour = G.C.UI.BACKGROUND_INACTIVE + e.config.button = nil + end + end \ No newline at end of file diff --git a/smods-main/tk_debug_window.py b/smods-main/tk_debug_window.py new file mode 100644 index 0000000..e5305f5 --- /dev/null +++ b/smods-main/tk_debug_window.py @@ -0,0 +1,649 @@ +import re +import socket +import string +import threading +import tkinter as tk +from datetime import datetime +from tkinter import filedialog + +log_levels = { + "TRACE": 0, + "DEBUG": 1, + "INFO ": 2, + "WARN ": 3, + "ERROR": 4, + "FATAL": 5 +} + + +# might or might not be a copy paste from https://stackoverflow.com/a/16375233 +class TextLineNumbers(tk.Canvas): + def __init__(self, *args, **kwargs): + tk.Canvas.__init__(self, *args, **kwargs, highlightthickness=0) + self.textwidget = None + + def attach(self, text_widget): + self.textwidget = text_widget + + def redraw(self, *args): + '''redraw line numbers''' + self.delete("all") + + i = self.textwidget.index("@0,0") + while True: + dline = self.textwidget.dlineinfo(i) + if dline is None: + break + y = dline[1] + linenum = str(i).split(".")[0] + self.create_text(2, y, anchor="nw", text=linenum, fill="#606366") + i = self.textwidget.index("%s+1line" % i) + + +class CustomText(tk.Text): + def __init__(self, *args, **kwargs): + tk.Text.__init__(self, *args, **kwargs) + + # create a proxy for the underlying widget + self._orig = self._w + "_orig" + self.tk.call("rename", self._w, self._orig) + self.tk.createcommand(self._w, self._proxy) + + def _proxy(self, *args): + # let the actual widget perform the requested action + cmd = (self._orig,) + args + result = self.tk.call(cmd) + + # generate an event if something was added or deleted, + # or the cursor position changed + if (args[0] in ("insert", "replace", "delete") or + args[0:3] == ("mark", "set", "insert") or + args[0:2] == ("xview", "moveto") or + args[0:2] == ("xview", "scroll") or + args[0:2] == ("yview", "moveto") or + args[0:2] == ("yview", "scroll") + ): + self.event_generate("<>", when="tail") + + # return what the actual widget returned + return result + + +class Log: + def __init__(self, log: str): + self.parse_error = False + log_parts = log.split(" :: ") + if len(log_parts) == 4: + self.timestamp_str = log_parts[0] + self.log_level = log_parts[1] + self.logger = log_parts[2] + self.log_str = log_parts[3] + elif len(log_parts) == 3: + self.timestamp_str = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') + self.logger = log_parts[0] + self.log_str = log_parts[1] + self.log_str = log_parts[2] + else: + self.parse_error = True + self.timestamp_str = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') + self.log_level = "DEBUG" + self.logger = "DefaultLogger" + self.log_str = log + + def __str__(self): + if not self.parse_error: + return f"{self.timestamp_str} :: {self.log_level} :: {self.logger} :: {self.log_str}\n" + return f"{self.timestamp_str} :: {self.log_str}\n" + + +class PlaceholderEntry(tk.Entry): + def __init__(self, *args, placeholder="", **kwargs): + super().__init__(*args, **kwargs) + self.placeholder = placeholder + self.user_has_interacted = False + self.insert(0, self.placeholder) + self.word_pattern = re.compile(r'[\s\W]|$') + self.config(fg='grey') + self.bind('', self.on_focus_out) + self.bind('', self.on_focus_in) + self.bind('', self.handle_ctrl_backspace) + self.bind('', self.handle_ctrl_delete) + self.bind('', self.on_key_press) # Bind key press event + + def on_focus_in(self, event): + if not self.user_has_interacted and self.get() == self.placeholder: + self.delete(0, 'end') + self.config(fg='black') + + def on_focus_out(self, event): + if not self.get(): + self.insert(0, self.placeholder) + self.config(fg='grey') + self.user_has_interacted = False # Reset flag if entry is empty + else: + self.user_has_interacted = True + + def on_key_press(self, event): + self.user_has_interacted = True # User has interacted when any key is pressed + + def reset_interaction_flag(self): + self.user_has_interacted = False + + def handle_ctrl_backspace(self, event: tk.Event): + # Get the current content of the entry and the cursor position + content = self.get() + cursor_pos = self.index(tk.INSERT) + + # If the last character before the cursor is a space or punctuation, delete it + if cursor_pos > 0 and (content[cursor_pos - 1] == ' ' or content[cursor_pos - 1] in string.punctuation): + self.delete(cursor_pos - 1, tk.INSERT) + return "break" # Prevent default behavior + + # Find the start of the word to the left of the cursor + pre_cursor = content[:cursor_pos] + match = self.word_pattern.search(pre_cursor[::-1]) # [\s\W]|$ matches spaces, punctuation, or end of string + word_start = cursor_pos - match.start() if match else 0 + + # Delete the word + self.delete(word_start, cursor_pos) + return "break" # Prevent default behavior + + def handle_ctrl_delete(self, event: tk.Event): + # Get the current content of the entry and the cursor position + content = self.get() + cursor_pos = self.index(tk.INSERT) + + # If the first character after the cursor is a space or punctuation, delete it + if len(content) > cursor_pos and (content[cursor_pos] == ' ' or content[cursor_pos] in string.punctuation): + self.delete(cursor_pos, cursor_pos + 1) + return "break" # Prevent default behavior + + # Find the end of the word to the right of the cursor + post_cursor = content[cursor_pos:] + match = self.word_pattern.search(post_cursor) # [\s\W]|$ matches spaces, punctuation, or end of string + word_end = match.start() if match else len(post_cursor) + + # Delete the word + self.delete(cursor_pos, cursor_pos + word_end) + return "break" # Prevent default behavior + + +class OptionsFrame(tk.Frame): + def __init__(self, parent): + super().__init__(parent) + self.global_search_frame = GlobalSearchFrame(self, parent) + self.specific_search_frame = SpecificSearchFrame(self, parent) + self.create_widgets() + + def inject_console(self, console): + self.global_search_frame.inject_console(console) + self.specific_search_frame.inject_console(console) + + def create_widgets(self): + self.global_search_frame.pack(side=tk.TOP, fill='x', expand=True) + self.specific_search_frame.pack(side=tk.BOTTOM, fill='x', expand=True) + + +class GlobalSearchFrame(tk.Frame): + def __init__(self, parent, root): + super().__init__(parent) + + self.after_id = None + self.root = root + self.console = None + + # Global search entry + self.search_entry_placeholder = "Search" + self.search_entry_var = tk.StringVar() + self.search_entry = PlaceholderEntry( + self, + placeholder=self.search_entry_placeholder, + textvariable=self.search_entry_var + ) + self.search_entry_var.trace("w", self.on_entry_changed) + self.search_entry.bind('', lambda event: self.console.text_widget.focus()) + self.search_entry.config(fg='grey') + + self.search_modes = [] + self.search_mode_var = tk.StringVar(value='normal') + self.search_mode_var.trace("w", self.apply_search_mode) + for mode, text in [('normal', 'normal'), ('match_case', 'match case'), ('regex', 'regex')]: + self.search_modes.append(tk.Radiobutton(self, text=text, variable=self.search_mode_var, value=mode)) + + self.create_widgets() + + def apply_search_mode(self, *args): + self.console.set_filter(global_search_mode=self.search_mode_var.get()) + + def inject_console(self, console): + self.console = console + + def create_widgets(self): + self.search_entry.pack(side=tk.LEFT, fill='x', expand=True, padx=(5, 0)) + for mode in self.search_modes: + mode.pack(side=tk.LEFT, padx=(5, 0)) + self.search_entry.bind('', lambda event: self.console.next_occurrence()) + self.search_entry.bind('', lambda event: self.console.previous_occurrence()) + + def on_entry_changed(self, *args): + if self.after_id: + self.root.after_cancel(self.after_id) + self.after_id = self.root.after(300, self.apply_search_entry_var) + + def apply_search_entry_var(self): + self.console.set_filter(global_search_str=self.search_entry_var.get()) + self.after_id = None + + +class Console(tk.Frame): + def __init__(self, parent, option_frame: OptionsFrame): + super().__init__(parent) + self.global_search_mode = "normal" + self.all_logs = [] + self.shown_logs = [] + self.option_frame = option_frame + self.text_widget = CustomText(self) + self.linenumbers = TextLineNumbers(self, width=30) + self.linenumbers.attach(self.text_widget) + self.text_widget.bind("<>", self._on_change) + self.text_widget.bind("", self._on_change) + self.scrollbar = tk.Scrollbar(self, command=self.text_widget.yview) + self.global_search_str = "" + self.logger_name = "" + self.log_level = "TRACE" + self.and_above = True + self.create_widgets() + + def _on_change(self, event): + self.linenumbers.redraw() + + def create_widgets(self): + self.scrollbar.pack(side=tk.RIGHT, fill='y') + self.linenumbers.pack(side=tk.LEFT, fill="y") + self.text_widget.pack(side=tk.LEFT, expand=True, fill='both') + self.text_widget.config(yscrollcommand=self.scrollbar.set) + self.text_widget.config(state=tk.DISABLED) + + def set_filter( + self, + global_search_str: str = None, + global_search_mode: str = None, + logger_name: str = None, + log_level: str = None, + and_above: bool = None + ): + if global_search_str is not None and self.option_frame.global_search_frame.search_entry.user_has_interacted: + self.global_search_str = global_search_str + + if logger_name is not None and self.option_frame.specific_search_frame.logger_entry.user_has_interacted: + self.logger_name = logger_name + + if global_search_mode is not None: + self.global_search_mode = global_search_mode + + if log_level is not None: + self.log_level = log_level + + if and_above is not None: + self.and_above = and_above + + self.apply_filters() + + def append_log(self, log: str): + log_obj = Log(log) + self.all_logs.append(log_obj) + if self.filter_log(log_obj): + self.shown_logs.append(log_obj) + # Check if the user is at the end before appending + at_end = self.text_widget.yview()[1] == 1.0 + self.text_widget.config(state=tk.NORMAL) + self.text_widget.insert(tk.END, str(log_obj)) + self.text_widget.config(state=tk.DISABLED) + if at_end: + self.text_widget.see(tk.END) + if self.global_search_str: + self.search_text() + + def clear_logs(self): + self.text_widget.config(state=tk.NORMAL) + self.text_widget.delete('1.0', tk.END) + self.text_widget.config(state=tk.DISABLED) + self.shown_logs.clear() + self.all_logs.clear() + self.apply_filters() + + def apply_filters(self): + # Re-filter all logs and update the text widget only if necessary + filtered_logs = [log for log in self.all_logs if self.filter_log(log)] + self.shown_logs = filtered_logs + self.update_text_widget() + + def filter_log(self, log): + # print(self.global_search_str, self.global_search_mode, self.logger_name, self.log_level, self.and_above) + if self.and_above: + flag = log_levels[log.log_level] >= log_levels[self.log_level] + else: + flag = log.log_level == self.log_level + + if self.logger_name: + flag = flag and self.logger_name in log.logger + + return flag + + def update_text_widget(self): + # Preserve the current view position unless at the end + at_end = self.text_widget.yview()[1] == 1.0 + self.text_widget.config(state=tk.NORMAL) + self.text_widget.delete('1.0', tk.END) + self.text_widget.config(state=tk.DISABLED) + for log in self.shown_logs: + self.text_widget.config(state=tk.NORMAL) + self.text_widget.insert(tk.END, str(log)) + self.text_widget.config(state=tk.DISABLED) + if at_end: + self.text_widget.see(tk.END) + + if self.global_search_str: + self.search_text() + + def search_text(self): + self.text_widget.tag_remove('found', '1.0', tk.END) + search_query = self.global_search_str.strip() + if not search_query: + return + + if self.global_search_mode == 'match_case': + pattern = re.escape(search_query) + elif self.global_search_mode == 'regex': + # Directly use the user input for regex, but be cautious of Tkinter's limited regex support + pattern = search_query + else: # normal mode, make it case-insensitive + pattern = '(?i)' + re.escape(search_query) # Add (?i) for case-insensitive search in Tkinter + + start = '1.0' + while True: + match_start = self.text_widget.search(pattern, start, tk.END, regexp=True) + if not match_start: + break + match_end = f"{match_start}+{len(search_query)}c" + self.text_widget.tag_add('found', match_start, match_end) + start = match_end + + self.text_widget.tag_config('found', background='yellow') + at_end = self.text_widget.yview()[1] == 1.0 + if at_end: + first_occurrence = self.text_widget.tag_ranges('found') + if first_occurrence: + self.text_widget.see(first_occurrence[0]) + self.next_occurrence() + + def prepare_occurrence_navigation(self): + current_tags = self.text_widget.tag_ranges('found') + if not current_tags: + return None, None + + # Ensure the 'current_found' tag exists with a blue background. + self.text_widget.tag_config('current_found', background='#ADD8E6') + + # Get the current position of the cursor in the text widget. + cursor_index = self.text_widget.index(tk.INSERT) + + # Remove the 'current_found' tag from the entire text widget. + self.text_widget.tag_remove('current_found', '1.0', tk.END) + + # Convert the current cursor index to a comparable value. + cursor_line, cursor_char = map(int, cursor_index.split('.')) + + return current_tags, (cursor_line, cursor_char) + + def next_occurrence(self): + current_tags, cursor_position = self.prepare_occurrence_navigation() + if not current_tags or not cursor_position: + return + + cursor_line, cursor_char = cursor_position + + for i in range(0, len(current_tags), 2): + tag_start = current_tags[i] + tag_end = current_tags[i + 1] + + # Convert tag start index to comparable values. + tag_start_line, tag_start_char = map(int, str(tag_start).split('.')) + + # Check if the tag start is greater than the cursor position. + if tag_start_line > cursor_line or (tag_start_line == cursor_line and tag_start_char > cursor_char): + self.text_widget.mark_set(tk.INSERT, tag_start) + self.text_widget.see(tag_start) + + # Apply the 'current_found' tag to the current occurrence. + self.text_widget.tag_add('current_found', tag_start, tag_end) + break + else: + # Wrap to the first tag if no next tag is found. + self.text_widget.mark_set(tk.INSERT, str(current_tags[0])) + self.text_widget.see(str(current_tags[0])) + self.text_widget.tag_add('current_found', current_tags[0], current_tags[1]) + + def previous_occurrence(self): + current_tags, cursor_position = self.prepare_occurrence_navigation() + if not current_tags or not cursor_position: + return + + cursor_line, cursor_char = cursor_position + + for i in range(len(current_tags) - 2, -1, -2): + tag_start = current_tags[i] + tag_end = current_tags[i + 1] + + # Convert tag start index to comparable values. + tag_start_line, tag_start_char = map(int, str(tag_start).split('.')) + + # Check if the tag start is less than the cursor position. + if tag_start_line < cursor_line or (tag_start_line == cursor_line and tag_start_char < cursor_char): + self.text_widget.mark_set(tk.INSERT, tag_start) + self.text_widget.see(tag_start) + + # Apply the 'current_found' tag to the current occurrence. + self.text_widget.tag_add('current_found', tag_start, tag_end) + break + else: + # Wrap to the last tag if no previous tag is found. + self.text_widget.mark_set(tk.INSERT, str(current_tags[-2])) + self.text_widget.see(str(current_tags[-2])) + self.text_widget.tag_add('current_found', current_tags[-2], current_tags[-1]) + + +class SpecificSearchFrame(tk.Frame): + def __init__(self, parent, root): + super().__init__(parent) + self.root = root + self.after_id = None + self.console = None + + # Logger name entry + self.logger_entry_placeholder = "Logger Name" + self.logger_entry_var = tk.StringVar() + self.logger_entry = PlaceholderEntry( + self, + placeholder=self.logger_entry_placeholder, + textvariable=self.logger_entry_var + ) + self.logger_entry_var.trace("w", self.on_entry_changed) + self.logger_entry.bind('', lambda event: self.console.text_widget.focus()) + self.logger_entry.config(fg='grey') + + # Log level dropdown + self.log_level_dropdown_var = tk.StringVar() + self.log_level_dropdown_var.set("TRACE") + self.log_level_dropdown = tk.OptionMenu( + self, + self.log_level_dropdown_var, + *log_levels.keys() + ) + self.log_level_dropdown_var.trace( + "w", + lambda *args: self.console.set_filter(log_level=self.log_level_dropdown_var.get()) + ) + + # And above checkbox + self.and_above_var = tk.BooleanVar() + self.and_above_var.set(True) + self.and_above_checkbox = tk.Checkbutton( + self, + text="And above", + variable=self.and_above_var, + onvalue=True, + offvalue=False, + command=lambda: self.console.set_filter(and_above=self.and_above_var.get()) + ) + + self.clear_log_button: tk.Button | None = None + + self.create_widgets() + + def inject_console(self, console): + self.console = console + self.clear_log_button = tk.Button( + self, + text="Clear Logs", + command=self.console.clear_logs + ) + self.clear_log_button.pack(side=tk.RIGHT, padx=(5, 0), fill='x', expand=True) + + def create_widgets(self): + self.logger_entry.pack(side=tk.LEFT, fill='x', expand=True, padx=(5, 0)) + self.log_level_dropdown.pack(side=tk.LEFT, padx=(5, 0), fill='x', expand=True) + self.and_above_checkbox.pack(side=tk.LEFT, padx=(5, 0), fill='x', expand=True) + + def on_entry_changed(self, *args): + if self.after_id: + self.root.after_cancel(self.after_id) + self.after_id = self.root.after(250, self.apply_logger_entry_var) + + def apply_logger_entry_var(self): + if self.logger_entry.user_has_interacted: + self.console.set_filter(logger_name=self.logger_entry_var.get()) + self.after_id = None + + +class ExportMenuBar(tk.Menu): + def __init__(self, parent, console: Console, *args, **kwargs): + super().__init__(parent, *args, **kwargs) + self.parent = parent + self.initialize_menu() + self.console = console + + def initialize_menu(self): + # Create a File menu + file_menu = tk.Menu(self, tearoff=0) + file_menu.add_command(label="All logs", command=self.export_all_logs) + file_menu.add_separator() + file_menu.add_command(label="Filtered logs", command=self.export_filtered_logs) + + # Adding the "File" menu to the menubar + self.add_cascade(label="Export", menu=file_menu) + + def export_all_logs(self): + file_path = filedialog.asksaveasfilename( + defaultextension=".log", + filetypes=[("Log files", "*.log"), ("All files", "*.*")], + initialfile=f"Balatro-AllLogs-{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.log" + ) + if file_path: + with open(file_path, "w") as f: + for log in self.console.all_logs: + f.write(str(log)) + + def export_filtered_logs(self): + file_path = filedialog.asksaveasfilename( + defaultextension=".log", + filetypes=[("Log files", "*.log"), ("All files", "*.*")], + initialfile=f"Balatro-FilteredLogs-{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.log" + ) + if file_path: + with open(file_path, "w") as f: + for log in self.console.shown_logs: + f.write(str(log)) + + +class MainWindow(tk.Tk): + def __init__(self): + super().__init__() + self.title("Steamodded Debug Console") + self.options_frame = OptionsFrame(self) + self.console = Console(self, self.options_frame) + self.options_frame.inject_console(self.console) + self.menu_bar = ExportMenuBar(self, self.console) + self.create_widgets() + + self.bind('', self.focus_search) + self.bind('', self.focus_search) + + self.bind('', lambda event: self.menu_bar.export_filtered_logs()) + self.bind('', lambda event: self.menu_bar.export_filtered_logs()) + + self.bind('', lambda event: self.menu_bar.export_all_logs()) + self.bind('', lambda event: self.menu_bar.export_all_logs()) + + self.bind('', lambda event: self.console.clear_logs()) + self.bind('', lambda event: self.console.clear_logs()) + + self.bind('', self.focus_logger) + self.bind('', self.focus_logger) + + def create_widgets(self): + self.console.pack(side=tk.TOP, expand=True, fill='both') + self.options_frame.pack(side=tk.BOTTOM, fill='x', expand=False) + self.config(menu=self.menu_bar) + + def get_console(self): + return self.console + + def focus_search(self, event): + self.options_frame.global_search_frame.search_entry.focus() + + def focus_logger(self, event): + self.options_frame.specific_search_frame.logger_entry.focus() + + +def client_handler(client_socket, console: Console): + buffer = [] + while True: + data = client_socket.recv(1024) + if not data: + break + + decoded_data = data.decode() + buffer.append(decoded_data) # Append new data to the buffer list + + # Join the buffer and split by "ENDOFLOG" + # This handles cases where "ENDOFLOG" is spread across multiple recv calls + combined_data = ''.join(buffer) + logs = combined_data.split("ENDOFLOG") + + # The last element might be an incomplete log; keep it in the buffer + buffer = [logs.pop()] if logs[-1] else [] + + # Append each complete log to the console + for log in logs: + if log: + console.append_log(log) + + # Handle any remaining data in the buffer after the connection is closed + if ''.join(buffer): + console.append_log(''.join(buffer)) + + +def listen_for_clients(console: Console): + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.bind(('localhost', 53153)) + server_socket.listen() + while True: + client, addr = server_socket.accept() + threading.Thread(target=client_handler, args=(client, console)).start() + + +if __name__ == "__main__": + root = MainWindow() + threading.Thread(target=listen_for_clients, daemon=True, args=(root.get_console(),)).start() + root.mainloop() diff --git a/smods-main/version.lua b/smods-main/version.lua new file mode 100644 index 0000000..807adbc --- /dev/null +++ b/smods-main/version.lua @@ -0,0 +1 @@ +return "1.0.0~ALPHA-1410b-STEAMODDED" diff --git a/smods-old-calc/LICENSE b/smods-old-calc/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/smods-old-calc/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/smods-old-calc/README.md b/smods-old-calc/README.md new file mode 100644 index 0000000..4d2aca8 --- /dev/null +++ b/smods-old-calc/README.md @@ -0,0 +1,29 @@ +# Steamodded - A Balatro ModLoader + +## Introduction + +Steamodded is a mod loader and injector for the game Balatro. Much like the [LÖVE framework](https://love2d.org/wiki/Main_Page) itself, it is built using [Lua](https://www.lua.org/). It is made with modularity and extensibility in mind, providing a large selection of APIs and other features to facilitate bringing your ideas to life. + +## Installation + +### How to Install Steamodded + +Click [here](https://github.com/Steamopollys/Steamodded/wiki). + +## How to Install a Mod + +- Navigate to your Mods directory (see the installation instructions). +- Put the mod into that directory. (The mod can be a single file if there is only one file provided, or it can be a whole folder.) +- Launch the game and enjoy! + +## Features + +Documentation for this project is currently incomplete. A collection of documentation pages and guides that are currently available can be found [here](https://github.com/Steamopollys/Steamodded/wiki). + +## Contributing + +This project is open for contribution; feel free to open a pull request. If you are adding new features, providing documentation is highly appreciated. + +## License + +This project is licensed under the GNU General Public License. This ensures that the software is free to use, modify, and distribute. For more details, click [here](https://github.com/Steamopollys/Steamodded/actions?tab=GPL-3.0-1-ov-file) diff --git a/smods-old-calc/TODO b/smods-old-calc/TODO new file mode 100644 index 0000000..455b484 --- /dev/null +++ b/smods-old-calc/TODO @@ -0,0 +1,29 @@ +# Documentation +## To do + + +- Challenge +- DeckSkin + +## In progress +- Enhancement + +## Done + +- Achievement +- Atlas +- Center (Joker, Consumable, Voucher, Back, Booster) +- Blind +- ObjectType +- UndiscoveredSprite +- Edition +- Language +- Sound +- Stake +- PokerHand +- Suit +- Rank +- Seal +- Sticker +- Rarity +- Tag diff --git a/smods-old-calc/assets/1x/default_achievements.png b/smods-old-calc/assets/1x/default_achievements.png new file mode 100644 index 0000000..112362f Binary files /dev/null and b/smods-old-calc/assets/1x/default_achievements.png differ diff --git a/smods-old-calc/assets/1x/mod_tags.png b/smods-old-calc/assets/1x/mod_tags.png new file mode 100644 index 0000000..c236b92 Binary files /dev/null and b/smods-old-calc/assets/1x/mod_tags.png differ diff --git a/smods-old-calc/assets/2x/default_achievements.png b/smods-old-calc/assets/2x/default_achievements.png new file mode 100644 index 0000000..5bfbaff Binary files /dev/null and b/smods-old-calc/assets/2x/default_achievements.png differ diff --git a/smods-old-calc/assets/2x/mod_tags.png b/smods-old-calc/assets/2x/mod_tags.png new file mode 100644 index 0000000..2ada9aa Binary files /dev/null and b/smods-old-calc/assets/2x/mod_tags.png differ diff --git a/smods-old-calc/config.lua b/smods-old-calc/config.lua new file mode 100644 index 0000000..032ff99 --- /dev/null +++ b/smods-old-calc/config.lua @@ -0,0 +1,7 @@ +return { + ["no_mod_badges"] = false, + ["graphics_mipmap_level"] = 3, + ["graphics_mipmap_level_options"] = {0, 2, 4, 8}, + ["achievements"] = 1, + ["seeded_unlocks"] = false, +} diff --git a/smods-old-calc/icon.png b/smods-old-calc/icon.png new file mode 100644 index 0000000..fcddcf9 Binary files /dev/null and b/smods-old-calc/icon.png differ diff --git a/smods-old-calc/libs/json/init.lua b/smods-old-calc/libs/json/init.lua new file mode 100644 index 0000000..28215d7 --- /dev/null +++ b/smods-old-calc/libs/json/init.lua @@ -0,0 +1 @@ +return require((...) .. '.json') \ No newline at end of file diff --git a/smods-old-calc/libs/json/json.lua b/smods-old-calc/libs/json/json.lua new file mode 100644 index 0000000..54d4448 --- /dev/null +++ b/smods-old-calc/libs/json/json.lua @@ -0,0 +1,388 @@ +-- +-- json.lua +-- +-- Copyright (c) 2020 rxi +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of +-- this software and associated documentation files (the "Software"), to deal in +-- the Software without restriction, including without limitation the rights to +-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +-- of the Software, and to permit persons to whom the Software is furnished to do +-- so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all +-- copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +-- SOFTWARE. +-- + +local json = { _version = "0.1.2" } + +------------------------------------------------------------------------------- +-- Encode +------------------------------------------------------------------------------- + +local encode + +local escape_char_map = { + [ "\\" ] = "\\", + [ "\"" ] = "\"", + [ "\b" ] = "b", + [ "\f" ] = "f", + [ "\n" ] = "n", + [ "\r" ] = "r", + [ "\t" ] = "t", +} + +local escape_char_map_inv = { [ "/" ] = "/" } +for k, v in pairs(escape_char_map) do + escape_char_map_inv[v] = k +end + + +local function escape_char(c) + return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte())) +end + + +local function encode_nil(val) + return "null" +end + + +local function encode_table(val, stack) + local res = {} + stack = stack or {} + + -- Circular reference? + if stack[val] then error("circular reference") end + + stack[val] = true + + if rawget(val, 1) ~= nil or next(val) == nil then + -- Treat as array -- check keys are valid and it is not sparse + local n = 0 + for k in pairs(val) do + if type(k) ~= "number" then + error("invalid table: mixed or invalid key types") + end + n = n + 1 + end + if n ~= #val then + error("invalid table: sparse array") + end + -- Encode + for i, v in ipairs(val) do + table.insert(res, encode(v, stack)) + end + stack[val] = nil + return "[" .. table.concat(res, ",") .. "]" + + else + -- Treat as an object + for k, v in pairs(val) do + if type(k) ~= "string" then + error("invalid table: mixed or invalid key types") + end + table.insert(res, encode(k, stack) .. ":" .. encode(v, stack)) + end + stack[val] = nil + return "{" .. table.concat(res, ",") .. "}" + end +end + + +local function encode_string(val) + return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"' +end + + +local function encode_number(val) + -- Check for NaN, -inf and inf + if val ~= val or val <= -math.huge or val >= math.huge then + error("unexpected number value '" .. tostring(val) .. "'") + end + return string.format("%.14g", val) +end + + +local type_func_map = { + [ "nil" ] = encode_nil, + [ "table" ] = encode_table, + [ "string" ] = encode_string, + [ "number" ] = encode_number, + [ "boolean" ] = tostring, +} + + +encode = function(val, stack) + local t = type(val) + local f = type_func_map[t] + if f then + return f(val, stack) + end + error("unexpected type '" .. t .. "'") +end + + +function json.encode(val) + return ( encode(val) ) +end + + +------------------------------------------------------------------------------- +-- Decode +------------------------------------------------------------------------------- + +local parse + +local function create_set(...) + local res = {} + for i = 1, select("#", ...) do + res[ select(i, ...) ] = true + end + return res +end + +local space_chars = create_set(" ", "\t", "\r", "\n") +local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",") +local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u") +local literals = create_set("true", "false", "null") + +local literal_map = { + [ "true" ] = true, + [ "false" ] = false, + [ "null" ] = nil, +} + + +local function next_char(str, idx, set, negate) + for i = idx, #str do + if set[str:sub(i, i)] ~= negate then + return i + end + end + return #str + 1 +end + + +local function decode_error(str, idx, msg) + local line_count = 1 + local col_count = 1 + for i = 1, idx - 1 do + col_count = col_count + 1 + if str:sub(i, i) == "\n" then + line_count = line_count + 1 + col_count = 1 + end + end + error( string.format("%s at line %d col %d", msg, line_count, col_count) ) +end + + +local function codepoint_to_utf8(n) + -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa + local f = math.floor + if n <= 0x7f then + return string.char(n) + elseif n <= 0x7ff then + return string.char(f(n / 64) + 192, n % 64 + 128) + elseif n <= 0xffff then + return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128) + elseif n <= 0x10ffff then + return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128, + f(n % 4096 / 64) + 128, n % 64 + 128) + end + error( string.format("invalid unicode codepoint '%x'", n) ) +end + + +local function parse_unicode_escape(s) + local n1 = tonumber( s:sub(1, 4), 16 ) + local n2 = tonumber( s:sub(7, 10), 16 ) + -- Surrogate pair? + if n2 then + return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) + else + return codepoint_to_utf8(n1) + end +end + + +local function parse_string(str, i) + local res = "" + local j = i + 1 + local k = j + + while j <= #str do + local x = str:byte(j) + + if x < 32 then + decode_error(str, j, "control character in string") + + elseif x == 92 then -- `\`: Escape + res = res .. str:sub(k, j - 1) + j = j + 1 + local c = str:sub(j, j) + if c == "u" then + local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1) + or str:match("^%x%x%x%x", j + 1) + or decode_error(str, j - 1, "invalid unicode escape in string") + res = res .. parse_unicode_escape(hex) + j = j + #hex + else + if not escape_chars[c] then + decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string") + end + res = res .. escape_char_map_inv[c] + end + k = j + 1 + + elseif x == 34 then -- `"`: End of string + res = res .. str:sub(k, j - 1) + return res, j + 1 + end + + j = j + 1 + end + + decode_error(str, i, "expected closing quote for string") +end + + +local function parse_number(str, i) + local x = next_char(str, i, delim_chars) + local s = str:sub(i, x - 1) + local n = tonumber(s) + if not n then + decode_error(str, i, "invalid number '" .. s .. "'") + end + return n, x +end + + +local function parse_literal(str, i) + local x = next_char(str, i, delim_chars) + local word = str:sub(i, x - 1) + if not literals[word] then + decode_error(str, i, "invalid literal '" .. word .. "'") + end + return literal_map[word], x +end + + +local function parse_array(str, i) + local res = {} + local n = 1 + i = i + 1 + while 1 do + local x + i = next_char(str, i, space_chars, true) + -- Empty / end of array? + if str:sub(i, i) == "]" then + i = i + 1 + break + end + -- Read token + x, i = parse(str, i) + res[n] = x + n = n + 1 + -- Next token + i = next_char(str, i, space_chars, true) + local chr = str:sub(i, i) + i = i + 1 + if chr == "]" then break end + if chr ~= "," then decode_error(str, i, "expected ']' or ','") end + end + return res, i +end + + +local function parse_object(str, i) + local res = {} + i = i + 1 + while 1 do + local key, val + i = next_char(str, i, space_chars, true) + -- Empty / end of object? + if str:sub(i, i) == "}" then + i = i + 1 + break + end + -- Read key + if str:sub(i, i) ~= '"' then + decode_error(str, i, "expected string for key") + end + key, i = parse(str, i) + -- Read ':' delimiter + i = next_char(str, i, space_chars, true) + if str:sub(i, i) ~= ":" then + decode_error(str, i, "expected ':' after key") + end + i = next_char(str, i + 1, space_chars, true) + -- Read value + val, i = parse(str, i) + -- Set + res[key] = val + -- Next token + i = next_char(str, i, space_chars, true) + local chr = str:sub(i, i) + i = i + 1 + if chr == "}" then break end + if chr ~= "," then decode_error(str, i, "expected '}' or ','") end + end + return res, i +end + + +local char_func_map = { + [ '"' ] = parse_string, + [ "0" ] = parse_number, + [ "1" ] = parse_number, + [ "2" ] = parse_number, + [ "3" ] = parse_number, + [ "4" ] = parse_number, + [ "5" ] = parse_number, + [ "6" ] = parse_number, + [ "7" ] = parse_number, + [ "8" ] = parse_number, + [ "9" ] = parse_number, + [ "-" ] = parse_number, + [ "t" ] = parse_literal, + [ "f" ] = parse_literal, + [ "n" ] = parse_literal, + [ "[" ] = parse_array, + [ "{" ] = parse_object, +} + + +parse = function(str, idx) + local chr = str:sub(idx, idx) + local f = char_func_map[chr] + if f then + return f(str, idx) + end + decode_error(str, idx, "unexpected character '" .. chr .. "'") +end + + +function json.decode(str) + if type(str) ~= "string" then + error("expected argument of type string, got " .. type(str)) + end + local res, idx = parse(str, next_char(str, 1, space_chars, true)) + idx = next_char(str, idx, space_chars, true) + if idx <= #str then + decode_error(str, idx, "trailing garbage") + end + return res +end + + +return json \ No newline at end of file diff --git a/smods-old-calc/libs/nativefs/LICENSE b/smods-old-calc/libs/nativefs/LICENSE new file mode 100644 index 0000000..828056f --- /dev/null +++ b/smods-old-calc/libs/nativefs/LICENSE @@ -0,0 +1,7 @@ +Copyright 2020 megagrump@pm.me + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/smods-old-calc/libs/nativefs/README.md b/smods-old-calc/libs/nativefs/README.md new file mode 100644 index 0000000..07e594b --- /dev/null +++ b/smods-old-calc/libs/nativefs/README.md @@ -0,0 +1,94 @@ +# This is a Thunderstore package mirror of EngineerSmith's `nativefs` repository with an added lovely patch. + +... + +This is a re-host as previously it was taken down by the original developer. Pull requests for fixes are welcome! + +# Native filesystem for LÖVE + +nativefs replicates a subset of the [love.filesystem](https://love2d.org/wiki/love.filesystem) API, but without LÖVE's path restrictions. + +## Available functions + +### nativefs + +Links in this list point to their `love.filesystem` counterparts. All functions are designed to behave the same way as `love.filesystem`, but without the path restrictions that LÖVE imposes; i.e., they allow full access to the filesystem. + +* [nativefs.newFile](https://love2d.org/wiki/love.filesystem.newFile) +* [nativefs.newFileData](https://love2d.org/wiki/love.filesystem.newFileData) +* [nativefs.mount](https://love2d.org/wiki/love.filesystem.mount) +* [nativefs.unmount](https://love2d.org/wiki/love.filesystem.unmount) +* [nativefs.read](https://love2d.org/wiki/love.filesystem.read) +* [nativefs.write](https://love2d.org/wiki/love.filesystem.write) +* [nativefs.append](https://love2d.org/wiki/love.filesystem.append) +* [nativefs.lines](https://love2d.org/wiki/love.filesystem.lines) +* [nativefs.load](https://love2d.org/wiki/love.filesystem.load) +* [nativefs.getWorkingDirectory](https://love2d.org/wiki/love.filesystem.getWorkingDirectory) +* [nativefs.getDirectoryItems](https://love2d.org/wiki/love.filesystem.getDirectoryItems) +* [nativefs.getInfo](https://love2d.org/wiki/love.filesystem.getInfo) +* [nativefs.createDirectory](https://love2d.org/wiki/love.filesystem.createDirectory) +* [nativefs.remove](https://love2d.org/wiki/love.filesystem.remove) +* nativefs.getDirectoryItemsInfo +* nativefs.getDriveList +* nativefs.setWorkingDirectory + +#### Additional `nativefs` functions + +Functions that are not available in `love.filesystem`: + +* `nativefs.getDirectoryItemsInfo(path)` +Returns a list of items in a directory that contains not only the names, but also the information returned by `getInfo` for each item. The return value is a list of files and directories, in which each entry is a table as returned by [getInfo](https://love2d.org/wiki/love.filesystem.getInfo), with an additional `name` field for each entry. Using this function is faster than calling `getInfo` separately for each item. + +* `nativefs.getDriveList()` +Returns a table with all populated drive letters on Windows (`{ 'C:/', 'D:/', ...}`). On systems that don't use drive letters, a table with the single entry `/` is returned. + +* `nativefs.setWorkingDirectory(directory)` +Changes the working directory. + +### File + +`nativefs.newFile` returns a `File` object that provides these functions: + +* [File:open](https://love2d.org/wiki/\(File\):open) +* [File:close](https://love2d.org/wiki/\(File\):close) +* [File:read](https://love2d.org/wiki/\(File\):read) +* [File:write](https://love2d.org/wiki/\(File\):write) +* [File:lines](https://love2d.org/wiki/\(File\):lines) +* [File:isOpen](https://love2d.org/wiki/\(File\):isOpen) +* [File:isEOF](https://love2d.org/wiki/\(File\):isEOF) +* [File:getFilename](https://love2d.org/wiki/\(File\):getFilename) +* [File:getMode](https://love2d.org/wiki/\(File\):getMode) +* [File:getBuffer](https://love2d.org/wiki/\(File\):getBuffer) +* [File:setBuffer](https://love2d.org/wiki/\(File\):setBuffer) +* [File:getSize](https://love2d.org/wiki/\(File\):getSize) +* [File:seek](https://love2d.org/wiki/\(File\):seek) +* [File:tell](https://love2d.org/wiki/\(File\):tell) +* [File:flush](https://love2d.org/wiki/\(File\):flush) +* [File:type](https://love2d.org/wiki/Object:type) +* [File:typeOf](https://love2d.org/wiki/Object:typeOf) +* [File:release](https://love2d.org/wiki/Object:release) + +Function names in this list are links to their LÖVE `File` counterparts. `File` is designed to work the same way as LÖVE's `File` objects. + +## Example + +```lua +local nativefs = require("nativefs") + +-- Prints all information on files in C:\Windows +local files = nativefs.getDirectoryItemsInfo("C:/Windows") +for i = 1, #files do + if files[i].type == "file" then + local info = nativefs.getInfo("C:/Windows/" .. files[i].name) + print(i .. ": " .. files[i] .. " : Type:" .. info.type .. ", Size:" .. tostring(info.size) .. ", last modified:" .. tostring(info.modtime)) + end +end +``` +## License +Copyright 2020 megagrump@pm.me + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/smods-old-calc/libs/nativefs/icon.png b/smods-old-calc/libs/nativefs/icon.png new file mode 100644 index 0000000..20ae917 Binary files /dev/null and b/smods-old-calc/libs/nativefs/icon.png differ diff --git a/smods-old-calc/libs/nativefs/init.lua b/smods-old-calc/libs/nativefs/init.lua new file mode 100644 index 0000000..46d2786 --- /dev/null +++ b/smods-old-calc/libs/nativefs/init.lua @@ -0,0 +1 @@ +return require((...) .. '.nativefs') diff --git a/smods-old-calc/libs/nativefs/manifest.json b/smods-old-calc/libs/nativefs/manifest.json new file mode 100644 index 0000000..2908a51 --- /dev/null +++ b/smods-old-calc/libs/nativefs/manifest.json @@ -0,0 +1,7 @@ +{ + "name": "nativefs", + "version_number": "1.0.0", + "website_url": "https://github.com/EngineerSmith/nativefs", + "description": "nativefs replicates a subset of the love.filesystem API, but without LÖVE's path restrictions.", + "dependencies": ["Thunderstore-lovely-0.3.0"] +} diff --git a/smods-old-calc/libs/nativefs/nativefs.lua b/smods-old-calc/libs/nativefs/nativefs.lua new file mode 100644 index 0000000..c6f36e0 --- /dev/null +++ b/smods-old-calc/libs/nativefs/nativefs.lua @@ -0,0 +1,495 @@ +--[[ +Copyright 2020 megagrump@pm.me + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +]]-- + +-- module("nativefs", package.seeall) + +local ffi, bit = require('ffi'), require('bit') +local C = ffi.C + +local fopen, getcwd, chdir, unlink, mkdir, rmdir +local BUFFERMODE, MODEMAP +local ByteArray = ffi.typeof('unsigned char[?]') +local function _ptr(p) return p ~= nil and p or nil end -- NULL pointer to nil + +local File = { + getBuffer = function(self) return self._bufferMode, self._bufferSize end, + getFilename = function(self) return self._name end, + getMode = function(self) return self._mode end, + isOpen = function(self) return self._mode ~= 'c' and self._handle ~= nil end, +} + +function File:open(mode) + if self._mode ~= 'c' then return false, "File " .. self._name .. " is already open" end + if not MODEMAP[mode] then return false, "Invalid open mode for " .. self._name .. ": " .. mode end + + local handle = _ptr(fopen(self._name, MODEMAP[mode])) + if not handle then return false, "Could not open " .. self._name .. " in mode " .. mode end + + self._handle, self._mode = ffi.gc(handle, C.fclose), mode + self:setBuffer(self._bufferMode, self._bufferSize) + + return true +end + +function File:close() + if self._mode == 'c' then return false, "File is not open" end + C.fclose(ffi.gc(self._handle, nil)) + self._handle, self._mode = nil, 'c' + return true +end + +function File:setBuffer(mode, size) + local bufferMode = BUFFERMODE[mode] + if not bufferMode then + return false, "Invalid buffer mode " .. mode .. " (expected 'none', 'full', or 'line')" + end + + if mode == 'none' then + size = math.max(0, size or 0) + else + size = math.max(2, size or 2) -- Windows requires buffer to be at least 2 bytes + end + + local success = self._mode == 'c' or C.setvbuf(self._handle, nil, bufferMode, size) == 0 + if not success then + self._bufferMode, self._bufferSize = 'none', 0 + return false, "Could not set buffer mode" + end + + self._bufferMode, self._bufferSize = mode, size + return true +end + +function File:getSize() + -- NOTE: The correct way to do this would be a stat() call, which requires a + -- lot more (system-specific) code. This is a shortcut that requires the file + -- to be readable. + local mustOpen = not self:isOpen() + if mustOpen and not self:open('r') then return 0 end + + local pos = mustOpen and 0 or self:tell() + C.fseek(self._handle, 0, 2) + local size = self:tell() + if mustOpen then + self:close() + else + self:seek(pos) + end + return size +end + +function File:read(containerOrBytes, bytes) + if self._mode ~= 'r' then return nil, 0 end + + local container = bytes ~= nil and containerOrBytes or 'string' + if container ~= 'string' and container ~= 'data' then + error("Invalid container type: " .. container) + end + + bytes = not bytes and containerOrBytes or 'all' + bytes = bytes == 'all' and self:getSize() - self:tell() or math.min(self:getSize() - self:tell(), bytes) + + if bytes <= 0 then + local data = container == 'string' and '' or love.data.newFileData('', self._name) + return data, 0 + end + + local data = love.data.newByteData(bytes) + local r = tonumber(C.fread(data:getFFIPointer(), 1, bytes, self._handle)) + + if container == 'data' then + -- FileData from ByteData requires LÖVE 11.4+ + local ok, fd = pcall(love.filesystem.newFileData, data, self._name) + if ok then return fd end + end + + local str = data:getString() + data:release() + data = container == 'data' and love.filesystem.newFileData(str, self._name) or str + return data, r +end + +local function lines(file, autoclose) + local BUFFERSIZE = 4096 + local buffer, bufferPos = ByteArray(BUFFERSIZE), 0 + local bytesRead = tonumber(C.fread(buffer, 1, BUFFERSIZE, file._handle)) + + local offset = file:tell() + return function() + file:seek(offset) + + local line = {} + while bytesRead > 0 do + for i = bufferPos, bytesRead - 1 do + if buffer[i] == 10 then -- end of line + bufferPos = i + 1 + return table.concat(line) + end + + if buffer[i] ~= 13 then -- ignore CR + table.insert(line, string.char(buffer[i])) + end + end + + bytesRead = tonumber(C.fread(buffer, 1, BUFFERSIZE, file._handle)) + offset, bufferPos = offset + bytesRead, 0 + end + + if not line[1] then + if autoclose then file:close() end + return nil + end + return table.concat(line) + end +end + +function File:lines() + if self._mode ~= 'r' then error("File is not opened for reading") end + return lines(self) +end + +function File:write(data, size) + if self._mode ~= 'w' and self._mode ~= 'a' then + return false, "File " .. self._name .. " not opened for writing" + end + + local toWrite, writeSize + if type(data) == 'string' then + writeSize = (size == nil or size == 'all') and #data or size + toWrite = data + else + writeSize = (size == nil or size == 'all') and data:getSize() or size + toWrite = data:getFFIPointer() + end + + if tonumber(C.fwrite(toWrite, 1, writeSize, self._handle)) ~= writeSize then + return false, "Could not write data" + end + return true +end + +function File:seek(pos) + return self._handle and C.fseek(self._handle, pos, 0) == 0 +end + +function File:tell() + if not self._handle then return nil, "Invalid position" end + return tonumber(C.ftell(self._handle)) +end + +function File:flush() + if self._mode ~= 'w' and self._mode ~= 'a' then + return nil, "File is not opened for writing" + end + return C.fflush(self._handle) == 0 +end + +function File:isEOF() + return not self:isOpen() or C.feof(self._handle) ~= 0 or self:tell() == self:getSize() +end + +function File:release() + if self._mode ~= 'c' then self:close() end + self._handle = nil +end + +function File:type() return 'File' end + +function File:typeOf(t) return t == 'File' end + +File.__index = File + +----------------------------------------------------------------------------- + +local nativefs = {} +local loveC = ffi.os == 'Windows' and ffi.load('love') or C + +function nativefs.newFile(name) + if type(name) ~= 'string' then + error("bad argument #1 to 'newFile' (string expected, got " .. type(name) .. ")") + end + return setmetatable({ + _name = name, + _mode = 'c', + _handle = nil, + _bufferSize = 0, + _bufferMode = 'none' + }, File) +end + +function nativefs.newFileData(filepath) + local f = nativefs.newFile(filepath) + local ok, err = f:open('r') + if not ok then return nil, err end + + local data, err = f:read('data', 'all') + f:close() + return data, err +end + +function nativefs.mount(archive, mountPoint, appendToPath) + return loveC.PHYSFS_mount(archive, mountPoint, appendToPath and 1 or 0) ~= 0 +end + +function nativefs.unmount(archive) + return loveC.PHYSFS_unmount(archive) ~= 0 +end + +function nativefs.read(containerOrName, nameOrSize, sizeOrNil) + local container, name, size + if sizeOrNil then + container, name, size = containerOrName, nameOrSize, sizeOrNil + elseif not nameOrSize then + container, name, size = 'string', containerOrName, 'all' + else + if type(nameOrSize) == 'number' or nameOrSize == 'all' then + container, name, size = 'string', containerOrName, nameOrSize + else + container, name, size = containerOrName, nameOrSize, 'all' + end + end + + local file = nativefs.newFile(name) + local ok, err = file:open('r') + if not ok then return nil, err end + + local data, size = file:read(container, size) + file:close() + return data, size +end + +local function writeFile(mode, name, data, size) + local file = nativefs.newFile(name) + local ok, err = file:open(mode) + if not ok then return nil, err end + + ok, err = file:write(data, size or 'all') + file:close() + return ok, err +end + +function nativefs.write(name, data, size) + return writeFile('w', name, data, size) +end + +function nativefs.append(name, data, size) + return writeFile('a', name, data, size) +end + +function nativefs.lines(name) + local f = nativefs.newFile(name) + local ok, err = f:open('r') + if not ok then return nil, err end + return lines(f, true) +end + +function nativefs.load(name) + local chunk, err = nativefs.read(name) + if not chunk then return nil, err end + return loadstring(chunk, name) +end + +function nativefs.getWorkingDirectory() + return getcwd() +end + +function nativefs.setWorkingDirectory(path) + if not chdir(path) then return false, "Could not set working directory" end + return true +end + +function nativefs.getDriveList() + if ffi.os ~= 'Windows' then return { '/' } end + local drives, bits = {}, C.GetLogicalDrives() + for i = 0, 25 do + if bit.band(bits, 2 ^ i) > 0 then + table.insert(drives, string.char(65 + i) .. ':/') + end + end + return drives +end + +function nativefs.createDirectory(path) + local current = path:sub(1, 1) == '/' and '/' or '' + for dir in path:gmatch('[^/\\]+') do + current = current .. dir .. '/' + local info = nativefs.getInfo(current, 'directory') + if not info and not mkdir(current) then return false, "Could not create directory " .. current end + end + return true +end + +function nativefs.remove(name) + local info = nativefs.getInfo(name) + if not info then return false, "Could not remove " .. name end + if info.type == 'directory' then + if not rmdir(name) then return false, "Could not remove directory " .. name end + return true + end + if not unlink(name) then return false, "Could not remove file " .. name end + return true +end + +local function withTempMount(dir, fn, ...) + local mountPoint = _ptr(loveC.PHYSFS_getMountPoint(dir)) + if mountPoint then return fn(ffi.string(mountPoint), ...) end + if not nativefs.mount(dir, '__nativefs__temp__') then return false, "Could not mount " .. dir end + local a, b = fn('__nativefs__temp__', ...) + nativefs.unmount(dir) + return a, b +end + +function nativefs.getDirectoryItems(dir) + local result, err = withTempMount(dir, love.filesystem.getDirectoryItems) + return result or {} +end + +local function getDirectoryItemsInfo(path, filtertype) + local items = {} + local files = love.filesystem.getDirectoryItems(path) + for i = 1, #files do + local filepath = string.format('%s/%s', path, files[i]) + local info = love.filesystem.getInfo(filepath, filtertype) + if info then + info.name = files[i] + table.insert(items, info) + end + end + return items +end + +function nativefs.getDirectoryItemsInfo(path, filtertype) + local result, err = withTempMount(path, getDirectoryItemsInfo, filtertype) + return result or {} +end + +local function getInfo(path, file, filtertype) + local filepath = string.format('%s/%s', path, file) + return love.filesystem.getInfo(filepath, filtertype) +end + +local function leaf(p) + p = p:gsub('\\', '/') + local last, a = p, 1 + while a do + a = p:find('/', a + 1) + if a then + last = p:sub(a + 1) + end + end + return last +end + +function nativefs.getInfo(path, filtertype) + local dir = path:match("(.*[\\/]).*$") or './' + local file = leaf(path) + local result, err = withTempMount(dir, getInfo, file, filtertype) + return result or nil +end + +----------------------------------------------------------------------------- + +MODEMAP = { r = 'rb', w = 'wb', a = 'ab' } +local MAX_PATH = 4096 + +ffi.cdef([[ + int PHYSFS_mount(const char* dir, const char* mountPoint, int appendToPath); + int PHYSFS_unmount(const char* dir); + const char* PHYSFS_getMountPoint(const char* dir); + + typedef struct FILE FILE; + + FILE* fopen(const char* path, const char* mode); + size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream); + size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream); + int fclose(FILE* stream); + int fflush(FILE* stream); + size_t fseek(FILE* stream, size_t offset, int whence); + size_t ftell(FILE* stream); + int setvbuf(FILE* stream, char* buffer, int mode, size_t size); + int feof(FILE* stream); +]]) + +if ffi.os == 'Windows' then + ffi.cdef([[ + int MultiByteToWideChar(unsigned int cp, uint32_t flags, const char* mb, int cmb, const wchar_t* wc, int cwc); + int WideCharToMultiByte(unsigned int cp, uint32_t flags, const wchar_t* wc, int cwc, const char* mb, + int cmb, const char* def, int* used); + int GetLogicalDrives(void); + int CreateDirectoryW(const wchar_t* path, void*); + int _wchdir(const wchar_t* path); + wchar_t* _wgetcwd(wchar_t* buffer, int maxlen); + FILE* _wfopen(const wchar_t* path, const wchar_t* mode); + int _wunlink(const wchar_t* path); + int _wrmdir(const wchar_t* path); + ]]) + + BUFFERMODE = { full = 0, line = 64, none = 4 } + + local function towidestring(str) + local size = C.MultiByteToWideChar(65001, 0, str, #str, nil, 0) + local buf = ffi.new('wchar_t[?]', size + 1) + C.MultiByteToWideChar(65001, 0, str, #str, buf, size) + return buf + end + + local function toutf8string(wstr) + local size = C.WideCharToMultiByte(65001, 0, wstr, -1, nil, 0, nil, nil) + local buf = ffi.new('char[?]', size + 1) + C.WideCharToMultiByte(65001, 0, wstr, -1, buf, size, nil, nil) + return ffi.string(buf) + end + + local nameBuffer = ffi.new('wchar_t[?]', MAX_PATH + 1) + + fopen = function(path, mode) return C._wfopen(towidestring(path), towidestring(mode)) end + getcwd = function() return toutf8string(C._wgetcwd(nameBuffer, MAX_PATH)) end + chdir = function(path) return C._wchdir(towidestring(path)) == 0 end + unlink = function(path) return C._wunlink(towidestring(path)) == 0 end + mkdir = function(path) return C.CreateDirectoryW(towidestring(path), nil) ~= 0 end + rmdir = function(path) return C._wrmdir(towidestring(path)) == 0 end +else + BUFFERMODE = { full = 0, line = 1, none = 2 } + + ffi.cdef([[ + char* getcwd(char *buffer, int maxlen); + int chdir(const char* path); + int unlink(const char* path); + int mkdir(const char* path, int mode); + int rmdir(const char* path); + ]]) + + local nameBuffer = ByteArray(MAX_PATH) + + fopen = C.fopen + unlink = function(path) return ffi.C.unlink(path) == 0 end + chdir = function(path) return ffi.C.chdir(path) == 0 end + mkdir = function(path) return ffi.C.mkdir(path, 0x1ed) == 0 end + rmdir = function(path) return ffi.C.rmdir(path) == 0 end + + getcwd = function() + local cwd = _ptr(C.getcwd(nameBuffer, MAX_PATH)) + return cwd and ffi.string(cwd) or nil + end +end + +return nativefs diff --git a/Steamodded/localization/en-us.lua b/smods-old-calc/localization/en-us.lua similarity index 100% rename from Steamodded/localization/en-us.lua rename to smods-old-calc/localization/en-us.lua diff --git a/smods-old-calc/localization/es_419.lua b/smods-old-calc/localization/es_419.lua new file mode 100644 index 0000000..b016289 --- /dev/null +++ b/smods-old-calc/localization/es_419.lua @@ -0,0 +1,117 @@ +return { + descriptions = { + Other = { + load_success = { + text = { + '¡Mod cargado', + '{C:green}con éxito{}!' + } + }, + load_failure_d = { + text = { + '¡Faltan {C:attention}dependencias{}!', + '#1#', + } + }, + load_failure_c = { + text = { + '¡Hay {C:attention}conflictos{} sin resolver!', + '#1#' + } + }, + load_failure_d_c = { + text = { + '¡Faltan {C:attention}dependencias!', + '#1#', + '¡Hay {C:attention}conflictos{} sin resolver!', + '#2#' + } + }, + load_failure_o = { + text = { + '¡Steamodded {C:attention}obsoleto{}!', + 'Las versiones por debajo de {C:money}0.9.8{}', + 'ya no tienen soporte.' + } + }, + load_failure_i = { + text = { + '{C:attention}¡Incompatible!{} Necesita la versión', + '#1# de Steamodded,', + 'pero la #2# está instalada.' + } + }, + load_failure_p = { -- To be translated + text = { + '{C:attention}Prefix Conflict!{}', + 'This mod\'s prefix is', + 'the same as another mod\'s.', + '({C:attention}#1#{})' + } + }, + load_failure_m = { -- To be translated + text = { + '{C:attention}Main File Not Found!{}', + 'This mod\'s main file', + 'could not be found.', + '({C:attention}#1#{})' + } + }, + load_disabled = { + text = { + '¡Este mod ha sido', + '{C:attention}desactivado{}!' + } + } + }, + Edition = { + e_negative_playing_card = { + name = "Negativa", + text = { + "{C:dark_edition}+#1#{} de tamaño de mano" + }, + }, + } + }, + misc = { + achievement_names = { + hidden_achievement = "???", + }, + achievement_descriptions = { + hidden_achievement = "¡Juega más para descubirlo!", + }, + dictionary = { + b_mods = 'Mods', + b_mods_cap = 'MODS', + b_modded_version = 'Modded Version!', -- To be translated + b_steamodded = 'Steamodded', + b_credits = 'Créditos', + b_open_mods_dir = 'Abrir directorio de Mods', + b_no_mods = 'No se han detectado mods...', + b_mod_list = 'Lista de Mods activos', + b_mod_loader = 'Cargador de Mods', + b_developed_by = 'desarrollado por ', + b_rewrite_by = 'Reescrito por ', + b_github_project = 'Proyecto de Github', + b_github_bugs_1 = 'Puedes reportar errores', + b_github_bugs_2 = 'y contribuir allí.', + b_disable_mod_badges = 'Desactivar insignias de mods', + b_author = 'Autor/a', + b_authors = 'Autores', + b_unknown = 'Desconocido', + b_lovely_mod = '(Lovely Mod) ', -- TODO + b_by = ' Por: ', + b_config = "Configuración", + b_additions = 'Adiciones', + b_stickers = 'Stickers', -- TODO + b_achievements = "Logros", + b_applies_stakes_1 = 'Aplica ', + b_applies_stakes_2 = '', + b_graphics_mipmap_level = "Mipmap level", -- TODO + }, + v_dictionary = { + c_types = '#1# Tipos', + cashout_hidden = '...y #1# más', + }, + } +} diff --git a/smods-old-calc/localization/es_ES.lua b/smods-old-calc/localization/es_ES.lua new file mode 100644 index 0000000..dbe46bd --- /dev/null +++ b/smods-old-calc/localization/es_ES.lua @@ -0,0 +1,117 @@ +return { + descriptions = { + Other = { + load_success = { + text = { + '¡Mod cargado', + '{C:green}con éxito{}!' + } + }, + load_failure_d = { + text = { + '¡Faltan {C:attention}dependencias{}!', + '#1#', + } + }, + load_failure_c = { + text = { + '¡Hay {C:attention}conflictos{} sin resolver!', + '#1#' + } + }, + load_failure_d_c = { + text = { + '¡Faltan {C:attention}dependencias!', + '#1#', + '¡Hay {C:attention}conflictos{} sin resolver!', + '#2#' + } + }, + load_failure_o = { + text = { + '¡Steamodded {C:attention}obsoleto{}!', + 'Las versiones por debajo de {C:money}0.9.8{}', + 'ya no tienen soporte.' + } + }, + load_failure_i = { + text = { + '{C:attention}¡Incompatible!{} Necesita la versión', + '#1# de Steamodded,', + 'pero la #2# está instalada.' + } + }, + load_failure_p = { -- To be translated + text = { + '{C:attention}Prefix Conflict!{}', + 'This mod\'s prefix is', + 'the same as another mod\'s.', + '({C:attention}#1#{})' + } + }, + load_failure_m = { -- To be translated + text = { + '{C:attention}Main File Not Found!{}', + 'This mod\'s main file', + 'could not be found.', + '({C:attention}#1#{})' + } + }, + load_disabled = { + text = { + '¡Este mod ha sido', + '{C:attention}desactivado{}!' + } + } + }, + Edition = { + e_negative_playing_card = { + name = "Negativa", + text = { + "{C:dark_edition}+#1#{} de tamaño de mano" + }, + }, + } + }, + misc = { + achievement_names = { + hidden_achievement = "???", + }, + achievement_descriptions = { + hidden_achievement = "¡Juega más para descubirlo!", + }, + dictionary = { + b_mods = 'Mods', + b_mods_cap = 'MODS', + b_modded_version = 'Modded Version!', -- To be translated + b_steamodded = 'Steamodded', + b_credits = 'Créditos', + b_open_mods_dir = 'Abrir directorio de Mods', + b_no_mods = 'No se han detectado mods...', + b_mod_list = 'Lista de Mods activos', + b_mod_loader = 'Cargador de Mods', + b_developed_by = 'desarrollado por ', + b_rewrite_by = 'Reescrito por ', + b_github_project = 'Proyecto de Github', + b_github_bugs_1 = 'Puedes reportar errores', + b_github_bugs_2 = 'y contribuir allí.', + b_disable_mod_badges = 'Desactivar insignias de mods', + b_author = 'Autor/a', + b_authors = 'Autores', + b_unknown = 'Desconocido', + b_lovely_mod = '(Lovely Mod) ', --TODO + b_by = ' Por: ', + b_config = "Configuración", + b_additions = 'Adiciones', + b_stickers = 'Stickers', -- TODO + b_achievements = "Logros", + b_applies_stakes_1 = 'Aplica ', + b_applies_stakes_2 = '', + b_graphics_mipmap_level = "Mipmap level", -- TODO + }, + v_dictionary = { + c_types = '#1# Tipos', + cashout_hidden = '...y #1# más', + }, + } +} diff --git a/smods-old-calc/localization/zh_CN.lua b/smods-old-calc/localization/zh_CN.lua new file mode 100644 index 0000000..f9e259d --- /dev/null +++ b/smods-old-calc/localization/zh_CN.lua @@ -0,0 +1,117 @@ +return { + descriptions = { + Other = { + load_success = { + text = { + '模组加载{C:green}成功!' + } + }, + load_failure_d = { + text = { + '{C:attention}依赖项{}缺失!', + '#1#' + } + }, + load_failure_c = { + text = { + '存在{C:attention}冲突项{}!', + '#1#' + } + }, + load_failure_d_c = { + text = { + '{C:attention}依赖项{}缺失!', + '#1#', + '存在{C:attention}冲突项{}!', + '#2#' + } + }, + load_failure_o = { + text = { + 'Steamodded版本{C:attention}过旧{}!', + '已不再支持', + '{C:money}0.9.8{}及以下版本' + } + }, + load_failure_i = { + text = { + '{C:attention}不兼容!', + '所需Steamodded版本为#1#', + '但当前为#2#' + } + }, + load_failure_p = { + text = { + '{C:attention}前缀冲突!{}', + '此模组的前缀和', + '另外一个模组相同!', + '({C:attention}#1#{})' + } + }, + load_failure_m = { -- To be translated + text = { + '{C:attention}Main File Not Found!{}', + 'This mod\'s main file', + 'could not be found.', + '({C:attention}#1#{})' + } + }, + load_disabled = { + text = { + '该模组', + '已被{C:attention}禁用{}!' + } + } + }, + Edition = { + e_negative_playing_card = { + name = "负片", + text = { + "手牌上限{C:dark_edition}+#1#" + }, + }, + } + }, + misc = { + achievement_names = { + hidden_achievement = "???", + }, + achievement_descriptions = { + hidden_achievement = "未发现", + }, + dictionary = { + b_mods = '模组', + b_mods_cap = '模组', + b_modded_version = '模组环境!', + b_steamodded = 'Steamodded', + b_credits = '鸣谢', + b_open_mods_dir = '打开模组目录', + b_no_mods = '未检测到任何模组……', + b_mod_list = '已启用模组列表', + b_mod_loader = '模组加载器', + b_developed_by = '作者:', + b_rewrite_by = '重写者:', + b_github_project = 'Github项目', + b_github_bugs_1 = '你可以在此汇报漏洞', + b_github_bugs_2 = '和提交贡献', + b_disable_mod_badges = '禁用模组横标', + b_author = '作者', + b_authors = '作者', + b_unknown = '未知', + b_lovely_mod = '(依赖Lovely加载器的补丁模组)', + b_by = ' 作者:', + b_config = "配置", + b_additions = '新增项目', + b_stickers = '贴纸', + b_achievements = "成就", + b_applies_stakes_1 = '', + b_applies_stakes_2 = '的限制也都起效', + b_graphics_mipmap_level = "多级渐远纹理层级", + }, + v_dictionary = { + c_types = '共有#1#种', + cashout_hidden = '……还有#1#', + }, + }, + +} diff --git a/Steamodded/lovely/achievements.toml b/smods-old-calc/lovely/achievements.toml similarity index 96% rename from Steamodded/lovely/achievements.toml rename to smods-old-calc/lovely/achievements.toml index ffc4aff..24ac308 100644 --- a/Steamodded/lovely/achievements.toml +++ b/smods-old-calc/lovely/achievements.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ## Achievement API @@ -100,7 +100,7 @@ match_indent = true target = 'functions/common_events.lua' pattern = 'if G\.GAME\.seeded or G\.GAME\.challenge then return end' position = 'at' -payload = 'if not SMODS.seeded_unlocks and (G.GAME.seeded or G.GAME.challenge) then return end' +payload = 'if not SMODS.config.seeded_unlocks and (G.GAME.seeded or G.GAME.challenge) then return end' [[patches]] [patches.regex] @@ -114,4 +114,4 @@ payload = 'if false then' target = 'functions/common_events.lua' pattern = 'if G\.GAME\.challenge then' position = 'at' -payload = 'if false then' \ No newline at end of file +payload = 'if false then' diff --git a/Steamodded/lovely/atlas.toml b/smods-old-calc/lovely/atlas.toml similarity index 87% rename from Steamodded/lovely/atlas.toml rename to smods-old-calc/lovely/atlas.toml index 46cb0ac..a3a1009 100644 --- a/Steamodded/lovely/atlas.toml +++ b/smods-old-calc/lovely/atlas.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Sprite API @@ -20,8 +20,8 @@ pattern = 'G.ASSET_ATLAS\[_center.atlas or _center.set\]' position = 'at' payload = ''' G.ASSET_ATLAS[(_center.undiscovered and (_center.undiscovered[G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or _center.undiscovered.atlas)) - or (SMODS.UndiscoveredSprites[_center.set] and (SMODS.UndiscoveredSprites[_center.set][G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or SMODS.UndiscoveredSprites[_center.set].atlas)) - or _center.set] or G.ASSET_ATLAS["Joker"]''' + or (SMODS.UndiscoveredSprites[_center.set] and (SMODS.UndiscoveredSprites[_center.set][G.SETTINGS.colourblind_option and 'hc_atlas' or 'lc_atlas'] or SMODS.UndiscoveredSprites[_center.set].atlas)) + or _center.set] or G.ASSET_ATLAS["Joker"]''' [[patches]] [patches.regex] @@ -82,10 +82,10 @@ pattern = 'G.ASSET_ATLAS["icons"]' position = 'after' match_indent = false payload = ''' - local _smods_atlas = _c and ((G.SETTINGS.colourblind_option and _c.hc_atlas or _c.lc_atlas) or _c.atlas) - if _smods_atlas then - _atlas = G.ASSET_ATLAS[_smods_atlas] or _atlas - end''' + local _smods_atlas = _c and ((G.SETTINGS.colourblind_option and _c.hc_atlas or _c.lc_atlas) or _c.atlas) + if _smods_atlas then + _atlas = G.ASSET_ATLAS[_smods_atlas] or _atlas + end''' ## Hide floating ? from undiscovered types # Card:draw() diff --git a/smods-old-calc/lovely/back.toml b/smods-old-calc/lovely/back.toml new file mode 100644 index 0000000..c769b4e --- /dev/null +++ b/smods-old-calc/lovely/back.toml @@ -0,0 +1,316 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Back API + +# Back:init() +[[patches]] +[patches.pattern] +target = 'back.lua' +pattern = "if not selected_back then selected_back = G.P_CENTERS.b_red end" +position = 'after' +match_indent = true +payload = "self.atlas = selected_back.unlocked and selected_back.atlas or nil" + +# Back:change_to() +[[patches]] +[patches.pattern] +target = 'back.lua' +pattern = "if not new_back then new_back = G.P_CENTERS.b_red end" +position = 'after' +match_indent = true +payload = "self.atlas = new_back.unlocked and new_back.atlas or nil" + +# G.FUNCS.change_viewed_back +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = "G.PROFILES[G.SETTINGS.profile].MEMORY.deck = args.to_val" +position = 'after' +match_indent = true +payload = ''' +for key, val in pairs(G.sticker_card.area.cards) do + val.children.back = false + val:set_ability(val.config.center, true) +end''' + +# Back:apply_to_run() +[[patches]] +[patches.pattern] +target = 'back.lua' +pattern = "function Back:apply_to_run()" +position = 'after' +match_indent = true +payload = ''' + local obj = self.effect.center + if obj.apply and type(obj.apply) == 'function' then + obj:apply() + end''' + +# Back:trigger_effect(args) +[[patches]] +[patches.pattern] +target = 'back.lua' +pattern = "if not args then return end" +position = 'after' +match_indent = true +payload = ''' + local obj = self.effect.center + if obj.trigger_effect and type(obj.trigger_effect) == 'function' then + local o = {obj:trigger_effect(args)} + if o then return unpack(o) end + end''' + +## Additonal trigger_effect contexts +## calculate_joker +# card.lua +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''G.jokers.cards[i]:calculate_joker({remove_playing_cards = true, removed = destroyed_cards}) + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'remove_playing_cards', removed = destroyed_cards})''' + +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''G.jokers.cards[i]:calculate_joker({open_booster = true, card = self}) + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'open_booster', card = self})''' + +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''G.jokers.cards[i]:calculate_joker({buying_card = true, card = self}) + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'buying_card', card = self})''' + +# game.lua +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = '''G.jokers.cards[i]:calculate_joker({first_hand_drawn = true}) + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'first_hand_drawn'})''' + +# functions/button_callbacks.lua +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''G.jokers.cards[i]:calculate_joker({using_consumeable = true, consumeable = card}) + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'using_consumeable', consumeable = card})''' + +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''G.jokers.cards[i]:calculate_joker({selling_card = true, card = card}) + end + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'selling_card', card = card})''' + +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''G.jokers.cards[i]:calculate_joker({buying_card = true, card = c1}) + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'buying_card', card = c1})''' + +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''G.jokers.cards[i]:calculate_joker({ending_shop = true}) + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'ending_shop'})''' + +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''G.jokers.cards[i]:calculate_joker({skipping_booster = true}) + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'skipping_booster'})''' + +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''G.jokers.cards[i]:calculate_joker({skip_blind = true}) + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'skip_blind'})''' + +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''G.jokers.cards[i]:calculate_joker({reroll_shop = true}) + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'reroll_shop'})''' + +# functions/state_events.lua +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = '''G.jokers.cards[i]:calculate_perishable() + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'end_of_round', game_over = game_over})''' + +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = '''G.jokers.cards[i]:calculate_joker({setting_blind = true, blind = G.GAME.round_resets.blind}) + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'setting_blind', blind = G.GAME.round_resets.blind})''' + +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = '''card_eval_status_text(G.jokers.cards[j], 'jokers', nil, 1, nil, eval) + end + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'discard', other_card = G.hand.highlighted[i], full_hand = G.hand.highlighted})''' + +## eval_card +# functions/state_events.lua +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = '''level_up_hand(G.jokers.cards[i], text) + end + end + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'before_hand', full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands})''' + +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = '''local effects = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, joker_main = true})''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'joker_main', joker = _card, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands})''' + +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = '''eval_card(G.jokers.cards[j], {cardarea = G.jokers, remove_playing_cards = true, removed = cards_destroyed}) + end''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'remove_playing_cards', removed = cards_destroyed})''' + +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = '''end + end + + }) end +''' +position = 'after' +match_indent = true +payload = '''G.GAME.selected_back:trigger_effect({context = 'after', full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands})''' + +## Back:generate_UI + +# Localization with `unlock` field in loc_txt, same as for Jokers +[[patches]] +[patches.pattern] +target = 'back.lua' +pattern = 'if not back_config.unlock_condition then' +position = 'at' +payload = ''' +local localized_by_smods +local key_override +if back_config.locked_loc_vars and type(back_config.locked_loc_vars) == 'function' then + local res = back_config:locked_loc_vars() or {} + loc_args = res.vars or {} + key_override = res.key +end +if G.localization.descriptions.Back[key_override or back_config.key].unlock_parsed then + localize{type = 'unlocks', key = key_override or back_config.key, set = 'Back', nodes = loc_nodes, vars = loc_args} + localized_by_smods = true +end +if not back_config.unlock_condition then''' +match_indent = true +[[patches]] +[patches.pattern] +target = 'back.lua' +pattern = '''localize{type = 'descriptions', key = 'demo_locked', set = "Other", nodes = loc_nodes, vars = loc_args}''' +position = 'at' +payload = ''' +if not localized_by_smods then + localize{type = 'descriptions', key = 'demo_locked', set = "Other", nodes = loc_nodes, vars = loc_args} +end''' +match_indent = true + +[[patches]] +[patches.pattern] +target = 'back.lua' +pattern = 'loc_args = {other_name}' +position = 'at' +payload = 'loc_args = loc_args or {other_name}' +match_indent = true +[[patches]] +[patches.pattern] +target = 'back.lua' +pattern = 'loc_args = {tostring(back_config.unlock_condition.amount)}' +position = 'at' +payload = 'loc_args = loc_args or {tostring(back_config.unlock_condition.amount)}' +match_indent = true +[[patches]] +[patches.pattern] +target = 'back.lua' +pattern = 'loc_args = {other_name, colours = {get_stake_col(back_config.unlock_condition.stake)}}' +position = 'at' +payload = 'loc_args = loc_args or {other_name, colours = {get_stake_col(back_config.unlock_condition.stake)}}' +match_indent = true + +[[patches]] +[patches.pattern] +target = 'back.lua' +pattern = "if name_to_check == 'Blue Deck'*" +position = 'at' +match_indent = true +payload = ''' +local key_override +if back_config.loc_vars and type(back_config.loc_vars) == 'function' then + local res = back_config:loc_vars() or {} + loc_args = res.vars or {} + key_override = res.key +elseif name_to_check == 'Blue Deck' then loc_args = {effect_config.hands}''' + +[[patches]] +[patches.regex] +target = 'back.lua' +pattern = "key = back_config\\.key" +position = 'at' +payload = "key = key_override or back_config.key" diff --git a/smods-old-calc/lovely/blind.toml b/smods-old-calc/lovely/blind.toml new file mode 100644 index 0000000..8ca1152 --- /dev/null +++ b/smods-old-calc/lovely/blind.toml @@ -0,0 +1,362 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Blind API + +## Set debuffed_by_blind, use it for Matador behavior +## Blind:debuff_card() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = 'card:set_debuff(true)' +position = 'after' +payload = "if card.debuff then card.debuffed_by_blind = true end" +match_indent = true +[[patches]] +[patches.regex] +target = 'blind.lua' +pattern = 'card:set_debuff\(true\); return end' +position = 'at' +payload = """ +card:set_debuff(true); if card.debuff then card.debuffed_by_blind = true end; return end""" + +## Card:set_debuff() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = ''' +self\.debuff = should_debuff +(?[\t ]*)end +''' +position = 'after' +payload = """if not self.debuff then self.debuffed_by_blind = false end + +""" +line_prepend = '$indent' + +## Blind functions + +# Blind:set_blind() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = "G.GAME.last_blind = G.GAME.last_blind or {}" +position = 'before' +match_indent = true +payload = ''' +local obj = self.config.blind +self.children.animatedSprite.atlas = G.ANIMATION_ATLAS[obj.atlas] or G.ANIMATION_ATLAS['blind_chips']''' + +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = '--add new debuffs' +position = 'before' +match_indent = true +payload = ''' +if not reset then + local obj = self.config.blind + if obj.set_blind and type(obj.set_blind) == 'function' then + obj:set_blind() + end +end''' + +# Blind:disable() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = "if self.name == 'The Water' then" +position = 'before' +match_indent = true +payload = ''' +local obj = self.config.blind +if obj.disable and type(obj.disable) == 'function' then + obj:disable() +end''' + +# Blind:defeat() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = "if self.name == 'The Manacle' and not self.disabled then" +position = 'before' +match_indent = true +payload = ''' +local obj = self.config.blind +if obj.defeat and type(obj.defeat) == 'function' then + obj:defeat() +end''' + +# Blind:debuff_card() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = "if self.debuff and not self.disabled and card.area ~= G.jokers then" +position = 'before' +match_indent = true +payload = ''' +local obj = self.config.blind +if not self.disabled and obj.recalc_debuff and type(obj.recalc_debuff) == 'function' then + if obj:recalc_debuff(card, from_blind) then + card:set_debuff(true) + if card.debuff then card.debuffed_by_blind = true end + else + card:set_debuff(false) + end + return +elseif not self.disabled and obj.debuff_card and type(obj.debuff_card) == 'function' then + sendWarnMessage(("Blind object %s has debuff_card function, recalc_debuff is preferred"):format(obj.key), obj.set) + if obj:debuff_card(card, from_blind) then + card:set_debuff(true) + if card.debuff then card.debuffed_by_blind = true end + else + card:set_debuff(false) + end + return +end''' + +# Blind:stay_flipped() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = "if area == G.hand then" +position = 'before' +match_indent = true +payload = ''' +local obj = self.config.blind +if obj.stay_flipped and type(obj.stay_flipped) == 'function' then + return obj:stay_flipped(area, card) +end''' + +# Blind:drawn_to_hand() +[[patches]] +[patches.regex] +target = 'blind.lua' +pattern = "(?[\t ]*)if self.name == 'Cerulean Bell' then\n" +position = 'before' +line_prepend = '$indent' +payload = ''' +local obj = self.config.blind +if obj.drawn_to_hand and type(obj.drawn_to_hand) == 'function' then + obj:drawn_to_hand() +end''' + +# Blind:debuff_hand() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = "if self.debuff then" +position = 'before' +match_indent = true +payload = ''' +local obj = self.config.blind +if obj.debuff_hand and type(obj.debuff_hand) == 'function' then + return obj:debuff_hand(cards, hand, handname, check) +end''' + +# Blind:modify_hand() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = "if self.disabled then return mult, hand_chips, false end" +position = 'after' +match_indent = true +payload = ''' +local obj = self.config.blind +if obj.modify_hand and type(obj.modify_hand) == 'function' then + return obj:modify_hand(cards, poker_hands, text, mult, hand_chips) +end''' + +# Blind:press_play() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = 'if self.name == "The Hook" then' +position = 'before' +match_indent = true +payload = ''' +local obj = self.config.blind +if obj.press_play and type(obj.press_play) == 'function' then + return obj:press_play() +end''' + +# Blind:get_loc_debuff_text() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = 'function Blind:get_loc_debuff_text()' +position = 'after' +match_indent = true +payload = ''' + local obj = self.config.blind + if obj.get_loc_debuff_text and type(obj.get_loc_debuff_text) == 'function' then + return obj:get_loc_debuff_text() + end''' + +# Blind:set_text() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = "local loc_target = localize{type = 'raw_descriptions', key = self.config.blind.key, set = 'Blind', vars = loc_vars or self.config.blind.vars}" +position = 'at' +match_indent = true +payload = ''' +local target = {type = 'raw_descriptions', key = self.config.blind.key, set = 'Blind', vars = loc_vars or self.config.blind.vars} +local obj = self.config.blind +if obj.loc_vars and type(obj.loc_vars) == 'function' then + local res = obj:loc_vars() or {} + target.vars = res.vars or target.vars + target.key = res.key or target.key +end +local loc_target = localize(target)''' + +# Blind:load() +[[patches]] +[patches.pattern] +target = 'blind.lua' +pattern = 'if G.P_BLINDS[blindTable.config_blind] then' +position = 'after' +match_indent = true +payload = ''' +if self.config.blind.atlas then + self.children.animatedSprite.atlas = G.ANIMATION_ATLAS[self.config.blind.atlas] +end''' + + +# create_UIBox_blind_choice() +# create_UIBox_round_scores_row() +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = "(?[\t ]*)blind_choice.animation = AnimatedSprite\\(0,0, 1.4, 1.4, (?G.ANIMATION_ATLAS\\['blind_chips'\\]), blind_choice.config.pos\\)" +position = 'at' +root_capture = 'atlas' +payload = "G.ANIMATION_ATLAS[blind_choice.config.atlas] or G.ANIMATION_ATLAS['blind_chips']" + +# create_UIBox_your_collection_blinds() +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = "(?[\t ]*)local temp_blind = AnimatedSprite\\(0,0,1.3,1.3, G.ANIMATION_ATLAS\\['blind_chips'\\], discovered and v.pos or G.b_undiscovered.pos\\)" +position = 'at' +payload = ''' + +local s = 1.3 +if math.ceil(#blind_tab/6) > 6 then + s = s * 6/math.ceil(#blind_tab/6) +end +local temp_blind = AnimatedSprite(0,0,s,s, G.ANIMATION_ATLAS[discovered and v.atlas or 'blind_chips'], discovered and v.pos or G.b_undiscovered.pos)''' +line_prepend = '$indent' + +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = 'blind_matrix[math.ceil((k-1)/5+0.001)][1+((k-1)%5)] = {n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={' +match_indent = true +position = 'at' +payload = ''' +local blinds_per_row = math.ceil(#blind_tab / 6) +local row = math.ceil((k - 1) / blinds_per_row + 0.001) +table.insert(blind_matrix[row], { + n = G.UIT.C, + config = { align = "cm", padding = 0.1 }, + nodes = { + ((k - blinds_per_row) % (2 * blinds_per_row) == 1) and { n = G.UIT.B, config = { h = 0.2, w = 0.5 } } or nil, + { n = G.UIT.O, config = { object = temp_blind, focus_with_object = true } }, + ((k - blinds_per_row) % (2 * blinds_per_row) == 0) and { n = G.UIT.B, config = { h = 0.2, w = 0.5 } } or nil, + } +})''' + +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = '[\t ]*\(k==6 or k ==16 or k == 26\) and \{n=G.UIT.B, config=\{h=0.2,w=0.5\}\} or nil,\n[\t ]*\{n=G.UIT.O, config=\{object = temp_blind, focus_with_object = true\}\},\n[\t ]*\(k==5 or k ==15 or k == 25\) and \{n=G.UIT.B, config=\{h=0.2,w=0.5\}\} or nil,\n[\t ]*\}\}' +position = 'at' +payload = '' + +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = 'table.sort(blind_tab, function (a, b) return a.order < b.order end)' +match_indent = true +position = 'at' +payload = ''' +table.sort(blind_tab, function(a, b) return a.order + (a.boss and a.boss.showdown and 1000 or 0) < b.order + (b.boss and b.boss.showdown and 1000 or 0) end)''' + +# add_round_eval_row() +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "local blind_sprite = AnimatedSprite(0, 0, 1.2,1.2, G.ANIMATION_ATLAS['blind_chips'], copy_table(G.GAME.blind.pos))" +match_indent = true +position = 'at' +payload = ''' +local obj = G.GAME.blind.config.blind +local blind_sprite = AnimatedSprite(0, 0, 1.2, 1.2, G.ANIMATION_ATLAS[obj.atlas] or G.ANIMATION_ATLAS['blind_chips'], copy_table(G.GAME.blind.pos))''' + +# create_UIBox_blind_choice() +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = "local loc_target = localize{type = 'raw_descriptions', key = blind_choice.config.key, set = 'Blind', vars = {localize(G.GAME.current_round.most_played_poker_hand, 'poker_hands')}}" +match_indent = true +position = 'at' +payload = ''' +local target = {type = 'raw_descriptions', key = blind_choice.config.key, set = 'Blind', vars = {}} +if blind_choice.config.name == 'The Ox' then + target.vars = {localize(G.GAME.current_round.most_played_poker_hand, 'poker_hands')} +end +local obj = blind_choice.config +if obj.loc_vars and _G['type'](obj.loc_vars) == 'function' then + local res = obj:loc_vars() or {} + target.vars = res.vars or target.vars + target.key = res.key or target.key +end +local loc_target = localize(target)''' + +# create_UIBox_blind_popup() +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = '''local loc_target = localize{type = 'raw_descriptions', key = blind.key, set = 'Blind', vars = vars or blind.vars}''' +match_indent = true +position = 'at' +payload = ''' +local target = {type = 'raw_descriptions', key = blind.key, set = 'Blind', vars = vars or blind.vars} +if blind.collection_loc_vars and type(blind.collection_loc_vars) == 'function' then + local res = blind:collection_loc_vars() or {} + target.vars = res.vars or target.vars + target.key = res.key or target.key +end +local loc_target = localize(target)''' + +# get_new_boss() +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = 'elseif not v.boss.showdown*' +match_indent = true +position = 'before' +payload = ''' +elseif v.in_pool and type(v.in_pool) == 'function' then + local res, options = v:in_pool() + if + ( + ((G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2) == + (v.boss.showdown or false) + ) or + (options or {}).ignore_showdown_check + then + eligible_bosses[k] = res and true or nil + end''' + +# G.UIDEF.challenge_description_tab +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = "local temp_blind = AnimatedSprite(0,0,1,1, G.ANIMATION_ATLAS['blind_chips'], v.pos)" +position = 'at' +match_indent = true +payload = "local temp_blind = AnimatedSprite(0,0,1,1, G.ANIMATION_ATLAS[v.atlas or ''] or G.ANIMATION_ATLAS['blind_chips'], v.pos)" diff --git a/smods-old-calc/lovely/blind_ui.toml b/smods-old-calc/lovely/blind_ui.toml new file mode 100644 index 0000000..8c84f3f --- /dev/null +++ b/smods-old-calc/lovely/blind_ui.toml @@ -0,0 +1,150 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Allow blinds to have more than 2 lines + +# create_UIBox_blind_choice() +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "if blind_state == 'Select' then blind_state = 'Current' end" +position = 'after' +payload = ''' +local blind_desc_nodes = {} +for k, v in ipairs(text_table) do + blind_desc_nodes[#blind_desc_nodes+1] = {n=G.UIT.R, config={align = "cm", maxw = 2.8}, nodes={ + {n=G.UIT.T, config={text = v or '-', scale = 0.32, colour = disabled and G.C.UI.TEXT_INACTIVE or G.C.WHITE, shadow = not disabled}} + }} +end''' +match_indent = true + +[[patches]] +[patches.regex] +target = "functions/UI_definitions.lua" +pattern = ''' +(?[\t ]*)text_table\[1\] and \{n=G\.UIT\.R, config=\{align = "cm", minh = 0\.7, padding = 0\.05, minw = 2\.9}, nodes=\{ +[\t ]* text_table\[1\] and \{n=G\.UIT\.R, config=\{align = "cm", maxw = 2\.8\}, nodes=\{ +[\t ]* \{n=G\.UIT\.T, config=\{id = blind_choice\.config\.key, ref_table = \{val = ''\}, ref_value = 'val', scale = 0\.32, colour = disabled and G\.C\.UI\.TEXT_INACTIVE or G\.C\.WHITE, shadow = not disabled, func = 'HUD_blind_debuff_prefix'\}\}, +[\t ]* \{n=G\.UIT\.T, config=\{text = text_table\[1\] or '\-', scale = 0\.32, colour = disabled and G\.C\.UI\.TEXT_INACTIVE or G\.C\.WHITE, shadow = not disabled\}\} +[\t ]* \}\} or nil, +[\t ]* text_table\[2\] and \{n=G\.UIT\.R, config=\{align = "cm", maxw = 2\.8\}, nodes=\{ +[\t ]* \{n=G\.UIT\.T, config=\{text = text_table\[2\] or '\-', scale = 0\.32, colour = disabled and G\.C\.UI\.TEXT_INACTIVE or G\.C\.WHITE, shadow = not disabled\}\} +[\t ]* \}\} or nil, +[\t ]*\}\} or nil,''' +position = "at" +payload = ''' +text_table[1] and {n=G.UIT.R, config={align = "cm", minh = 0.7, padding = 0.05, minw = 2.9}, nodes = blind_desc_nodes} or nil,''' +line_prepend = '$indent' + +# create_UIBox_HUD_blind() +# Padding and contained nodes are set in G.FUNCS.HUD_blind_debuff (overrides.lua) +[[patches]] +[patches.regex] +target = "functions/UI_definitions.lua" +pattern = ''' +(?[\t ]*)\{n=G\.UIT\.R, config=\{align = "cm", padding = 0\.05\}, nodes=\{ +[\t ]* \{n=G\.UIT\.R, config=\{align = "cm", minh = 0\.3, maxw = 4\.2\}, nodes=\{ +[\t ]* \{n=G\.UIT\.T, config=\{ref_table = \{val = ''\}, ref_value = 'val', scale = scale\*0\.9, colour = G\.C\.UI\.TEXT_LIGHT, func = 'HUD_blind_debuff_prefix'\}\}, +[\t ]* \{n=G\.UIT\.T, config=\{ref_table = G\.GAME\.blind\.loc_debuff_lines, ref_value = 1, scale = scale\*0\.9, colour = G\.C\.UI\.TEXT_LIGHT, id = 'HUD_blind_debuff_1', func = 'HUD_blind_debuff'\}\} +[\t ]* \}\}, +[\t ]* \{n=G\.UIT\.R, config=\{align = "cm", minh = 0\.3, maxw = 4\.2\}, nodes=\{ +[\t ]* \{n=G\.UIT\.T, config=\{ref_table = G\.GAME\.blind\.loc_debuff_lines, ref_value = 2, scale = scale\*0\.9, colour = G\.C\.UI\.TEXT_LIGHT, id = 'HUD_blind_debuff_2', func = 'HUD_blind_debuff'\}\} +[\t ]* \}\}, +[\t ]*\}\},''' +position = "at" +payload = ''' +{n=G.UIT.R, config={align = "cm", id = 'HUD_blind_debuff', func = 'HUD_blind_debuff'}, nodes={}},''' +line_prepend = '$indent' + +# Blind:set_text +[[patches]] +[patches.regex] +target = "blind.lua" +pattern = """ +(?[\t ]*)self\\.loc_debuff_lines\\[1\\] = '' +[\t ]*self\\.loc_debuff_lines\\[2\\] = ''""" +position = 'at' +payload = 'EMPTY(self.loc_debuff_lines)' +line_prepend = '$indent' + +[[patches]] +[patches.pattern] +target = "blind.lua" +pattern = "for k, v in ipairs(loc_target) do" +position = 'before' +payload = 'EMPTY(self.loc_debuff_lines)' +match_indent = true + +[[patches]] +[patches.pattern] +target = "blind.lua" +pattern = "self.loc_debuff_text = self.loc_debuff_text..v..(k <= #loc_target and ' ' or '')" +position = 'after' +payload = "self.loc_debuff_lines[k] = v" +match_indent = true + +[[patches]] +[patches.regex] +target = "blind.lua" +pattern = """ +(?[\t ]*)self\\.loc_debuff_lines\\[1\\] = loc_target\\[1\\] or '' +[\t ]*self\\.loc_debuff_lines\\[2\\] = loc_target\\[2\\] or '' +""" +position = 'at' +payload = '' + +## Add a box with h=3.64 (magic number equal to the height of HUD_blind) +## centered inside 'row_blind' +# create_UIBox_HUD +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = """{n=G.UIT.R, config={align = "cm", id = 'row_blind', minw = 1, minh = 3.75}, nodes={}},""" +position = 'at' +payload = """{n=G.UIT.R, config={align = "cm", id = 'row_blind', minw = 1, minh = 3.75}, nodes={ + {n=G.UIT.B, config={w=0, h=3.64, id = 'row_blind_bottom'}, nodes={}} +}},""" +match_indent = true + +## Blind UI's bottom edge is aligned to it +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = "config = {major = G.HUD:get_UIE_by_ID('row_blind'), align = 'cm', offset = {x=0,y=-10}, bond = 'Weak'}" +position = 'at' +payload = "config = {major = G.HUD:get_UIE_by_ID('row_blind_bottom'), align = 'bmi', offset = {x=0,y=-10}, bond = 'Weak'}" +match_indent = true + +## Patch G.GAME.blind:juice_up() across all files + +[[patches]] +[patches.regex] +target = "functions/common_events.lua" +pattern = ''' +(?[\t ]*)G\.HUD_blind:get_UIE_by_ID\('HUD_blind_debuff_1'\):juice_up\(0\.3, 0\) +[\t ]*G\.HUD_blind:get_UIE_by_ID\('HUD_blind_debuff_2'\):juice_up\(0\.3, 0\) +[\t ]*G\.GAME\.blind:juice_up\(\)''' +position = 'at' +payload = 'SMODS.juice_up_blind()' +line_prepend = '$indent' + +[[patches]] +[patches.regex] +target = "functions/state_events.lua" +pattern = ''' +(?[\t ]*)G\.HUD_blind:get_UIE_by_ID\('HUD_blind_debuff_1'\):juice_up\(0\.3, 0\) +[\t ]*G\.HUD_blind:get_UIE_by_ID\('HUD_blind_debuff_2'\):juice_up\(0\.3, 0\) +[\t ]*G\.GAME\.blind:juice_up\(\)''' +position = 'at' +payload = 'SMODS.juice_up_blind()' +line_prepend = '$indent' + +# remove statically added 1 from The Wheel's collection description +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = '''\(k ==1 and blind\.name == 'The Wheel' and '1' or ''\)\.\.''' +position = 'at' +payload = '' diff --git a/Steamodded/lovely/booster.toml b/smods-old-calc/lovely/booster.toml similarity index 99% rename from Steamodded/lovely/booster.toml rename to smods-old-calc/lovely/booster.toml index d35cf92..033acf0 100644 --- a/Steamodded/lovely/booster.toml +++ b/smods-old-calc/lovely/booster.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ## Booster Pack API @@ -186,4 +186,4 @@ if self.cost ~= 0 then ease_dollars(-self.cost) inc_career_stat('c_shop_dollars_spent', self.cost) end''' -line_prepend = '$indent' \ No newline at end of file +line_prepend = '$indent' diff --git a/Steamodded/lovely/center.toml b/smods-old-calc/lovely/center.toml similarity index 67% rename from Steamodded/lovely/center.toml rename to smods-old-calc/lovely/center.toml index 5c1eca8..3090115 100644 --- a/Steamodded/lovely/center.toml +++ b/smods-old-calc/lovely/center.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Center API @@ -14,7 +14,7 @@ position = 'before' payload = ''' local obj = self.config.center if obj.set_ability and type(obj.set_ability) == 'function' then - obj:set_ability(self, initial, delay_sprites) + obj:set_ability(self, initial, delay_sprites) end ''' @@ -26,13 +26,13 @@ pattern = "self.ability.bonus = (self.ability.bonus or 0) + (center.config.bonus position = "after" payload = """ for k, v in pairs(center.config) do - if k ~= 'bonus' then - if type(v) == 'table' then - self.ability[k] = copy_table(v) - else - self.ability[k] = v - end - end + if k ~= 'bonus' then + if type(v) == 'table' then + self.ability[k] = copy_table(v) + else + self.ability[k] = v + end + end end""" match_indent = true @@ -45,8 +45,8 @@ position = 'before' payload = ''' local obj = self.config.center if self.ability.set ~= "Enhanced" and obj.calculate and type(obj.calculate) == 'function' then - local o, t = obj:calculate(self, context) - if o or t then return o, t end + local o, t = obj:calculate(self, context) + if o or t then return o, t end end''' match_indent = true @@ -60,7 +60,7 @@ match_indent = true payload = ''' local obj = self.config.center if obj.update and type(obj.update) == 'function' then - obj:update(self, dt) + obj:update(self, dt) end''' # Card:generate_UIBox_ability_table() @@ -89,7 +89,7 @@ position = 'at' match_indent = true payload = ''' if not _c.generate_ui or type(_c.generate_ui) ~= 'function' then - full_UI_table.name = localize{type = 'name', set = _c.set, key = _c.key, nodes = full_UI_table.name} + full_UI_table.name = localize{type = 'name', set = _c.set, key = _c.key, nodes = full_UI_table.name} end''' [[patches]] @@ -100,8 +100,8 @@ position = 'before' match_indent = true payload = ''' elseif _c.generate_ui and type(_c.generate_ui) == 'function' then - _c:generate_ui(info_queue, card, desc_nodes, specific_vars, full_UI_table) - if specific_vars and specific_vars.pinned then info_queue[#info_queue+1] = {key = 'pinned_left', set = 'Other'} end + _c:generate_ui(info_queue, card, desc_nodes, specific_vars, full_UI_table) + if specific_vars and specific_vars.pinned then info_queue[#info_queue+1] = {key = 'pinned_left', set = 'Other'} end if specific_vars and specific_vars.sticker then info_queue[#info_queue+1] = {key = string.lower(specific_vars.sticker)..'_sticker', set = 'Other'} end''' [[patches]] @@ -111,13 +111,30 @@ pattern = "(?[\t ]+)if (?_c.name == 'Golden Ticket' then)" line_prepend = '$indent' position = 'at' payload = ''' +local res = {} if _c.locked_loc_vars and type(_c.locked_loc_vars) == 'function' then - local res = _c:locked_loc_vars(info_queue) or {} - loc_vars = res.vars or {} - specific_vars = specific_vars or {} - specific_vars.not_hidden = res.not_hidden or specific_vars.not_hidden + res = _c:locked_loc_vars(info_queue) or {} + loc_vars = res.vars or {} + specific_vars = specific_vars or {} + specific_vars.not_hidden = res.not_hidden or specific_vars.not_hidden elseif $rest''' +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +position = 'at' +match_indent = true +pattern = "localize{type = 'unlocks', key = 'joker_locked_legendary', set = 'Other', nodes = desc_nodes, vars = loc_vars}" +payload = "localize{type = 'unlocks', key = res.key or 'joker_locked_legendary', set = res.set or 'Other', nodes = desc_nodes, vars = loc_vars, text_colour = res.text_colour, scale = res.scale}" + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +position = 'at' +match_indent = true +pattern = "localize{type = 'unlocks', key = _c.key, set = _c.set, nodes = desc_nodes, vars = loc_vars}" +payload = "localize{type = 'unlocks', key = res.key or _c.key, set = res.set or _c.set, nodes = desc_nodes, vars = loc_vars, text_colour = res.text_colour, scale = res.scale}" + [[patches]] [patches.pattern] target = 'functions/common_events.lua' @@ -126,6 +143,8 @@ match_indent = true pattern = 'elseif desc_nodes ~= full_UI_table.main then' payload = 'elseif desc_nodes ~= full_UI_table.main and not desc_nodes.name then' + + # check_for_unlock() [[patches]] [patches.regex] @@ -137,9 +156,9 @@ payload = ''' local custom_check if not card.unlocked and card.check_for_unlock and type(card.check_for_unlock) == 'function' then - ret = card:check_for_unlock(args) - if ret then unlock_card(card) end - custom_check = true + ret = card:check_for_unlock(args) + if ret then unlock_card(card) end + custom_check = true end''' [[patches]] @@ -168,8 +187,8 @@ position = 'before' payload = ''' local obj = self.config.center if obj.use and type(obj.use) == 'function' then - obj:use(self, area, copier) - return + obj:use(self, area, copier) + return end''' # Card:can_use_consumable() @@ -182,7 +201,7 @@ position = 'before' payload = ''' local obj = self.config.center if obj.can_use and type(obj.can_use) == 'function' then - return obj:can_use(self) + return obj:can_use(self) end''' # G.UIDEF.card_h_popup() @@ -195,19 +214,19 @@ position = 'at' payload = ''' local obj = card.config.center $if - if obj and (obj.set_card_type_badge or obj.type and obj.type.set_card_type_badge) then - if obj.type and type(obj.type.set_card_type_badge) == 'function' then - obj.type:set_card_type_badge(obj, card, badges) - end - if type(obj.set_card_type_badge) == 'function' then - obj:set_card_type_badge(card, badges) - end - else - $rest - end + if obj and (obj.set_card_type_badge or obj.type and obj.type.set_card_type_badge) then + if obj.type and type(obj.type.set_card_type_badge) == 'function' then + obj.type:set_card_type_badge(obj, card, badges) + end + if type(obj.set_card_type_badge) == 'function' then + obj:set_card_type_badge(card, badges) + end + else + $rest + end end if obj and obj.set_badges and type(obj.set_badges) == 'function' then - obj:set_badges(card, badges) + obj:set_badges(card, badges) end''' [[patches]] @@ -218,15 +237,15 @@ line_prepend = '$indent' position = 'after' payload = ''' if AUT.card_type ~= 'Locked' and AUT.card_type ~= 'Undiscovered' then - SMODS.create_mod_badges(card.config.center, badges) - if card.base then - SMODS.create_mod_badges(SMODS.Ranks[card.base.value], badges) - SMODS.create_mod_badges(SMODS.Suits[card.base.suit], badges) - end - if card.config and card.config.tag then - SMODS.create_mod_badges(SMODS.Tags[card.config.tag.key], badges) - end - badges.mod_set = nil + SMODS.create_mod_badges(card.config.center, badges) + if card.base then + SMODS.create_mod_badges(SMODS.Ranks[card.base.value], badges) + SMODS.create_mod_badges(SMODS.Suits[card.base.suit], badges) + end + if card.config and card.config.tag then + SMODS.create_mod_badges(SMODS.Tags[card.config.tag.key], badges) + end + badges.mod_set = nil end''' # set_discover_tallies() @@ -239,10 +258,10 @@ position = 'at' payload = ''' local tally = G.DISCOVER_TALLIES[v.set:lower()..'s'] if tally then - tally.of = tally.of + 1 - if v.discovered then - tally.tally = tally.tally + 1 - end + tally.of = tally.of + 1 + if v.discovered then + tally.tally = tally.tally + 1 + end end''' [[patches]] @@ -261,7 +280,7 @@ line_prepend = '$indent' position = 'before' payload = ''' for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do - G.DISCOVER_TALLIES[v:lower()..'s'] = {tally = 0, of = 0} + G.DISCOVER_TALLIES[v:lower()..'s'] = {tally = 0, of = 0} end''' # create_UIBox_your_collection() @@ -274,12 +293,12 @@ position = 'before' payload = ''' local consumable_nodes = {} if #SMODS.ConsumableType.ctype_buffer <= 3 then - for _, key in ipairs(SMODS.ConsumableType.ctype_buffer) do - local id = 'your_collection_'..key:lower()..'s' - consumable_nodes[#consumable_nodes+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = G.DISCOVER_TALLIES[key:lower()..'s'], minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) - end + for _, key in ipairs(SMODS.ConsumableType.ctype_buffer) do + local id = 'your_collection_'..key:lower()..'s' + consumable_nodes[#consumable_nodes+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = G.DISCOVER_TALLIES[key:lower()..'s'], minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) + end else - consumable_nodes[#consumable_nodes+1] = UIBox_button({ button = 'your_collection_consumables', label = {localize('b_stat_consumables'), localize{ type = 'variable', key = 'c_types', vars = {#SMODS.ConsumableType.ctype_buffer} } }, count = G.DISCOVER_TALLIES['consumeables'], minw = 4, minh = 4, id = 'your_collection_consumables', colour = G.C.FILTER }) + consumable_nodes[#consumable_nodes+1] = UIBox_button({ button = 'your_collection_consumables', label = {localize('b_stat_consumables'), localize{ type = 'variable', key = 'c_types', vars = {#SMODS.ConsumableType.ctype_buffer} } }, count = G.DISCOVER_TALLIES['consumeables'], minw = 4, minh = 4, id = 'your_collection_consumables', colour = G.C.FILTER }) end ''' @@ -301,8 +320,8 @@ position = 'before' payload = ''' local obj = center or self.config.center if obj.redeem and type(obj.redeem) == 'function' then - obj:redeem(self) - return + obj:redeem(self) + return end''' # create_card_for_shop() @@ -315,7 +334,7 @@ position = 'at' payload = ''' local total_rate = G.GAME.joker_rate + G.GAME.playing_card_rate for _,v in ipairs(SMODS.ConsumableType.ctype_buffer) do - total_rate = total_rate + G.GAME[v:lower()..'_rate'] + total_rate = total_rate + G.GAME[v:lower()..'_rate'] end''' [[patches]] @@ -328,9 +347,9 @@ payload = ''' -- need to preserve order to leave RNG unchanged local rates = $li for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do - if not (v == 'Tarot' or v == 'Planet' or v == 'Spectral') then - table.insert(rates, { type = v, val = G.GAME[v:lower()..'_rate'] }) - end + if not (v == 'Tarot' or v == 'Planet' or v == 'Spectral') then + table.insert(rates, { type = v, val = G.GAME[v:lower()..'_rate'] }) + end end for _, v in ipairs(rates) do''' @@ -342,13 +361,13 @@ pattern = "if not forced_key and soulable and (not G.GAME.banned_keys['c_soul']) match_indent = true position = 'after' payload = ''' - for _, v in ipairs(SMODS.Consumable.legendaries) do - if (_type == v.type.key or _type == v.soul_set) and not (G.GAME.used_jokers[v.key] and not next(find_joker("Showman")) and not v.can_repeat_soul) and (not v.in_pool or (type(v.in_pool) ~= "function") or v:in_pool()) then - if pseudorandom('soul_'..v.key.._type..G.GAME.round_resets.ante) > (1 - v.soul_rate) then - forced_key = v.key - end - end - end''' + for _, v in ipairs(SMODS.Consumable.legendaries) do + if (_type == v.type.key or _type == v.soul_set) and not (G.GAME.used_jokers[v.key] and not next(find_joker("Showman")) and not v.can_repeat_soul) and (not v.in_pool or (type(v.in_pool) ~= "function") or v:in_pool()) then + if pseudorandom('soul_'..v.key.._type..G.GAME.round_resets.ante) > (1 - v.soul_rate) then + forced_key = v.key + end + end + end''' # Card:add_to_deck() [[patches]] @@ -360,7 +379,7 @@ position = 'before' payload = ''' local obj = self.config.center if obj and obj.add_to_deck and type(obj.add_to_deck) == 'function' then - obj:add_to_deck(self, from_debuff) + obj:add_to_deck(self, from_debuff) end''' # Card:remove_from_deck() @@ -373,7 +392,7 @@ position = 'before' payload = ''' local obj = self.config.center if obj and obj.remove_from_deck and type(obj.remove_from_deck) == 'function' then - obj:remove_from_deck(self, from_debuff) + obj:remove_from_deck(self, from_debuff) end''' # G.FUNCS.use_card() @@ -387,9 +406,9 @@ payload = ''' local nc if card.ability.consumeable then local obj = card.config.center - if obj.keep_on_use and type(obj.keep_on_use) == 'function' then - nc = obj:keep_on_use(card) - end + if obj.keep_on_use and type(obj.keep_on_use) == 'function' then + nc = obj:keep_on_use(card) + end end if not nc and card.area then card.area:remove_card(card) end''' @@ -414,7 +433,7 @@ match_indent = true position = 'at' payload = ''' if _center.set_sprites and type(_center.set_sprites) == 'function' then - _center:set_sprites(self, _front) + _center:set_sprites(self, _front) end if true then''' @@ -428,7 +447,7 @@ position = 'at' payload = ''' local obj = self.config.center if obj.load and type(obj.load) == 'function' then - obj:load(self, cardTable, other_card) + obj:load(self, cardTable, other_card) elseif self.config.center.name == "Half Joker" then''' # Card:calculate_dollar_bonus() @@ -455,21 +474,21 @@ match_indent = true payload = ''' local center = self.config.center if center.draw and type(center.draw) == 'function' then - center:draw(self, layer) + center:draw(self, layer) end if center.set == 'Default' or center.set == 'Enhanced' and not center.replace_base_card then - if not center.no_suit then - local suit = SMODS.Suits[self.base.suit] or {} - if suit.draw and type(suit.draw) == 'function' then - suit:draw(self, layer) - end - end - if not center.no_rank then - local rank = SMODS.Ranks[self.base.value] or {} - if rank.draw and type(rank.draw) == 'function' then - rank:draw(self, layer) - end - end + if not center.no_suit then + local suit = SMODS.Suits[self.base.suit] or {} + if suit.draw and type(suit.draw) == 'function' then + suit:draw(self, layer) + end + end + if not center.no_rank then + local rank = SMODS.Ranks[self.base.value] or {} + if rank.draw and type(rank.draw) == 'function' then + rank:draw(self, layer) + end + end end ''' @@ -482,6 +501,15 @@ match_indent = true payload = ''' local seal = G.P_SEALS[self.seal or {}] or {} if type(seal.draw) == 'function' then - seal:draw(self, layer) + seal:draw(self, layer) elseif self.seal then -''' \ No newline at end of file +''' + +# no_blueprint check +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = 'if other_joker and other_joker ~= self then' +payload = 'if other_joker and other_joker ~= self and not context.no_blueprint then' diff --git a/smods-old-calc/lovely/challenge.toml b/smods-old-calc/lovely/challenge.toml new file mode 100644 index 0000000..0db9203 --- /dev/null +++ b/smods-old-calc/lovely/challenge.toml @@ -0,0 +1,21 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + +# function G.UIDEF.challenge_list_page() +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "local challenge_unlocked = G.PROFILES[G.SETTINGS.profile].challenges_unlocked and (G.PROFILES[G.SETTINGS.profile].challenges_unlocked >= k)" +position = 'after' +payload = """ +if v.unlocked and type(v.unlocked) == 'function' then + challenge_unlocked = v:unlocked() +elseif type(v.unlocked) == 'boolean' then + challenge_unlocked = v.unlocked +end +challenge_unlocked = challenge_unlocked or G.PROFILES[G.SETTINGS.profile].all_unlocked + +""" +match_indent = true diff --git a/smods-old-calc/lovely/compact_cashout.toml b/smods-old-calc/lovely/compact_cashout.toml new file mode 100644 index 0000000..98676f3 --- /dev/null +++ b/smods-old-calc/lovely/compact_cashout.toml @@ -0,0 +1,65 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + + +# +# End of round money +# + +# Hide off screen rows + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if config.name ~= 'bottom' then" +position = "after" +payload = ''' + total_cashout_rows = (total_cashout_rows or 0) + 1 + if total_cashout_rows > 7 then + return + end''' +match_indent = true + +# Reset rows amount + +[[patches]] +[patches.regex] +target = "functions/state_events.lua" +pattern = 'G\.FUNCS\.evaluate_round = function\(\)' +position = "after" +payload = ''' + + total_cashout_rows = 0''' + +# Add UI row with total rows hidden + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "add_round_eval_row({name = 'bottom', dollars = dollars})" +position = "before" +payload = ''' +if total_cashout_rows > 7 then + local total_hidden = total_cashout_rows - 7 + + G.E_MANAGER:add_event(Event({ + trigger = 'before',delay = 0.38, + func = function() + local hidden = {n=G.UIT.R, config={align = "cm"}, nodes={ + {n=G.UIT.O, config={object = DynaText({ + string = {localize{type = 'variable', key = 'cashout_hidden', vars = {total_hidden}}}, + colours = {G.C.WHITE}, shadow = true, float = false, + scale = 0.45, + font = G.LANGUAGES['en-us'].font, pop_in = 0 + })}} + }} + + G.round_eval:add_child(hidden, G.round_eval:get_UIE_by_ID('bonus_round_eval')) + return true + end + })) +end''' +match_indent = true + diff --git a/smods-old-calc/lovely/compat_0_9_8.toml b/smods-old-calc/lovely/compat_0_9_8.toml new file mode 100644 index 0000000..a61c552 --- /dev/null +++ b/smods-old-calc/lovely/compat_0_9_8.toml @@ -0,0 +1,38 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + +# fallback for card.ability.name +# Card:set_ability() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "self.ability.bonus = (self.ability.bonus or 0) + (center.config.bonus or 0)" +position = 'after' +payload = "if not self.ability.name then self.ability.name = center.key end" +match_indent = true + +# generate_card_ui() +# `card_type` is used to check whether card should be nil; non-recursive calls +# to generate_card_ui always have that arg set +[[patches]] +[patches.regex] +target = "functions/common_events.lua" +pattern = '(?[\t ]*)function generate_card_ui\([^)]*\)\n' +position = "after" +line_prepend = '$indent' +payload = """ + if card == nil and card_type then + card = SMODS.compat_0_9_8.generate_UIBox_ability_table_card + end + +""" +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "for _, v in ipairs(info_queue) do" +position = 'before' +payload = "SMODS.compat_0_9_8.generate_UIBox_ability_table_card = nil" +match_indent = true + diff --git a/smods-old-calc/lovely/core.toml b/smods-old-calc/lovely/core.toml new file mode 100644 index 0000000..899b0cc --- /dev/null +++ b/smods-old-calc/lovely/core.toml @@ -0,0 +1,24 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = "self.SPEEDFACTOR = 1" +position = "after" +payload = "initSteamodded()" +match_indent = true + +[[patches]] +[patches.copy] +target = "main.lua" +position = "append" +sources = ["src/core.lua"] + +[[patches]] +[patches.module] +before = "main.lua" +source = "version.lua" +name = "SMODS.version" diff --git a/smods-old-calc/lovely/crash_handler.toml b/smods-old-calc/lovely/crash_handler.toml new file mode 100644 index 0000000..cd590af --- /dev/null +++ b/smods-old-calc/lovely/crash_handler.toml @@ -0,0 +1,20 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +[[patches]] +[patches.pattern] +target = "main.lua" +pattern = "function love.errhand(msg)" +position = "at" +payload = "if false then" +match_indent = true + +[[patches]] +[patches.copy] +target = "main.lua" +position = "prepend" +sources = [ + "src/crash_handler.lua", +] diff --git a/Steamodded/lovely/deck_skins.toml b/smods-old-calc/lovely/deck_skins.toml similarity index 99% rename from Steamodded/lovely/deck_skins.toml rename to smods-old-calc/lovely/deck_skins.toml index 7501bfe..7f29989 100644 --- a/Steamodded/lovely/deck_skins.toml +++ b/smods-old-calc/lovely/deck_skins.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 #========================================================# # Choose any rank for custom deck and use provided atlas # @@ -125,4 +125,4 @@ function create_UIBox_customize_deck() return t end -''' \ No newline at end of file +''' diff --git a/Steamodded/lovely/dollar_row.toml b/smods-old-calc/lovely/dollar_row.toml similarity index 95% rename from Steamodded/lovely/dollar_row.toml rename to smods-old-calc/lovely/dollar_row.toml index 06f543b..005d471 100644 --- a/Steamodded/lovely/dollar_row.toml +++ b/smods-old-calc/lovely/dollar_row.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Dollar row patches (API removed) @@ -48,7 +48,7 @@ pattern = "for i = 1, num_dollars or 1 do" position = "at" payload = ''' local dollars_to_loop -if num_dollars < 0 then dollars_to_loop = num_dollars*-1 else dollars_to_loop = num_dollars end +if num_dollars < 0 then dollars_to_loop = (num_dollars*-1)+1 else dollars_to_loop = num_dollars end for i = 1, dollars_to_loop do''' match_indent = true @@ -76,4 +76,4 @@ else if num_dollars < 0 then r = {n=G.UIT.T, config={text = localize('$'), colour = G.C.RED, scale = ((num_dollars > 20 and 0.28) or (num_dollars > 9 and 0.43) or 0.58), shadow = true, hover = true, can_collide = false, juice = true}} else r = {n=G.UIT.T, config={text = localize('$'), colour = G.C.MONEY, scale = ((num_dollars > 20 and 0.28) or (num_dollars > 9 and 0.43) or 0.58), shadow = true, hover = true, can_collide = false, juice = true}} end end''' -match_indent = true \ No newline at end of file +match_indent = true diff --git a/Steamodded/lovely/edition.toml b/smods-old-calc/lovely/edition.toml similarity index 99% rename from Steamodded/lovely/edition.toml rename to smods-old-calc/lovely/edition.toml index 9ef0081..b92bc6d 100644 --- a/Steamodded/lovely/edition.toml +++ b/smods-old-calc/lovely/edition.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 # Fix debug mode edition cycling [[patches]] @@ -462,7 +462,7 @@ pattern = "if context.cardarea == G.jokers or context.card == G.consumeables the match_indent = true position = "before" payload = """ -if card.edition and card.edition.key then +if not card.ability.extra_enhancement and card.edition and card.edition.key then local ed = SMODS.Centers[card.edition.key] if ed.calculate and type(ed.calculate) == 'function' then context.from_playing_card = true diff --git a/smods-old-calc/lovely/enhancement.toml b/smods-old-calc/lovely/enhancement.toml new file mode 100644 index 0000000..2800831 --- /dev/null +++ b/smods-old-calc/lovely/enhancement.toml @@ -0,0 +1,423 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +## no_rank, no_suit, all_suits + +# Card:get_id() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if self.ability.effect == 'Stone Card' and not self.vampired then" +match_indent = true +position = "at" +payload = '''if SMODS.has_no_rank(self) and not self.vampired then''' + +# Card:get_chip_bonus() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +(?[\t ]*)if self\.ability\.effect == 'Stone Card' then +[\t ]* return self\.ability\.bonus \+ \(self\.ability\.perma_bonus or 0\) +[\t ]*end''' +position = "at" +payload = ''' +if self.ability.effect == 'Stone Card' or self.config.center.replace_base_card then + return self.ability.bonus + (self.ability.perma_bonus or 0) +end''' +line_prepend = '$indent' + +# Card:calculate_joker() +# Raised Fist +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if temp_ID >= G.hand.cards[i].base.id and G.hand.cards[i].ability.effect ~= 'Stone Card' then temp_Mult = G.hand.cards[i].base.nominal; temp_ID = G.hand.cards[i].base.id; raised_card = G.hand.cards[i] end" +match_indent = true +position = "at" +payload = """if temp_ID >= G.hand.cards[i].base.id and not SMODS.has_no_rank(G.hand.cards[i]) then + temp_Mult = G.hand.cards[i].base.nominal + temp_ID = G.hand.cards[i].base.id + raised_card = G.hand.cards[i] +end""" +# Flower Pot, Seeing Double +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if context.scoring_hand[i].ability.name ~= 'Wild Card' then" +match_indent = true +position = "at" +payload = '''if not SMODS.has_any_suit(context.scoring_hand[i]) then''' + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if context.scoring_hand[i].ability.name == 'Wild Card' then" +match_indent = true +position = "at" +payload = '''if SMODS.has_any_suit(context.scoring_hand[i]) then''' + +# Card:get_suit() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = '''(?[\t ]*)if self\.ability\.effect == 'Stone Card' then''' +line_prepend = '$indent' +position = "at" +payload = '''if SMODS.has_no_suit(self) then''' +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = 'if self.ability.name == "Wild Card" then' +match_indent = true +position = "at" +payload = '''if SMODS.has_any_suit(self) then''' +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = 'if self.ability.name == "Wild Card" and not self.debuff then' +match_indent = true +position = "at" +payload = '''if SMODS.has_any_suit(self) and not self.debuff then''' + +# check_for_unlock +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if v.ability.name ~= 'Stone Card' and v.base.suit == 'Hearts' then" +match_indent = true +position = "at" +payload = "if not SMODS.has_no_suit(v) and v.base.suit == 'Hearts' then" + +# reset_idol_card() +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "valid_idol_cards[#valid_idol_cards+1] = v" +match_indent = true +position = "at" +payload = """if not SMODS.has_no_suit(v) and not SMODS.has_no_rank(v) then + valid_idol_cards[#valid_idol_cards+1] = v +end""" + +# reset_mail_rank() +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "valid_mail_cards[#valid_mail_cards+1] = v" +match_indent = true +position = "at" +payload = """if not SMODS.has_no_rank(v) then + valid_mail_cards[#valid_mail_cards+1] = v +end""" + +# reset_castle_card() +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "valid_castle_cards[#valid_castle_cards+1] = v" +match_indent = true +position = "at" +payload = """if not SMODS.has_no_suit(v) then + valid_castle_cards[#valid_castle_cards+1] = v +end""" + +# G.FUNCS.evaluate_play() +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "if G.play.cards[i].ability.effect == 'Stone Card' then" +match_indent = true +position = "at" +payload = '''if SMODS.always_scores(G.play.cards[i]) then''' +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "if scoring_hand[i].ability.effect ~= 'Stone Card' then" +match_indent = true +position = "at" +payload = '''if not SMODS.has_no_rank(scoring_hand[i]) then''' +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "G.GAME.cards_played[scoring_hand[i].base.value].suits[scoring_hand[i].base.suit] = true" +match_indent = true +position = "at" +payload = """if not SMODS.has_no_suit(scoring_hand[i]) then + G.GAME.cards_played[scoring_hand[i].base.value].suits[scoring_hand[i].base.suit] = true +end""" + + +## replace_base_card +# Determines whether to draw the base card's front or not +# Card:draw() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if self.children.front and self.ability.effect ~= 'Stone Card' then" +match_indent = true +position = "at" +payload = "if self.children.front and self.ability.effect ~= 'Stone Card' and not self.config.center.replace_base_card then" + +# Card:generate_UIBox_ability_table() +# replaces two consecutive lines +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if (_c.name == 'Stone Card') then full_UI_table.name = true end" +match_indent = true +position = "at" +payload = "if _c.name == 'Stone Card' or _c.replace_base_card then full_UI_table.name = true" +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if (specific_vars.playing_card and (_c.name ~= 'Stone Card')) then" +match_indent = true +position = "at" +payload = "elseif specific_vars.playing_card then" + +# eval_card() +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "function eval_card(card, context)" +match_indent = true +position = "after" +payload = """ + local enhancement_calculated = false + local center = card.config.center""" +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "local jokers = card:calculate_joker(context)" +match_indent = true +position = "before" +payload = """ +if card.ability.set == 'Enhanced' and center.calculate and type(center.calculate) == 'function' then + center:calculate(card, context, ret) + enhancement_calculated = true +end""" +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "local seals = card:calculate_seal(context)" +match_indent = true +position = "before" +payload = """ +if card.ability.set == 'Enhanced' and center.calculate and type(center.calculate) == 'function' then + center:calculate(card, context, ret) + enhancement_calculated = true +end""" +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if context.cardarea == G.jokers or context.card == G.consumeables then" +match_indent = true +position = "before" +payload = """ +if not enhancement_calculated and card.ability.set == 'Enhanced' and center.calculate and type(center.calculate) == 'function' then + center:calculate(card, context, ret) + enhancement_calculated = true +end +local seals = not card.ability.extra_enhancement and card:calculate_seal(context) +if seals then + ret.seals = seals +end""" + + +## Add additional eval_card() calls + +# Game:update_draw_to_hand() + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = "G.GAME.current_round.discards_used == 0 and G.GAME.facing_blind then" +match_indent = true +position = "after" +payload = """ +for i = 1, #G.hand.cards do + eval_card(G.hand.cards[i], {first_hand_drawn = true}) +end""" + +# G.FUNCS.discard_cards_from_highlighted() + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "inc_career_stat('c_cards_discarded', highlighted_count)" +match_indent = true +position = "after" +payload = """ +for i = 1, #G.hand.cards do + eval_card(G.hand.cards[i], {pre_discard = true, full_hand = G.hand.highlighted, hook = hook}) +end""" +[[patches]] +[patches.regex] +target = "functions/state_events.lua" +pattern = ''' +(?[\t ]*)G\.hand\.highlighted\[i\]:calculate_seal\(\{discard = true\}\) +[\t ]*local removed = false''' +line_prepend = '$indent' +position = "at" +payload = """ +local removed = false +local eval = nil +eval = eval_card(G.hand.highlighted[i], {discard = true, full_hand = G.hand.highlighted}) +if eval and eval.remove then + removed = true + card_eval_status_text(G.hand.highlighted[i], 'jokers', nil, 1, nil, eval) +end""" + +## Allow cards to function as multiple enhancements (e.g. from jokers) + +# Calculate extra enhancements when played +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "local effects = {eval_card(scoring_hand[i], {cardarea = G.play, full_hand = G.play.cards, scoring_hand = scoring_hand, poker_hand = text})}" +position = "after" +payload = ''' +local post_effect = {seals = effects[1].seals, edition = effects[1].edition} +effects[1].seals = nil +effects[1].edition = nil +local extra_enhancements = SMODS.get_enhancements(scoring_hand[i], true) +local old_ability = copy_table(scoring_hand[i].ability) +local old_center = scoring_hand[i].config.center +local old_center_key = scoring_hand[i].config.center_key +for k, _ in pairs(extra_enhancements) do + if G.P_CENTERS[k] then + scoring_hand[i]:set_ability(G.P_CENTERS[k]) + scoring_hand[i].ability.extra_enhancement = k + effects[#effects+1] = eval_card(scoring_hand[i], {cardarea = G.play, full_hand = G.play.cards, scoring_hand = scoring_hand, poker_hand = text, extra_enhancement = true}) + end +end +effects[#effects+1] = post_effect +scoring_hand[i].ability = old_ability +scoring_hand[i].config.center = old_center +scoring_hand[i].config.center_key = old_center_key +scoring_hand[i]:set_sprites(old_center) +''' +match_indent = true + +# Calculate extra enhancements when held in hand +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "local effects = {eval_card(G.hand.cards[i], {cardarea = G.hand, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands})}" +position = "after" +payload = ''' +local extra_enhancements = SMODS.get_enhancements(G.hand.cards[i], true) +local old_ability = copy_table(G.hand.cards[i].ability) +local old_center = G.hand.cards[i].config.center +local old_center_key = G.hand.cards[i].config.center_key +for k, _ in pairs(extra_enhancements) do + if G.P_CENTERS[k] then + G.hand.cards[i]:set_ability(G.P_CENTERS[k]) + G.hand.cards[i].ability.extra_enhancement = k + effects[#effects+1] = eval_card(G.hand.cards[i], {cardarea = G.hand, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, extra_enhancement = true}) + end +end +G.hand.cards[i].ability = old_ability +G.hand.cards[i].config.center = old_center +G.hand.cards[i].config.center_key = old_center_key +G.hand.cards[i]:set_sprites(old_center) +''' +match_indent = true + +# Calculate extra enhancements when held in hand at end of round +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "local effects = {G.hand.cards[i]:get_end_of_round_effect()}" +position = "after" +payload = ''' +local extra_enhancements = SMODS.get_enhancements(G.hand.cards[i], true) +local old_ability = copy_table(G.hand.cards[i].ability) +local old_center = G.hand.cards[i].config.center +local old_center_key = G.hand.cards[i].config.center_key +for k, _ in pairs(extra_enhancements) do + if G.P_CENTERS[k] then + G.hand.cards[i]:set_ability(G.P_CENTERS[k]) + G.hand.cards[i].ability.extra_enhancement = k + effects[#effects+1] = G.hand.cards[i]:get_end_of_round_effect() + end +end +G.hand.cards[i].ability = old_ability +G.hand.cards[i].config.center = old_center +G.hand.cards[i].config.center_key = old_center_key +G.hand.cards[i]:set_sprites(old_center) +''' +match_indent = true + +# Prevent blue seal effect on extra enhancements at end of round +[[patches]] +[patches.pattern] +target = "card" +pattern = "if self.seal == 'Blue' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then" +position = "before" +payload = ''' +if self.extra_enhancement then return ret end +''' +match_indent = true + +# Use the has enhancement function for enhancement gates +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if vv.config.center.key == v.enhancement_gate then" +position = "at" +payload = "if SMODS.has_enhancement(vv, v.enhancement_gate) then" +match_indent = true + +# Glass Card shattering +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if card.ability.name == 'Glass Card' then" +position = "at" +payload = "if SMODS.has_enhancement(card, 'm_glass') then" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "if G.hand.highlighted[i].ability.name == 'Glass Card' then" +position = "at" +payload = "if SMODS.has_enhancement(G.hand.highlighted[i], 'm_glass') then" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "if scoring_hand[i].ability.name == 'Glass Card' and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/scoring_hand[i].ability.extra then" +position = "at" +payload = "if SMODS.has_enhancement(scoring_hand[i], 'm_glass') and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/(scoring_hand[i].ability.name == 'Glass Card' and scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) then" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "if scoring_hand[i].ability.name == 'Glass Card' then" +position = "at" +payload = "if SMODS.has_enhancement(scoring_hand[i], 'm_glass') then" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "if cards_destroyed[i].ability.name == 'Glass Card' then" +position = "at" +payload = "if SMODS.has_enhancement(cards_destroyed[i], 'm_glass') then" +match_indent = true + +# Prevent blue seals from applying on quantum enhancement calc +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if self.seal == 'Blue' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then" +position = "at" +payload = "if self.seal == 'Blue' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit and not self.ability.extra_enhancement then" +match_indent = true diff --git a/Steamodded/lovely/fixes.toml b/smods-old-calc/lovely/fixes.toml similarity index 80% rename from Steamodded/lovely/fixes.toml rename to smods-old-calc/lovely/fixes.toml index 4b8b68a..3f51b23 100644 --- a/Steamodded/lovely/fixes.toml +++ b/smods-old-calc/lovely/fixes.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Fixes for either base game code or general mod compatibility @@ -498,6 +498,61 @@ position = "at" payload = ''' if true then''' +## Make vanilla enhancement jokers work with extra enhancements + +# Steel Joker +[[patches]] +[patches.pattern] +target = "card.lua" +match_indent = true +pattern = "if v.config.center == G.P_CENTERS.m_steel then self.ability.steel_tally = self.ability.steel_tally+1 end" +position = "at" +payload = "if SMODS.has_enhancement(v, 'm_steel') then self.ability.steel_tally = self.ability.steel_tally+1 end" + +# Stone Joker +[[patches]] +[patches.pattern] +target = "card.lua" +match_indent = true +pattern = "if v.config.center == G.P_CENTERS.m_stone then self.ability.stone_tally = self.ability.stone_tally+1 end" +position = "at" +payload = "if SMODS.has_enhancement(v, 'm_stone') then self.ability.stone_tally = self.ability.stone_tally+1 end" + +# Golden Ticket +[[patches]] +[patches.pattern] +target = "card.lua" +match_indent = true +pattern = "context.other_card.ability.name == 'Gold Card' then" +position = "at" +payload = "SMODS.has_enhancement(context.other_card, 'm_gold') then" + +# Golden Ticket Unlock +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +match_indent = true +pattern = "if args.cards[j].ability.name == 'Gold Card' then" +position = "at" +payload = "if SMODS.has_enhancement(args.cards[j], 'm_gold') then" + +# Glass Joker +[[patches]] +[patches.pattern] +target = "card.lua" +match_indent = true +pattern = "if val.ability.name == 'Glass Card' then shattered_glass = shattered_glass + 1 end" +position = "at" +payload = "if SMODS.has_enhancement(val, 'm_glass') then shattered_glass = shattered_glass + 1 end" + +# Driver's License +[[patches]] +[patches.pattern] +target = "card.lua" +match_indent = true +pattern = "if v.config.center ~= G.P_CENTERS.c_base then self.ability.driver_tally = self.ability.driver_tally+1 end" +position = "at" +payload = "if next(SMODS.get_enhancements(v)) then self.ability.driver_tally = self.ability.driver_tally+1 end" # Basegame fix for the reroll vouchers redeem function when only the center but no card object exists # Card:apply_to_run @@ -534,4 +589,73 @@ if effects[ii].h_chips then update_hand_text({delay = 0}, {chips = hand_chips}) card_eval_status_text(effects[ii].card, 'chips', effects[ii].h_chips, percent) end -''' \ No newline at end of file +''' + +# Fix booster skip issues maybe? +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = "if G.pack_cards and (G.pack_cards.cards[1]) and" +position = "at" +payload = ''' +if G.pack_cards and (not (G.GAME.STOP_USE and G.GAME.STOP_USE > 0)) and +''' +match_indent = true + +# Due to STOP_USE being used we can remove this dumb check +# could probably remove the rest of it since it serves no purpose otherwise, but whatever +[[patches]] +[patches.regex] +target = "functions/button_callbacks.lua" +pattern = '''and \(G\.hand\.cards\[1\] or \(G\.hand\.config\.card_limit <= 0\)\)''' +position = "at" +payload = ''' ''' +match_indent = true + +# Fixes Steam API not loading on unix +[[patches]] +[patches.pattern] +target = 'main.lua' +match_indent = true +position = 'after' +pattern = '--To control when steam communication happens, make sure to send updates to steam as little as possible' +payload = '''local cwd = NFS.getWorkingDirectory() +NFS.setWorkingDirectory(love.filesystem.getSourceBaseDirectory()) +''' + +[[patches]] +[patches.pattern] +target = 'main.lua' +match_indent = true +position = 'before' +pattern = '--Set up the render window and the stage for the splash screen, then enter the gameloop with :update' +payload = '''NFS.setWorkingDirectory(cwd) +''' + +[[patches]] +[patches.pattern] +target = "main.lua" +pattern = '''if os == 'OS X' or os == 'Windows' then''' +position = "at" +payload = '''if os == 'OS X' or os == 'Windows' or os == 'Linux' then''' +overwrite = true +match_indent = true + +[[patches]] +[patches.pattern] +target = "main.lua" +pattern = '''if os == 'OS X' then''' +position = "at" +payload = '''if os == 'OS X' or os == 'Linux' then''' +overwrite = true +match_indent = true + +[[patches]] +[patches.pattern] +target = "main.lua" +pattern = "st = require 'luasteam'" +position = "at" +payload = """local success, _st = pcall(require, 'luasteam') +if success then st = _st else sendWarnMessage(_st); st = {} end""" +overwrite = true +match_indent = true diff --git a/Steamodded/lovely/joker_retrigger.toml b/smods-old-calc/lovely/joker_retrigger.toml similarity index 99% rename from Steamodded/lovely/joker_retrigger.toml rename to smods-old-calc/lovely/joker_retrigger.toml index 3066c7f..f7ba100 100644 --- a/Steamodded/lovely/joker_retrigger.toml +++ b/smods-old-calc/lovely/joker_retrigger.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 # main joker retriggering [[patches]] diff --git a/smods-old-calc/lovely/keybind.toml b/smods-old-calc/lovely/keybind.toml new file mode 100644 index 0000000..80272b8 --- /dev/null +++ b/smods-old-calc/lovely/keybind.toml @@ -0,0 +1,82 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + +# Check all registered keybinds +# inserted inside Controller:key_press_update + +[[patches]] +[patches.pattern] +target = 'engine/controller.lua' +pattern = "if not _RELEASE_MODE then" +position = "before" +payload = ''' +for _, keybind in pairs(SMODS.Keybinds) do + if keybind.action and keybind.key_pressed == key and keybind.event == 'pressed' then + local execute = true + for _, other_key in pairs(keybind.held_keys) do + if not self.held_keys[other_key] then + execute = false + break + end + end + if execute then + keybind:action() + end + end +end +''' +match_indent = true + +# Controller:key_release_update +[[patches]] +[patches.pattern] +target = 'engine/controller.lua' +pattern = "function Controller:key_release_update(key, dt)" +position = "after" +payload = ''' +for _, keybind in pairs(SMODS.Keybinds) do + if keybind.action and keybind.key_pressed == key and keybind.event == 'released' then + local execute = true + for _, other_key in pairs(keybind.held_keys) do + if not self.held_keys[other_key] then + execute = false + break + end + end + if execute then + keybind:action() + end + end +end +''' +match_indent = true + +[[patches]] +[patches.regex] +target = 'engine/controller.lua' +pattern = 'if key == "r"' +position = 'before' +line_prepend = '$indent' +payload = ''' +for _, keybind in pairs(SMODS.Keybinds) do + if keybind.key_pressed == key and keybind.event == 'held' and keybind.held_duration then + if self.held_key_times[key] > keybind.held_duration then + local execute = true + for _, other_key in pairs(keybind.held_keys) do + if not self.held_keys[other_key] then + execute = false + break + end + end + if execute then + keybind:action() + self.held_key_times[key] = nil + end + else + self.held_key_times[key] = self.held_key_times[key] + dt + end + end +end +''' diff --git a/smods-old-calc/lovely/language.toml b/smods-old-calc/lovely/language.toml new file mode 100644 index 0000000..5c89e5d --- /dev/null +++ b/smods-old-calc/lovely/language.toml @@ -0,0 +1,59 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Language API + +# Game:set_language() +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = "if not (love.filesystem.read('localization/'..G.SETTINGS.language..'.lua')) or G.F_ENGLISH_ONLY then" +position = 'at' +payload = 'if false then' +match_indent = true + +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = "local localization = love.filesystem.getInfo('localization/'..G.SETTINGS.language..'.lua')" +position = 'at' +payload = "local localization = love.filesystem.getInfo('localization/'..G.SETTINGS.language..'.lua') or love.filesystem.getInfo('localization/en-us.lua')" +match_indent = true + +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = "self.localization = assert(loadstring(love.filesystem.read('localization/'..G.SETTINGS.language..'.lua')))()" +position = 'at' +payload = "self.localization = assert(loadstring(love.filesystem.read('localization/'..G.SETTINGS.language..'.lua') or love.filesystem.read('localization/en-us.lua')))()" +match_indent = true + +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = "self.LANG = self.LANGUAGES[self.SETTINGS.language] or self.LANGUAGES['en-us']" +position = 'at' +payload = "self.LANG = self.LANGUAGES[self.SETTINGS.real_language or self.SETTINGS.language] or self.LANGUAGES['en-us']" +match_indent = true + +# G.FUNCS.change_lang + +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = "G.SETTINGS.language = lang.key" +position = 'at' +payload = """G.SETTINGS.language = lang.loc_key or lang.key +G.SETTINGS.real_language = lang.key""" +match_indent = true + +# G.FUNCS.warn_lang (wtf) +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = 'if (_infotip_object.config.set ~= e.config.ref_table.label) and (not G.F_NO_ACHIEVEMENTS) then' +position = 'at' +payload = 'if (_infotip_object.config.set ~= e.config.ref_table.label) then' +match_indent = true diff --git a/smods-old-calc/lovely/libs.toml b/smods-old-calc/lovely/libs.toml new file mode 100644 index 0000000..b7e8e9a --- /dev/null +++ b/smods-old-calc/lovely/libs.toml @@ -0,0 +1,16 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + +[[patches]] +[patches.module] +source = "libs/json/json.lua" +before = "main.lua" +name = "json" + +[[patches]] +[patches.module] +source = "libs/nativefs/nativefs.lua" +before = "main.lua" +name = "nativefs" diff --git a/smods-old-calc/lovely/loader.toml b/smods-old-calc/lovely/loader.toml new file mode 100644 index 0000000..dfe4bd9 --- /dev/null +++ b/smods-old-calc/lovely/loader.toml @@ -0,0 +1,27 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + +### Supporting code for loader.lua + +## Save discovered, unlocked states +# Game:init_item_prototypes() +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = "meta.alerted = meta.alerted or {}" +position = 'after' +payload = ''' +for _, t in ipairs{ + G.P_CENTERS, + G.P_BLINDS, + G.P_TAGS, + G.P_SEALS, +} do + for k, v in pairs(t) do + SMODS._save_d_u(v) + v._discovered_unlocked_overwritten = true + end +end''' +match_indent = true diff --git a/smods-old-calc/lovely/menu.toml b/smods-old-calc/lovely/menu.toml new file mode 100644 index 0000000..0e3e9fb --- /dev/null +++ b/smods-old-calc/lovely/menu.toml @@ -0,0 +1,60 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''local main_menu = nil''' +position = "after" +payload = '''local mods = nil''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''main_menu = UIBox_button{ label = {localize('b_main_menu')}, button = "go_to_menu", minw = 5}''' +position = "after" +payload = '''mods = UIBox_button{ id = "mods_button", label = {localize('b_mods')}, button = "mods_button", minw = 5}''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = '''G.ARGS.set_alerts_alertables[11].should_alert = alert_booster''' +position = "after" +payload = '''table.insert(G.ARGS.set_alerts_alertables, {id = 'mods_button', alert_uibox_name = 'mods_button_alert', should_alert = SMODS.mod_button_alert})''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''main_menu,''' +position = "after" +payload = '''mods,''' +match_indent = true + + +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = '''self.ASSET_ATLAS[self.asset_atli[i].name].image = love.graphics.newImage(self.asset_atli[i].path, {mipmaps = true, dpiscale = self.SETTINGS.GRAPHICS.texture_scaling})''' +position = 'after' +payload = ''' +local mipmap_level = SMODS.config.graphics_mipmap_level_options[SMODS.config.graphics_mipmap_level] +if mipmap_level and mipmap_level > 0 then + self.ASSET_ATLAS[self.asset_atli[i].name].image:setMipmapFilter('linear', mipmap_level) +end''' +match_indent = true + + +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = '''create_option_cycle({w = 4,scale = 0.8, label = localize("b_set_CRT_bloom"),options = localize('ml_bloom_opt'), opt_callback = 'change_crt_bloom', current_option = G.SETTINGS.GRAPHICS.bloom}),''' +position = 'after' +payload = ''' +create_option_cycle({label = localize('b_graphics_mipmap_level'),scale = 0.8, options = SMODS.config.graphics_mipmap_level_options, opt_callback = 'SMODS_change_mipmap', current_option = SMODS.config.graphics_mipmap_level}),''' +match_indent = true + diff --git a/smods-old-calc/lovely/mod.toml b/smods-old-calc/lovely/mod.toml new file mode 100644 index 0000000..225effb --- /dev/null +++ b/smods-old-calc/lovely/mod.toml @@ -0,0 +1,70 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + +### Per-mod functions + +# end_round() +[[patches]] +[patches.regex] +target = 'functions/state_events.lua' +pattern = '''(?[\t ]*)reset_castle_card\(\)''' +line_prepend = '$indent' +position = 'after' +payload = ''' +for _, mod in ipairs(SMODS.mod_list) do + if mod.reset_game_globals and type(mod.reset_game_globals) == 'function' then + mod.reset_game_globals(false) + end +end''' + +# Game:start_run() +[[patches]] +[patches.regex] +target = 'game.lua' +pattern = '''(?[\t ]*)reset_castle_card\(\)''' +line_prepend = '$indent' +position = 'after' +payload = ''' +for _, mod in ipairs(SMODS.mod_list) do + if mod.reset_game_globals and type(mod.reset_game_globals) == 'function' then + mod.reset_game_globals(true) + end +end''' + +# Card:set_debuff() +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = "function Card:set_debuff(should_debuff)" +position = 'after' +match_indent = true +payload = ''' + for _, mod in ipairs(SMODS.mod_list) do + if mod.set_debuff and type(mod.set_debuff) == 'function' then + local res = mod.set_debuff(self) + if res == 'prevent_debuff' then + if self.debuff then + self.debuff = false + if self.area == G.jokers then self:add_to_deck(true) end + self.debuffed_by_blind = false + end + return + end + should_debuff = should_debuff or res + end + end + for k, v in pairs(self.ability.debuff_sources or {}) do + if v == 'prevent_debuff' then + if self.debuff then + self.debuff = false + if self.area == G.jokers then self:add_to_deck(true) end + end + self.debuffed_by_blind = false + return + end + should_debuff = should_debuff or v + end + +''' diff --git a/smods-old-calc/lovely/number_formatting.toml b/smods-old-calc/lovely/number_formatting.toml new file mode 100644 index 0000000..0107ffa --- /dev/null +++ b/smods-old-calc/lovely/number_formatting.toml @@ -0,0 +1,171 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +# +# Use number_format for... +# + +# DynaText + +[[patches]] +[patches.regex] +target = "engine/text.lua" +pattern = 'tostring\((?v\.ref_table and v\.ref_table\[v\.ref_value\] or v\.string)\)' +position = "at" +payload = "format_ui_value($param)" + +# Cash Out + +[[patches]] +[patches.regex] +target = "functions/common_events.lua" +pattern = ''' +localize\('\$'\)\.\.config\.dollars''' +position = "at" +payload = "localize('$')..format_ui_value(config.dollars)" + +# End of round money + +[[patches]] +[patches.regex] +target = "functions/common_events.lua" +pattern = ''' +localize\('\$'\)\.\.num_dollars\}''' +position = "at" +payload = "localize('$')..format_ui_value(num_dollars)}" + +# Tooltip numbers + +[[patches]] +[patches.regex] +target = "functions/misc_functions.lua" +pattern = '(?args\.vars\[tonumber\(subpart\[1\]\)\])' +position = "at" +payload = 'format_ui_value($param)' + +# Poker Hand chips + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}," +position = "at" +payload = "{n=G.UIT.T, config={text = number_format(G.GAME.hands[handname].chips, 1000000), scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}," +match_indent = true + +# Poker Hand mult + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}" +position = "at" +payload = "{n=G.UIT.T, config={text = number_format(G.GAME.hands[handname].mult, 1000000), scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}" +match_indent = true + +# Continue Run - Money + +[[patches]] +[patches.regex] +target = "functions/UI_definitions.lua" +pattern = 'tostring\(saved_game\.GAME\.dollars\)' +position = "at" +payload = "format_ui_value(saved_game.GAME.dollars)" + +# Continue Run - Best Hand - bigger size + +[[patches]] +[patches.regex] +target = "functions/UI_definitions.lua" +pattern = 'scale_number\(saved_game\.GAME\.round_scores\.hand\.amt\, 0\.8\*scale\)' +position = "at" +payload = "scale_number(saved_game.GAME.round_scores.hand.amt, 0.8*scale, 100000000000)" + + +# +# Custom sci notation switch point +# + +## number_format +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = 'function number_format(num)' +position = "at" +payload = ''' +function number_format(num, e_switch_point) + if type(num) ~= 'number' then return num end + + local sign = (num >= 0 and "") or "-" + num = math.abs(num)''' +match_indent = true + +[[patches]] +[patches.regex] +target = "functions/misc_functions.lua" +pattern = 'num >= G\.E_SWITCH_POINT' +position = "at" +payload = "num >= (e_switch_point or G.E_SWITCH_POINT)" + +# 1. Fix floating point error (1.000e92 instead of 10.000e91) +# 2. Lower precision with higher numbers +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = ''' +return string.format("%.3f",x/(10^fac))..'e'..fac''' +position = "at" +payload = ''' +if num == math.huge then + return sign.."naneinf" +end + +local mantissa = round_number(x/(10^fac), 3) +if mantissa >= 10 then + mantissa = mantissa / 10 + fac = fac + 1 +end +return sign..(string.format(fac >= 100 and "%.1fe%i" or fac >= 10 and "%.2fe%i" or "%.3fe%i", mantissa, fac))''' +match_indent = true + +# Remove trailing zeroes +# E.g. X1.5 being displayed as X1.50 +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = ''' +return string.format(num ~= math.floor(num) and (num >= 100 and "%.0f" or num >= 10 and "%.1f" or "%.2f") or "%.0f", num):reverse():gsub("(%d%d%d)", "%1,"):gsub(",$", ""):reverse()''' +position = "at" +payload = ''' +local formatted +if num ~= math.floor(num) and num < 100 then + formatted = string.format(num >= 10 and "%.1f" or "%.2f", num) + if formatted:sub(-1) == "0" then + formatted = formatted:gsub("%.?0+$", "") + end + -- Return already to avoid comas being added + if num < 0.01 then return tostring(num) end +else + formatted = string.format("%.0f", num) +end +return sign..(formatted:reverse():gsub("(%d%d%d)", "%1,"):gsub(",$", ""):reverse())''' +match_indent = true + +## scale_number +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = 'function scale_number(number, scale, max)' +position = "at" +payload = 'function scale_number(number, scale, max, e_switch_point)' +match_indent = true + +[[patches]] +[patches.regex] +target = "functions/button_callbacks.lua" +pattern = 'number >= G\.E_SWITCH_POINT' +position = "at" +payload = "math.abs(number) >= (e_switch_point or G.E_SWITCH_POINT)" + diff --git a/smods-old-calc/lovely/playing_card.toml b/smods-old-calc/lovely/playing_card.toml new file mode 100644 index 0000000..1f6a244 --- /dev/null +++ b/smods-old-calc/lovely/playing_card.toml @@ -0,0 +1,299 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Playing Card API + +# Game:init_game_object() +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = 'function Game:init_game_object()' +position = 'after' +match_indent = true +payload = ''' + local cards_played = {} + for _,v in ipairs(SMODS.Rank.obj_buffer) do + cards_played[v] = { suits = {}, total = 0 } + end''' + +[[patches]] +[patches.regex] +target = "game.lua" +pattern = '(?[\t ]*)cards_played = \{\n(.*\n){13}[\t ]*\},' +position = 'at' +line_prepend = '$indent' +payload = ''' + cards_played = cards_played, + disabled_suits = {}, + disabled_ranks = {},''' + +# Game:start_run() +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = 'local _ = nil' +position = 'before' +match_indent = true +payload = ''' +if type(SMODS.Ranks[v.value].in_pool) == 'function' and not SMODS.Ranks[v.value]:in_pool({initial_deck = true, suit = v.suit}) +or type(SMODS.Suits[v.suit].in_pool) == 'function' and not SMODS.Suits[v.suit]:in_pool({initial_deck = true, rank = v.value}) then + goto continue +end''' + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = "if self.GAME.starting_params.erratic_suits_and_ranks then _, k = pseudorandom_element(G.P_CARDS, pseudoseed('erratic')) end" +position = 'at' +match_indent = true +payload = '''if self.GAME.starting_params.erratic_suits_and_ranks then + v, k = pseudorandom_element(G.P_CARDS, pseudoseed('erratic'), {starting_deck = true}) +end''' + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = 'local _r, _s = string.sub(k, 3, 3), string.sub(k, 1, 1)' +position = 'at' +match_indent = true +payload = 'local _r, _s = SMODS.Ranks[v.value].card_key, SMODS.Suits[v.suit].card_key' + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = "if self.GAME.starting_params.no_faces and (_r == 'K' or _r == 'Q' or _r == 'J') then keep = false end" +position = 'at' +match_indent = true +payload = ''' +if self.GAME.starting_params.no_faces and SMODS.Ranks[v.value].face then keep = false end''' + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = "if keep then card_protos[#card_protos+1] = {s=_s,r=_r,e=_e,d=_d,g=_g} end" +position = "after" +payload = "::continue::" +match_indent = true + +# loc_colour() +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +pattern = 'return G.ARGS.LOC_COLOURS[_c] or _default or G.C.UI.TEXT_DARK' +position = 'before' +match_indent = true +payload = ''' + for _, v in ipairs(SMODS.Rarity.obj_buffer) do + G.ARGS.LOC_COLOURS[v:lower()] = G.C.RARITY[v] + end + for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do + G.ARGS.LOC_COLOURS[v:lower()] = G.C.SECONDARY_SET[v] + end + for _, v in ipairs(SMODS.Suit.obj_buffer) do + G.ARGS.LOC_COLOURS[v:lower()] = G.C.SUITS[v] + end''' + +# get_flush() +[[patches]] +[patches.regex] +target = "functions/misc_functions.lua" +pattern = '(?[\t ]*)local suits = \{\n[\t ]*"Spades",\n[\t ]*"Hearts",\n[\t ]*"Clubs",\n[\t ]*"Diamonds"\n[\t ]*\}\n[\t ]*if #hand > 5 or (?#hand < \(5 - \(four_fingers and 1 or 0\)\) then return ret else)' +position = 'at' +line_prepend = '$indent' +payload = ''' +local suits = SMODS.Suit.obj_buffer +if $restcond''' + +# get_X_same() +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +pattern = 'local vals = {{},{},{},{},{},{},{},{},{},{},{},{},{},{}}' +position = 'at' +match_indent = true +payload = ''' +local vals = {} +for i = 1, SMODS.Rank.max_id.value do + vals[i] = {} +end''' + +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +pattern = 'function get_X_same(num, hand)' +position = 'at' +match_indent = true +payload = '''function get_X_same(num, hand, or_more)''' + +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +pattern = 'if #curr == num then' +position = 'at' +match_indent = true +payload = '''if or_more and (#curr >= num) or (#curr == num) then''' + +# Card:get_nominal() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = 'function Card:get_nominal\(mod\)\n([\t ]+.*\n)*end' +position = 'at' +payload = ''' +function Card:get_nominal(mod) + local mult = 1 + local rank_mult = 1 + if mod == 'suit' then mult = 10000 end + if self.ability.effect == 'Stone Card' or (self.config.center.no_suit and self.config.center.no_rank) then + mult = -10000 + elseif self.config.center.no_suit then + mult = 0 + elseif self.config.center.no_rank then + rank_mult = 0 + end + return 10*self.base.nominal*rank_mult + self.base.suit_nominal*mult + (self.base.suit_nominal_original or 0)*0.0001*mult + 10*self.base.face_nominal*rank_mult + 0.000001*self.unique_val +end''' + +# Card:set_base() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = "(?[\t ]*)if self.base.value == '2' then self.base.nominal = 2; self.base.id = 2(\n[\t ]+elseif .*)*" +position = 'at' +line_prepend = '$indent' +payload = ''' +local rank = SMODS.Ranks[self.base.value] or {} +self.base.nominal = rank.nominal or 0 +self.base.face_nominal = rank.face_nominal or 0 +self.base.id = rank.id''' + +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = "(?[\t ]*)if self.base.suit == 'Diamonds' then self.base.suit_nominal = 0.01; self.base.suit_nominal_original = suit_base_nominal_original or 0.001 (\n[\t ]+elseif .*)*" +position = 'at' +line_prepend = '$indent' +payload = ''' +local suit = SMODS.Suits[self.base.suit] or {} +self.base.suit_nominal = suit.suit_nominal or 0 +self.base.suit_nominal_original = suit_base_nominal_original or suit.suit_nominal or 0''' + +# Card:change_suit() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = "(?[\t ]*)local new_code = [\\s\\S]*?local new_val = [\\s\\S]*?local new_card = G.P_CARDS\\[new_code..new_val\\]" +position = 'at' +line_prepend = '$indent' +payload = ''' +local new_code = SMODS.Suits[new_suit].card_key +local new_val = SMODS.Ranks[self.base.value].card_key +local new_card = G.P_CARDS[new_code..'_'..new_val]''' + +# Card:is_face() +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = "(?[\t ]*)if id == 11 or id == 12 or id == 13 or next\\(find_joker\\(\"Pareidolia\"\\)\\) then" +position = 'at' +line_prepend = '$indent' +payload = ''' +local rank = SMODS.Ranks[self.base.value] +if not id then return end +if (id > 0 and rank and rank.face) or next(find_joker("Pareidolia")) then''' + + +# tally_sprite() +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = '(?[\t ]*local t_s = Sprite\(0,0,0.5,0.5,)G.ASSET_ATLAS\[.*?\](?.*?\))' +position = 'at' +payload = '$start G.ASSET_ATLAS[suit and SMODS.Suits[suit][G.SETTINGS.colourblind_option and "hc_ui_atlas" or "lc_ui_atlas"]] or G.ASSET_ATLAS[("ui_"..(G.SETTINGS.colourblind_option and "2" or "1"))]$rest' + +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = 'function tally_sprite(pos, value, tooltip)' +position = 'at' +match_indent = true +payload = 'function tally_sprite(pos, value, tooltip, suit)' + +# G.UIDEF.challenge_description_tab() +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = "(?[\t ]*)local SUITS = \\{(\n.*){5}\n[\t ]*local suit_map = \\{'S', 'H', 'C', 'D'\\}" +position = 'at' +line_prepend = '$indent' +payload = ''' +local SUITS = {} +local suit_map = {} +for i = #SMODS.Suit.obj_buffer, 1, -1 do + local suit = SMODS.Suits[SMODS.Suit.obj_buffer[i]] + SUITS[suit.card_key] = {} + suit_map[#suit_map+1] = suit.card_key +end''' + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = 'local _r, _s = string.sub(k, 3, 3), string.sub(k, 1, 1)' +position = 'at' +match_indent = true +payload = 'local _r, _s = SMODS.Ranks[v.value].card_key, SMODS.Suits[v.suit].card_key' + +# TODO there may need to be a way to let in_pool know what challenge is being displayed +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = 'local keep, _e, _d, _g = true, nil, nil, nil' +position = 'after' +match_indent = true +payload = ''' +if type(SMODS.Ranks[v.value].in_pool) == 'function' and not SMODS.Ranks[v.value]:in_pool({initial_deck = true, suit = v.suit}) then + keep = false +end +if type(SMODS.Suits[v.suit].in_pool) == 'function' and not SMODS.Suits[v.suit]:in_pool({initial_deck = true, rank = v.value}) then + keep = false +end''' + +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = '(?[\t ]*)for j = 1, 4 do\n[\t ]*(?if SUITS\[suit_map\[j\]\]\[1\] then\n[\t ]*table.sort.*(\n.*)*?)\n[\t ]*0\.42\*G.CARD_H,' +position = 'at' +line_prepend = '$indent' +payload = ''' +local num_suits = 0 +for j = 1, #suit_map do + if SUITS[suit_map[j]][1] then num_suits = num_suits + 1 end +end +for j = 1, #suit_map do + $mid + (0.42 - (num_suits <= 4 and 0 or num_suits >= 8 and 0.28 or 0.07 * (num_suits - 4))) * G.CARD_H,''' + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = '--Fill all remaining info if this is the main desc' +position = 'before' +match_indent = true +payload = '''if card_type == 'Default' or card_type == 'Enhanced' and not _c.replace_base_card and card and card.base then + if not _c.no_suit then + local suit = SMODS.Suits[card.base.suit] or {} + if suit.loc_vars and type(suit.loc_vars) == 'function' then + suit:loc_vars(info_queue, card) + end + end + if not _c.no_rank then + local rank = SMODS.Ranks[card.base.value] or {} + if rank.loc_vars and type(rank.loc_vars) == 'function' then + rank:loc_vars(info_queue, card) + end + end +end + +''' diff --git a/smods-old-calc/lovely/poker_hand.toml b/smods-old-calc/lovely/poker_hand.toml new file mode 100644 index 0000000..d6f0f05 --- /dev/null +++ b/smods-old-calc/lovely/poker_hand.toml @@ -0,0 +1,60 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + +### Poker Hand API + +# evaluate_poker_hand() +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "local parts = {" +position = 'before' +payload = ''' +for _,v in ipairs(SMODS.PokerHand.obj_buffer) do + results[v] = {} +end''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "if next(parts._5) and next(parts._flush) then" +position = 'before' +payload = ''' +for _,_hand in pairs(SMODS.PokerHands) do + if _hand.atomic_part and type(_hand.atomic_part) == 'function' then + parts[_hand.key] = _hand.atomic_part(hand) + end +end''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "return results" +position = 'before' +payload = ''' +for _,_hand in pairs(SMODS.PokerHands) do + if _hand.composite and type(_hand.composite) == 'function' then + local other_hands + results[_hand.key], other_hands = _hand.composite(parts) + results[_hand.key] = results[_hand.key] or {} + if other_hands and type(other_hands) == 'table' then + for k, v in pairs(other_hands) do + results[k] = v + end + end + else + results[_hand.key] = parts[_hand.key] + end +end +results.top = nil +for _, v in ipairs(G.handlist) do + if not results.top and results[v] then + results.top = results[v] + break + end +end''' +match_indent = true diff --git a/smods-old-calc/lovely/pool.toml b/smods-old-calc/lovely/pool.toml new file mode 100644 index 0000000..e08d9f7 --- /dev/null +++ b/smods-old-calc/lovely/pool.toml @@ -0,0 +1,185 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Functions that affect random selection from pools + +# pseudorandom_element() +# TODO special cases for now +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "function pseudorandom_element(_t, seed)" +position = "at" +payload = """function pseudorandom_element(_t, seed, args) + -- TODO special cases for now + -- Preserves reverse nominal order for Suits, nominal+face_nominal order for Ranks + -- for vanilla RNG + if _t == SMODS.Suits then + _t = SMODS.Suit:obj_list(true) + end + if _t == SMODS.Ranks then + _t = SMODS.Rank:obj_list() + end +""" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "keys[#keys+1] = {k = k,v = v}" +position = "at" +payload = """ +local keep = true +local in_pool_func = + args and args.in_pool + or type(v) == 'table' and type(v.in_pool) == 'function' and v.in_pool + or _t == G.P_CARDS and function(c) + --Handles special case for Erratic Deck + local initial_deck = args and args.starting_deck or false + + return not ( + type(SMODS.Ranks[c.value].in_pool) == 'function' and not SMODS.Ranks[c.value]:in_pool({initial_deck = initial_deck, suit = c.suit}) + or type(SMODS.Suits[c.suit].in_pool) == 'function' and not SMODS.Suits[c.suit]:in_pool({initial_deck = initial_deck, rank = c.value}) + ) + end +if in_pool_func then + keep = in_pool_func(v, args) +end +if keep then + keys[#keys+1] = {k = k,v = v} +end""" +match_indent = true + +# fixes pseudorandom_element on an empty list +# nil, nil is returned in that case +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "local key = keys[math.random(#keys)].k" +position = "before" +payload = "if #keys == 0 then return nil, nil end" +match_indent = true + +## get_current_pool() + +# Centers + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "else _starting_pool, _pool_key = G.P_CENTER_POOLS[_type], _type..(_append or '')" +match_indent = true +position = 'before' +payload = ''' +elseif SMODS.ObjectTypes[_type] and SMODS.ObjectTypes[_type].rarities then + local rarities = SMODS.ObjectTypes[_type].rarities + local rarity + if _legendary and rarities.legendary then + rarity = rarities.legendary.key + else + rarity = _rarity or SMODS.poll_rarity(_type, 'rarity_'.._type..G.GAME.round_resets.ante..(_append or '')) + end + _starting_pool, _pool_key = SMODS.ObjectTypes[_type].rarity_pools[rarity], _type..rarity..(_append or '')''' + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "if _type == 'Tarot' or _type == 'Tarot_Planet' then _pool[#_pool + 1] = \"c_strength\"" +match_indent = true +position = 'at' +payload = ''' +if SMODS.ObjectTypes[_type] and SMODS.ObjectTypes[_type].default and G.P_CENTERS[SMODS.ObjectTypes[_type].default] then + _pool[#_pool+1] = SMODS.ObjectTypes[_type].default +elseif _type == 'Tarot' or _type == 'Tarot_Planet' then _pool[#_pool + 1] = "c_strength"''' + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "if v.name == 'Black Hole' or v.name == 'The Soul' then" +match_indent = true +position = 'at' +payload = "if v.name == 'Black Hole' or v.name == 'The Soul' or v.hidden then" + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "if _type == 'Enhanced' then" +match_indent = true +position = 'before' +payload = ''' +local in_pool, pool_opts +if v.in_pool and type(v.in_pool) == 'function' then + in_pool, pool_opts = v:in_pool({ source = _append }) +end +pool_opts = pool_opts or {} +''' + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = 'elseif not (G.GAME.used_jokers[v.key] and not next(find_joker("Showman"))) and' +match_indent = true +position = 'at' +payload = '''elseif not (G.GAME.used_jokers[v.key] and not pool_opts.allow_duplicates and not next(find_joker("Showman"))) and''' + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "if add and not G.GAME.banned_keys[v.key] then" +match_indent = true +position = 'before' +payload = ''' +if v.in_pool and type(v.in_pool) == 'function' then + add = in_pool and (add or pool_opts.override_base_checks) +end +''' + +## G.GAME.used_jokers now checks keys, not names +# Card:set_ability() +# Remove the old center from `used_jokers` if set_ability overrides +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "local old_center = self.config.center" +position = 'after' +payload = ''' +if old_center and not next(SMODS.find_card(old_center.key, true)) then + G.GAME.used_jokers[old_center.key] = nil +end''' +match_indent = true +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +(?[\t ]*)for k, v in pairs\(G\.P_CENTERS\) do +[\t ]*if v\.name == self\.ability\.name then +[\t ]*G\.GAME\.used_jokers\[k\] = true +[\t ]*end +[\t ]*end''' +position = "at" +payload = ''' +if self.config.center.key then + G.GAME.used_jokers[self.config.center.key] = true +end +''' +line_prepend = "$indent" +# Card:remove() +[[patches]] +[patches.regex] +target = "card.lua" +pattern = ''' +(?[\t ]*)for k, v in pairs\(G\.P_CENTERS\) do +[\t ]*if v\.name == self\.ability\.name then +[\t ]*if not next\(find_joker\(self\.ability\.name, true\)\) then +[\t ]*G\.GAME\.used_jokers\[k\] = nil +[\t ]*end +[\t ]*end +[\t ]*end''' +position = "at" +payload = ''' +if not next(SMODS.find_card(self.config.center.key, true)) then + G.GAME.used_jokers[self.config.center.key] = nil +end''' +line_prepend = "$indent" diff --git a/Steamodded/lovely/rarity.toml b/smods-old-calc/lovely/rarity.toml similarity index 98% rename from Steamodded/lovely/rarity.toml rename to smods-old-calc/lovely/rarity.toml index 4573811..f75a3dc 100644 --- a/Steamodded/lovely/rarity.toml +++ b/smods-old-calc/lovely/rarity.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Rarity API @@ -56,4 +56,4 @@ target = "card.lua" pattern = "if self.ability.name == 'Baseball Card' and context.other_joker.config.center.rarity == 2 and self ~= context.other_joker then" position = "at" payload = '''if self.ability.name == 'Baseball Card' and (context.other_joker.config.center.rarity == 2 or context.other_joker.config.center.rarity == "Uncommon") and self ~= context.other_joker then''' -match_indent = true \ No newline at end of file +match_indent = true diff --git a/Steamodded/lovely/seal.toml b/smods-old-calc/lovely/seal.toml similarity index 99% rename from Steamodded/lovely/seal.toml rename to smods-old-calc/lovely/seal.toml index ad922d3..45c7708 100644 --- a/Steamodded/lovely/seal.toml +++ b/smods-old-calc/lovely/seal.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Seal API # Card:open() @@ -157,6 +157,7 @@ if seal and seal.generate_ui ~= 0 then local res = seal:loc_vars(info_queue, card) or {} t.vars = res.vars t.key = res.key or t.key + t.set = res.set or t.set end else''' [[patches]] diff --git a/smods-old-calc/lovely/sound.toml b/smods-old-calc/lovely/sound.toml new file mode 100644 index 0000000..481300e --- /dev/null +++ b/smods-old-calc/lovely/sound.toml @@ -0,0 +1,167 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +#modulate_sound() +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +pattern = 'G.SOUND_MANAGER.channel:push(G.ARGS.push)' +match_indent = true +position = 'after' +payload = ''' +SMODS.previous_track = SMODS.previous_track or '' +local in_sync = (SMODS.Sounds[desired_track] or {}).sync +local out_sync = (SMODS.Sounds[SMODS.previous_track] or {}).sync +local should_sync = true +if (type(in_sync) == 'table' and not in_sync[SMODS.previous_track]) or in_sync == false then should_sync = false end +if (type(out_sync) == 'table' and not out_sync[desired_track]) or out_sync == false then should_sync = false end +if + SMODS.previous_track and SMODS.previous_track ~= desired_track and + not should_sync +then + G.ARGS.push.type = 'restart_music' + G.SOUND_MANAGER.channel:push(G.ARGS.push) +end +SMODS.previous_track = desired_track''' + +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +pattern = 'G.ARGS.push.ambient_control = G.SETTINGS.ambient_control' +match_indent = true +position = 'after' +payload = ''' +if SMODS.remove_replace_sound and SMODS.remove_replace_sound ~= desired_track then + SMODS.Sound.replace_sounds[SMODS.remove_replace_sound] = nil + SMODS.remove_replace_sound = nil +end +local replace_sound = SMODS.Sound.replace_sounds[desired_track] +if replace_sound then + local replaced_track = desired_track + desired_track = replace_sound.key + G.ARGS.push.desired_track = desired_track + if SMODS.previous_track ~= desired_track then + if replace_sound.times > 0 then replace_sound.times = replace_sound.times - 1 end + if replace_sound.times == 0 then SMODS.remove_replace_sound = replaced_track end + end +end +local stop_sound = SMODS.Sound.stop_sounds[desired_track] +if SMODS.Sound.stop_sounds[desired_track] then + if SMODS.previous_track ~= '' and stop_sound > 0 then stop_sound = stop_sound - 1 end + SMODS.Sound.stop_sounds[desired_track] = stop_sound ~= 0 and stop_sound or nil + SMODS.previous_track = '' + return +end +''' + +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +pattern = "(G.STATE == G.STATES.SPLASH and '') or" +match_indent = true +position = 'after' +payload = 'SMODS.Sound:get_current_music() or' + +# PLAY_SOUND +[[patches]] +[patches.pattern] +target = 'engine/sound_manager.lua' +pattern = '''local s = {sound = love.audio.newSource("resources/sounds/"..args.sound_code..'.ogg', should_stream and "stream" or 'static')}''' +match_indent = true +position = 'at' +payload = ''' +local c = SMODS_Sounds[args.sound_code] +local s = c and +{sound = love.audio.newSource(love.sound.newDecoder(c.data), c.should_stream and 'stream' or 'static'), per = c.per, vol = c.vol } or +{sound = love.audio.newSource("resources/sounds/"..args.sound_code..'.ogg', should_stream and "stream" or 'static')}''' + +# pass in custom sounds +[[patches]] +[patches.pattern] +target = 'engine/sound_manager.lua' +pattern = "DISABLE_SFX = false" +match_indent = true +position = 'after' +payload = ''' +SMODS_Sounds = {} +''' +[[patches]] +[patches.pattern] +target = 'engine/sound_manager.lua' +pattern = "elseif request.type == 'stop' then" +match_indent = true +position = 'before' +payload = ''' +elseif request.type == 'sound_source' then + SMODS_Sounds[request.sound_code] = { + sound_code = request.sound_code, + data = request.data, + sound = sound, + per = request.per, + vol = request.vol, + } + SOURCES[request.sound_code] = {} +''' + +[[patches]] +[patches.pattern] +target = 'engine/sound_manager.lua' +pattern = "s.original_pitch = args.per or 1" +match_indent = true +position = 'at' +payload = 's.original_pitch = ((args.type ~= "sound") and s.per) or args.per or 1' + +[[patches]] +[patches.pattern] +target = 'engine/sound_manager.lua' +pattern = "s.original_volume = args.vol or 1" +match_indent = true +position = 'at' +payload = 's.original_volume = ((args.type ~= "sound") and s.vol) or args.vol or 1' + +# don't crash RESTART_MUSIC + +[[patches]] +[patches.pattern] +target = 'engine/sound_manager.lua' +pattern = "RESTART_MUSIC()" +match_indent = true +position = 'at' +payload = 'RESTART_MUSIC(request)' + +# fix looping for music of different length + +[[patches]] +[patches.regex] +target = 'engine/sound_manager.lua' +pattern = """(?[\t ]*)function MODULATE\\(args\\)(\n.*){9}""" +line_prepend = '$indent' +position = 'at' +payload = """function MODULATE(args) + if args.desired_track ~= '' then + local sound = ((SOURCES[current_track or {}] or {})[1] or {}).sound + if not sound or not sound:isPlaying() then + RESTART_MUSIC(args) + end + end +""" +[[patches]] +[patches.pattern] +target = 'engine/sound_manager.lua' +pattern = "for _, s in pairs(v) do" +match_indent = true +position = 'at' +payload = """current_track = args.desired_track +for _, s in pairs(v) do""" + +# [[patches]] +# [patches.pattern] +# target = 'engine/sound_manager.lua' +# pattern = 'if s.sound and not s.sound:isPlaying() then' +# match_indent = true +# position = 'at' +# payload = '''if s.sound and s.sound:isPlaying() then +# s.sound:stop() +# elseif s.sound and not s.sound:isPlaying() then''' diff --git a/smods-old-calc/lovely/stake.toml b/smods-old-calc/lovely/stake.toml new file mode 100644 index 0000000..839175f --- /dev/null +++ b/smods-old-calc/lovely/stake.toml @@ -0,0 +1,190 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +# Fix areas where highest stake is hardcoded as Gold Stake +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "if G.PROFILES[G.SETTINGS.profile].all_unlocked then max_stake = 8 end" +position = "at" +payload = "if G.PROFILES[G.SETTINGS.profile].all_unlocked then max_stake = #G.P_CENTER_POOLS['Stake'] end" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "for i = 1, math.min(max_stake+1, 8) do" +position = "at" +payload = "for i = 1, math.min(max_stake+1, #G.P_CENTER_POOLS['Stake']) do" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "if G.GAME.stake >= 8 then" +position = "at" +payload = "if G.GAME.stake >= #G.P_CENTER_POOLS['Stake'] then" +match_indent = true + +# Stake modifier API +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = "if self.GAME.stake >= 2 then" +position = "before" +payload = "if false then" +match_indent = true + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = "if self.GAME.stake >= 8 then self.GAME.modifiers.enable_rentals_in_shop = true end" +position = "after" +payload = "end SMODS.setup_stake(self.GAME.stake)" +match_indent = true + +# Stake shininess API +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "if _stake == 8 then" +position = "at" +payload = "if G.P_CENTER_POOLS['Stake'][_stake].shiny then" +match_indent = true + +# Override stake listing to make room for our recursive version +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "for i = G.GAME.stake-1, 2, -1 do" +position = "before" +payload = "if false then" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = 'other_col = {n=G.UIT.R, config={align = "cm", padding = 0.05, r = 0.1, colour = G.C.L_BLACK}, nodes=stake_desc_rows}' +position = "before" +payload = "end SMODS.applied_stakes_UI(G.GAME.stake, stake_desc_rows)" +match_indent = true + +# Set win stake to that specified in unlocked stake +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = 'for i = 1, G.GAME.stake do' +position = "at" +payload = '''for i = 1, +(G.P_CENTER_POOLS["Stake"][G.GAME.stake].unlocked_stake) and +(G.P_STAKES[G.P_CENTER_POOLS["Stake"][G.GAME.stake].unlocked_stake].stake_level-1) or (G.GAME.stake-1) +do''' +match_indent = true + +# Stake Sprites +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = 'local stake_sprite = Sprite(0,0,_scale*1,_scale*1,G.ASSET_ATLAS["chips"], G.P_CENTER_POOLS.Stake[_stake].pos)' +position = "at" +payload = 'local stake_sprite = Sprite(0,0,_scale*1,_scale*1,G.ASSET_ATLAS[G.P_CENTER_POOLS.Stake[_stake].atlas], G.P_CENTER_POOLS.Stake[_stake].pos)' +match_indent = true + +# Achievements and unlocks +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = 'if highest_win >= 2 then' +position = "at" +payload = 'if highest_win >= G.P_STAKES["stake_red"].stake_level then' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = 'if highest_win >= 4 then' +position = "at" +payload = 'if highest_win >= G.P_STAKES["stake_black"].stake_level then' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = 'if highest_win >= 8 then' +position = "at" +payload = 'if highest_win >= G.P_STAKES["stake_gold"].stake_level then' +match_indent = true + +# get_blind_amount +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = 'function get_blind_amount(ante)' +position = "after" +payload = '''if G.GAME.modifiers.scaling and G.GAME.modifiers.scaling > 3 then return SMODS.get_blind_amount(ante) end''' +match_indent = true + +# set_joker_usage +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = 'G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key] = {count = 1, order = v.config.center.order, wins = {}, losses = {}}' +position = "at" +payload = 'G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key] = {count = 1, order = v.config.center.order, wins = {}, losses = {}, wins_by_key = {}, losses_by_key = {}}' +match_indent = true + +# set_joker_win +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = 'G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key] = G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key] or {count = 1, order = v.config.center.order, wins = {}, losses = {}}' +position = "at" +payload = 'G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key] = G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key] or {count = 1, order = v.config.center.order, wins = {}, losses = {}, wins_by_key = {}, losses_by_key = {}}' +match_indent = true + +#set_joker_win +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = 'G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].wins[G.GAME.stake] = (G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].wins[G.GAME.stake] or 0) + 1' +position = "after" +payload = 'G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].wins_by_key[SMODS.stake_from_index(G.GAME.stake)] = (G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].wins_by_key[SMODS.stake_from_index(G.GAME.stake)] or 0) + 1' +match_indent = true + +#set_joker_loss +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = 'G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].losses[G.GAME.stake] = (G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].losses[G.GAME.stake] or 0) + 1' +position = "after" +payload = 'G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].losses_by_key[SMODS.stake_from_index(G.GAME.stake)] = (G.PROFILES[G.SETTINGS.profile].joker_usage[v.config.center_key].losses_by_key[SMODS.stake_from_index(G.GAME.stake)] or 0) + 1' +match_indent = true + +# set_deck_usage +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = 'G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] = {count = 1, order = G.GAME.selected_back.effect.center.order, wins = {}, losses = {}}' +position = "at" +payload = 'G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] = {count = 1, order = G.GAME.selected_back.effect.center.order, wins = {}, losses = {}, wins_by_key = {}, losses_by_key = {}}' +match_indent = true + +# set_deck_loss +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = 'if not G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] then G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] = {count = 1, order = G.GAME.selected_back.effect.center.order, wins = {}, losses = {}} end' +position = "at" +payload = 'if not G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] then G.PROFILES[G.SETTINGS.profile].deck_usage[deck_key] = {count = 1, order = G.GAME.selected_back.effect.center.order, wins = {}, losses = {}, wins_by_key = {}, losses_by_key = {}} end' +match_indent = true + +# G.UIDEF.viewed_stake_option +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = 'G.viewed_stake = math.min(max_stake+1, G.viewed_stake)' +position = "after" +payload = '''if G.viewed_stake > #G.P_CENTER_POOLS.Stake then G.viewed_stake = #G.P_CENTER_POOLS.Stake end''' +match_indent = true diff --git a/Steamodded/lovely/sticker.toml b/smods-old-calc/lovely/sticker.toml similarity index 96% rename from Steamodded/lovely/sticker.toml rename to smods-old-calc/lovely/sticker.toml index d077e47..57ff049 100644 --- a/Steamodded/lovely/sticker.toml +++ b/smods-old-calc/lovely/sticker.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Sticker API @@ -35,6 +35,7 @@ if sticker then res = sticker:loc_vars(info_queue, card) or {} t.vars = res.vars or {} t.key = res.key or t.key + t.set = res.set or t.set end info_queue[#info_queue+1] = t else''' @@ -91,7 +92,7 @@ payload = '''if G.GAME.modifiers.enable_rentals_in_shop and pseudorandom((area = [[patches]] [patches.pattern] target = "card.lua" -pattern = '''elseif self.sprite_facing == 'back' then''' +pattern = '''if self.ability.name == 'The Soul' and (self.config.center.discovered or self.bypass_discovery_center) then''' match_indent = true position = "before" payload = ''' @@ -145,4 +146,4 @@ target = 'cardarea.lua' pattern = '''table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*(a.pinned and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*(b.pinned and b.sort_id or 0) end)''' position = 'at' match_indent = true -payload = '''table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*((a.pinned and not a.ignore_pinned) and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*((b.pinned and not b.ignore_pinned) and b.sort_id or 0) end)''' \ No newline at end of file +payload = '''table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*((a.pinned and not a.ignore_pinned) and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*((b.pinned and not b.ignore_pinned) and b.sort_id or 0) end)''' diff --git a/Steamodded/lovely/tag.toml b/smods-old-calc/lovely/tag.toml similarity index 79% rename from Steamodded/lovely/tag.toml rename to smods-old-calc/lovely/tag.toml index de0c05b..633ecb1 100644 --- a/Steamodded/lovely/tag.toml +++ b/smods-old-calc/lovely/tag.toml @@ -1,7 +1,7 @@ [manifest] version = "1.0.0" dump_lua = true -priority = 0 +priority = -10 ### Tag API # Tag:apply_to_run() @@ -12,13 +12,13 @@ pattern = "function Tag:apply_to_run(_context)" position = 'after' match_indent = true payload = ''' - if self.triggered then return end - local obj = SMODS.Tags[self.key] - local res - if obj and obj.apply and type(obj.apply) == 'function' then - res = obj:apply(self, _context) - end - if res then return res end + if self.triggered then return end + local obj = SMODS.Tags[self.key] + local res + if obj and obj.apply and type(obj.apply) == 'function' then + res = obj:apply(self, _context) + end + if res then return res end ''' # Tag:set_ability() @@ -29,11 +29,11 @@ pattern = "function Tag:set_ability()" position = 'after' match_indent = true payload = ''' - local obj = SMODS.Tags[self.key] - local res - if obj and obj.set_ability and type(obj.set_ability) == 'function' then - obj:set_ability(self) - end + local obj = SMODS.Tags[self.key] + local res + if obj and obj.set_ability and type(obj.set_ability) == 'function' then + obj:set_ability(self) + end ''' # create_UIBox_your_collection_tags() @@ -56,11 +56,11 @@ else tag_pool = G.P_TAGS end for k, v in pairs(tag_pool) do - counter = counter + 1 - tag_tab[#tag_tab+1] = v + counter = counter + 1 + tag_tab[#tag_tab+1] = v end for i = 1, math.ceil(counter / 6) do - table.insert(tag_matrix, {}) + table.insert(tag_matrix, {}) end''' [[patches]] @@ -72,7 +72,7 @@ line_prepend = '$indent' payload = ''' local table_nodes = {} for i = 1, math.ceil(counter / 6) do - table.insert(table_nodes, {n=G.UIT.R, config={align = "cm"}, nodes=tag_matrix[i]}) + table.insert(table_nodes, {n=G.UIT.R, config={align = "cm"}, nodes=tag_matrix[i]}) end''' [[patches]] diff --git a/smods-old-calc/lovely/threads.toml b/smods-old-calc/lovely/threads.toml new file mode 100644 index 0000000..85c2580 --- /dev/null +++ b/smods-old-calc/lovely/threads.toml @@ -0,0 +1,30 @@ +# Necessary to kill threads which lets us restart the game. + +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + +[[patches]] +[patches.pattern] +target = "engine/save_manager.lua" +pattern = "if request then" +position = "after" +payload = "if request.type == 'kill' then return end" +match_indent = true + +[[patches]] +[patches.pattern] +target = "engine/http_manager.lua" +pattern = "if request then" +position = "after" +payload = "if request.type == 'kill' then return end" +match_indent = true + +[[patches]] +[patches.pattern] +target = "engine/sound_manager.lua" +pattern = "if request then" +position = "after" +payload = "if request.type == 'kill' then return end" +match_indent = true diff --git a/smods-old-calc/lovely/ui.toml b/smods-old-calc/lovely/ui.toml new file mode 100644 index 0000000..5a2eff1 --- /dev/null +++ b/smods-old-calc/lovely/ui.toml @@ -0,0 +1,213 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +### Addition Tab + +## Decks tab +# create_UIBox_your_collection_decks() +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''G.GAME.viewed_back = Back(G.P_CENTERS.b_red)''' +position = "at" +payload = ''' +local deck_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Back) +G.GAME.viewed_back = Back(G.ACTIVE_MOD_UI and deck_pool[1] or G.P_CENTERS.b_red)''' +match_indent = true + +# create_UIBox_your_collection_decks() +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = '''(?[\t ]*)for k, v in ipairs\(G\.P_CENTER_POOLS\.Back\) do\n[\s\S]{4}ordered_names\[#ordered_names\+1\] = v\.name\n[\s\S]{2}end''' +position = 'at' +payload = ''' +for k, v in ipairs(deck_pool) do + ordered_names[#ordered_names+1] = v.key +end''' +line_prepend = '$indent' + +# create_UIBox_your_collection_decks() +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''local t = create_UIBox_generic_options({ back_func = 'your_collection', contents = {''' +position = "at" +payload = '''local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = {''' +match_indent = true + +# G.FUNCS.your_collection_deck_page +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = '''G.GAME.viewed_back:change_to(G.P_CENTER_POOLS.Back[args.to_key])''' +position = "at" +payload = ''' +local deck_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Back) +G.GAME.viewed_back:change_to(deck_pool[args.to_key])''' +match_indent = true + +# create_UIBox_your_collection() +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +pattern = '''(?[\t ]*)UIBox_button\(\{button = 'your_collection_blinds', label = \{localize\('b_blinds'\)\}, count = G\.DISCOVER_TALLIES\.blinds, minw = 5, minh = 2.0, id = 'your_collection_blinds', focus_args = \{snap_to = true\}\}\),''' +position = 'after' +payload = '''UIBox_button({button = 'your_collection_other_gameobjects', label = {localize('k_other')}, minw = 5, id = 'your_collection_other_gameobjects', focus_args = {snap_to = true}}),''' + +# Fix UIElement.config.chosen being overriden if choice=true is set +# UIElement:click() +[[patches]] +[patches.pattern] +target = "engine/ui.lua" +match_indent = true +position = "after" +pattern = "if self.config.choice then" +payload = " local chosen_temp = self.config.chosen" + +[[patches]] +[patches.pattern] +target = "engine/ui.lua" +match_indent = true +position = "at" +pattern = "self.config.chosen = true" +payload = "self.config.chosen = chosen_temp or true" + +# Escape from mod menu saves config +# Needs to be before all checks +[[patches]] +[patches.pattern] +target = 'engine/controller.lua' +pattern = "function Controller:key_press_update(key, dt)" +position = "after" +payload = ''' + if key == "escape" and G.ACTIVE_MOD_UI then + G.FUNCS.exit_mods() + end +''' +match_indent = true + +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +position = 'before' +line_prepend = '$indent' +pattern = ''' +(?[\t ]*)return \{n=G\.UIT\.ROOT, config = \{align = 'cm', colour = G\.C\.CLEAR\}, nodes=\{ +[\t ]*\{n=G\.UIT\.C,''' +payload = ''' +local cols +if #info_boxes <= 3 then + cols = 1 +elseif #info_boxes <= 10 then + cols = 2 +elseif #info_boxes <= 24 then + cols = 3 +else + cols = 4 +end +local nodes_per_col = math.ceil(#info_boxes/cols) +local info_cols = {} +for i = 0, cols-1 do + local col = {} + for j = 1, nodes_per_col do + local info_box = info_boxes[i*nodes_per_col+j] + if info_box then + table.insert(col, info_box) + else break end + end + table.insert(info_cols, {n=G.UIT.C, config = {align="cm"}, nodes = col}) +end +info_boxes = {{n=G.UIT.R, config = {align="cm", padding = 0.05, card_pos = card.T.x }, nodes = info_cols}} +''' + +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +match_indent = true +position = 'at' +pattern = "config = {offset = {x=-0.03,y=0}, align = 'cl', parent = e}" +payload = """config = (not e.config.ref_table or not e.config.ref_table[1].config.card_pos or e.config.ref_table[1].config.card_pos > G.ROOM.T.w*0.4) and + {offset = {x=-0.03,y=0}, align = 'cl', parent = e} or + {offset = {x=0.03,y=0}, align = 'cr', parent = e}""" + +[[patches]] +[patches.pattern] +target = 'tag.lua' +match_indent = true +position = 'at' +pattern = "_self.config.h_popup_config ={align = 'cl', offset = {x=-0.1,y=0},parent = _self}" +payload = """_self.config.h_popup_config = (_self.T.x > G.ROOM.T.w*0.4) and + {align = 'cl', offset = {x=-0.1,y=0},parent = _self} or + {align = 'cr', offset = {x=0.1,y=0},parent = _self}""" + +# desc_from_rows +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +position = 'at' +pattern = 'colour = empty and G\.C\.CLEAR or G\.C\.UI\.BACKGROUND_WHITE' +payload = 'colour = desc_nodes.background_colour or empty and G.C.CLEAR or G.C.UI.BACKGROUND_WHITE' + +# info_tip_from_rows +[[patches]] +[patches.regex] +target = 'functions/UI_definitions.lua' +position = 'at' +pattern = 'padding = 0\.05, colour = G\.C\.WHITE\}' +payload = 'padding = 0.05, colour = desc_nodes.background_colour or G.C.WHITE}' + +# localize +[[patches]] +[patches.regex] +target = 'functions/misc_functions.lua' +position = 'after' +pattern = '\(part\.control\.C and loc_colour\(part\.control\.C\)\)' +payload = ' or args.text_colour' + +[[patches]] +[patches.regex] +target = 'functions/misc_functions.lua' +position = 'at' +pattern = 'loc_colour\(part\.control\.C or nil, args\.default_col\)' +payload = 'not part.control.C and args.text_colour or loc_colour(part.control.C or nil, args.default_col)' + +[[patches]] +[patches.regex] +target = 'functions/misc_functions.lua' +position = 'after' +pattern = 'part\.control\.s and tonumber\(part\.control\.s\)' +payload = ' or args.scale ' + +# set_discover_tallies() +# exclude no_collection objects +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +match_indent = true +position = 'at' +pattern = "if not v.omit then" +payload = "if not v.omit and not v.no_collection then" + +[[patches]] +[patches.regex] +target = 'functions/misc_functions.lua' +line_prepend = '$indent' +position = 'at' +pattern = '(?[\t ]*)(?for _, v in pairs\(G\.P_[BT].*)(?(\n.*){7})' +payload = '''$start + if not v.no_collection then + $rest +end +''' + +#set_alerts() +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'at' +pattern = "if v.discovered and not v.alerted then" +payload = "if v.discovered and not v.alerted and not v.no_collection then" diff --git a/smods-old-calc/lovely/ui_elements.toml b/smods-old-calc/lovely/ui_elements.toml new file mode 100644 index 0000000..96050d0 --- /dev/null +++ b/smods-old-calc/lovely/ui_elements.toml @@ -0,0 +1,121 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +## colour argument fix +# create_tabs() +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = '''tab_buttons[#tab_buttons+1] = UIBox_button({id = 'tab_but_'..(v.label or ''), ref_table = v, button = 'change_tab', label = {v.label}, minh = 0.8*args.scale, minw = 2.5*args.scale, col = true, choice = true, scale = args.text_scale, chosen = v.chosen, func = v.func, focus_args = {type = 'none'}})''' +position = 'at' +payload = '''tab_buttons[#tab_buttons+1] = UIBox_button({id = 'tab_but_'..(v.label or ''), ref_table = v, button = 'change_tab', label = {v.label}, minh = 0.8*args.scale, minw = 2.5*args.scale, col = true, choice = true, scale = args.text_scale, chosen = v.chosen, func = v.func, colour = args.colour, focus_args = {type = 'none'}})''' +match_indent = true + +# UIElement:draw_self() +[[patches]] +[patches.pattern] +target = 'engine/ui.lua' +pattern = '''love.graphics.polygon("fill", get_chosen_triangle_from_rect(self.layered_parallax.x, self.layered_parallax.y, self.VT.w*G.TILESIZE, self.VT.h*G.TILESIZE, self.config.chosen == 'vert'))''' +position = 'before' +payload = '''love.graphics.setColor(self.config.colour)''' +match_indent = true + + +## multiple text input fix +# create_text_input() +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = '''args.current_prompt_text = ''''' +position = 'after' +payload = '''args.id = args.id or "text_input"''' +match_indent = true +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = '''ui_letters[#ui_letters+1] = {n=G.UIT.T, config={ref_table = args, ref_value = 'current_prompt_text', scale = args.text_scale, colour = lighten(copy_table(args.colour), 0.4), id = 'prompt'}}''' +position = 'at' +payload = '''ui_letters[#ui_letters+1] = {n=G.UIT.T, config={ref_table = args, ref_value = 'current_prompt_text', scale = args.text_scale, colour = lighten(copy_table(args.colour), 0.4), id = args.id..'_prompt'}}''' +match_indent = true +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = '''ui_letters[i] = {n=G.UIT.T, config={ref_table = text.letters, ref_value = i, scale = args.text_scale, colour = G.C.UI.TEXT_LIGHT, id = 'letter_'..i}}''' +position = 'at' +payload = '''ui_letters[i] = {n=G.UIT.T, config={ref_table = text.letters, ref_value = i, scale = args.text_scale, colour = G.C.UI.TEXT_LIGHT, id = args.id..'_letter_'..i}}''' +match_indent = true +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = '''ui_letters[#ui_letters+1] = {n=G.UIT.B, config={r = 0.03,w=0.1, h=0.4, colour = position_text_colour, id = 'position', func = 'flash'}}''' +position = 'at' +payload = '''ui_letters[#ui_letters+1] = {n=G.UIT.B, config={r = 0.03,w=0.1, h=0.4, colour = position_text_colour, id = args.id..'_position', func = 'flash'}}''' +match_indent = true +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = '''{n=G.UIT.C, config={align = "cm", draw_layer = 1, colour = G.C.CLEAR}, nodes = {''' +position = 'at' +payload = '''{n=G.UIT.C, config={align = "cm", colour = G.C.CLEAR}, nodes = {''' +match_indent = true +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = '''{n=G.UIT.C, config={id = 'text_input', align = "cm", padding = 0.05, r = 0.1, draw_layer = 2, hover = true, colour = args.colour,minw = args.w, min_h = args.h, button = 'select_text_input', shadow = true}, nodes={''' +position = 'at' +payload = '''{n=G.UIT.C, config={id = args.id, align = "cm", padding = 0.05, r = 0.1, hover = true, colour = args.colour,minw = args.w, min_h = args.h, button = 'select_text_input', shadow = true}, nodes={''' +match_indent = true + +# G.FUNCS.select_text_input +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''G.CONTROLLER.text_input_hook = e.children[1].children[1]''' +position = 'after' +payload = '''G.CONTROLLER.text_input_id = e.config.id''' +match_indent = true + +# G.FUNCS.paste_seed +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''G.CONTROLLER.text_input_hook = e.UIBox:get_UIE_by_ID('text_input').children[1].children[1]''' +position = 'after' +payload = """G.CONTROLLER.text_input_id = 'text_input'""" +match_indent = true + +# G.FUNCS.flash +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''if G.CONTROLLER.text_input_hook then''' +position = 'at' +payload = '''if G.CONTROLLER.text_input_hook and G.CONTROLLER.text_input_id == e.config.id:sub(1,string.len(G.CONTROLLER.text_input_id)) then''' +match_indent = true + +# TRANSPOSE_TEXT_INPUT() +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''if hook.children[i].config.id == 'position' then''' +position = 'at' +payload = '''if hook.children[i].config.id == G.CONTROLLER.text_input_id..'_position' then''' +match_indent = true +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''local real_letter = hook.children[position_child+dir].config.id:sub(1, 7) == 'letter_' and hook.children[position_child+dir].config.text ~= ''''' +position = 'at' +payload = '''local real_letter = hook.children[position_child+dir].config.id:sub(1, 8+string.len(G.CONTROLLER.text_input_id)) == G.CONTROLLER.text_input_id..'_letter_' and hook.children[position_child+dir].config.text ~= ''''' +match_indent = true + +# GET_TEXT_FROM_INPUT() +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +pattern = '''if hook.children[i].config and hook.children[i].config.id:sub(1, 7) == 'letter_' and hook.children[i].config.text ~= '' then''' +position = 'at' +payload = '''if hook.children[i].config and hook.children[i].config.id:sub(1, 8+string.len(G.CONTROLLER.text_input_id)) == G.CONTROLLER.text_input_id..'_letter_' and hook.children[i].config.text ~= '' then''' +match_indent = true diff --git a/smods-old-calc/manifest.json b/smods-old-calc/manifest.json new file mode 100644 index 0000000..0b06fff --- /dev/null +++ b/smods-old-calc/manifest.json @@ -0,0 +1,10 @@ +{ + "name": "Steamodded", + "version_number": "0.9.8", + "website_url": "https://github.com/Steamopollys/Steamodded", + "description": "A Balatro ModLoader", + "dependencies": [ + "Thunderstore-lovely-0.3.1", + "metherul-nativefs-1.0.0" + ] +} diff --git a/smods-old-calc/src/compat_0_9_8.lua b/smods-old-calc/src/compat_0_9_8.lua new file mode 100644 index 0000000..7875d1c --- /dev/null +++ b/smods-old-calc/src/compat_0_9_8.lua @@ -0,0 +1,536 @@ +SMODS.compat_0_9_8 = {} +SMODS.compat_0_9_8.load_done = false + +function SMODS.compat_0_9_8.load() + if SMODS.compat_0_9_8.load_done then + return + end + + function SMODS.compat_0_9_8.delay_register(cls, self) + if self.delay_register then + self.delay_register = nil + return + end + cls.super.register(self) + end + + function SMODS.compat_0_9_8.joker_loc_vars(self, info_queue, card) + local vars, main_end + if self.loc_def and type(self.loc_def) == 'function' then + vars, main_end = self.loc_def(card, info_queue) + end + if self.tooltip and type(self.tooltip) == 'function' then + self.tooltip(self, info_queue) + end + if vars then + return { + vars = vars, + main_end = main_end + } + else + return {} + end + end + -- Applies to Tarot, Planet, Spectral and Voucher + function SMODS.compat_0_9_8.tarot_loc_vars(self, info_queue, card) + local vars, main_end + if self.loc_def and type(self.loc_def) == 'function' then + vars, main_end = self.loc_def(self, info_queue) + end + if self.tooltip and type(self.tooltip) == 'function' then + self.tooltip(self, info_queue) + end + if vars then + return { + vars = vars, + main_end = main_end + } + else + return {} + end + end + + SMODS.compat_0_9_8.init_queue = {} + SMODS.INIT = setmetatable({}, { + __newindex = function(t, k, v) + SMODS.compat_0_9_8.init_queue[k] = v + rawset(t, k, v) + end + }) + function SMODS.findModByID(id) + return SMODS.Mods[id] + end + function SMODS.end_calculate_context(c) + return c.joker_main + end + function SMODS.LOAD_LOC() + init_localization() + end + + SMODS.SOUND_SOURCES = SMODS.Sounds + function register_sound(name, path, filename) + SMODS.Sound { + key = name, + path = filename, + } + end + function modded_play_sound(sound_code, stop_previous_instance, volume, pitch) + return SMODS.Sound.play(nil, pitch, volume, stop_previous_instance, sound_code) + end + + SMODS.Card = { + SUITS = SMODS.Suits, + RANKS = SMODS.Ranks, + SUIT_LIST = SMODS.Suit.obj_buffer, + RANK_LIST = SMODS.Rank.obj_buffer, + } + + SMODS.compat_0_9_8.Deck_new = SMODS.Back:extend { + register = function(self) + SMODS.compat_0_9_8.delay_register(SMODS.compat_0_9_8.Deck_new, self) + end, + __index = function(t, k) + if k == 'slug' then return t.key + elseif k == 'spritePos' then return t.pos + end + return getmetatable(t)[k] + end, + __newindex = function(t, k, v) + if k == 'slug' then t.key = v; return + elseif k == 'spritePos' then t.pos = v; return + end + rawset(t, k, v) + end, + } + SMODS.Deck = {} + function SMODS.Deck.new(self, name, slug, config, spritePos, loc_txt, unlocked, discovered) + return SMODS.compat_0_9_8.Deck_new { + name = name, + key = slug, + config = config, + pos = spritePos, + loc_txt = loc_txt, + unlocked = unlocked, + discovered = discovered, + atlas = config and config.atlas, + delay_register = true + } + end + SMODS.Decks = SMODS.Centers + + SMODS.Sprites = {} + SMODS.compat_0_9_8.Sprite_new = SMODS.Atlas:extend { + register = function(self) + if self.delay_register then + self.delay_register = nil + return + end + if self.registered then + sendWarnMessage(('Detected duplicate register call on object %s'):format(self.key), self.set) + return + end + SMODS.compat_0_9_8.Sprite_new.super.register(self) + table.insert(SMODS.Sprites, self) + end, + __index = function(t, k) + if k == 'name' then return t.key + end + return getmetatable(t)[k] + end, + __newindex = function(t, k, v) + if k == 'name' then t.key = v; return + end + rawset(t, k, v) + end, + } + SMODS.Sprite = {} + function SMODS.Sprite.new(self, name, top_lpath, path, px, py, type, frames) + local atlas_table + if type == 'animation_atli' then + atlas_table = 'ANIMATION_ATLAS' + else + atlas_table = 'ASSET_ATLAS' + end + return SMODS.compat_0_9_8.Sprite_new { + key = name, + path = path, + atlas_table = atlas_table, + px = px, + py = py, + frames = frames, + delay_register = true + } + end + + SMODS.compat_0_9_8.Joker_new = SMODS.Joker:extend { + loc_vars = SMODS.compat_0_9_8.joker_loc_vars, + register = function(self) + SMODS.compat_0_9_8.delay_register(SMODS.compat_0_9_8.Joker_new, self) + end, + __index = function(t, k) + if k == 'slug' then return t.key + elseif k == 'atlas' and SMODS.Atlases[t.key] then return t.key + elseif k == 'spritePos' then return t.pos + end + return getmetatable(t)[k] + end, + __newindex = function(t, k, v) + if k == 'slug' then t.key = v; return + elseif k == 'spritePos' then t.pos = v; return + end + if k == 'calculate' or k == 'set_ability' or k == 'set_badges' or k == 'update' then + local v_ref = v + v = function(self, ...) + return v_ref(...) + end + end + rawset(t, k, v) + end, + } + function SMODS.Joker.new(self, name, slug, config, spritePos, loc_txt, rarity, cost, unlocked, discovered, + blueprint_compat, eternal_compat, effect, atlas, soul_pos) + local x = SMODS.compat_0_9_8.Joker_new { + name = name, + key = slug, + config = config, + pos = spritePos, + loc_txt = loc_txt, + rarity = rarity, + cost = cost, + unlocked = unlocked, + discovered = discovered, + blueprint_compat = blueprint_compat, + eternal_compat = eternal_compat, + effect = effect, + atlas = atlas, + soul_pos = soul_pos, + delay_register = true + } + return x + end + SMODS.Jokers = SMODS.Centers + + function SMODS.compat_0_9_8.extend_consumable_class(SMODS_cls) + local cls + cls = SMODS_cls:extend { + loc_vars = SMODS.compat_0_9_8.tarot_loc_vars, + register = function(self) + SMODS.compat_0_9_8.delay_register(cls, self) + end, + __index = function(t, k) + if k == 'slug' then + return t.key + elseif k == 'atlas' and SMODS.Atlases[t.key] then + return t.key + end + return getmetatable(t)[k] + end, + __newindex = function(t, k, v) + if k == 'slug' then + t.key = v; return + elseif k == 'spritePos' then + t.pos = v; return + end + if k == 'set_badges' or k == 'use' or k == 'can_use' or k == 'update' then + local v_ref = v + v = function(self, ...) + return v_ref(...) + end + end + rawset(t, k, v) + end + } + return cls + end + + SMODS.compat_0_9_8.Tarot_new = SMODS.compat_0_9_8.extend_consumable_class(SMODS.Tarot) + function SMODS.Tarot.new(self, name, slug, config, pos, loc_txt, cost, cost_mult, effect, consumeable, discovered, + atlas) + return SMODS.compat_0_9_8.Tarot_new { + name = name, + key = slug, + config = config, + pos = pos, + loc_txt = loc_txt, + cost = cost, + cost_mult = cost_mult, + effect = effect, + consumeable = consumeable, + discovered = discovered, + atlas = atlas, + delay_register = true + } + end + SMODS.Tarots = SMODS.Centers + + SMODS.compat_0_9_8.Planet_new = SMODS.compat_0_9_8.extend_consumable_class(SMODS.Planet) + function SMODS.Planet.new(self, name, slug, config, pos, loc_txt, cost, cost_mult, effect, freq, consumeable, + discovered, atlas) + return SMODS.compat_0_9_8.Planet_new { + name = name, + key = slug, + config = config, + pos = pos, + loc_txt = loc_txt, + cost = cost, + cost_mult = cost_mult, + effect = effect, + freq = freq, + consumeable = consumeable, + discovered = discovered, + atlas = atlas, + delay_register = true + } + end + SMODS.Planets = SMODS.Centers + + SMODS.compat_0_9_8.Spectral_new = SMODS.compat_0_9_8.extend_consumable_class(SMODS.Spectral) + function SMODS.Spectral.new(self, name, slug, config, pos, loc_txt, cost, consumeable, discovered, atlas) + return SMODS.compat_0_9_8.Spectral_new { + name = name, + key = slug, + config = config, + pos = pos, + loc_txt = loc_txt, + cost = cost, + consumeable = consumeable, + discovered = discovered, + atlas = atlas, + delay_register = true + } + end + SMODS.Spectrals = SMODS.Centers + + SMODS.compat_0_9_8.Seal_new = SMODS.Seal:extend { + class_prefix = false, + register = function(self) + if self.delay_register then + self.delay_register = nil + return + end + if self.registered then + sendWarnMessage(('Detected duplicate register call on object %s'):format(self.key), self.set) + return + end + if self:check_dependencies() and not self.obj_table[self.label] then + self.obj_table[self.label] = self + self.obj_buffer[#self.obj_buffer + 1] = self.label + self.registered = true + end + end, + __index = function(t, k) + if k == 'name' then return t.key + end + return getmetatable(t)[k] + end, + __newindex = function(t, k, v) + if k == 'name' then t.key = v; return + end + rawset(t, k, v) + end, + } + function SMODS.Seal.new(self, name, label, full_name, pos, loc_txt, atlas, discovered, color) + return SMODS.compat_0_9_8.Seal_new { + key = name, + label = label, + full_name = full_name, + pos = pos, + loc_txt = { + description = loc_txt, + label = full_name + }, + atlas = atlas, + discovered = discovered, + colour = color, + delay_register = true + } + end + + SMODS.compat_0_9_8.Voucher_new = SMODS.Voucher:extend { + loc_vars = SMODS.compat_0_9_8.tarot_loc_vars, + register = function(self) + SMODS.compat_0_9_8.delay_register(SMODS.compat_0_9_8.Voucher_new, self) + end, + __index = function(t, k) + if k == 'slug' then return t.key + elseif k == 'atlas' and SMODS.Atlases[t.key] then return t.key + end + return getmetatable(t)[k] + end, + __newindex = function(t, k, v) + if k == 'slug' then t.key = v; return + end + if k == 'update' then + local v_ref = v + v = function(self, ...) + return v_ref(...) + end + elseif k == 'redeem' then + local v_ref = v + v = function(center, card) + local center_table = { + name = center and center.name or card and card.ability.name, + extra = center and center.config.extra or card and card.ability.extra + } + return v_ref(center_table) + end + end + rawset(t, k, v) + end + } + function SMODS.Voucher.new(self, name, slug, config, pos, loc_txt, cost, unlocked, discovered, available, requires, + atlas) + return SMODS.compat_0_9_8.Voucher_new { + name = name, + key = slug, + config = config, + pos = pos, + loc_txt = loc_txt, + cost = cost, + unlocked = unlocked, + discovered = discovered, + available = available, + requires = requires, + atlas = atlas, + delay_register = true + } + end + SMODS.Vouchers = SMODS.Centers + + SMODS.compat_0_9_8.Blind_new = SMODS.Blind:extend { + register = function(self) + SMODS.compat_0_9_8.delay_register(SMODS.compat_0_9_8.Blind_new, self) + end, + __index = function(t, k) + if k == 'slug' then return t.key + end + return getmetatable(t)[k] + end, + __newindex = function(t, k, v) + if k == 'slug' then t.key = v; return + end + if k == 'set_blind' + or k == 'disable' + or k == 'defeat' + or k == 'debuff_card' + or k == 'stay_flipped' + or k == 'drawn_to_hand' + or k == 'debuff_hand' + or k == 'modify_hand' + or k == 'press_play' + or k == 'get_loc_debuff_text' then + local v_ref = v + v = function(self, ...) + return v_ref(G.GAME.blind, ...) + end + end + rawset(t, k, v) + end + } + function SMODS.Blind.new(self, name, slug, loc_txt, dollars, mult, vars, debuff, pos, boss, boss_colour, defeated, + atlas) + return SMODS.compat_0_9_8.Blind_new { + name = name, + key = slug, + loc_txt = loc_txt, + dollars = dollars, + mult = mult, + loc_vars = { + vars = vars, + }, + debuff = debuff, + pos = pos, + boss = boss, + boss_colour = boss_colour, + defeated = defeated, + atlas = atlas, + delay_register = true + } + end + + SMODS.compat_0_9_8.loc_proxies = setmetatable({}, {__mode = 'k'}) + -- Indexing a table `t` that has this metatable instead indexes `t.capture_table`. + -- Handles nested indices by instead indexing `t.capture_table` with the + -- concatenation of all indices, separated by dots. + SMODS.compat_0_9_8.loc_proxy_mt = { + __index = function(t, k) + if rawget(t, 'stop_capture') then + return t.orig_t[k] + end + local new_idx_str = t.idx_str .. "." .. k + -- first check capture_table + if t.capture_table[new_idx_str] ~= nil then + return t.capture_table[new_idx_str] + end + -- then fall back to orig_t + local orig_v = t.orig_t[k] + if type(orig_v) ~= 'table' then + -- reached a non-table value, stop proxying + return orig_v + end + local ret = setmetatable({ + -- concatenation of all indexes, starting from G.localization + -- separated by dots and preceded by a dot + idx_str = new_idx_str, + -- table we would be indexing + orig_t = orig_v, + capture_table = t.capture_table, + }, SMODS.compat_0_9_8.loc_proxy_mt) + SMODS.compat_0_9_8.loc_proxies[ret] = true + return ret + end, + __newindex = function(t, k, v) + if rawget(t, 'stop_capture') then + t.orig_t[k] = v; return + end + local new_idx_str = t.idx_str .. "." .. k + t.capture_table[new_idx_str] = v + end + } + -- Drop-in replacement for G.localization. Captures changes in `capture_table` + function SMODS.compat_0_9_8.loc_proxy(capture_table) + local ret = setmetatable({ + idx_str = '', + orig_t = G.localization, + capture_table = capture_table, + }, SMODS.compat_0_9_8.loc_proxy_mt) + SMODS.compat_0_9_8.loc_proxies[ret] = true + return ret + end + function SMODS.compat_0_9_8.stop_loc_proxies() + collectgarbage() + for proxy, _ in pairs(SMODS.compat_0_9_8.loc_proxies) do + rawset(proxy, 'stop_capture', true) + SMODS.compat_0_9_8.loc_proxies[proxy] = nil + end + end + + SMODS.compat_0_9_8.load_done = true +end + +function SMODS.compat_0_9_8.with_compat(func) + SMODS.compat_0_9_8.load() + local localization_ref = G.localization + init_localization_ref = init_localization + local captured_loc = {} + G.localization = SMODS.compat_0_9_8.loc_proxy(captured_loc) + function init_localization() + G.localization = localization_ref + init_localization_ref() + G.localization = SMODS.compat_0_9_8.loc_proxy(captured_loc) + end + func() + G.localization = localization_ref + init_localization = init_localization_ref + SMODS.compat_0_9_8.stop_loc_proxies() + function SMODS.current_mod.process_loc_text() + for idx_str, v in pairs(captured_loc) do + local t = G + local k = 'localization' + for cur_k in idx_str:gmatch("[^%.]+") do + t, k = t[k], cur_k + end + t[k] = v + end + end +end diff --git a/smods-old-calc/src/core.lua b/smods-old-calc/src/core.lua new file mode 100644 index 0000000..146b3ef --- /dev/null +++ b/smods-old-calc/src/core.lua @@ -0,0 +1,76 @@ +--- STEAMODDED CORE +--- MODULE CORE + +SMODS = {} +MODDED_VERSION = require'SMODS.version' +SMODS.id = 'Steamodded' +SMODS.version = MODDED_VERSION:gsub('%-STEAMODDED', '') +SMODS.can_load = true +SMODS.meta_mod = true + +-- Include lovely and nativefs modules +local nativefs = require "nativefs" +local lovely = require "lovely" +local json = require "json" + +local lovely_mod_dir = lovely.mod_dir:gsub("/$", "") +NFS = nativefs +-- make lovely_mod_dir an absolute path. +-- respects symlink/.. combos +NFS.setWorkingDirectory(lovely_mod_dir) +lovely_mod_dir = NFS.getWorkingDirectory() +-- make sure NFS behaves the same as love.filesystem +NFS.setWorkingDirectory(love.filesystem.getSaveDirectory()) + +JSON = json + +local function set_mods_dir() + local love_dirs = { + love.filesystem.getSaveDirectory(), + love.filesystem.getSourceBaseDirectory() + } + for _, love_dir in ipairs(love_dirs) do + if lovely_mod_dir:sub(1, #love_dir) == love_dir then + -- relative path from love_dir + SMODS.MODS_DIR = lovely_mod_dir:sub(#love_dir+2) + NFS.setWorkingDirectory(love_dir) + return + end + end + SMODS.MODS_DIR = lovely_mod_dir +end +set_mods_dir() + +local function find_self(directory, target_filename, target_line, depth) + depth = depth or 1 + if depth > 3 then return end + for _, filename in ipairs(NFS.getDirectoryItems(directory)) do + local file_path = directory .. "/" .. filename + local file_type = NFS.getInfo(file_path).type + if file_type == 'directory' or file_type == 'symlink' then + local f = find_self(file_path, target_filename, target_line, depth+1) + if f then return f end + elseif filename == target_filename then + local first_line = NFS.read(file_path):match('^(.-)\n') + if first_line == target_line then + -- use parent directory + return directory:match('^(.+/)') + end + end + end +end + +SMODS.path = find_self(SMODS.MODS_DIR, 'core.lua', '--- STEAMODDED CORE') + +for _, path in ipairs { + "src/ui.lua", + "src/index.lua", + "src/utils.lua", + "src/overrides.lua", + "src/game_object.lua", + "src/logging.lua", + "src/compat_0_9_8.lua", + "src/loader.lua", +} do + assert(load(NFS.read(SMODS.path..path), ('=[SMODS _ "%s"]'):format(path)))() +end diff --git a/Steamodded/src/crash_handler.lua b/smods-old-calc/src/crash_handler.lua similarity index 100% rename from Steamodded/src/crash_handler.lua rename to smods-old-calc/src/crash_handler.lua diff --git a/Steamodded/src/game_object.lua b/smods-old-calc/src/game_object.lua similarity index 94% rename from Steamodded/src/game_object.lua rename to smods-old-calc/src/game_object.lua index 3fe86d8..f07fc3b 100644 --- a/Steamodded/src/game_object.lua +++ b/smods-old-calc/src/game_object.lua @@ -221,6 +221,11 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. -- Setting generate_ui to this sentinel value -- makes vanilla localization code run instead of SMODS's code orig_o.generate_ui = 0 + else + -- reset the value if otherwise, in case when the object was taken over before and this value was already set to 0 + if orig_o.generate_ui == 0 then + orig_o.generate_ui = nil + end end -- TODO -- it's unclear how much we should modify `obj` on a failed take_ownership call. @@ -230,8 +235,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. orig_o.dependencies = orig_o.dependencies or {} if not silent then table.insert(orig_o.dependencies, SMODS.current_mod.id) end else - orig_o.mod = SMODS.current_mod - if silent then orig_o.no_main_mod_badge = true end + if not silent then orig_o.mod = SMODS.current_mod end orig_o.rarity_original = orig_o.rarity end if orig_o._saved_d_u then @@ -292,7 +296,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. self.font = G.FONTS[type(self.font) == 'number' and self.font or 1] or G.FONTS[1] end G.LANGUAGES[self.key] = self - if self.key == G.SETTINGS.language then G.LANG = self end + if self.key == (G.SETTINGS.real_language or G.SETTINGS.language) then G.LANG = self end end, } @@ -349,11 +353,11 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. end, inject = function(self) local file_path = type(self.path) == 'table' and - (self.path[G.SETTINGS.language] or self.path['default'] or self.path['en-us']) or self.path + ((G.SETTINGS.real_language and self.path[G.SETTINGS.real_language]) or self.path[G.SETTINGS.language] or self.path['default'] or self.path['en-us']) or self.path if file_path == 'DEFAULT' then return end -- language specific sprites override fully defined sprites only if that language is set - if self.language and not (G.SETTINGS.language == self.language) then return end - if not self.language and self.obj_table[('%s_%s'):format(self.key, G.SETTINGS.language)] then return end + if self.language and G.SETTINGS.language ~= self.language and G.SETTINGS.real_language ~= self.language then return end + if not self.language and (self.obj_table[('%s_%s'):format(self.key, G.SETTINGS.language)] or self.obj_table[('%s_%s'):format(self.key, G.SETTINGS.real_language)]) then return end self.full_path = (self.mod and self.mod.path or SMODS.path) .. 'assets/' .. G.SETTINGS.GRAPHICS.texture_scaling .. 'x/' .. file_path local file_data = assert(NFS.newFileData(self.full_path), @@ -425,14 +429,17 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. end, inject = function(self) local file_path = type(self.path) == 'table' and - (self.path[G.SETTINGS.language] or self.path['default'] or self.path['en-us']) or self.path + ((G.SETTINGS.real_language and self.path[G.SETTINGS.real_language]) or self.path[G.SETTINGS.language] or self.path['default'] or self.path['en-us']) or self.path if file_path == 'DEFAULT' then return end + local prev_path = self.full_path self.full_path = (self.mod and self.mod.path or SMODS.path) .. 'assets/sounds/' .. file_path + if prev_path == self.full_path then return end self.data = NFS.read('data', self.full_path) - self.decoder = love.sound.newDecoder(self.data) + --self.decoder = love.sound.newDecoder(self.data) self.should_stream = string.find(self.key, 'music') or string.find(self.key, 'stream') or string.find(self.key, 'ambient') - self.sound = love.audio.newSource(self.decoder, self.should_stream and 'stream' or 'static') + --self.sound = love.audio.newSource(self.decoder, self.should_stream and 'stream' or 'static') + if prev_path then G.SOUND_MANAGER.channel:push({ type = 'stop' }) end G.SOUND_MANAGER.channel:push({ type = 'sound_source', sound_code = self.sound_code, data = self.data, should_stream = self.should_stream, per = self.pitch, vol = self.volume }) end, register_global = function(self) @@ -584,7 +591,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. process_loc_text = function(self) -- empty loc_txt indicates there are existing values that shouldn't be changed or it isn't necessary if not self.loc_txt or not next(self.loc_txt) then return end - local target = self.loc_txt[G.SETTINGS.language] or self.loc_txt['default'] or self.loc_txt['en-us'] or + local target = (G.SETTINGS.real_language and self.loc_txt[G.SETTINGS.real_language]) or self.loc_txt[G.SETTINGS.language] or self.loc_txt['default'] or self.loc_txt['en-us'] or self.loc_txt local applied_text = "{s:0.8}" .. localize('b_applies_stakes_1') local any_applied @@ -911,75 +918,11 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. prefix_config = { key = false }, collection_rows = { 6, 6 }, create_UIBox_your_collection = function(self) - local deck_tables = {} - - G.your_collection = {} - for j = 1, #self.collection_rows do - G.your_collection[j] = CardArea( - G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2, G.ROOM.T.h, - (self.collection_rows[j] + 0.25) * G.CARD_W, - 1 * G.CARD_H, - { card_limit = self.collection_rows[j], type = 'title', highlight_limit = 0, collection = true }) - table.insert(deck_tables, - { - n = G.UIT.R, - config = { align = "cm", padding = 0, no_fill = true }, - nodes = { - { n = G.UIT.O, config = { object = G.your_collection[j] } } - } - } - ) - end - - local consumable_pool = SMODS.collection_pool(G.P_CENTER_POOLS[self.key]) - - local sum = 0 - for j = 1, #G.your_collection do - for i = 1, self.collection_rows[j] do - sum = sum + 1 - local center = consumable_pool[sum] - if not center then break end - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w / 2, G.your_collection[j].T.y, - G.CARD_W, G.CARD_H, nil, center) - card:start_materialize(nil, i > 1 or j > 1) - G.your_collection[j]:emplace(card) - end - end - - local center_options = {} - for i = 1, math.ceil(#consumable_pool / sum) do - table.insert(center_options, - localize('k_page') .. - ' ' .. tostring(i) .. '/' .. tostring(math.ceil(#consumable_pool / sum))) - end - - INIT_COLLECTION_CARD_ALERTS() - local option_nodes = { create_option_cycle({ - options = center_options, - w = 4.5, - cycle_shoulders = true, - opt_callback = 'your_collection_' .. string.lower(self.key) .. '_page', - focus_args = { snap_to = true, nav = 'wide' }, - current_option = 1, - colour = G.C.RED, - no_pips = true - }) } local type_buf = {} - if G.ACTIVE_MOD_UI then - for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do - if modsCollectionTally(G.P_CENTER_POOLS[v]).of > 0 then type_buf[#type_buf + 1] = v end - end - else - type_buf = SMODS.ConsumableType.ctype_buffer + for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do + if not v.no_collection and (not G.ACTIVE_MOD_UI or modsCollectionTally(G.P_CENTER_POOLS[v]).of > 0) then type_buf[#type_buf + 1] = v end end - local t = create_UIBox_generic_options({ - back_func = #type_buf>3 and 'your_collection_consumables' or G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', - contents = { - { n = G.UIT.R, config = { align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05 }, nodes = deck_tables }, - { n = G.UIT.R, config = { align = "cm", padding = 0 }, nodes = option_nodes }, - } - }) - return t + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS[self.key], self.collection_rows, { back_func = #type_buf>3 and 'your_collection_consumables' or nil }) end, register = function(self) SMODS.ConsumableType.super.register(self) @@ -999,51 +942,11 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. definition = self:create_UIBox_your_collection(), } end - G.FUNCS['your_collection_' .. string.lower(self.key) .. '_page'] = function(args) - if not args or not args.cycle_config then return end - for j = 1, #G.your_collection do - for i = #G.your_collection[j].cards, 1, -1 do - local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) - c:remove() - c = nil - end - end - local sum = 0 - for j = 1, #G.your_collection do - sum = sum + self.collection_rows[j] - end - - local consumable_pool = {} - if G.ACTIVE_MOD_UI then - for _, v in ipairs(G.P_CENTER_POOLS[self.key]) do - if v.mod and G.ACTIVE_MOD_UI.id == v.mod.id then consumable_pool[#consumable_pool+1] = v end - end - else - consumable_pool = G.P_CENTER_POOLS[self.key] - end - - sum = sum * (args.cycle_config.current_option - 1) - for j = 1, #G.your_collection do - for i = 1, self.collection_rows[j] do - sum = sum + 1 - local center = consumable_pool[sum] - if not center then break end - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w / 2, - G.your_collection[j].T.y, G - .CARD_W, G.CARD_H, G.P_CARDS.empty, center) - card:start_materialize(nil, i > 1 or j > 1) - G.your_collection[j]:emplace(card) - end - end - INIT_COLLECTION_CARD_ALERTS() - end end, process_loc_text = function(self) - if not next(self.loc_txt) then return end SMODS.process_loc_text(G.localization.misc.dictionary, 'k_' .. string.lower(self.key), self.loc_txt, 'name') SMODS.process_loc_text(G.localization.misc.dictionary, 'b_' .. string.lower(self.key) .. '_cards', self.loc_txt, 'collection') - -- SMODS.process_loc_text(G.localization.misc.labels, string.lower(self.key), self.loc_txt, 'label') -- redundant SMODS.process_loc_text(G.localization.descriptions.Other, 'undiscovered_' .. string.lower(self.key), self.loc_txt, 'undiscovered') end, @@ -1158,8 +1061,8 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. target.scale = res.scale target.text_colour = res.text_colour end - if desc_nodes == full_UI_table.main and not full_UI_table.name and self.set ~= 'Enhanced' then - full_UI_table.name = localize { type = 'name', set = target.set, key = target.key, nodes = full_UI_table.name } + if desc_nodes == full_UI_table.main and not full_UI_table.name then + full_UI_table.name = self.set == 'Enhanced' and 'temp_value' or localize { type = 'name', set = target.set, key = target.key, nodes = full_UI_table.name } elseif desc_nodes ~= full_UI_table.main and not desc_nodes.name and self.set ~= 'Enhanced' then desc_nodes.name = localize{type = 'name_text', key = target.key, set = target.set } end @@ -1385,7 +1288,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. end, --]] update_pack = function(self, dt) - if G.buttons then self.buttons:remove(); G.buttons = nil end + if G.buttons then G.buttons:remove(); G.buttons = nil end if G.shop then G.shop.alignment.offset.y = G.ROOM.T.y+11 end if not G.STATE_COMPLETE then @@ -2315,12 +2218,11 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. if G.localization.misc.collabs[self.suit] == nil then G.localization.misc.collabs[self.suit] = {["1"] = 'Default'} end - - if self.loc_txt and self.loc_txt[G.SETTINGS.language] then - G.localization.misc.collabs[self.suit][self.suit_index .. ''] = self.loc_txt[G.SETTINGS.language] - elseif G.localization.misc.collabs[self.suit][self.suit_index .. ''] == nil then - G.localization.misc.collabs[self.suit][self.suit_index .. ''] = self.key + if not self.loc_txt then + G.localization.misc.collabs[self.suit][self.suit_index .. ''] = G.localization.misc.collabs[self.suit][self.suit_index .. ''] or self.key + return end + SMODS.process_loc_text(G.localization.misc.collabs[self.suit], self.suit_index..'', self.loc_txt) end, register = function (self) if self.registered then @@ -2611,7 +2513,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. } local res = {} if self.loc_vars and type(self.loc_vars) == 'function' then - -- card is a dead arg here + -- card is actually a `Tag` here res = self:loc_vars(info_queue, card) or {} target.vars = res.vars or target.vars target.key = res.key or target.key @@ -3049,18 +2951,31 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. -- print("Keybind pressed") -- end, - -- TODO : option to specify if keybind activates on hold, press or release + event = 'pressed', + held_duration = 1, required_params = { - 'key', 'key_pressed', 'action', }, set = 'Keybind', class_prefix = 'keybind', - + register = function(self) + self.key = self.key or (#self.obj_buffer..'') + SMODS.Keybind.super.register(self) + end, inject = function(_) end } + + SMODS.Keybind { + key_pressed = 'm', + event = 'held', + held_duration = 1.1, + action = function(self) + SMODS.save_all_config() + SMODS.restart_game() + end + } ------------------------------------------------------------------------------------------------- ------- API CODE GameObject.Achievements diff --git a/smods-old-calc/src/index.lua b/smods-old-calc/src/index.lua new file mode 100644 index 0000000..699ac1c --- /dev/null +++ b/smods-old-calc/src/index.lua @@ -0,0 +1,32 @@ +SMODS.fetch_index = function() + SMODS.index = {} + local https = require"https" + local status, contents = https.request("https://github.com/Aurelius7309/Steamodded.index/archive/refs/heads/main.zip") + if status ~= 200 then return false end + love.filesystem.write('index.zip', contents) + if not love.filesystem.mount('index.zip', 'index') then return false end + local path = 'index/Steamodded.index-main/mods/' + for _, filename in ipairs(love.filesystem.getDirectoryItems(path)) do + local key, ext = filename:sub(1, -6), filename:sub(-5) + if ext:lower() == '.json' then + local success, data = pcall(function() return JSON.decode(love.filesystem.read(path..filename)) end) + if success and data.id == key then SMODS.index[key] = data end + end + end + love.filesystem.unmount('index.zip') + return true +end + +SMODS.update_mod_files = function(id) + local mod = SMODS.Mods[id] + if not mod then return false end + local use_git = os.execute('git -v') == 0 + if false and use_git and os.execute(('cd %s & git pull'):format(mod.path)) == 0 then + return true + end + local https = require"https" + local url = mod.github or (SMODS.index[id] or {}).github + local status, contents = https.request(url) -- TODO account for branches + local hash = contents:match('"currentOid":"([^"]*)"') + sendWarnMessage(hash, "Index") +end diff --git a/Steamodded/src/loader.lua b/smods-old-calc/src/loader.lua similarity index 92% rename from Steamodded/src/loader.lua rename to smods-old-calc/src/loader.lua index 249a61e..231e630 100644 --- a/Steamodded/src/loader.lua +++ b/smods-old-calc/src/loader.lua @@ -18,6 +18,7 @@ function loadMods(modsDirectory) } SMODS.mod_priorities = {} SMODS.mod_list = {} + SMODS.provided_mods = {} -- for legacy header support local header_components = { name = { pattern = '%-%-%- MOD_NAME: ([^\n]+)\n', required = true }, @@ -159,7 +160,19 @@ function loadMods(modsDirectory) __ = { check = function(mod) if SMODS.Mods[mod.id] then error('dupe') end end}, - provides = { type = 'table' } + provides = { type = 'table', check = function(mod, t) + t = t or {} + for _,v in pairs(t) do + v = v:gsub('%s', '') + local id = v:match '^([^(%s]+)' + local ver = v:match '%((.-)%)' + ver = (ver and V(ver):is_valid()) and ver or mod.version + if id and ver then + SMODS.provided_mods[id] = SMODS.provided_mods[id] or {} + table.insert(SMODS.provided_mods[id], { version = ver, mod = mod }) + end + end + end} } @@ -252,9 +265,6 @@ function loadMods(modsDirectory) path = mod.path, } end - for _,v in ipairs(mod.provides or {}) do - SMODS.Mods[v] = SMODS.Mods[v] or mod - end SMODS.Mods[mod.id] = mod SMODS.mod_priorities[mod.priority] = SMODS.mod_priorities[mod.priority] or {} table.insert(SMODS.mod_priorities[mod.priority], mod) @@ -458,6 +468,19 @@ function loadMods(modsDirectory) end end if fulfilled then y.fulfilled = true end + else + for _, provided in ipairs(SMODS.provided_mods[id] or {}) do + if provided.mod ~= mod and check_dependencies(provided.mod, seen) then + fulfilled = true + local dep_ver = V(provided.version) + for _, v in ipairs(y) do + if not v.op(dep_ver, v.ver) then + fulfilled = false + end + end + if fulfilled then y.fulfilled = true; y.provided = provided end + end + end end end if not fulfilled then @@ -477,6 +500,19 @@ function loadMods(modsDirectory) break end end + else + for _, provided in ipairs(SMODS.provided_mods[id] or {}) do + if provided.mod ~= mod and check_dependencies(provided.mod, seen) then + conflict = true + local dep_ver = V(provided.version) + for _, v in ipairs(y) do + if not v.op(dep_ver, v.ver) then + conflict = false + break + end + end + end + end end if conflict then can_load = false @@ -494,7 +530,13 @@ function loadMods(modsDirectory) end for _, x in ipairs(mod.dependencies or {}) do for _, y in ipairs(x) do - if y.fulfilled then SMODS.Mods[y.id].can_load = true end + if y.fulfilled then + if y.provided then + y.provided.mod.can_load = true + else + SMODS.Mods[y.id].can_load = true + end + end end end return true @@ -584,10 +626,10 @@ end local function initializeModUIFunctions() for id, modInfo in pairs(SMODS.mod_list) do - G.FUNCS["openModUI_" .. modInfo.id] = function(arg_736_0) + G.FUNCS["openModUI_" .. modInfo.id] = function(e) G.ACTIVE_MOD_UI = modInfo G.FUNCS.overlay_menu({ - definition = create_UIBox_mods(arg_736_0) + definition = create_UIBox_mods(e) }) end end diff --git a/Steamodded/src/logging.lua b/smods-old-calc/src/logging.lua similarity index 100% rename from Steamodded/src/logging.lua rename to smods-old-calc/src/logging.lua diff --git a/Steamodded/src/overrides.lua b/smods-old-calc/src/overrides.lua similarity index 82% rename from Steamodded/src/overrides.lua rename to smods-old-calc/src/overrides.lua index a7ab755..dd52a29 100644 --- a/Steamodded/src/overrides.lua +++ b/smods-old-calc/src/overrides.lua @@ -684,7 +684,22 @@ function G.UIDEF.deck_preview(args) or nil, stones and {n = G.UIT.T, config = {text = '' .. stones, colour = (stones > 0 and G.C.WHITE or G.C.UI.TRANSPARENT_LIGHT), scale = 0.4, shadow = true}} or nil,}} - + local hidden_ranks = {} + for _, rank in ipairs(rank_name_mapping) do + local count = 0 + for _, suit in ipairs(suit_map) do + count = count + #SUITS[suit][rank] + end + if count == 0 and SMODS.Ranks[rank].in_pool and not SMODS.Ranks[rank]:in_pool({suit=''}) then + hidden_ranks[rank] = true + end + end + local hidden_suits = {} + for _, suit in ipairs(suit_map) do + if suit_counts[suit] == 0 and SMODS.Suits[suit].in_pool and not SMODS.Suits[suit]:in_pool({rank=''}) then + hidden_suits[suit] = true + end + end local _row = {} local _bg_col = G.C.JOKER_GREY for k, v in ipairs(rank_name_mapping) do @@ -699,12 +714,12 @@ function G.UIDEF.deck_preview(args) {n = G.UIT.T, config = {text = '' .. SMODS.Ranks[v].shorthand, colour = _colour, scale = 1.6 * _tscale } },}}, {n = G.UIT.R, config = {align = "cm", minw = _minw + 0.04, minh = _minh, colour = G.C.L_BLACK, r = 0.1 }, nodes = { {n = G.UIT.T, config = {text = '' .. (rank_counts[v] or 0), colour = flip_col, scale = _tscale, shadow = true } }}}}}}} - table.insert(_row, _col) + if not hidden_ranks[v] then table.insert(_row, _col) end end table.insert(deck_tables, {n = G.UIT.R, config = {align = "cm", padding = 0.04 }, nodes = _row }) for _, suit in ipairs(suit_map) do - if not (SMODS.Suits[suit].hidden and suit_counts[suit] == 0) then + if not hidden_suits[suit] then _row = {} _bg_col = mix_colours(G.C.SUITS[suit], G.C.L_BLACK, 0.7) for _, rank in ipairs(rank_name_mapping) do @@ -713,7 +728,7 @@ function G.UIDEF.deck_preview(args) local _col = {n = G.UIT.C, config = {align = "cm", padding = 0.05, minw = _minw + 0.098, minh = _minh }, nodes = { {n = G.UIT.T, config = {text = '' .. #SUITS[suit][rank], colour = _colour, scale = _tscale, shadow = true, lang = G.LANGUAGES['en-us'] } },}} - table.insert(_row, _col) + if not hidden_ranks[rank] then table.insert(_row, _col) end end table.insert(deck_tables, {n = G.UIT.R, config = {align = "cm", r = 0.1, padding = 0.04, minh = 0.4, colour = _bg_col }, nodes = @@ -722,7 +737,7 @@ function G.UIDEF.deck_preview(args) end for k, v in ipairs(suit_map) do - if not (SMODS.Suits[v].hidden and suit_counts[v] == 0) then + if not hidden_suits[v] then local t_s = Sprite(0, 0, 0.3, 0.3, G.ASSET_ATLAS[SMODS.Suits[v][G.SETTINGS.colourblind_option and "hc_ui_atlas" or "lc_ui_atlas"]] or G.ASSET_ATLAS[("ui_" .. (G.SETTINGS.colourblind_option and "2" or "1"))], SMODS.Suits[v].ui_pos) @@ -926,10 +941,16 @@ function G.UIDEF.view_deck(unplayed_only) }}, } -- add suit tallies + local hidden_suits = {} + for _, suit in ipairs(suit_map) do + if suit_tallies[suit] == 0 and SMODS.Suits[suit].in_pool and not SMODS.Suits[suit]:in_pool({rank=''}) then + hidden_suits[suit] = true + end + end local i = 1 local num_suits_shown = 0 for i = 1, #suit_map do - if not (SMODS.Suits[suit_map[i]].hidden and suit_tallies[suit_map[i]] == 0) then + if not hidden_suits[suit_map[i]] then num_suits_shown = num_suits_shown+1 end end @@ -937,7 +958,7 @@ function G.UIDEF.view_deck(unplayed_only) local n_nodes = {} while i <= #suit_map do while #n_nodes < suits_per_row and i <= #suit_map do - if not (SMODS.Suits[suit_map[i]].hidden and suit_tallies[suit_map[i]] == 0) then + if not hidden_suits[suit_map[i]] then table.insert(n_nodes, tally_sprite( SMODS.Suits[suit_map[i]].ui_pos, { @@ -1183,134 +1204,6 @@ function evaluate_poker_hand(hand) return results end --#endregion ---#region editions -function create_UIBox_your_collection_editions(exit) - local deck_tables = {} - local edition_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Edition) - local rows, cols = (#edition_pool > 5 and 2 or 1), 5 - local page = 0 - - G.your_collection = {} - for j = 1, rows do - G.your_collection[j] = CardArea(G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2, G.ROOM.T.h, 5.3 * G.CARD_W, 1.03 * G.CARD_H, - { - card_limit = cols, - type = 'title', - highlight_limit = 0, - collection = true - }) - table.insert(deck_tables, - {n = G.UIT.R, config = {align = "cm", padding = 0, no_fill = true}, nodes = { - {n = G.UIT.O, config = {object = G.your_collection[j]}}}} - ) - end - - table.sort(edition_pool, function(a, b) return a.order < b.order end) - - local count = math.min(cols * rows, #edition_pool) - local index = 1 + (rows * cols * page) - for j = 1, rows do - for i = 1, cols do - local edition = edition_pool[index] - - if not edition then - break - end - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w / 2, G.your_collection[j].T.y, - G.CARD_W, G.CARD_H, nil, edition) - card:start_materialize(nil, i > 1 or j > 1) - if edition.discovered then card:set_edition(edition.key, true, true) end - G.your_collection[j]:emplace(card) - index = index + 1 - end - if index > count then - break - end - end - - local edition_options = {} - - local t = create_UIBox_generic_options({ - infotip = localize('ml_edition_seal_enhancement_explanation'), - back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or exit or 'your_collection', - snap_back = true, - contents = { - {n = G.UIT.R, config = {align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = - deck_tables}} - }) - - if #edition_pool > rows * cols then - for i = 1, math.ceil(#edition_pool / (rows * cols)) do - table.insert(edition_options, localize('k_page') .. ' ' .. tostring(i) .. '/' .. - tostring(math.ceil(#edition_pool / (rows * cols)))) - end - t = create_UIBox_generic_options({ - infotip = localize('ml_edition_seal_enhancement_explanation'), - back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or exit or 'your_collection', - snap_back = true, - contents = { - {n = G.UIT.R, config = {align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = - deck_tables}, - {n = G.UIT.R, config = {align = "cm"}, nodes = { - create_option_cycle({ - options = edition_options, - w = 4.5, - cycle_shoulders = true, - opt_callback = 'your_collection_editions_page', - focus_args = { snap_to = true, nav = 'wide' }, - current_option = 1, - r = rows, - c = cols, - colour = G.C.RED, - no_pips = true - })}} - } - }) - end - return t -end - -G.FUNCS.your_collection_editions_page = function(args) - if not args or not args.cycle_config then - return - end - local edition_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Edition) - local rows = (#edition_pool > 5 and 2 or 1) - local cols = 5 - local page = args.cycle_config.current_option - if page > math.ceil(#edition_pool / (rows * cols)) then - page = page - math.ceil(#edition_pool / (rows * cols)) - end - local count = rows * cols - local offset = (rows * cols) * (page - 1) - - for j = 1, #G.your_collection do - for i = #G.your_collection[j].cards, 1, -1 do - if G.your_collection[j] ~= nil then - local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) - c:remove() - c = nil - end - end - end - - for j = 1, rows do - for i = 1, cols do - if count % rows > 0 and i <= count % rows and j == cols then - offset = offset - 1 - break - end - local idx = i + (j - 1) * cols + offset - if idx > #edition_pool then return end - local edition = edition_pool[idx] - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w / 2, G.your_collection[j].T.y, - G.CARD_W, G.CARD_H, G.P_CARDS.empty, edition) - if edition.discovered then card:set_edition(edition.key, true, true) end - card:start_materialize(nil, i > 1 or j > 1) - G.your_collection[j]:emplace(card) - end - end -end -- Init custom card parameters. local card_init = Card.init @@ -1446,7 +1339,8 @@ function Card:set_edition(edition, immediate, silent) G.consumeables.config.card_limit = G.consumeables.config.card_limit + v elseif self.ability.set == 'Joker' then G.jokers.config.card_limit = G.jokers.config.card_limit + v - elseif self.area == G.hand and not (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK) then + elseif self.area == G.hand then + local is_in_pack = (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or (G.STATE == G.STATES.SMODS_BOOSTER_OPENED and SMODS.OPENED_BOOSTER.config.center.draw_hand)) G.E_MANAGER:add_event(Event({ trigger = 'immediate', func = function() @@ -1454,7 +1348,9 @@ function Card:set_edition(edition, immediate, silent) G.hand.config.real_card_limit = G.hand.config.real_card_limit + v end G.hand.config.card_limit = G.hand.config.card_limit + v - G.FUNCS.draw_from_deck_to_hand(v) + if not is_in_pack then + G.FUNCS.draw_from_deck_to_hand(v) + end return true end })) @@ -1577,6 +1473,7 @@ end local cge = Card.get_edition function Card:get_edition() + if self.ability.extra_enhancement then return end local ret = cge(self) if self.edition and self.edition.key then local ed = SMODS.Centers[self.edition.key] @@ -1587,260 +1484,6 @@ function Card:get_edition() return ret end ---#endregion ---#region enhancements UI -function create_UIBox_your_collection_enhancements(exit) - local deck_tables = {} - local rows, cols = 2, 4 - local page = 0 - local enhancement_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Enhanced) - G.your_collection = {} - for j = 1, rows do - G.your_collection[j] = CardArea(G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2, G.ROOM.T.h, 4.25 * G.CARD_W, 1.03 * G.CARD_H, - { - card_limit = cols, - type = 'title', - highlight_limit = 0, - collection = true - }) - table.insert(deck_tables, - {n = G.UIT.R, config = {align = "cm", padding = 0, no_fill = true}, nodes = { - {n = G.UIT.O, config = {object = G.your_collection[j]}}} - }) - end - - table.sort(enhancement_pool, function(a, b) return a.order < b.order end) - - local count = math.min(cols * rows, #enhancement_pool) - local index = 1 + (rows * cols * page) - for j = 1, rows do - for i = 1, cols do - local center = enhancement_pool[index] - if not center then - break - end - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w / 2, G.your_collection[j].T.y, G - .CARD_W, G.CARD_H, G.P_CARDS.empty, center) - card:set_ability(center, true, true) - G.your_collection[j]:emplace(card) - index = index + 1 - end - if index > count then - break - end - end - - local enhancement_options = {} - - local t = create_UIBox_generic_options({ - infotip = localize('ml_edition_seal_enhancement_explanation'), - back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or exit or 'your_collection', - snap_back = true, - contents = { - {n = G.UIT.R, config = {align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05 }, nodes = - deck_tables} - } - }) - - if #enhancement_pool > rows * cols then - for i = 1, math.ceil(#enhancement_pool / (rows * cols)) do - table.insert(enhancement_options, localize('k_page') .. ' ' .. tostring(i) .. '/' .. - tostring(math.ceil(#enhancement_pool / (rows * cols)))) - end - t = create_UIBox_generic_options({ - infotip = localize('ml_edition_seal_enhancement_explanation'), - back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or exit or 'your_collection', - snap_back = true, - contents = { - {n = G.UIT.R, config = {align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = - deck_tables}, - {n = G.UIT.R, config = {align = "cm"}, nodes = { - create_option_cycle({ - options = enhancement_options, - w = 4.5, - cycle_shoulders = true, - opt_callback = 'your_collection_enhancements_page', - focus_args = { snap_to = true, nav = 'wide' }, - current_option = 1, - r = rows, - c = cols, - colour = G.C.RED, - no_pips = true - })}} - } - }) - end - return t -end - -G.FUNCS.your_collection_enhancements_page = function(args) - if not args or not args.cycle_config then - return - end - local rows = 2 - local cols = 4 - local page = args.cycle_config.current_option - local enhancement_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Enhanced) - if page > math.ceil(#enhancement_pool / (rows * cols)) then - page = page - math.ceil(#enhancement_pool / (rows * cols)) - end - local count = rows * cols - local offset = (rows * cols) * (page - 1) - - for j = 1, #G.your_collection do - for i = #G.your_collection[j].cards, 1, -1 do - if G.your_collection[j] ~= nil then - local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) - c:remove() - c = nil - end - end - end - - for j = 1, rows do - for i = 1, cols do - if count % rows > 0 and i <= count % rows and j == cols then - offset = offset - 1 - break - end - local idx = i + (j - 1) * cols + offset - if idx > #enhancement_pool then return end - local center = enhancement_pool[idx] - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w / 2, G.your_collection[j].T.y, - G.CARD_W, G.CARD_H, G.P_CARDS.empty, center) - card:set_ability(center, true, true) - card:start_materialize(nil, i > 1 or j > 1) - G.your_collection[j]:emplace(card) - end - end -end ---#endregion ---#region seals ui -function create_UIBox_your_collection_seals(exit) - local deck_tables = {} - local seal_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Seal) - local rows, cols = (#seal_pool > 5 and 2 or 1), 5 - local page = 0 - - G.your_collection = {} - for j = 1, rows do - G.your_collection[j] = CardArea(G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2, G.ROOM.T.h, 5.3 * G.CARD_W, 1.03 * G.CARD_H, - { - card_limit = cols, - type = 'title', - highlight_limit = 0, - collection = true - }) - table.insert(deck_tables, - {n = G.UIT.R, config = {align = "cm", padding = 0, no_fill = true}, nodes = { - {n = G.UIT.O, config = {object = G.your_collection[j]}}}} - ) - end - - table.sort(seal_pool, function(a, b) return a.order < b.order end) - - local count = math.min(cols * rows, #seal_pool) - local index = 1 + (rows * cols * page) - for j = 1, rows do - for i = 1, cols do - local seal = seal_pool[index] - - if not seal then - break - end - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w / 2, G.your_collection[j].T.y, - G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS.c_base) - card:set_seal(seal.key, true) - G.your_collection[j]:emplace(card) - index = index + 1 - end - if index > count then - break - end - end - - local edition_options = {} - - local t = create_UIBox_generic_options({ - infotip = localize('ml_edition_seal_enhancement_explanation'), - back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or exit or 'your_collection', - snap_back = true, - contents = { - {n = G.UIT.R, config = {align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = - deck_tables}} - }) - - if #seal_pool > rows * cols then - for i = 1, math.ceil(#seal_pool / (rows * cols)) do - table.insert(edition_options, localize('k_page') .. ' ' .. tostring(i) .. '/' .. - tostring(math.ceil(#seal_pool / (rows * cols)))) - end - t = create_UIBox_generic_options({ - infotip = localize('ml_edition_seal_enhancement_explanation'), - back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or exit or 'your_collection', - snap_back = true, - contents = { - {n = G.UIT.R, config = {align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = - deck_tables}, - {n = G.UIT.R, config = {align = "cm"}, nodes = { - create_option_cycle({ - options = edition_options, - w = 4.5, - cycle_shoulders = true, - opt_callback = 'your_collection_seals_page', - focus_args = { snap_to = true, nav = 'wide' }, - current_option = 1, - r = rows, - c = cols, - colour = G.C.RED, - no_pips = true - })}} - } - }) - end - return t -end - -G.FUNCS.your_collection_seals_page = function(args) - if not args or not args.cycle_config then - return - end - local seal_pool = SMODS.collection_pool(G.P_CENTER_POOLS.Seal) - local rows, cols = (#seal_pool > 5 and 2 or 1), 5 - local page = args.cycle_config.current_option - if page > math.ceil(#seal_pool / (rows * cols)) then - page = page - math.ceil(#seal_pool / (rows * cols)) - end - local count = rows * cols - local offset = (rows * cols) * (page - 1) - - for j = 1, #G.your_collection do - for i = #G.your_collection[j].cards, 1, -1 do - if G.your_collection[j] ~= nil then - local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) - c:remove() - c = nil - end - end - end - - for j = 1, rows do - for i = 1, cols do - if count % rows > 0 and i <= count % rows and j == cols then - offset = offset - 1 - break - end - local idx = i + (j - 1) * cols + offset - if idx > #seal_pool then return end - local seal = seal_pool[idx] - local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w / 2, G.your_collection[j].T.y, - G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS.c_base) - card:set_seal(seal.key, true) - G.your_collection[j]:emplace(card) - end - end -end ---#endregion function get_joker_win_sticker(_center, index) local joker_usage = G.PROFILES[G.SETTINGS.profile].joker_usage[_center.key] or {} if joker_usage.wins then @@ -2083,3 +1726,22 @@ function Card:calculate_joker(context) return ret, triggered end --#endregion + +--#region quantum enhancements API +-- prevent base chips from applying with extra enhancements +local gcb = Card.get_chip_bonus +function Card:get_chip_bonus() + if not self.ability.extra_enhancement then + return gcb(self) + end + if self.debuff then return 0 end + return self.ability.bonus + (self.ability.perma_bonus or 0) +end + +-- prevent quantum enhacements from applying seal effects +local ccs = Card.calculate_seal +function Card:calculate_seal(context) + if self.ability.extra_enhancement then return end + return ccs(self, context) +end +--#endregion \ No newline at end of file diff --git a/smods-old-calc/src/ui.lua b/smods-old-calc/src/ui.lua new file mode 100644 index 0000000..c83357e --- /dev/null +++ b/smods-old-calc/src/ui.lua @@ -0,0 +1,1800 @@ +SMODS.GUI = {} +SMODS.GUI.DynamicUIManager = {} + +function STR_UNPACK(str) + local chunk, err = loadstring(str) + if chunk then + setfenv(chunk, {}) -- Use an empty environment to prevent access to potentially harmful functions + local success, result = pcall(chunk) + if success then + return result + else + print("Error unpacking string: " .. result) + return nil + end + else + print("Error loading string: " .. err) + return nil + end +end + + +local gameMainMenuRef = Game.main_menu +function Game:main_menu(change_context) + gameMainMenuRef(self, change_context) + UIBox({ + definition = { + n = G.UIT.ROOT, + config = { + align = "cm", + colour = G.C.UI.TRANSPARENT_DARK + }, + nodes = { + { + n = G.UIT.T, + config = { + scale = 0.3, + text = MODDED_VERSION, + colour = G.C.UI.TEXT_LIGHT + } + } + } + }, + config = { + align = "tri", + bond = "Weak", + offset = { + x = 0, + y = 0.3 + }, + major = G.ROOM_ATTACH + } + }) +end + +local gameUpdateRef = Game.update +function Game:update(dt) + if G.STATE ~= G.STATES.SPLASH and G.MAIN_MENU_UI then + local node = G.MAIN_MENU_UI:get_UIE_by_ID("main_menu_play") + + if node and not node.children.alert then + node.children.alert = UIBox({ + definition = create_UIBox_card_alert({ + text = localize('b_modded_version'), + no_bg = true, + scale = 0.4, + text_rot = -0.2 + }), + config = { + align = "tli", + offset = { + x = -0.1, + y = 0 + }, + major = node, + parent = node + } + }) + node.children.alert.states.collide.can = false + end + end + gameUpdateRef(self, dt) +end + +local function wrapText(text, maxChars) + local wrappedText = "" + local currentLineLength = 0 + + for word in text:gmatch("%S+") do + if currentLineLength + #word <= maxChars then + wrappedText = wrappedText .. word .. ' ' + currentLineLength = currentLineLength + #word + 1 + else + wrappedText = wrappedText .. '\n' .. word .. ' ' + currentLineLength = #word + 1 + end + end + + return wrappedText +end + +-- Helper function to concatenate author names +local function concatAuthors(authors) + if type(authors) == "table" then + return table.concat(authors, ", ") + end + return authors or localize('b_unknown') +end + + +SMODS.LAST_SELECTED_MOD_TAB = "mod_desc" +function create_UIBox_mods(args) + local mod = G.ACTIVE_MOD_UI + if not SMODS.LAST_SELECTED_MOD_TAB then SMODS.LAST_SELECTED_MOD_TAB = "mod_desc" end + + local mod_tabs = {} + table.insert(mod_tabs, buildModDescTab(mod)) + local additions_tab = buildAdditionsTab(mod) + if additions_tab then table.insert(mod_tabs, additions_tab) end + local credits_func = mod.credits_tab + if credits_func and type(credits_func) == 'function' then + table.insert(mod_tabs, { + label = localize("b_credits"), + chosen = SMODS.LAST_SELECTED_MOD_TAB == "credits" or false, + tab_definition_function = function(...) + SMODS.LAST_SELECTED_MOD_TAB = "credits" + return credits_func(...) + end + }) + end + local config_func = mod.config_tab + if config_func and type(config_func) == 'function' then + table.insert(mod_tabs, { + label = localize("b_config"), + chosen = SMODS.LAST_SELECTED_MOD_TAB == "config" or false, + tab_definition_function = function(...) + SMODS.LAST_SELECTED_MOD_TAB = "config" + return config_func(...) + end + }) + end + + local mod_has_achievement + for _, v in pairs(SMODS.Achievements) do + if v.mod.id == mod.id then mod_has_achievement = true end + end + if mod_has_achievement then table.insert(mod_tabs, + { + label = localize("b_achievements"), + chosen = SMODS.LAST_SELECTED_MOD_TAB == "achievements" or false, + tab_definition_function = function() + SMODS.LAST_SELECTED_MOD_TAB = "achievements" + return buildAchievementsTab(mod) + end + }) + end + + local custom_ui_func = mod.extra_tabs + if custom_ui_func and type(custom_ui_func) == 'function' then + local custom_tabs = custom_ui_func() + if next(custom_tabs) and #custom_tabs == 0 then custom_tabs = { custom_tabs } end + for i, v in ipairs(custom_tabs) do + local id = mod.id..'_'..i + v.chosen = (SMODS.LAST_SELECTED_MOD_TAB == id) or false + v.label = v.label or '' + local def = v.tab_definition_function + assert(def, ('Custom defined mod tab with label "%s" from mod with id %s is missing definition function'):format(v.label, mod.id)) + v.tab_definition_function = function(...) + SMODS.LAST_SELECTED_MOD_TAB = id + return def(...) + end + table.insert(mod_tabs, v) + end + end + + return (create_UIBox_generic_options({ + back_func = "mods_button", + contents = { + { + n = G.UIT.R, + config = { + padding = 0, + align = "tm" + }, + nodes = { + create_tabs({ + snap_to_nav = true, + colour = G.C.BOOSTER, + tabs = mod_tabs + }) + } + } + } + })) +end + +function buildModDescTab(mod) + G.E_MANAGER:add_event(Event({ + blockable = false, + func = function() + G.REFRESH_ALERTS = nil + return true + end + })) + local label = mod.name + if (G.localization.descriptions.Mod or {})[mod.id] then + label = localize { type = 'name_text', set = 'Mod', key = mod.id } + end + return { + label = label, + chosen = SMODS.LAST_SELECTED_MOD_TAB == "mod_desc" or false, + tab_definition_function = function() + local modNodes = {} + local scale = 0.75 -- Scale factor for text + local maxCharsPerLine = 50 + + local wrappedDescription = wrapText(mod.description or '', maxCharsPerLine) + + local authors = localize('b_author' .. (#mod.author > 1 and 's' or '')) .. ': ' .. concatAuthors(mod.author) + + -- Authors names in blue + table.insert(modNodes, { + n = G.UIT.R, + config = { + padding = 0, + align = "cm", + r = 0.1, + emboss = 0.1, + outline = 1, + padding = 0.07 + }, + nodes = { + { + n = G.UIT.T, + config = { + text = authors, + shadow = true, + scale = scale * 0.65, + colour = G.C.BLUE, + } + } + } + }) + + -- Mod description + if (G.localization.descriptions.Mod or {})[mod.id] then + modNodes[#modNodes + 1] = {} + local loc_vars = mod.description_loc_vars and mod:description_loc_vars() or {} + localize { type = 'descriptions', key = loc_vars.key or mod.id, set = 'Mod', nodes = modNodes[#modNodes], vars = loc_vars.vars, scale = loc_vars.scale, text_colour = loc_vars.text_colour } + modNodes[#modNodes] = desc_from_rows(modNodes[#modNodes]) + modNodes[#modNodes].config.colour = loc_vars.background_colour or modNodes[#modNodes].config.colour + else + table.insert(modNodes, { + n = G.UIT.R, + config = { + padding = 0.2, + align = "cm" + }, + nodes = { + { + n = G.UIT.T, + config = { + text = wrappedDescription, + shadow = true, + scale = scale * 0.5, + colour = G.C.UI.TEXT_LIGHT + } + } + } + }) + end + + local custom_ui_func = mod.custom_ui + if custom_ui_func and type(custom_ui_func) == 'function' then + custom_ui_func(modNodes) + end + + return { + n = G.UIT.ROOT, + config = { + emboss = 0.05, + minh = 6, + r = 0.1, + minw = 6, + align = "tm", + padding = 0.2, + colour = G.C.BLACK + }, + nodes = modNodes + } + end + } +end + +function buildAdditionsTab(mod) + local consumable_nodes = {} + for _, key in ipairs(SMODS.ConsumableType.ctype_buffer) do + local id = 'your_collection_'..key:lower()..'s' + local tally = modsCollectionTally(G.P_CENTER_POOLS[key]) + if tally.of > 0 then + consumable_nodes[#consumable_nodes+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = tally, minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) + end + end + if #consumable_nodes > 3 then + consumable_nodes = { UIBox_button({ button = 'your_collection_consumables', label = {localize('b_stat_consumables'), localize{ type = 'variable', key = 'c_types', vars = {#consumable_nodes} } }, count = modsCollectionTally(G.P_CENTER_POOLS.Consumeables), minw = 4, minh = 4, id = 'your_collection_consumables', colour = G.C.FILTER }) } + end + + local leftside_nodes = {} + for _, v in ipairs { { k = 'Joker', minh = 1.7, scale = 0.6 }, { k = 'Back', b = 'decks' }, { k = 'Voucher' } } do + v.b = v.b or v.k:lower()..'s' + v.l = v.l or v.b + local tally = modsCollectionTally(G.P_CENTER_POOLS[v.k]) + if tally.of > 0 then + leftside_nodes[#leftside_nodes+1] = UIBox_button({button = 'your_collection_'..v.b, label = {localize('b_'..v.l)}, count = modsCollectionTally(G.P_CENTER_POOLS[v.k]), minw = 5, minh = v.minh, scale = v.scale, id = 'your_collection_'..v.b}) + end + end + if #consumable_nodes > 0 then + leftside_nodes[#leftside_nodes + 1] = { + n = G.UIT.R, + config = { align = "cm", padding = 0.1, r = 0.2, colour = G.C.BLACK }, + nodes = { + { + n = G.UIT.C, + config = { align = "cm", maxh = 2.9 }, + nodes = { + { n = G.UIT.T, config = { text = localize('k_cap_consumables'), scale = 0.45, colour = G.C.L_BLACK, vert = true, maxh = 2.2 } }, + } + }, + { n = G.UIT.C, config = { align = "cm", padding = 0.15 }, nodes = consumable_nodes } + } + } + end + + local rightside_nodes = {} + for _, v in ipairs { { k = 'Enhanced', b = 'enhancements', l = 'enhanced_cards'}, { k = 'Seal' }, { k = 'Edition' }, { k = 'Booster', l = 'booster_packs' }, { b = 'tags', p = G.P_TAGS }, { b = 'blinds', p = G.P_BLINDS, minh = 2.0 }, } do + v.b = v.b or v.k:lower()..'s' + v.l = v.l or v.b + v.p = v.p or G.P_CENTER_POOLS[v.k] + local tally = modsCollectionTally(v.p) + if tally.of > 0 then + rightside_nodes[#rightside_nodes+1] = UIBox_button({button = 'your_collection_'..v.b, label = {localize('b_'..v.l)}, count = modsCollectionTally(v.p), minw = 5, minh = v.minh, id = 'your_collection_'..v.b}) + end + end + local has_other_gameobjects = create_UIBox_Other_GameObjects() + if has_other_gameobjects then + rightside_nodes[#rightside_nodes+1] = UIBox_button({button = 'your_collection_other_gameobjects', label = {localize('k_other')}, minw = 5, id = 'your_collection_other_gameobjects', focus_args = {snap_to = true}}) + end + + local t = {n=G.UIT.R, config={align = "cm",padding = 0.2, minw = 7}, nodes={ + {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes = leftside_nodes }, + {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes = rightside_nodes } + }} + + local modNodes = {} + table.insert(modNodes, t) + return (#leftside_nodes > 0 or #rightside_nodes > 0 ) and { + label = localize("b_additions"), + chosen = SMODS.LAST_SELECTED_MOD_TAB == "additions" or false, + tab_definition_function = function() + SMODS.LAST_SELECTED_MOD_TAB = "additions" + return { + n = G.UIT.ROOT, + config = { + emboss = 0.05, + minh = 6, + r = 0.1, + minw = 6, + align = "tm", + padding = 0.2, + colour = G.C.BLACK + }, + nodes = modNodes + } + end + } or nil +end + +-- Disable alerts when in Additions tab +local set_alerts_ref = set_alerts +function set_alerts() + if G.ACTIVE_MOD_UI then + else + set_alerts_ref() + end +end + +G.FUNCS.your_collection_other_gameobjects = function(e) + G.SETTINGS.paused = true + G.FUNCS.overlay_menu{ + definition = create_UIBox_Other_GameObjects(), + } +end + +function create_UIBox_Other_GameObjects() + local custom_gameobject_tabs = {{}} + local curr_height = 0 + local curr_col = 1 + local other_collections_tabs = {} + local smods_uibox_buttons = { + { + count = G.ACTIVE_MOD_UI and modsCollectionTally(SMODS.Stickers), --Returns nil outside of G.ACTIVE_MOD_UI but we don't use it anyways + button = UIBox_button({button = 'your_collection_stickers', label = {localize('b_stickers')}, count = G.ACTIVE_MOD_UI and modsCollectionTally(SMODS.Stickers), minw = 5, id = 'your_collection_stickers'}) + } + } + + if G.ACTIVE_MOD_UI then + for _, tab in pairs(smods_uibox_buttons) do + if tab.count.of > 0 then other_collections_tabs[#other_collections_tabs+1] = tab.button end + end + if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.custom_collection_tabs then + object_tabs = G.ACTIVE_MOD_UI.custom_collection_tabs() + for _, tab in ipairs(object_tabs) do + other_collections_tabs[#other_collections_tabs+1] = tab + end + end + else + for _, tab in pairs(smods_uibox_buttons) do + other_collections_tabs[#other_collections_tabs+1] = tab.button + end + for _, mod in pairs(SMODS.Mods) do + if mod.custom_collection_tabs and type(mod.custom_collection_tabs) == "function" then + object_tabs = mod.custom_collection_tabs() + for _, tab in ipairs(object_tabs) do + other_collections_tabs[#other_collections_tabs+1] = tab + end + end + end + end + + local custom_gameobject_rows = {} + if #other_collections_tabs > 0 then + for _, gameobject_tabs in ipairs(other_collections_tabs) do + table.insert(custom_gameobject_tabs[curr_col], gameobject_tabs) + curr_height = curr_height + gameobject_tabs.nodes[1].config.minh + if curr_height > 6 then --TODO: Verify that this is the ideal number + curr_height = 0 + curr_col = curr_col + 1 + custom_gameobject_tabs[curr_col] = {} + end + end + for _, v in ipairs(custom_gameobject_tabs) do + table.insert(custom_gameobject_rows, {n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes = v}) + end + + local t = {n=G.UIT.C, config={align = "cm", r = 0.1, colour = G.C.BLACK, padding = 0.1, emboss = 0.05, minw = 7}, nodes={ + {n=G.UIT.R, config={align = "cm", padding = 0.15}, nodes = custom_gameobject_rows} + }} + + return create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = {t}}) + else + return nil + end +end + +G.FUNCS.your_collection_consumables = function(e) + G.SETTINGS.paused = true + G.FUNCS.overlay_menu{ + definition = create_UIBox_your_collection_consumables(), + } +end + +function create_UIBox_your_collection_consumables() + local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = { + { n = G.UIT.C, config = { align = 'cm', minw = 11.5, minh = 6 }, nodes = { + { n = G.UIT.O, config = { id = 'consumable_collection', object = Moveable() },} + }}, + }}) + G.E_MANAGER:add_event(Event({func = function() + G.FUNCS.your_collection_consumables_page({ cycle_config = { current_option = 1 }}) + return true + end})) + return t +end + +G.FUNCS.your_collection_consumables_page = function(args) + if not args or not args.cycle_config then return end + if G.OVERLAY_MENU then + local uie = G.OVERLAY_MENU:get_UIE_by_ID('consumable_collection') + if uie then + if uie.config.object then + uie.config.object:remove() + end + uie.config.object = UIBox{ + definition = G.UIDEF.consumable_collection_page(args.cycle_config.current_option), + config = { align = 'cm', parent = uie} + } + end + end +end + +G.UIDEF.consumable_collection_page = function(page) + local nodes_per_page = 10 + local page_offset = nodes_per_page * ((page or 1) - 1) + local type_buf = {} + if G.ACTIVE_MOD_UI then + for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do + if modsCollectionTally(G.P_CENTER_POOLS[v]).of > 0 then type_buf[#type_buf + 1] = v end + end + else + type_buf = SMODS.ConsumableType.ctype_buffer + end + local center_options = {} + for i = 1, math.ceil(#type_buf / nodes_per_page) do + table.insert(center_options, + localize('k_page') .. + ' ' .. tostring(i) .. '/' .. tostring(math.ceil(#type_buf / nodes_per_page))) + end + local option_nodes = { create_option_cycle({ + options = center_options, + w = 4.5, + cycle_shoulders = true, + opt_callback = 'your_collection_consumables_page', + focus_args = { snap_to = true, nav = 'wide' }, + current_option = page or 1, + colour = G.C.RED, + no_pips = true + }) } + local function create_consumable_nodes(_start, _end) + local t = {} + for i = _start, _end do + local key = type_buf[i] + if not key then + if i == _start then break end + t[#t+1] = { n = G.UIT.R, config = { align ='cm', minh = 0.81 }, nodes = {}} + else + local id = 'your_collection_'..key:lower()..'s' + t[#t+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = G.ACTIVE_MOD_UI and modsCollectionTally(G.P_CENTER_POOLS[key]) or G.DISCOVER_TALLIES[key:lower()..'s'], minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) + end + end + return t + end + + local t = { n = G.UIT.C, config = { align = 'cm' }, nodes = { + {n=G.UIT.R, config = {align="cm"}, nodes = { + {n=G.UIT.C, config={align = "tm", padding = 0.15}, nodes= create_consumable_nodes(page_offset + 1, page_offset + math.ceil(nodes_per_page/2))}, + {n=G.UIT.C, config={align = "tm", padding = 0.15}, nodes= create_consumable_nodes(page_offset+1+math.ceil(nodes_per_page/2), page_offset + nodes_per_page)}, + }}, + {n=G.UIT.R, config = {align="cm"}, nodes = option_nodes}, + }} + return t +end + +function buildAchievementsTab(mod, current_page) + current_page = current_page or 1 + fetch_achievements() + local achievement_matrix = {{},{}} + local achievements_per_row = 3 + local achievements_pool = {} + for k, v in pairs(G.ACHIEVEMENTS) do + if v.mod and v.mod.id == mod.id then achievements_pool[#achievements_pool+1] = v end + end + + local achievement_tab = {} + for k, v in pairs(achievements_pool) do + achievement_tab[#achievement_tab+1] = v + end + + table.sort(achievement_tab, function(a, b) return (a.order or 1) < (b.order or 1) end) + + local row = 1 + local max_lines = 2 + for i = 1, achievements_per_row*2 do + local v = achievement_tab[i+((achievements_per_row*2)*(current_page-1))] + if not v then break end + local temp_achievement = Sprite(0,0,1.1,1.1,G.ASSET_ATLAS[v.atlas or "achievements"], v.earned and v.pos or {x=0, y=0}) + temp_achievement:define_draw_steps({ + {shader = 'dissolve', shadow_height = 0.05}, + {shader = 'dissolve'} + }) + if i == 1 then + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = (function() + G.CONTROLLER:snap_to{node = temp_achievement} + return true + end) + })) + end + temp_achievement.float = true + temp_achievement.states.hover.can = true + temp_achievement.states.drag.can = false + temp_achievement.states.collide.can = true + --temp_achievement.config = {blind = v, force_focus = true} + temp_achievement.hover = function() + if not G.CONTROLLER.dragging.target or G.CONTROLLER.using_touch then + if not temp_achievement.hovering and temp_achievement.states.visible then + temp_achievement.hovering = true + temp_achievement.hover_tilt = 3 + temp_achievement:juice_up(0.05, 0.02) + play_sound('chips1', math.random()*0.1 + 0.55, 0.12) + Node.hover(temp_achievement) + if temp_achievement.children.alert then + temp_achievement.children.alert:remove() + temp_achievement.children.alert = nil + v.alerted = true + G:save_progress() + end + end + end + temp_achievement.stop_hover = function() temp_achievement.hovering = false; Node.stop_hover(temp_achievement); temp_achievement.hover_tilt = 0 end + end + + -- Description + local achievement_text = {} + local maxCharsPerLine = 30 + local function wrapText(text, maxChars) + local wrappedText = {""} + local curr_line = 1 + local currentLineLength = 0 + + for word in text:gmatch("%S+") do + if currentLineLength + #word <= maxChars then + wrappedText[curr_line] = wrappedText[curr_line] .. word .. ' ' + currentLineLength = currentLineLength + #word + 1 + else + wrappedText[curr_line] = string.sub(wrappedText[curr_line], 0, -2) + curr_line = curr_line + 1 + wrappedText[curr_line] = "" + wrappedText[curr_line] = wrappedText[curr_line] .. word .. ' ' + currentLineLength = #word + 1 + end + end + + wrappedText[curr_line] = string.sub(wrappedText[curr_line], 0, -2) + return wrappedText + end + + local loc_target = (v.hidden_text and not v.earned) and {localize("hidden_achievement", 'achievement_descriptions')} or wrapText(localize(v.key, 'achievement_descriptions'), maxCharsPerLine) + local loc_name = (v.hidden_name and not v.earned) and localize("hidden_achievement", 'achievement_names') or localize(v.key, 'achievement_names') + + local ability_text = {} + if loc_target then + for k, v in ipairs(loc_target) do + ability_text[#ability_text + 1] = {n=G.UIT.R, config={align = "cm"}, nodes={{n=G.UIT.T, config={text = v, scale = 0.35, shadow = true, colour = G.C.WHITE}}}} + end + end + max_lines = math.max(max_lines, #ability_text) + achievement_text[#achievement_text + 1] = + {n=G.UIT.R, config={align = "cm", emboss = 0.05, r = 0.1, minw = 4, maxw = 4, padding = 0.05, colour = G.C.WHITE, minh = 0.4*max_lines+0.1}, nodes={ + ability_text[1] and {n=G.UIT.R, config={align = "cm", padding = 0.08, colour = G.C.GREY, r = 0.1, emboss = 0.05, minw = 3.9, maxw = 3.9, minh = 0.4*max_lines}, nodes=ability_text} or nil + }} + + table.insert(achievement_matrix[row], { + n = G.UIT.C, + config = { align = "cm", padding = 0.1 }, + nodes = { + {n=G.UIT.R, config = {align = "cm"}, nodes = { + {n=G.UIT.R, config = {align = "cm", padding = 0.1}, nodes = {{ n = G.UIT.O, config = { object = temp_achievement, focus_with_object = true }}}}, + { + n=G.UIT.R, config = {align = "cm", minw = 4, maxw = 4, padding = 0.05}, nodes = { + {n=G.UIT.R, config={align = "cm", emboss = 0.05, r = 0.1, padding = 0.1, minh = 0.6, colour = G.C.GREY}, nodes={ + {n=G.UIT.O, config={align = "cm", maxw = 3.8, object = DynaText({string = loc_name, maxw = 3.8, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, spacing = 1, bump = true, scale = 0.4})}}, + }}, + {n=G.UIT.R, config={align = "cm"}, nodes=achievement_text}, + }, + }, + }}, + }, + }) + if #achievement_matrix[row] == achievements_per_row then + row = row + 1 + achievement_matrix[row] = {} + max_lines = 2 + end + end + + local achievements_options = {} + for i = 1, math.ceil(#achievements_pool/(2*achievements_per_row)) do + table.insert(achievements_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#achievements_pool/(2*achievements_per_row)))) + end + + local t = { + {n=G.UIT.C, config={}, nodes={ + {n=G.UIT.C, config={align = "cm"}, nodes={ + {n=G.UIT.R, config={align = "cm"}, nodes={ + {n=G.UIT.R, config={align = "cm", padding = 0.1 }, nodes=achievement_matrix[1]}, + {n=G.UIT.R, config={align = "cm", padding = 0.1 }, nodes=achievement_matrix[2]}, + create_option_cycle({options = achievements_options, w = 4.5, cycle_shoulders = true, opt_callback = 'achievments_tab_page', focus_args = {snap_to = true, nav = 'wide'},current_option = current_page, colour = G.C.RED, no_pips = true}) + }} + }} + }}} + return { + n = G.UIT.ROOT, + config = { + emboss = 0.05, + minh = 6, + r = 0.1, + minw = 6, + align = "tm", + padding = 0.2, + colour = G.C.BLACK + }, + nodes = t + } +end + +G.FUNCS.achievments_tab_page = function(args) + if not args or not args.cycle_config then return end + achievement_matrix = {{},{}} + + local tab_contents = G.OVERLAY_MENU:get_UIE_by_ID('tab_contents') + tab_contents.config.object:remove() + tab_contents.config.object = UIBox{ + definition = buildAchievementsTab(G.ACTIVE_MOD_UI, args.cycle_config.current_option), + config = {offset = {x=0,y=0}, parent = tab_contents, type = 'cm'} + } + tab_contents.UIBox:recalculate() +end + +-- TODO: Optimize this. +function modsCollectionTally(pool, set) + local set = set or nil + local obj_tally = {tally = 0, of = 0} + + for _, v in pairs(pool) do + if v.mod and G.ACTIVE_MOD_UI.id == v.mod.id and not v.no_collection then + if set then + if v.set and v.set == set then + obj_tally.of = obj_tally.of+1 + if v.discovered then + obj_tally.tally = obj_tally.tally+1 + end + end + else + obj_tally.of = obj_tally.of+1 + if v.discovered then + obj_tally.tally = obj_tally.tally+1 + end + end + end + end + + return obj_tally +end + +-- TODO: Make better solution +local UIBox_button_ref = UIBox_button +function UIBox_button(args) + local button = UIBox_button_ref(args) + button.nodes[1].config.count = args.count + return button +end + +function buildModtag(mod) + local tag_pos, tag_message, tag_atlas = { x = 0, y = 0 }, "load_success", mod.prefix and mod.prefix .. '_modicon' or 'modicon' + local specific_vars = {} + + if not mod.can_load then + tag_message = "load_failure" + tag_atlas = "mod_tags" + specific_vars = {} + if next(mod.load_issues.dependencies) then + tag_message = tag_message..'_d' + table.insert(specific_vars, concatAuthors(mod.load_issues.dependencies)) + end + if next(mod.load_issues.conflicts) then + tag_message = tag_message .. '_c' + table.insert(specific_vars, concatAuthors(mod.load_issues.conflicts)) + end + if mod.load_issues.outdated then tag_message = 'load_failure_o' end + if mod.load_issues.version_mismatch then + tag_message = 'load_failure_i' + specific_vars = {mod.load_issues.version_mismatch, MODDED_VERSION:gsub('-STEAMODDED', '')} + end + if mod.load_issues.main_file_not_found then + tag_message = 'load_failure_m' + specific_vars = {mod.main_file} + end + if mod.load_issues.prefix_conflict then + tag_message = 'load_failure_p' + local name = mod.load_issues.prefix_conflict + for _, m in ipairs(SMODS.mod_list) do + if m.id == mod.load_issues.prefix_conflict then + name = m.name or name + end + end + specific_vars = {name} + end + if mod.disabled then + tag_pos = {x = 1, y = 0} + tag_message = 'load_disabled' + end + end + + + local tag_sprite_tab = nil + + local tag_sprite = Sprite(0, 0, 0.8*1, 0.8*1, G.ASSET_ATLAS[tag_atlas] or G.ASSET_ATLAS['tags'], tag_pos) + tag_sprite.T.scale = 1 + tag_sprite_tab = {n= G.UIT.C, config={align = "cm", padding = 0}, nodes={ + {n=G.UIT.O, config={w=0.8*1, h=0.8*1, colour = G.C.BLUE, object = tag_sprite, focus_with_object = true}}, + }} + tag_sprite:define_draw_steps({ + {shader = 'dissolve', shadow_height = 0.05}, + {shader = 'dissolve'}, + }) + tag_sprite.float = true + tag_sprite.states.hover.can = true + tag_sprite.states.drag.can = false + tag_sprite.states.collide.can = true + + tag_sprite.hover = function(_self) + if not G.CONTROLLER.dragging.target or G.CONTROLLER.using_touch then + if not _self.hovering and _self.states.visible then + _self.hovering = true + if _self == tag_sprite then + _self.hover_tilt = 3 + _self:juice_up(0.05, 0.02) + play_sound('paper1', math.random()*0.1 + 0.55, 0.42) + play_sound('tarot2', math.random()*0.1 + 0.55, 0.09) + end + tag_sprite.ability_UIBox_table = generate_card_ui({set = "Other", discovered = false, key = tag_message}, nil, specific_vars, 'Other', nil, false) + _self.config.h_popup = G.UIDEF.card_h_popup(_self) + _self.config.h_popup_config ={align = 'cl', offset = {x=-0.1,y=0},parent = _self} + Node.hover(_self) + if _self.children.alert then + _self.children.alert:remove() + _self.children.alert = nil + G:save_progress() + end + end + end + end + tag_sprite.stop_hover = function(_self) _self.hovering = false; Node.stop_hover(_self); _self.hover_tilt = 0 end + + tag_sprite:juice_up() + + return tag_sprite_tab +end + +-- Helper function to create a clickable mod box +local function createClickableModBox(modInfo, scale) + local function invert(c) + return {1-c[1], 1-c[2], 1-c[3], c[4]} + end + local col, text_col + if modInfo.should_enable == nil then + modInfo.should_enable = not modInfo.disabled + end + if SMODS.full_restart == nil then + SMODS.full_restart = 0 + end + if modInfo.can_load then + col = G.C.BOOSTER + elseif modInfo.disabled then + col = G.C.UI.BACKGROUND_INACTIVE + else + col = mix_colours(G.C.RED, G.C.UI.BACKGROUND_INACTIVE, 0.7) + text_col = G.C.TEXT_DARK + end + local label = { " " .. modInfo.name .. " " } + if modInfo.lovely_only then + label[2] = localize('b_lovely_mod') + else + label[2] = localize('b_by') .. concatAuthors(modInfo.author) .. " " + end + local but = UIBox_button { + label = label, + shadow = true, + scale = scale, + colour = col, + text_colour = text_col, + button = "openModUI_" .. modInfo.id, + minh = 0.8, + minw = 7 + } + if modInfo.lovely_only then + local config = but.nodes[1].nodes[2].nodes[1].config + config.colour = mix_colours(invert(col), G.C.UI.TEXT_INACTIVE, 0.8) + config.scale = scale * .8 + end + if modInfo.version and modInfo.version ~= '0.0.0' then + table.insert(but.nodes[1].nodes[1].nodes, { + n = G.UIT.T, + config = { + text = ('(%s) '):format(modInfo.version), + scale = scale*0.8, + colour = mix_colours(invert(col), G.C.UI.TEXT_INACTIVE, 0.8), + shadow = true, + }, + }) + end + if modInfo.config_tab then + table.insert(but.nodes[1].nodes[1].nodes, { + n = G.UIT.O, + config = { + object = Sprite(0,0,0.4,0.4, G.ASSET_ATLAS['mod_tags'], {x=2,y=0}) + } + }) + end + return { + n = G.UIT.R, + config = { padding = 0, align = "cm" }, + nodes = { + { + n = G.UIT.C, + config = { align = "cm" }, + nodes = { + buildModtag(modInfo) + } + }, + { + n = G.UIT.C, + config = { align = "cm", padding = 0.1 }, + nodes = {}, + }, + { n = G.UIT.C, config = { padding = 0, align = "cm" }, nodes = { but } }, + create_toggle({ + label = '', + ref_table = modInfo, + ref_value = 'should_enable', + col = true, + w = 0, + h = 0.5, + callback = ( + function(_set_toggle) + if not modInfo.should_enable then + NFS.write(modInfo.path .. '.lovelyignore', '') + else + NFS.remove(modInfo.path .. '.lovelyignore') + end + local toChange = 1 + if modInfo.should_enable == not modInfo.disabled then + toChange = -1 + end + SMODS.full_restart = SMODS.full_restart + toChange + end + ) + }), + }} + +end + +function G.FUNCS.openModsDirectory(options) + love.system.openURL(SMODS.MODS_DIR) +end + +function G.FUNCS.mods_buttons_page(options) + if not options or not options.cycle_config then + return + end +end + +function SMODS.load_mod_config(mod) + local s1, config = pcall(function() + return load(NFS.read(('config/%s.jkr'):format(mod.id)), ('=[SMODS %s "config"]'):format(mod.id))() + end) + local s2, default_config = pcall(function() + return load(NFS.read(('%sconfig.lua'):format(mod.path)), ('=[SMODS %s "default_config"]'):format(mod.id))() + end) + if not s1 or type(config) ~= 'table' then config = {} end + if not s2 or type(default_config) ~= 'table' then default_config = {} end + mod.config = {} + for k, v in pairs(default_config) do mod.config[k] = v end + for k, v in pairs(config) do mod.config[k] = v end + return mod.config +end +SMODS:load_mod_config() +function SMODS.save_mod_config(mod) + local success = pcall(function() + NFS.createDirectory('config') + assert(mod.config and next(mod.config)) + local serialized = 'return '..serialize(mod.config) + NFS.write(('config/%s.jkr'):format(mod.id), serialized) + end) + return success +end +function SMODS.save_all_config() + SMODS:save_mod_config() + for _, v in ipairs(SMODS.mod_list) do + if v.can_load then + local save_func = type(v.save_mod_config) == 'function' and v.save_mod_config or SMODS.save_mod_config + save_func(v) + end + end +end + +function G.FUNCS.exit_mods(e) + G.ACTIVE_MOD_UI = nil + SMODS.save_all_config() + if SMODS.full_restart and SMODS.full_restart ~= 0 then + -- launch a new instance of the game and quit the current one + SMODS.restart_game() + end + SMODS.IN_MODS_TAB = nil + if e then + -- This is only needed when back button is pressed + G.FUNCS.exit_overlay_menu(e) + end +end + +function create_UIBox_mods_button() + local scale = 0.75 + SMODS.browse_search = SMODS.browse_search or '' + return (create_UIBox_generic_options({ + back_func = 'exit_mods', + contents = { + { + n = G.UIT.R, + config = { + padding = 0, + align = "cm" + }, + nodes = { + create_tabs({ + snap_to_nav = true, + colour = G.C.BOOSTER, + tabs = { + { + label = localize('b_mods'), + chosen = true, + tab_definition_function = function() + return SMODS.GUI.DynamicUIManager.initTab({ + updateFunctions = { + modsList = G.FUNCS.update_mod_list, + }, + staticPageDefinition = SMODS.GUI.staticModListContent() + }) + end + }, + -- { + -- label = localize('b_browse'), + -- tab_definition_function = function() + -- return { + -- n = G.UIT.ROOT, + -- config = { + -- align = "cm", + -- padding = 0.05, + -- colour = G.C.CLEAR, + -- }, + -- nodes = { + -- { + -- n = G.UIT.C, + -- config = { align = 'cm' }, + -- nodes = { + -- { + -- n = G.UIT.R, + -- config = { align = 'cl' }, + -- nodes = { + -- create_text_input{ + -- prompt_text = localize('b_search_prompt'), + -- max_length = 50, + -- text_scale = 0.6, + -- w = 6, + -- h = 1, + -- ref_table = SMODS, + -- ref_value = "browse_search", + -- extended_corpus = true, + -- }, + -- UIBox_button{ + -- button = 'browse_search', + -- label = {localize('b_search_button')}, + -- minw = 3, + -- colour = G.C.RED + -- } + -- } + -- }, + -- { + -- n = G.UIT.R, + -- config = { align = 'cm', emboss = 0.05, colour = G.C.BLACK, minh=5, minw=10.5}, + -- nodes = { + -- { + -- n = G.UIT.O, + -- config = { align = 'cm', object = Moveable(), id = 'browse_mods'} + -- } + -- } + -- } + -- } + -- } + -- } + -- } + -- end, + -- }, + { + + label = localize('b_credits'), + tab_definition_function = function() + return { + n = G.UIT.ROOT, + config = { + emboss = 0.05, + minh = 6, + r = 0.1, + minw = 6, + align = "cm", + padding = 0.2, + colour = G.C.BLACK + }, + nodes = { + { + n = G.UIT.R, + config = { + padding = 0, + align = "cm" + }, + nodes = { + { + n = G.UIT.T, + config = { + text = localize('b_mod_loader'), + shadow = true, + scale = scale * 0.8, + colour = G.C.UI.TEXT_LIGHT + } + } + } + }, + { + n = G.UIT.R, + config = { + padding = 0, + align = "cm" + }, + nodes = { + { + n = G.UIT.T, + config = { + text = localize('b_developed_by'), + shadow = true, + scale = scale * 0.8, + colour = G.C.UI.TEXT_LIGHT + } + }, + { + n = G.UIT.T, + config = { + text = "Steamo", + shadow = true, + scale = scale * 0.8, + colour = G.C.BLUE + } + } + } + }, + { + n = G.UIT.R, + config = { + padding = 0, + align = "cm" + }, + nodes = { + { + n = G.UIT.T, + config = { + text = localize('b_rewrite_by'), + shadow = true, + scale = scale * 0.8, + colour = G.C.UI.TEXT_LIGHT + } + }, + { + n = G.UIT.T, + config = { + text = "Aure", + shadow = true, + scale = scale * 0.8, + colour = G.C.BLUE + } + } + } + }, + { + n = G.UIT.R, + config = { + padding = 0.2, + align = "cm", + }, + nodes = { + UIBox_button({ + minw = 3.85, + button = "steamodded_github", + label = {localize('b_github_project')} + }) + } + }, + { + n = G.UIT.R, + config = { + padding = 0.2, + align = "cm" + }, + nodes = { + { + n = G.UIT.T, + config = { + text = localize('b_github_bugs_1')..'\n'..localize('b_github_bugs_2'), + shadow = true, + scale = scale * 0.5, + colour = G.C.UI.TEXT_LIGHT + } + }, + + } + }, + } + } + end + }, + { + label = localize('b_config'), + tab_definition_function = function() + return { + n = G.UIT.ROOT, + config = { + align = "cm", + padding = 0.05, + colour = G.C.CLEAR, + }, + nodes = { + create_toggle { + label = localize('b_disable_mod_badges'), + ref_table = SMODS.config, + ref_value = 'no_mod_badges', + }, + create_toggle { + label = localize('b_seeded_unlocks'), + info = {localize('b_seeded_unlocks_info')}, + ref_table = SMODS.config, + ref_value = 'seeded_unlocks', + }, + create_option_cycle { + w = 4.5, + scale = 0.8, + label = localize('b_achievements'), + options = localize('ml_achievement_settings'), + opt_callback = 'update_achievement_settings', + current_option = SMODS.config.achievements, + cycle_shoulders = true, + } + } + } + end + } + } + }) + } + } + } + })) +end + +G.FUNCS.update_achievement_settings = function(e) + local opt = (e.cycle_config or {}).current_option or 1 + SMODS.config.achievements = opt + G.F_NO_ACHIEVEMENTS = opt == 1 +end + +G.FUNCS.browse_search = function(e) + SMODS.fetch_index() + +end + +G.FUNCS.browse_mods_page = function(args) + local page = args.cycle_config and args.cycle_config.current_option or 1 +end + +function G.FUNCS.steamodded_github(e) + love.system.openURL("https://github.com/Steamopollys/Steamodded") +end + +function G.FUNCS.mods_button(e) + G.SETTINGS.paused = true + SMODS.LAST_SELECTED_MOD_TAB = nil + SMODS.IN_MODS_TAB = true + + G.FUNCS.overlay_menu({ + definition = create_UIBox_mods_button() + }) +end + +local create_UIBox_main_menu_buttonsRef = create_UIBox_main_menu_buttons +function create_UIBox_main_menu_buttons() + local modsButton = UIBox_button({ + id = "mods_button", + minh = 1.55, + minw = 1.85, + col = true, + button = "mods_button", + colour = G.C.BOOSTER, + label = {localize('b_mods_cap')}, + scale = 0.45 * 1.2 + }) + local menu = create_UIBox_main_menu_buttonsRef() + table.insert(menu.nodes[1].nodes[1].nodes, modsButton) + menu.nodes[1].nodes[1].config = {align = "cm", padding = 0.15, r = 0.1, emboss = 0.1, colour = G.C.L_BLACK, mid = true} + if SMODS.mod_button_alert then + G.E_MANAGER:add_event(Event({ + func = function() + if G.MAIN_MENU_UI then -- Wait until the ui is rendered before spawning the alert + UIBox{definition = create_UIBox_card_alert(), config = {align="tri", offset = {x = 0.05, y = -0.05}, major = G.MAIN_MENU_UI:get_UIE_by_ID('mods_button'), can_collide = false}} + return true + end + end, + blocking = false, + blockable = false + })) + end + return menu +end + +local create_UIBox_profile_buttonRef = create_UIBox_profile_button +function create_UIBox_profile_button() + local profile_menu = create_UIBox_profile_buttonRef() + profile_menu.nodes[1].config = {align = "cm", padding = 0.11, r = 0.1, emboss = 0.1, colour = G.C.L_BLACK} + return(profile_menu) +end + +-- Disable achievments and crash report upload +function initGlobals() + G.F_NO_ACHIEVEMENTS = SMODS.config.achievements == 1 + G.F_CRASH_REPORTS = false +end + +function G.FUNCS.update_mod_list(args) + if not args or not args.cycle_config then return end + SMODS.GUI.DynamicUIManager.updateDynamicAreas({ + ["modsList"] = SMODS.GUI.dynamicModListContent(args.cycle_config.current_option) + }) +end + +-- Same as Balatro base game code, but accepts a value to match against (rather than the index in the option list) +-- e.g. create_option_cycle({ current_option = 1 }) vs. SMODS.GUID.createOptionSelector({ current_option = "Page 1/2" }) +function SMODS.GUI.createOptionSelector(args) + args = args or {} + args.colour = args.colour or G.C.RED + args.options = args.options or { + 'Option 1', + 'Option 2' + } + + local current_option_index = 1 + for i, option in ipairs(args.options) do + if option == args.current_option then + current_option_index = i + break + end + end + args.current_option_val = args.options[current_option_index] + args.current_option = current_option_index + args.opt_callback = args.opt_callback or nil + args.scale = args.scale or 1 + args.ref_table = args.ref_table or nil + args.ref_value = args.ref_value or nil + args.w = (args.w or 2.5)*args.scale + args.h = (args.h or 0.8)*args.scale + args.text_scale = (args.text_scale or 0.5)*args.scale + args.l = '<' + args.r = '>' + args.focus_args = args.focus_args or {} + args.focus_args.type = 'cycle' + + local info = nil + if args.info then + info = {} + for k, v in ipairs(args.info) do + table.insert(info, {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ + {n=G.UIT.T, config={text = v, scale = 0.3*args.scale, colour = G.C.UI.TEXT_LIGHT}} + }}) + end + info = {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes=info} + end + + local disabled = #args.options < 2 + local pips = {} + for i = 1, #args.options do + pips[#pips+1] = {n=G.UIT.B, config={w = 0.1*args.scale, h = 0.1*args.scale, r = 0.05, id = 'pip_'..i, colour = args.current_option == i and G.C.WHITE or G.C.BLACK}} + end + + local choice_pips = not args.no_pips and {n=G.UIT.R, config={align = "cm", padding = (0.05 - (#args.options > 15 and 0.03 or 0))*args.scale}, nodes=pips} or nil + + local t = + {n=G.UIT.C, config={align = "cm", padding = 0.1, r = 0.1, colour = G.C.CLEAR, id = args.id and (not args.label and args.id or nil) or nil, focus_args = args.focus_args}, nodes={ + {n=G.UIT.C, config={align = "cm",r = 0.1, minw = 0.6*args.scale, hover = not disabled, colour = not disabled and args.colour or G.C.BLACK,shadow = not disabled, button = not disabled and 'option_cycle' or nil, ref_table = args, ref_value = 'l', focus_args = {type = 'none'}}, nodes={ + {n=G.UIT.T, config={ref_table = args, ref_value = 'l', scale = args.text_scale, colour = not disabled and G.C.UI.TEXT_LIGHT or G.C.UI.TEXT_INACTIVE}} + }}, + args.mid and + {n=G.UIT.C, config={id = 'cycle_main'}, nodes={ + {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ + args.mid + }}, + not disabled and choice_pips or nil + }} + or {n=G.UIT.C, config={id = 'cycle_main', align = "cm", minw = args.w, minh = args.h, r = 0.1, padding = 0.05, colour = args.colour,emboss = 0.1, hover = true, can_collide = true, on_demand_tooltip = args.on_demand_tooltip}, nodes={ + {n=G.UIT.R, config={align = "cm"}, nodes={ + {n=G.UIT.R, config={align = "cm"}, nodes={ + {n=G.UIT.O, config={object = DynaText({string = {{ref_table = args, ref_value = "current_option_val"}}, colours = {G.C.UI.TEXT_LIGHT},pop_in = 0, pop_in_rate = 8, reset_pop_in = true,shadow = true, float = true, silent = true, bump = true, scale = args.text_scale, non_recalc = true})}}, + }}, + {n=G.UIT.R, config={align = "cm", minh = 0.05}, nodes={ + }}, + not disabled and choice_pips or nil + }} + }}, + {n=G.UIT.C, config={align = "cm",r = 0.1, minw = 0.6*args.scale, hover = not disabled, colour = not disabled and args.colour or G.C.BLACK,shadow = not disabled, button = not disabled and 'option_cycle' or nil, ref_table = args, ref_value = 'r', focus_args = {type = 'none'}}, nodes={ + {n=G.UIT.T, config={ref_table = args, ref_value = 'r', scale = args.text_scale, colour = not disabled and G.C.UI.TEXT_LIGHT or G.C.UI.TEXT_INACTIVE}} + }}, + }} + + if args.cycle_shoulders then + t = + {n=G.UIT.R, config={align = "cm", colour = G.C.CLEAR}, nodes = { + {n=G.UIT.C, config={minw = 0.7,align = "cm", colour = G.C.CLEAR,func = 'set_button_pip', focus_args = {button = 'leftshoulder', type = 'none', orientation = 'cm', scale = 0.7, offset = {x = -0.1, y = 0}}}, nodes = {}}, + {n=G.UIT.C, config={id = 'cycle_shoulders', padding = 0.1}, nodes={t}}, + {n=G.UIT.C, config={minw = 0.7,align = "cm", colour = G.C.CLEAR,func = 'set_button_pip', focus_args = {button = 'rightshoulder', type = 'none', orientation = 'cm', scale = 0.7, offset = {x = 0.1, y = 0}}}, nodes = {}}, + }} + else + t = + {n=G.UIT.R, config={align = "cm", colour = G.C.CLEAR, padding = 0.0}, nodes = { + t + }} + end + if args.label or args.info then + t = {n=G.UIT.R, config={align = "cm", padding = 0.05, id = args.id or nil}, nodes={ + args.label and {n=G.UIT.R, config={align = "cm"}, nodes={ + {n=G.UIT.T, config={text = args.label, scale = 0.5*args.scale, colour = G.C.UI.TEXT_LIGHT}} + }} or nil, + t, + info, + }} + end + return t +end + +local function generateBaseNode(staticPageDefinition) + return { + n = G.UIT.ROOT, + config = { + emboss = 0.05, + minh = 6, + r = 0.1, + minw = 8, + align = "cm", + padding = 0.2, + colour = G.C.BLACK + }, + nodes = { + staticPageDefinition + } + } +end + +-- Initialize a tab with sections that can be updated dynamically (e.g. modifying text labels, showing additional UI elements after toggling buttons, etc.) +function SMODS.GUI.DynamicUIManager.initTab(args) + local updateFunctions = args.updateFunctions + local staticPageDefinition = args.staticPageDefinition + + for _, updateFunction in pairs(updateFunctions) do + G.E_MANAGER:add_event(Event({func = function() + updateFunction{cycle_config = {}} + return true + end})) + end + return generateBaseNode(staticPageDefinition) +end + +-- Call this to trigger an update for a list of dynamic content areas +function SMODS.GUI.DynamicUIManager.updateDynamicAreas(uiDefinitions) + for id, uiDefinition in pairs(uiDefinitions) do + local dynamicArea = G.OVERLAY_MENU:get_UIE_by_ID(id) + if dynamicArea and dynamicArea.config.object then + dynamicArea.config.object:remove() + dynamicArea.config.object = UIBox{ + definition = uiDefinition, + config = {offset = {x=0, y=0}, align = 'cm', parent = dynamicArea} + } + end + end +end + +local function recalculateModsList(page) + page = page or SMODS.LAST_VIEWED_MODS_PAGE or 1 + SMODS.LAST_VIEWED_MODS_PAGE = page + local modsPerPage = 4 + local startIndex = (page - 1) * modsPerPage + 1 + local endIndex = startIndex + modsPerPage - 1 + local totalPages = math.ceil(#SMODS.mod_list / modsPerPage) + local currentPage = localize('k_page') .. ' ' .. page .. "/" .. totalPages + local pageOptions = {} + for i = 1, totalPages do + table.insert(pageOptions, (localize('k_page') .. ' ' .. tostring(i) .. "/" .. totalPages)) + end + local showingList = #SMODS.mod_list > 0 + + return currentPage, pageOptions, showingList, startIndex, endIndex, modsPerPage +end + +-- Define the content in the pane that does not need to update +-- Should include OBJECT nodes that indicate where the dynamic content sections will be populated +-- EX: in this pane the 'modsList' node will contain the dynamic content which is defined in the function below +function SMODS.GUI.staticModListContent() + local scale = 0.75 + local currentPage, pageOptions, showingList = recalculateModsList() + return { + n = G.UIT.ROOT, + config = { + minh = 6, + r = 0.1, + minw = 10, + align = "tm", + padding = 0.2, + colour = G.C.BLACK + }, + nodes = { + -- row container + { + n = G.UIT.R, + config = { align = "cm", padding = 0.05 }, + nodes = { + -- column container + { + n = G.UIT.C, + config = { align = "cm", minw = 3, padding = 0.2, r = 0.1, colour = G.C.CLEAR }, + nodes = { + -- title row + { + n = G.UIT.R, + config = { + padding = 0.05, + align = "cm" + }, + nodes = { + UIBox_button({ + label = { localize('b_mod_list') }, + shadow = true, + scale = scale*0.85, + colour = G.C.BOOSTER, + button = "openModsDirectory", + minh = scale, + minw = 9 + }), + } + }, + + -- add some empty rows for spacing + { + n = G.UIT.R, + config = { align = "cm", padding = 0.05 }, + nodes = {} + }, + { + n = G.UIT.R, + config = { align = "cm", padding = 0.05 }, + nodes = {} + }, + { + n = G.UIT.R, + config = { align = "cm", padding = 0.05 }, + nodes = {} + }, + { + n = G.UIT.R, + config = { align = "cm", padding = 0.05 }, + nodes = {} + }, + + -- dynamic content rendered in this row container + -- list of 4 mods on the current page + { + n = G.UIT.R, + config = { + padding = 0.05, + align = "cm", + minh = 2, + minw = 4 + }, + nodes = { + {n=G.UIT.O, config={id = 'modsList', object = Moveable()}}, + } + }, + + -- another empty row for spacing + { + n = G.UIT.R, + config = { align = "cm", padding = 0.3 }, + nodes = {} + }, + + -- page selector + -- does not appear when list of mods is empty + showingList and SMODS.GUI.createOptionSelector({label = "", scale = 0.8, options = pageOptions, opt_callback = 'update_mod_list', no_pips = true, current_option = ( + currentPage + )}) or nil + } + }, + } + }, + } + } +end + +function SMODS.GUI.dynamicModListContent(page) + local scale = 0.75 + local _, __, showingList, startIndex, endIndex, modsPerPage = recalculateModsList(page) + + local modNodes = {} + + -- If no mods are loaded, show a default message + if showingList == false then + table.insert(modNodes, { + n = G.UIT.R, + config = { + padding = 0, + align = "cm" + }, + nodes = { + { + n = G.UIT.T, + config = { + text = localize('b_no_mods'), + shadow = true, + scale = scale * 0.5, + colour = G.C.UI.TEXT_DARK + } + } + } + }) + else + local modCount = 0 + local id = 0 + + for _, condition in ipairs({ + function(m) return not m.can_load and not m.disabled end, + function(m) return m.can_load end, + function(m) return m.disabled end, + }) do + for _, modInfo in ipairs(SMODS.mod_list) do + if modCount >= modsPerPage then break end + if condition(modInfo) then + id = id + 1 + if id >= startIndex and id <= endIndex then + table.insert(modNodes, createClickableModBox(modInfo, scale * 0.5)) + modCount = modCount + 1 + end + end + end + end + end + + return { + n = G.UIT.C, + config = { + r = 0.1, + align = "cm", + padding = 0.2, + }, + nodes = modNodes + } +end + +G.FUNCS.SMODS_change_mipmap = function(args) + SMODS.config.graphics_mipmap_level = args.to_key + G:set_render_settings() + SMODS:save_mod_config() +end + +SMODS.card_collection_UIBox = function(_pool, rows, args) + args = args or {} + args.w_mod = args.w_mod or 1 + args.h_mod = args.h_mod or 1 + args.card_scale = args.card_scale or 1 + local deck_tables = {} + local pool = SMODS.collection_pool(_pool) + + G.your_collection = {} + local cards_per_page = 0 + local row_totals = {} + for j = 1, #rows do + if cards_per_page >= #pool and args.collapse_single_page then + rows[j] = nil + else + row_totals[j] = cards_per_page + cards_per_page = cards_per_page + rows[j] + G.your_collection[j] = CardArea( + G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, + (args.w_mod*rows[j]+0.25)*G.CARD_W, + args.h_mod*G.CARD_H, + {card_limit = rows[j], type = args.area_type or 'title', highlight_limit = 0, collection = true} + ) + table.insert(deck_tables, + {n=G.UIT.R, config={align = "cm", padding = 0.07, no_fill = true}, nodes={ + {n=G.UIT.O, config={object = G.your_collection[j]}} + }}) + end + end + + local options = {} + for i = 1, math.ceil(#pool/cards_per_page) do + table.insert(options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#pool/cards_per_page))) + end + + G.FUNCS.SMODS_card_collection_page = function(e) + if not e or not e.cycle_config then return end + for j = 1, #G.your_collection do + for i = #G.your_collection[j].cards, 1, -1 do + local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i]) + c:remove() + c = nil + end + end + for j = 1, #rows do + for i = 1, rows[j] do + local center = pool[i+row_totals[j] + (cards_per_page*(e.cycle_config.current_option - 1))] + if not center then break end + local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w/2, G.your_collection[j].T.y, G.CARD_W*args.card_scale, G.CARD_H*args.card_scale, G.P_CARDS.empty, (args.center and G.P_CENTERS[args.center]) or center) + if args.modify_card then args.modify_card(card, center, i, j) end + if not args.no_materialize then card:start_materialize(nil, i>1 or j>1) end + G.your_collection[j]:emplace(card) + end + end + INIT_COLLECTION_CARD_ALERTS() + end + + G.FUNCS.SMODS_card_collection_page{ cycle_config = { current_option = 1 }} + + local t = create_UIBox_generic_options({ back_func = (args and args.back_func) or G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', snap_back = args.snap_back, infotip = args.infotip, contents = { + {n=G.UIT.R, config={align = "cm", r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables}, + (not args.hide_single_page or cards_per_page < #pool) and {n=G.UIT.R, config={align = "cm"}, nodes={ + create_option_cycle({options = options, w = 4.5, cycle_shoulders = true, opt_callback = 'SMODS_card_collection_page', current_option = 1, colour = G.C.RED, no_pips = true, focus_args = {snap_to = true, nav = 'wide'}}) + }} or nil, + }}) + return t +end + +create_UIBox_your_collection_jokers = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Joker, {5,5,5}, { + no_materialize = true, + modify_card = function(card, center) card.sticker = get_joker_win_sticker(center) end, + h_mod = 0.95, + }) +end +create_UIBox_your_collection_boosters = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Booster, {4,4}, { + h_mod = 1.3, + w_mod = 1.25, + card_scale = 1.27, + }) +end +create_UIBox_your_collection_vouchers = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Voucher, {4,4}, { + area_type = 'voucher', + modify_card = function(card, center, i, j) + card.ability.order = i+(j-1)*4 + end, + }) +end +create_UIBox_your_collection_enhancements = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Enhanced, {4,4}, { + no_materialize = true, + snap_back = true, + h_mod = 1.03, + infotip = localize('ml_edition_seal_enhancement_explanation'), + hide_single_page = true, + }) +end +create_UIBox_your_collection_editions = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Edition, {5,5}, { + snap_back = true, + h_mod = 1.03, + infotip = localize('ml_edition_seal_enhancement_explanation'), + hide_single_page = true, + collapse_single_page = true, + modify_card = function(card, center) + if center.discovered then card:set_edition(center.key, true, true) end + end, + }) +end + +create_UIBox_your_collection_seals = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Seal, {5,5}, { + snap_back = true, + infotip = localize('ml_edition_seal_enhancement_explanation'), + hide_single_page = true, + collapse_single_page = true, + center = 'c_base', + h_mod = 1.03, + modify_card = function(card, center) + card:set_seal(center.key, true) + end, + }) +end + +G.FUNCS.your_collection_stickers = function(e) + G.SETTINGS.paused = true + G.FUNCS.overlay_menu{ + definition = create_UIBox_your_collection_stickers(), + } +end + +create_UIBox_your_collection_stickers = function() + return SMODS.card_collection_UIBox(SMODS.Stickers, {5,5}, { + snap_back = true, + hide_single_page = true, + collapse_single_page = true, + center = 'c_base', + h_mod = 1.03, + back_func = 'your_collection_other_gameobjects', + modify_card = function(card, center) + card.ignore_pinned = true + center:apply(card, true) + end, + }) +end diff --git a/Steamodded/src/utils.lua b/smods-old-calc/src/utils.lua similarity index 78% rename from Steamodded/src/utils.lua rename to smods-old-calc/src/utils.lua index 5b9ead4..31b0343 100644 --- a/Steamodded/src/utils.lua +++ b/smods-old-calc/src/utils.lua @@ -177,7 +177,7 @@ end function SMODS.process_loc_text(ref_table, ref_value, loc_txt, key) local target = (type(loc_txt) == 'table') and - (loc_txt[G.SETTINGS.language] or loc_txt['default'] or loc_txt['en-us']) or loc_txt + ((G.SETTINGS.real_language and loc_txt[G.SETTINGS.real_language]) or loc_txt[G.SETTINGS.language] or loc_txt['default'] or loc_txt['en-us']) or loc_txt if key and (type(target) == 'table') then target = target[key] end if not (type(target) == 'string' or target and next(target)) then return end ref_table[ref_value] = target @@ -219,6 +219,7 @@ end function SMODS.handle_loc_file(path) local dir = path .. 'localization/' handle_loc_file(dir, G.SETTINGS.language, true) + if G.SETTINGS.real_language then handle_loc_file(dir, G.SETTINGS.real_language, true) end handle_loc_file(dir, 'default') handle_loc_file(dir, 'en-us') end @@ -327,13 +328,24 @@ function SMODS.create_card(t) if t.seal then _card:set_seal(t.seal) end if t.stickers then for i, v in ipairs(t.stickers) do - if SMODS.Stickers[v]:should_apply(_card, t.area, true) then SMODS.Stickers[v]:apply(_card, true) end + local s = SMODS.Stickers[v] + if not s or type(s.should_apply) ~= 'function' or s:should_apply(_card, t.area, true) then + SMODS.Stickers[v]:apply(_card, true) + end end end return _card end +function SMODS.add_card(t) + local card = SMODS.create_card(t) + card:add_to_deck() + local area = t.area or G.jokers + area:emplace(card) + return card +end + function SMODS.debuff_card(card, debuff, source) debuff = debuff or nil source = source and tostring(source) or nil @@ -349,6 +361,21 @@ function SMODS.recalc_debuff(card) end function SMODS.restart_game() + if ((G or {}).SOUND_MANAGER or {}).channel then + G.SOUND_MANAGER.channel:push({ + type = "kill", + }) + end + if ((G or {}).SAVE_MANAGER or {}).channel then + G.SAVE_MANAGER.channel:push({ + type = "kill", + }) + end + if ((G or {}).HTTP_MANAGER or {}).channel then + G.HTTP_MANAGER.channel:push({ + type = "kill", + }) + end if love.system.getOS() ~= 'OS X' then love.thread.newThread("os.execute(...)\n"):start('"' .. arg[-2] .. '" ' .. table.concat(arg, " ")) else @@ -521,7 +548,6 @@ V_MT = { beta = b.beta, rev = b.rev, } - if b.beta == -1 and a.beta == 0 then return false end if a.major ~= b.major then return a.major < b.major end if a.minor ~= b.minor then return a.minor < b.minor end if a.patch ~= b.patch then return a.patch < b.patch end @@ -798,6 +824,65 @@ function time(func, ...) return 1000*(end_time-start_time) end +function SMODS.get_enhancements(card, extra_only) + local enhancements = {} + if card.config.center.key ~= "c_base" and not extra_only then + enhancements[card.config.center.key] = true + end + if G.jokers and G.jokers.cards then + for i=1, #G.jokers.cards do + local eval = G.jokers.cards[i]:calculate_joker({other_card = card, check_enhancement = true, no_blueprint = true }) + if eval then + for k, _ in pairs(eval) do + if G.P_CENTERS[k] then + enhancements[k] = true + end + end + end + end + end + if extra_only and enhancements[card.config.center.key] then + enhancements[card.config.center.key] = nil + end + return enhancements +end + +function SMODS.has_enhancement(card, key) + if card.config.center.key == key then return true end + if G.jokers and G.jokers.cards then + for i=1, #G.jokers.cards do + local eval = G.jokers.cards[i]:calculate_joker({other_card = card, check_enhancement = true, no_blueprint = true }) + if eval and type(eval) == 'table' and eval[key] then return true end + end + end + return false +end + +function SMODS.has_no_suit(card) + local is_stone = false + local is_wild = false + for k, _ in pairs(SMODS.get_enhancements(card)) do + if k == 'm_stone' or G.P_CENTERS[k].no_suit then is_stone = true end + if k == 'm_wild' or G.P_CENTERS[k].any_suit then is_wild = true end + end + return is_stone and not is_wild +end +function SMODS.has_any_suit(card) + for k, _ in pairs(SMODS.get_enhancements(card)) do + if k == 'm_wild' or G.P_CENTERS[k].any_suit then return true end + end +end +function SMODS.has_no_rank(card) + for k, _ in pairs(SMODS.get_enhancements(card)) do + if k == 'm_stone' or G.P_CENTERS[k].no_rank then return true end + end +end +function SMODS.always_scores(card) + for k, _ in pairs(SMODS.get_enhancements(card)) do + if k == 'm_stone' or G.P_CENTERS[k].always_scores then return true end + end +end + SMODS.collection_pool = function(_base_pool) local pool = {} if type(_base_pool) ~= 'table' then return pool end @@ -810,4 +895,126 @@ SMODS.collection_pool = function(_base_pool) end if not is_array then table.sort(pool, function(a,b) return a.order < b.order end) end return pool -end \ No newline at end of file +end + +SMODS.find_mod = function(id) + local ret = {} + local mod = SMODS.Mods[id] or {} + if mod.can_load then ret[#ret+1] = mod end + for _,v in ipairs(SMODS.provided_mods[id] or {}) do + if v.mod.can_load then ret[#ret+1] = v.mod end + end + return ret +end + +local flat_copy_table = function(tbl) + local new = {} + for i, v in pairs(tbl) do + new[i] = v + end + return new +end + +---Seatch for val anywhere deep in tbl. Return a table of finds, or the first found if immediate is provided. +SMODS.deepfind = function(tbl, val, immediate) + local seen = {[tbl] = true} + local collector = {} + local stack = { {tbl = tbl, path = {}, objpath = {}} } + + --while there are any elements to traverse + while #stack > 0 do + --pull the top off of the stack and start traversing it (by default this will be the last element of the last traversed table found in pairs) + local current = table.remove(stack) + --the current table we wish to traverse + local currentTbl = current.tbl + --the current path + local currentPath = current.path + --the current object path + local currentObjPath = current.objpath + + --for every table that we have + for i, v in pairs(currentTbl) do + --if the value matches + if v == val then + --copy our values and store it in the collector + local newPath = flat_copy_table(currentPath) + local newObjPath = flat_copy_table(currentObjPath) + table.insert(newPath, i) + table.insert(newObjPath, v) + table.insert(collector, {table = currentTbl, index = i, tree = newPath, objtree = newObjPath}) + if immediate then + return collector + end + --otherwise, if its a traversable table we havent seen yet + elseif type(v) == "table" and not seen[v] then + --make sure we dont see it again + seen[v] = true + --and then place it on the top of the stack + local newPath = flat_copy_table(currentPath) + local newObjPath = flat_copy_table(currentObjPath) + table.insert(newPath, i) + table.insert(newObjPath, v) + table.insert(stack, {tbl = v, path = newPath, objpath = newObjPath}) + end + end + end + + return collector +end + +--Seatch for val as an index anywhere deep in tbl. Return a table of finds, or the first found if immediate is provided. +SMODS.deepfindbyindex = function(tbl, val, immediate) + local seen = {[tbl] = true} + local collector = {} + local stack = { {tbl = tbl, path = {}, objpath = {}} } + + --while there are any elements to traverse + while #stack > 0 do + --pull the top off of the stack and start traversing it (by default this will be the last element of the last traversed table found in pairs) + local current = table.remove(stack) + --the current table we wish to traverse + local currentTbl = current.tbl + --the current path + local currentPath = current.path + --the current object path + local currentObjPath = current.objpath + + --for every table that we have + for i, v in pairs(currentTbl) do + --if the value matches + if i == val then + --copy our values and store it in the collector + local newPath = flat_copy_table(currentPath) + local newObjPath = flat_copy_table(currentObjPath) + table.insert(newPath, i) + table.insert(newObjPath, v) + table.insert(collector, {table = currentTbl, index = i, tree = newPath, objtree = newObjPath}) + if immediate then + return collector + end + --otherwise, if its a traversable table we havent seen yet + elseif type(v) == "table" and not seen[v] then + --make sure we dont see it again + seen[v] = true + --and then place it on the top of the stack + local newPath = flat_copy_table(currentPath) + local newObjPath = flat_copy_table(currentObjPath) + table.insert(newPath, i) + table.insert(newObjPath, v) + table.insert(stack, {tbl = v, path = newPath, objpath = newObjPath}) + end + end + end + + return collector +end + +-- this is for debugging +SMODS.debug_calculation = function() + G.contexts = {} + local cj = Card.calculate_joker + function Card:calculate_joker(context) + for k,v in pairs(context) do G.contexts[k] = (G.contexts[k] or 0) + 1 end + return cj(self, context) + end +end diff --git a/Steamodded/tk_debug_window.py b/smods-old-calc/tk_debug_window.py similarity index 100% rename from Steamodded/tk_debug_window.py rename to smods-old-calc/tk_debug_window.py diff --git a/smods-old-calc/version.lua b/smods-old-calc/version.lua new file mode 100644 index 0000000..47a1eb7 --- /dev/null +++ b/smods-old-calc/version.lua @@ -0,0 +1 @@ +return "1.0.0~ALPHA-1304a-STEAMODDED"