fixed gitignore

This commit is contained in:
Vomitblood 2025-05-20 03:22:28 +08:00
parent f35a81d0d2
commit fcb112ca14
91 changed files with 13655 additions and 1 deletions

1
.gitignore vendored
View file

@ -1,2 +1 @@
**/lovely*.log **/lovely*.log
lovely/

View file

@ -0,0 +1,49 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 0
# Patch dynamic ante display into
# function create_UIBox_your_collection_blinds(exit)
# this will only work for vanilla, as steamodded overrides this
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "local ante_amounts = {}"
position = "before"
payload = '''
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
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "for i = 1, math.min(16, math.max(16, G.PROFILES[G.SETTINGS.profile].high_scores.furthest_ante.amt)) do"
position = "at"
payload = '''
for i = min_ante, max_ante do
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "local spacing = 1 - math.min(20, math.max(15, G.PROFILES[G.SETTINGS.profile].high_scores.furthest_ante.amt))*0.06"
position = "at"
payload = '''
-- :3
'''
match_indent = true

View file

@ -0,0 +1,26 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 69
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = '''
local max_cards = math.max(#self.cards, self.config.temp_limit)'''
position = "after"
payload = '''
if max_cards_override then max_cards = max_cards_override end'''
match_indent = true
[[patches]]
[patches.regex]
target = "cardarea.lua"
pattern = '''
if self\.config\.type == \'hand\' and [^\n]*then'''
position = "after"
payload = '''
local max_cards_override = (Cartomancer.SETTINGS.dynamic_hand_align and self.config.temp_limit - #self.cards > 5) and #self.cards
'''

View file

@ -0,0 +1,30 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 69
[[patches]]
[patches.regex]
target = "functions/button_callbacks.lua"
position = "at"
pattern = '''
(?<value>math\.max\(0\., math\.log\(G\.ARGS\.score_intensity\.earned_score, 5\)-2\))'''
payload = "Cartomancer.get_flames_intensity()"
[[patches]]
[patches.regex]
target = "functions/misc_functions.lua"
position = "at"
pattern = '''
(?<value>\(not G\.video_organ and G\.STATE == G\.STATES\.SPLASH\) and 0 or AC\[k\]\.vol and v\.volfunc\(AC\[k\]\.vol\) or 0)'''
payload = "Cartomancer.handle_flames_volume($value)"
[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
pattern = '''_F.timer = _F.timer + G.real_dt*(1 + _F.intensity*0.2)'''
position = 'at'
payload = '''
_F.timer = Cartomancer.handle_flames_timer(_F.timer, _F.intensity)'''
match_indent = true

View file

@ -0,0 +1,30 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 0
# Add no sort button to
# create_UIBox_buttons
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '''
{n=G.UIT.T, config={text = localize('b_sort_hand'), scale = text_scale*0.8, colour = G.C.UI.TEXT_LIGHT}}'''
position = "before"
payload = '''
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'''
match_indent = true
# Set default value of G.hand.cart_sorting
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '''
function create_UIBox_buttons()'''
position = "after"
payload = '''
if G.hand and G.hand.cart_sorting == nil then G.hand.cart_sorting = true end
'''
match_indent = true

View file

@ -0,0 +1,28 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 69
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "self.children.area_uibox:draw()"
position = "after"
payload = '''
if self == G.jokers then
Cartomancer.add_visibility_controls()
end
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "function CardArea:emplace(card, location, stay_flipped)"
position = "after"
payload = '''
if self == G.jokers then
Cartomancer.handle_joker_added(card)
end
'''
match_indent = true

View file

@ -0,0 +1,20 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 69
[[patches]]
[patches.pattern]
target = 'engine/controller.lua'
pattern = "function Controller:key_press_update(key, dt)"
position = "after"
payload = '''
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
'''
match_indent = true

View file

@ -0,0 +1,85 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 69
# Make all drawn cards visible
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "local stay_flipped = G.GAME and G.GAME.blind and G.GAME.blind:stay_flipped(self, card)"
position = "before"
payload = '''
if self == G.hand and not card.states.visible then
card.states.visible = true
end'''
match_indent = true
# Fix drawing specific card staying invisible
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "local stay_flipped = G.GAME and G.GAME.blind and G.GAME.blind:stay_flipped(to, card)"
position = "before"
payload = '''
if card and to == G.hand and not card.states.visible then
card.states.visible = true
end'''
match_indent = true
# Replace drawing deck pile
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = '''
local deck_height = (self.config.deck_height or 0.15)/52
for k, card in ipairs(self.cards) do
if card.facing == 'front' then card:flip() end
if not card.states.drag.is then
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'''
position = "at"
payload = '''
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
end
end'''
match_indent = true

View file

@ -0,0 +1,15 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 69
[[patches]]
[patches.pattern]
target = 'main.lua'
pattern = '''assert(load(nfs.read(Saturn.PATH .. "/core/logic/hide_played.lua")))()'''
position = 'at'
payload = '''
-- Disabled for Cartomancer deck viewer compatibility.
-- assert(load(nfs.read(Saturn.PATH .. "/core/logic/hide_played.lua")))()'''
match_indent = true

View file

@ -0,0 +1,15 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 69
# Add unique count
[[patches]]
[patches.pattern]
target = "main.lua"
match_indent = true
pattern = "modded and {"
position = "before"
payload = '''
not unplayed_only and Cartomancer.add_unique_count() or nil, -- Cartomancer Steamodded 0.9.8 compatibility'''

View file

@ -0,0 +1,103 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 69
# If somehow someone still uses version that old - maybe add this pattern too
# -- Steamodded<0917b
# for k, v in ipairs(G.playing_cards) do
# table.insert(SUITS[v.base.suit], v)
[[patches]]
[patches.pattern]
target = '=[SMODS _ "src/overrides.lua"]'
match_indent = true
pattern = '''
for k, v in ipairs(G.playing_cards) do
if v.base.suit then table.insert(SUITS[v.base.suit], v) end'''
position = "at"
payload = '''
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 {deck_view = true, greyed = true}
if greyed then
card_string = string.format('%sGreyed', card_string)
end
if greyed and Cartomancer.SETTINGS.deck_view_hide_drawn_cards then
-- Ignore this card.
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
'''
[[patches]]
[patches.pattern]
target = '=[SMODS _ "src/overrides.lua"]'
match_indent = true
pattern = 'card_limit = #SUITS[suit_map[j]],'
position = "at"
payload = 'card_limit = #SUITS_SORTED[suit_map[j]],'
[[patches]]
[patches.pattern]
target = '=[SMODS _ "src/overrides.lua"]'
match_indent = true
pattern = '''
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'''
position = "at"
payload = '''
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
'''
[[patches]]
[patches.pattern]
target = '=[SMODS _ "src/overrides.lua"]'
match_indent = true
pattern = ' modded and {n = G.UIT.R, config = {align = "cm"}, nodes = {'
position = "at"
payload = '''
not unplayed_only and Cartomancer.add_unique_count() or nil,
modded and {n = G.UIT.R, config = {align = "cm"}, nodes = {'''

View file

@ -0,0 +1,146 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 69
#
# Vanilla patches
#
# Overwrite how suits are added
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "table.insert(SUITS[v.base.suit], v)"
position = "at"
payload = '''
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 {deck_view = true}
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'''
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '''
if SUITS[suit_map[j]][1] then
local view_deck = CardArea('''
position = "at"
payload = '''
if SUITS_SORTED[suit_map[j]][1] then
local view_deck = CardArea('''
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "local suit_map = {'Spades', 'Hearts', 'Clubs', 'Diamonds'}"
position = "after"
payload = "local SUITS_SORTED = Cartomancer.tablecopy(SUITS)"
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "local suit_tallies = {['Spades'] = 0, ['Hearts'] = 0, ['Clubs'] = 0, ['Diamonds'] = 0}"
position = "before"
payload = '''
-----------------------------------------------------------
-- Add empty card area to view deck to fix a visual issue with missing deck.
if not next(deck_tables) 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 = 1, 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}}
}}
)
end
-----------------------------------------------------------
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "{card_limit = #SUITS[suit_map[j]], type = 'title', view_deck = true, highlight_limit = 0, card_w = G.CARD_W*0.7, draw_layers = {'card'}})"
position = "at"
payload = "{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'}})"
match_indent = true
# Add unique count
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '''modded and {n=G.UIT.R, config={align = "cm"}, nodes={'''
position = "before"
payload = "not unplayed_only and Cartomancer.add_unique_count() or nil,"
match_indent = true
# Overwrite cards copy and display code
#Note for self: multi line pattern patches only work with original spacing.
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '''
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'''
position = "at"
payload = '''
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
'''
match_indent = true

View file

@ -0,0 +1,14 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 69
[[patches]]
[patches.pattern]
target = 'game.lua'
pattern = '''G.FUNCS.blind_chip_UI_scale(G.hand_text_area.blind_chips)'''
position = 'before'
payload = '''
Cartomancer.update_tags_visibility()'''
match_indent = true

View file

@ -0,0 +1,90 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 69
# Localization
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "boot_timer('prep stage', 'splash prep',1)"
position = "before"
payload = "Cartomancer.load_mod_file('internal/localization.lua', 'localization')"
match_indent = true
# Add tab button to settings menu
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
match_indent = true
position = "before"
pattern = '''local t = create_UIBox_generic_options({back_func = 'options',contents = {create_tabs('''
payload = '''
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
'''
# Use custom button
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
match_indent = true
position = "at"
pattern = '''but_UI_label'''
payload = '''
args.ref_table and args.ref_table.custom_button or but_UI_label -- Cartomancer'''
# Use custom color
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
match_indent = true
position = "at"
pattern = '''colour = args.colour,'''
payload = '''
colour = args.ref_table and args.ref_table.colour or args.colour, -- Cartomancer'''
# From steamodded for vertical tabs support.
# 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"
# Add dynamic label support to UIBox_button
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
match_indent = true
position = "before"
pattern = "for k, v in ipairs(args.label) do"
payload = '''
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
'''

View file

@ -0,0 +1,58 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 69
# Replace joker sorting. Needs better mod compat
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "if self.config.type == 'joker' or self.config.type == 'title_2' then"
position = "at"
payload = '''
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'''
match_indent = true
# Hide all cards that are off-screen
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if not self.states.visible then return end"
position = "after"
payload = '''
if self.VT.x < -3 or self.VT.x > G.TILE_W + 2.5 then return end'''
match_indent = true
# Add slider ID
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '''{n=G.UIT.B, config={w=startval,h=args.h, r = 0.1, colour = args.colour, ref_table = args, refresh_movement = true}},'''
position = "at"
payload = '''
{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}},
'''
match_indent = true
# Hide slider value
[[patches]]
[patches.regex]
target = "functions/UI_definitions.lua"
pattern = '''
(?<content>\{n=G\.UIT\.C\, config=\{align = "cm"\, minh = args\.h\,r = 0\.1\, minw = 0\.8\, colour = args\.colour\,shadow = true\}\, nodes=\{
[\t ]*\{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\}\}
[\t ]*\}\})\,'''
position = "at"
payload = '''
not args.hide_val and $content or nil'''

View file

@ -0,0 +1,300 @@
[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
if owned then return prob*owned else return prob end
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
# Yellow Stake - Glass can't destroy Eternals
# Glass Stake - Any card can shatter
[[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)
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
# 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

View file

@ -0,0 +1,38 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
## Cryptid Achievements
# Check to earn some achievements on startup
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''check_for_unlock({type = 'blind_discoveries'})'''
position = "after"
payload = '''
if change_context ~= "splash" then
if not (G.ACHIEVEMENTS and G.ACHIEVEMENTS['ach_cry_used_crash'] and G.ACHIEVEMENTS['ach_cry_used_crash'].earned) then check_for_unlock({type = 'ach_cry_used_crash'}) end
if not (G.ACHIEVEMENTS and G.ACHIEVEMENTS['ach_cry_traffic_jam'] and G.ACHIEVEMENTS['ach_cry_traffic_jam'].earned) then check_for_unlock({type = 'win_challenge_startup'}) end
if not (G.ACHIEVEMENTS and G.ACHIEVEMENTS['ach_cry_perfectly_balanced'] and G.ACHIEVEMENTS['ach_cry_perfectly_balanced'].earned) then check_for_unlock({type = 'win_stake_startup'}) end
end'''
match_indent = true
# Cryptid the Cryptid check
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''new_cards[#new_cards+1] = _card'''
position = "before"
payload = '''if _card.config.center.key == "c_cryptid" then check_for_unlock({type = "cryptid_the_cryptid"}) end'''
match_indent = true
# WHAT HAVE YOU DONE check
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''local sliced_card = G.jokers.cards[my_pos+1]'''
position = "after"
payload = '''if sliced_card.config.center.rarity == "cry_exotic" then check_for_unlock({type = "what_have_you_done"}) end'''
match_indent = true

80
Cryptid/lovely/blind.toml Normal file
View file

@ -0,0 +1,80 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# The Tax effect
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "func = (function() update_hand_text({delay = 0, immediate = true}, {mult = 0, chips = 0, chip_total = math.floor(hand_chips*mult), level = '', handname = ''});play_sound('button', 0.9, 0.6);return true end)"
position = "at"
payload = "func = (function() update_hand_text({delay = 0, immediate = true}, {mult = 0, chips = 0, chip_total = G.GAME.blind.cry_cap_score and G.GAME.blind:cry_cap_score(math.floor(hand_chips*mult)) or math.floor(hand_chips*mult), level = '', handname = ''});play_sound('button', 0.9, 0.6);return true end)"
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "ease_to = G.GAME.chips + math.floor(hand_chips*mult),"
position = "at"
payload = "ease_to = G.GAME.chips + (G.GAME.blind.cry_cap_score and G.GAME.blind:cry_cap_score(math.floor(hand_chips*mult)) or math.floor(hand_chips*mult)),"
match_indent = true
# Bunco (Magenta Dagger) and Cryptid (The Tax) compat
[[patches]]
[patches.pattern]
target = 'functions/state_events.lua'
pattern = "ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1),"
position = 'at'
match_indent = true
payload = '''ease_to = G.GAME.chips + (G.GAME.blind.cry_cap_score and G.GAME.blind:cry_cap_score(math.floor(hand_chips*mult)) or math.floor(hand_chips*mult)) * (e and e.antiscore and -1 or 1),'''
# Fix a crash related to undebuffing Jokers at end of round
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if not G.P_CENTERS['e_'..(self.edition.type)].discovered then"
position = "at"
payload = "if self.edition.type and G.P_CENTERS['e_'..(self.edition.type)] and not G.P_CENTERS['e_'..(self.edition.type)].discovered then"
match_indent = true
# Blocks hands with more than 5 cards with Psychic
[[patches]]
[patches.pattern]
target = "blind.lua"
pattern = "if self.debuff.h_size_ge and #cards < self.debuff.h_size_ge then"
position = "before"
payload = '''
if self.name == "The Psychic" and #cards > 5 then
self.triggered = true
return true
end
'''
match_indent = true
# Shut the up plz and ty
[[patches]]
[patches.pattern]
target = "blind.lua"
pattern = '''sendWarnMessage(("Blind object %s has debuff_card function, recalc_debuff is preferred"):format(obj.key), obj.set)'''
position = "at"
payload = '''
-- sendWarnMessage(("Blind object %s has debuff_card function, recalc_debuff is preferred"):format(obj.key), obj.set)
'''
match_indent = true
# track game overs by blinds on profiles
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '''local blind_choice = {config = G.GAME.blind.config.blind or G.P_BLINDS.bl_small}'''
position = "after"
payload = '''
local cry_defeated_by = blind_choice.config.name or "Small Blind"
if not G.PROFILES[G.SETTINGS.profile].cry_defeated_by_blind then G.PROFILES[G.SETTINGS.profile].cry_defeated_by_blind = {} end
G.PROFILES[G.SETTINGS.profile].cry_defeated_by_blind[cry_defeated_by] = (G.PROFILES[G.SETTINGS.profile].cry_defeated_by_blind[cry_defeated_by] or 0) + 1
check_for_unlock({ type = "lose_to_specific_blind", blind = cry_defeated_by, amount = G.PROFILES[G.SETTINGS.profile].cry_defeated_by_blind[cry_defeated_by] })
'''
match_indent = true

335
Cryptid/lovely/cat.toml Normal file
View file

@ -0,0 +1,335 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 1
# what in ze fuck am i cooking
[[patches]]
[patches.pattern]
target = "tag.lua"
pattern = '''tag_sprite.states.collide.can = true'''
position = "after"
payload = '''
if self.key == 'tag_cry_cat' then tag_sprite.states.click.can = true; tag_sprite.states.drag.can = true end
'''
match_indent = true
# m
[[patches]]
[patches.pattern]
target = "tag.lua"
pattern = '''tag_sprite.stop_hover = function(_self) _self.hovering = false; Node.stop_hover(_self); _self.hover_tilt = 0 end'''
position = "after"
payload = '''
tag_sprite.click = function(_self)
if self.key == 'tag_cry_cat' and self.HUD_tag then
for i = 1, #G.GAME.tags do
local other_cat = G.GAME.tags[i]
if other_cat.key == 'tag_cry_cat' then
if not self.ability.level then self.ability.level = 1 end
if not other_cat.ability.level then other_cat.ability.level = 1 end -- setting ability just doesn't seem to be working... so you get this
if (self.ability.level == other_cat.ability.level) and (other_cat ~= self) and not cry_too_fast_kitty then
cry_too_fast_kitty = true
local perc = (other_cat.ability.level + 1)/10
if perc > 1 then perc = 1 end
local edition = G.P_CENTER_POOLS.Edition[1]
local j = 1
while j < other_cat.ability.level + 1 do
for i = 2, #G.P_CENTER_POOLS.Edition do
j = j + 1
if j >= other_cat.ability.level + 1 then
edition = G.P_CENTER_POOLS.Edition[i]
break
end
end
end
G.E_MANAGER:add_event(Event({
delay = 0.0,
trigger = 'immediate',
func = (function()
attention_text({
text = ""..other_cat.ability.level,
colour = G.C.WHITE,
scale = 1,
hold = 0.3/G.SETTINGS.GAMESPEED,
cover = other_cat.HUD_tag,
cover_colour = G.C.DARK_EDITION,
align = 'cm',
})
play_sound('generic1', 0.8 + perc/2, 0.6)
play_sound('multhit1', 0.9 + perc/2, 0.4)
return true
end)
}))
G.E_MANAGER:add_event(Event({
delay = 0.0,
trigger = 'immediate',
func = (function()
attention_text({
text = "-",
colour = G.C.WHITE,
scale = 1,
hold = 0.3/G.SETTINGS.GAMESPEED,
cover = self.HUD_tag,
cover_colour = G.C.RED,
align = 'cm',
})
return true
end)
}))
G.E_MANAGER:add_event(Event({
func = (function()
self.HUD_tag.states.visible = false
return true
end)
}))
G.E_MANAGER:add_event(Event({ -- i have no idea what this does but i'm not messing with it
func = func
}))
other_cat.ability.level = other_cat.ability.level + 1
if self.ability.shiny then
if not Cryptid.shinytagdata[self.key] then
Cryptid.shinytagdata[self.key] = true
Cryptid.save()
end
end
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.7,
func = (function()
other_cat:juice_up(0.25, 0.1)
other_cat.ability.edshader = edition.shader
play_sound(edition.sound.sound, (edition.sound.per or 1)*1.3, (edition.sound.vol or 0.25)*0.6)
self:remove()
cry_too_fast_kitty = nil
return true
end)
}))
break
end
end
end
end
end
'''
match_indent = true
# tag_sprite draw
[[patches]]
[patches.pattern]
target = "tag.lua"
pattern = '''tag_sprite.stop_hover = function(_self) _self.hovering = false; Node.stop_hover(_self); _self.hover_tilt = 0 end'''
position = "after"
payload = '''
tag_sprite.draw = function(_self)
if not _self.states.visible then return end
_self.tilt_var = self.tilt_var or {mx = 0, my = 0, dx = _self.tilt_var.dx or 0, dy = _self.tilt_var.dy or 0, amt = 0}
_self.tilt_var.mx, _self.tilt_var.my = G.CONTROLLER.cursor_position.x, G.CONTROLLER.cursor_position.y
_self.tilt_var.amt = math.abs(_self.hover_offset.y + _self.hover_offset.x - 10)*0.3
_self.ARGS.send_to_shader = _self.ARGS.send_to_shader or {}
_self.ARGS.send_to_shader[1] = math.min(_self.VT.r*3, 1) + G.TIMERS.REAL/(28) + (_self.juice and _self.juice.r*10 or 0) + _self.tilt_var.amt
_self.ARGS.send_to_shader[2] = G.TIMERS.REAL*2
_self.tilt_var = _self.tilt_var or {}
_self.tilt_var.mx, _self.tilt_var.my =G.CONTROLLER.cursor_position.x,G.CONTROLLER.cursor_position.y
_self.role.draw_major = _self
_self:draw_shader('dissolve', 0.1)
local ed = _self.config.tag.ability.edshader
if ed then
if ed == 'foil' or ed == 'cry_noisy' then
_self:draw_shader('dissolve')
end
_self:draw_shader(ed, nil, _self.ARGS.send_to_shader)
if ed == 'negative' or ed == 'cry_oversat' then
_self:draw_shader('negative_shine', nil, _self.ARGS.send_to_shader)
end
else
_self:draw_shader('dissolve')
end
add_to_drawhash(_self)
end
'''
match_indent = true
# init tilt_var
[[patches]]
[patches.pattern]
target = "tag.lua"
pattern = '''tag_sprite.T.scale = 1'''
position = "before"
payload = '''
tag_sprite.tilt_var = {mx = 0, my = 0, dx = 0, dy = 0, amt = 0}
'''
match_indent = true
# make the cat tag meow (can probably do this without injecting?)
[[patches]]
[patches.pattern]
target = "tag.lua"
pattern = '''play_sound('tarot2', math.random()*0.1 + 0.55, 0.09)'''
position = "before"
payload = '''
if self.key == 'tag_cry_cat' and not self.hide_ability then
play_sound('cry_meow'..math.random(4), 1.26, 0.12);
end'''
match_indent = true
# shiny tags
[[patches]]
[patches.pattern]
target = "tag.lua"
pattern = '''local tag_sprite = Sprite(0,0,_size*1,_size*1,G.ASSET_ATLAS[(not self.hide_ability) and G.P_TAGS[self.key].atlas or "tags"], (self.hide_ability) and G.tag_undiscovered.pos or self.pos)'''
position = "at"
payload = '''
local tagatlas = G.ASSET_ATLAS[(not self.hide_ability) and G.P_TAGS[self.key].atlas or "tags"]
if self.ability.shiny and not self.hide_ability then
if not G.P_TAGS[self.key].atlas then
tagatlas = G.ASSET_ATLAS['cry_shinyv']
elseif G.P_TAGS[self.key].atlas == 'cry_tag_cry' then
tagatlas = G.ASSET_ATLAS['cry_shinyc']
end
end
local tag_sprite = Sprite(0,0,_size*1,_size*1,tagatlas, (self.hide_ability) and G.tag_undiscovered.pos or self.pos)
'''
match_indent = true
# collection
# nice pattern match?
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/overrides.lua"]'''
pattern = '''
opt_callback = 'your_collection_tags_page',
focus_args = { snap_to = true, nav = 'wide' },
current_option = page,
colour = G.C.RED,
no_pips = true
})
}
}'''
position = "after"
payload = '''
,
Cryptid.shinytag_tally() > 0 and create_toggle{ -- tally function runs way too often but whatever
label = localize('k_cry_shiny'),
w = 0,
ref_table = G,
ref_value = "showshinytags"
} or nil,
'''
match_indent = true
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/overrides.lua"]'''
pattern = '''
if not v.discovered then temp_tag.hide_ability = true end
'''
position = "before"
payload = '''
if G.showshinytags then
temp_tag.ability.shiny = true
if not Cryptid.shinytagdata[temp_tag.key] then
temp_tag.hide_ability = true
end
end
'''
match_indent = true
# i can't seem to get the tag page easily
# i'm also surprised this doesn't multipatch
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/overrides.lua"]'''
pattern = '''
local page = args.cycle_config.current_option or 1
'''
position = "at"
payload = '''
if args then G.cry_current_tagpage = args.cycle_config.current_option end
local page = args and args.cycle_config.current_option or G.cry_current_tagpage or 1
'''
match_indent = true
# update collection
# scuffed
[[patches]]
[patches.pattern]
target = '''game.lua'''
pattern = '''
self.E_MANAGER:update(self.real_dt)
'''
position = "before"
payload = '''
if not G.showshinytags then G.showshinytags = false end
if not G.showshinytags_b then G.showshinytags_b = false end
if G.showshinytags ~= G.showshinytags_b then
G.showshinytags_b = G.showshinytags
G.FUNCS.your_collection_tags_page()
end
'''
match_indent = true
# save+loading time
# cryptidsave stuff
[[patches]]
[patches.pattern]
target = '''game.lua'''
pattern = '''
if not love.filesystem.getInfo(G.SETTINGS.profile..'/'..'meta.jkr') then love.filesystem.append( G.SETTINGS.profile..'/'..'meta.jkr', 'return {}') end
'''
position = "after"
payload = '''
if not love.filesystem.getInfo(G.SETTINGS.profile..'/'..'cryptidsave.jkr') then love.filesystem.append( G.SETTINGS.profile..'/'..'cryptidsave.jkr', 'return {}') end
'''
match_indent = true
[[patches]]
[patches.pattern]
target = '''game.lua'''
pattern = '''
local meta = STR_UNPACK(get_compressed(G.SETTINGS.profile..'/'..'meta.jkr') or 'return {}')
'''
position = "after"
payload = '''
local cryptidsave = STR_UNPACK(get_compressed(G.SETTINGS.profile..'/'..'cryptidsave.jkr') or 'return {}')
if cryptidsave and cryptidsave.shinytags then
Cryptid.shinytagdata = copy_table(cryptidsave.shinytags)
else
-- populated later when tags actually exist
Cryptid.shinytagdata = {}
end
'''
match_indent = true
[[patches]]
[patches.pattern]
target = '''tag.lua'''
pattern = '''
function Tag:yep(message, _colour, func)
'''
position = "after"
payload = '''
if self.ability.shiny then
if not Cryptid.shinytagdata[self.key] then
Cryptid.shinytagdata[self.key] = true
Cryptid.save()
end
end
'''
match_indent = true

109
Cryptid/lovely/ccd.toml Normal file
View file

@ -0,0 +1,109 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# This is sacrilegious
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "self.GAME.starting_deck_size = #G.playing_cards"
position = "before"
payload = '''
if G.GAME.modifiers.cry_ccd then
for k, v in pairs(G.playing_cards) do
v:set_ability(Cryptid.random_consumable('cry_ccd',{"no_doe", "no_grc"}, nil, nil, true), true, nil)
end
end
'''
match_indent = true
# Aura use conditions
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if G.hand and (#G.hand.highlighted == 1) and G.hand.highlighted[1] and (not G.hand.highlighted[1].edition) then return true end"
position = "at"
payload = '''
if self.area ~= G.hand then
return G.hand and (#G.hand.highlighted == 1) and G.hand.highlighted[1] and (not G.hand.highlighted[1].edition)
else
local idx = 1
if G.hand.highlighted[1] == self then
local idx = 2
end
return (#G.hand.highlighted == 2) and (not G.hand.highlighted[idx].edition)
end
'''
match_indent = true
# Prevent counting CCD consumables for pack uses
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = "if area == G.consumeables then"
position = "at"
payload = "if area == G.consumeables or area == G.hand then"
match_indent = true
# Fix bugs from removing CCD
# This really shouldn't be in the card drawing code, but it doesn't really matter since that's where it crashes anyway lol
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if not self.config.center.discovered and (self.ability.consumeable or self.config.center.unlocked) and not self.config.center.demo and not self.bypass_discovery_center then"
position = "before"
payload = "if self.ability.set == 'Enhanced' then self.ability.consumeable = nil end"
match_indent = true
# ui, ui, ui
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '''name_from_rows(AUT.name, is_playing_card and G.C.WHITE or nil),'''
position = "at"
payload = '''
AUT.ccd and name_from_rows(AUT.ccd.name, G.C.WHITE) or nil,
AUT.ccd and desc_from_rows(AUT.ccd.main) or nil,
name_from_rows(AUT.name, is_playing_card and G.C.WHITE or nil),
'''
match_indent = true
# i love patching like five billion things
[[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, self)'''
position = "before"
payload = '''
if card_type ~= 'Default' and card_type ~= 'Enhanced' and self.playing_card then
loc_vars = loc_vars or {}
loc_vars.ccd = {
playing_card = not not self.base.colour, value = self.base.value, suit = self.base.suit, colour = self.base.colour,
nominal_chips = self.base.nominal > 0 and self.base.nominal or nil,
bonus_chips = (self.ability.bonus + (self.ability.perma_bonus or 0)) > 0 and (self.ability.bonus + (self.ability.perma_bonus or 0)) or nil,
}
end
'''
match_indent = true
# lalala ok this is a mess
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''local loc_vars = {}'''
position = "before"
payload = '''
if specific_vars and specific_vars.ccd then
full_UI_table.ccd = {name = {}, main = {}}
localize{type = 'other', key = 'playing_card', set = 'Other', nodes = full_UI_table.ccd.name, vars = {localize(specific_vars.ccd.value, 'ranks'), localize(specific_vars.ccd.suit, 'suits_plural'), colours = {specific_vars.ccd.colour}}}
full_UI_table.ccd.name = full_UI_table.ccd.name[1]
if specific_vars.ccd.nominal_chips then
localize{type = 'other', key = 'card_chips', nodes = full_UI_table.ccd.main, vars = {specific_vars.ccd.nominal_chips}}
end
if specific_vars.ccd.bonus_chips then
localize{type = 'other', key = 'card_extra_chips', nodes = full_UI_table.ccd.main, vars = {specific_vars.ccd.bonus_chips}}
end
end
'''
match_indent = true

View file

@ -0,0 +1,31 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Rush Hour - remove tags
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "if type == 'Small' then"
position = "at"
payload = "if type == 'Small' and not G.GAME.modifiers.cry_no_tags then"
match_indent = true
# Rush Hour - remove tags
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "elseif type == 'Big' then"
position = "at"
payload = "elseif type == 'Big' and not G.GAME.modifiers.cry_no_tags then"
match_indent = true
# Rush Hour - remove tags
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "elseif not run_info then"
position = "at"
payload = "elseif type == 'Boss' and not run_info then"
match_indent = true

384
Cryptid/lovely/code.toml Normal file
View file

@ -0,0 +1,384 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Code UI disables hold R shortcut
[[patches]]
[patches.pattern]
target = "engine/controller.lua"
pattern = 'if key == "r" and not G.SETTINGS.paused then'
position = "at"
payload = 'if key == "r" and not G.SETTINGS.paused and not (G.GAME and G.GAME.USING_CODE) then'
match_indent = true
# Payload - cash out UI
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "elseif config.name == 'interest' then"
position = "before"
payload = '''
elseif config.name == 'interest_payload' then
table.insert(left_text, {n=G.UIT.T, config={text = num_dollars, scale = 0.8*scale, colour = G.C.SECONDARY_SET.Code, shadow = true, juice = true}})
table.insert(left_text,{n=G.UIT.O, config={object = DynaText({string = {" "..localize{type = 'variable', key = 'interest', vars = {G.GAME.interest_amount*config.payload, 5, G.GAME.interest_amount*config.payload*G.GAME.interest_cap/5}}}, colours = {G.C.SECONDARY_SET.Code}, shadow = true, pop_in = 0, scale = 0.4*scale, silent = true})}})
'''
match_indent = true
# Payload - cash out
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "if G.GAME.dollars >= 5 and not G.GAME.modifiers.no_interest then"
position = "at"
payload = '''
if G.GAME.dollars >= 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
if G.GAME.interest_amount*math.min(math.floor(G.GAME.dollars/5), G.GAME.interest_cap/5) == G.GAME.interest_amount*G.GAME.interest_cap/5 then
G.PROFILES[G.SETTINGS.profile].career_stats.c_round_interest_cap_streak = G.PROFILES[G.SETTINGS.profile].career_stats.c_round_interest_cap_streak + 1
else
G.PROFILES[G.SETTINGS.profile].career_stats.c_round_interest_cap_streak = 0
end
end
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'''
match_indent = true
# Revert - fix a crash
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = "if area and area.cards[1] then"
position = "at"
payload = "if area and area.cards and area.cards[1] then"
match_indent = true
# Crash - use glitched shader
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "G.SHADERS['CRT']:send('glitch_intensity', 0)--0.1*G.SETTINGS.GRAPHICS.crt/100 + (G.screenwipe_amt) + 1)"
position = "at"
payload = "G.SHADERS['CRT']:send('glitch_intensity', glitched_intensity or 0)"
match_indent = true
# Semicolon - don't lose
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = '''G.RESET_JIGGLES = true'''
position = 'after'
match_indent = true
payload = '''
if G.GAME.current_round.semicolon then
game_over = false
end
'''
# Semicolon - end screen text
[[patches]]
[patches.regex]
target = "functions/common_events.lua"
pattern = '''localize\('ph_mr_bones'\)..' '\}, colours = \{G.C.FILTER'''
position = 'at'
# match_indent = true
line_prepend = ''
payload = '''(G.GAME.current_round.semicolon and ";" or localize('ph_mr_bones'))..' '}, colours = {(G.GAME.current_round.semicolon and G.C.SET.Code or G.C.FILTER)'''
# Semicolon - polished UI
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''{n=G.UIT.T, config={text = localize('b_cash_out')..": ", scale = 1, colour = G.C.UI.TEXT_LIGHT, shadow = true}},'''
position = "at"
payload = '''{n=G.UIT.T, config={text = G.GAME.current_round.semicolon and localize('k_end_blind') or (localize('b_cash_out')..": "), scale = 1, colour = G.C.UI.TEXT_LIGHT, shadow = true}},'''
match_indent = true
# Semicolon - polished UI
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''{n=G.UIT.T, config={text = localize('$')..config.dollars, scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}}'''
position = "at"
payload = '''{n=G.UIT.T, config={text = not G.GAME.current_round.semicolon and localize('$')..config.dollars or ';', scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}}'''
match_indent = true
# Semicolon - polished UI
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''{n=G.UIT.R, config={id = 'cash_out_button', align = "cm", padding = 0.1, minw = 7, r = 0.15, colour = G.C.ORANGE, shadow = true, hover = true, one_press = true, button = 'cash_out', focus_args = {snap_to = true}}, nodes={'''
position = "at"
payload = '''{n=G.UIT.R, config={id = 'cash_out_button', align = "cm", padding = 0.1, minw = 7, r = 0.15, colour = G.GAME.current_round.semicolon and G.C.SET.Code or G.C.ORANGE, shadow = true, hover = true, one_press = true, button = 'cash_out', focus_args = {snap_to = true}}, nodes={'''
match_indent = true
# Semicolon - reset value at start of round
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "G.GAME.blind:set_blind(G.GAME.round_resets.blind)"
position = "after"
payload = '''
G.GAME.current_round.semicolon = false
'''
match_indent = true
# Delete - placeholder booster, in the case that all are deleted
[[patches]]
[patches.regex]
target = "functions/common_events.lua"
pattern = '''return center\nend\n\nfunction get_current_pool\(_type, _rarity, _legendary, _append\)'''
position = "before"
payload = '''if not center then center = G.P_CENTERS['p_buffoon_normal_1'] end '''
# Delete - banished keys prevent pool stuff, guess we're going for this method after all
[[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 G.GAME.cry_banished_keys[v.key] then add = nil end'''
match_indent = true
# Delete - multiuse 1
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if card.area and (not nc or card.area == G.pack_cards) then card.area:remove_card(card) end'''
position = "before"
payload = '''
local cry_muse = false
if card.ability.cry_multiuse and not (card.ability.cry_multiuse <= 1) then
cry_muse = true
dont_dissolve = true
end
'''
match_indent = true
# Delete - multiuse 2
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if (prev_state == G.STATES.TAROT_PACK or prev_state == G.STATES.PLANET_PACK or'''
position = "before"
payload = '''
if cry_muse then
card.ability.cry_multiuse = card.ability.cry_multiuse - 1
card.ability.extra_value = -1 * math.max(1, math.floor(card.cost/2))
card:set_cost()
delay(0.4)
-- i make my own card eval status text :D
card:juice_up()
play_sound('generic1')
attention_text({
text = format_ui_value(card.ability.cry_multiuse),
scale = 1.1,
hold = 0.6,
major = card,
backdrop_colour = G.C.SECONDARY_SET[card.config.center.set],
align = 'bm',
offset = {x = 0, y = 0.2}
})
delay(0.8)
local _area = area ~= G.pack_cards and area or G.consumeables
draw_card(G.play, _area, 1, 'up', true, card, nil, true)
end
'''
match_indent = true
# Delete - init table to avoid headaches
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''ecto_minus = 1,'''
position = "after"
payload = '''
cry_banished_keys = {},
'''
match_indent = true
# Run - don't clear shop
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''if self.shop then self.shop:remove(); self.shop = nil end'''
position = "at"
payload = '''if self.shop and not G.GAME.USING_CODE then self.shop:remove(); self.shop = nil end'''
match_indent = true
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''ease_background_colour_blind(G.STATES.SHOP)'''
position = "at"
payload = '''if not G.GAME.USING_RUN then ease_background_colour_blind(G.STATES.SHOP) end'''
match_indent = true
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''if self.STATE == self.STATES.SELECTING_HAND then'''
position = "before"
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
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = '''G.FUNCS.draw_from_deck_to_hand = function(e)'''
position = "before"
payload = '''
G.FUNCS.draw_from_hand_to_run = function(e)
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"
pattern = '''G.shop.alignment.offset.y = -5.3'''
position = "at"
payload = '''if not G.shop then return true end
G.shop.alignment.offset.y = -5.3'''
match_indent = true
# Increase highlight limit for consumables
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "{card_limit = self.GAME.starting_params.consumable_slots, type = 'joker', highlight_limit = 1})"
position = "at"
payload = "{card_limit = self.GAME.starting_params.consumable_slots, type = 'joker', highlight_limit = 1e100})"
match_indent = true
# Increase highlight limit for jokers
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "{card_limit = self.GAME.starting_params.joker_slots, type = 'joker', highlight_limit = 1})"
position = "at"
payload = "{card_limit = self.GAME.starting_params.joker_slots, type = 'joker', highlight_limit = 1e100})"
match_indent = true
# Satellite Uplink
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''card = create_card("Planet", G.pack_cards, nil, nil, true, true, nil, 'pl1')'''
position = "at"
payload = '''
if G.GAME.used_vouchers.v_cry_satellite_uplink and pseudorandom('cry_satellite_uplink') > 0.8 then
card = create_card("Code", G.pack_cards, nil, nil, true, true, nil, 'pl2')
else
card = create_card("Planet", G.pack_cards, nil, nil, true, true, nil, 'pl1')
end
'''
match_indent = true
# Exploit - reset variables
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = '''-- TARGET: effects after hand evaluation'''
position = "after"
payload = '''
G.E_MANAGER:add_event(Event({
func = function()
G.GAME.cry_exploit_override = nil
return true
end
}))
'''
match_indent = true
# Exploit - patch into smods
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/overrides.lua"]'''
pattern = '''disp_text = text'''
position = "before"
payload = '''
text = G.GAME.cry_exploit_override or text
'''
match_indent = true
# Double Tag makes exact copy of rework tag
[[patches]]
[patches.pattern]
target = "tag.lua"
pattern = 'add_tag(Tag(_context.tag.key))'
position = "at"
payload = '''
local tag = Tag(_context.tag.key)
if _context.tag.key == "tag_cry_rework" then
tag.ability.rework_edition = _context.tag.ability.rework_edition
tag.ability.rework_key = _context.tag.ability.rework_key
end
add_tag(tag)
'''
match_indent = true

View file

@ -0,0 +1,29 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Conveyor Deck - Don't sort 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 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)"
position = "at"
payload = "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 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) end"
match_indent = true
# Start of round effects
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "G.GAME.blind:set_blind(G.GAME.round_resets.blind)"
position = "after"
payload = '''
if G.GAME.modifiers.cry_conveyor and #G.jokers.cards>0 then
local duplicated_joker = copy_card(G.jokers.cards[#G.jokers.cards])
duplicated_joker:add_to_deck()
G.jokers:emplace(duplicated_joker)
G.jokers.cards[1]:start_dissolve()
end
'''
match_indent = true

27
Cryptid/lovely/cube.toml Normal file
View file

@ -0,0 +1,27 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Joker Lock
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "elseif v.enhancement_gate then"
position = "before"
payload = '''
elseif v.source_gate then
if v.source_gate ~= _append then
add = nil
else
add = true
end
elseif v.joker_gate then
add = nil
for kk, vv in pairs(G.jokers.cards) do
if vv.ability.name == v.joker_gate then
add = true
end
end
'''
match_indent = true

View file

@ -0,0 +1,30 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# non-pack scaling in pack slots
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "G.shop_booster.T.y, G.CARD_W*1.27, G.CARD_H*1.27, G.P_CARDS.empty, G.P_CENTERS[G.GAME.current_round.used_packs[i]], {bypass_discovery_center = true, bypass_discovery_ui = true})"
position = "at"
payload = "G.shop_booster.T.y, G.CARD_W*(G.P_CENTERS[G.GAME.current_round.used_packs[i]].set == 'Booster' and 1.27 or 1), G.CARD_H*(G.P_CENTERS[G.GAME.current_round.used_packs[i]].set == 'Booster' and 1.27 or 1), G.P_CARDS.empty, G.P_CENTERS[G.GAME.current_round.used_packs[i]], {bypass_discovery_center = true, bypass_discovery_ui = true})"
match_indent = true
# scaling issues when reclaiming Overstock
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "G.GAME.shop.joker_max*1.02*G.CARD_W,"
position = "at"
payload = "math.min(G.GAME.shop.joker_max,4)*1.02*G.CARD_W,"
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "G.shop_jokers.T.w = G.GAME.shop.joker_max*1.01*G.CARD_W"
position = "at"
payload = "G.shop_jokers.T.w = math.min(G.GAME.shop.joker_max,4)*1.02*G.CARD_W"
match_indent = true

View file

@ -0,0 +1,199 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Turn Jimbo into Jolly Joker
[[patches]]
[patches.pattern]
target = "card_character.lua"
pattern = 'self.children.card.states.visible = false'
position = "before"
payload = "self.children.card:set_ability(G.P_CENTERS.j_jolly)"
match_indent = true
[[patches]]
[patches.pattern]
target = "card_character.lua"
pattern = 'colours = {G.C.RED, G.C.BLUE, G.C.ORANGE},'
position = "at"
payload = 'colours = {G.C.CRY_EXOTIC, G.C.BLUE, G.C.CRY_JOLLY},'
match_indent = true
# Make profiles all start with a prefix
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = 'self:load_profile(G.SETTINGS.profile or 1)'
position = "before"
payload = '''Cryptid.profile_prefix = Jen and "J" or "M"
if type(G.SETTINGS.profile) ~= "string" or G.SETTINGS.profile:sub(1, #Cryptid.profile_prefix) ~= Cryptid.profile_prefix then
G.SETTINGS.profile = Cryptid.profile_prefix .. "1"
end
for i = 1, 3 do
G.PROFILES[Cryptid.profile_prefix .. i] = {}
end'''
match_indent = true
# Remove the builtin "P" prefix
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = 'profile_data.name = profile_data.name or ("P".._profile)'
position = "at"
payload = 'profile_data.name = profile_data.name or (_profile)'
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = 'G.PROFILES[G.SETTINGS.profile].name = "P"..G.SETTINGS.profile'
position = "at"
payload = 'G.PROFILES[G.SETTINGS.profile].name = G.SETTINGS.profile'
match_indent = true
# Pre-load all profiles in selection menu
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = 'for i = 1, 3 do'
position = "after"
payload = 'i = Cryptid.profile_prefix .. i'
match_indent = true
# Gameset sprite in profile screen
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '{n=G.UIT.C, config={align = "cl", minw = rwidth}, nodes={{n=G.UIT.T, config={text = tostring(profile_data.career_stats.c_wins),colour = G.C.RED, shadow = true, scale = 1*scale}}}}'
position = "after"
payload = ',{n=G.UIT.C, config={align = "cl", minw = rwidth}, nodes={{n=G.UIT.O, config={object = Cryptid.gameset_sprite(1, _profile)}}}}'
match_indent = true
# Gameset sprite in deck select
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '{n=G.UIT.C, config={align = "cm", minw = 2.5}, nodes={}}'
position = "at"
payload = '{n=G.UIT.C, config={align = "cm", minw = 0.2}, nodes={}},{n=G.UIT.C, config={align = "cl", minw = rwidth}, nodes={{n=G.UIT.O, config={object = Cryptid.gameset_sprite()}}}}'
match_indent = true
# Gameset sprite in win screen
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '{n=G.UIT.R, config={align = "cm", minh = 0.4, minw = 0.1}, nodes={}},'
position = "at"
payload = '{n=G.UIT.R, config={align = "cm", minh = 0.1, minw = 0.1}, nodes={}},'
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = 'not show_win_cta and {n=G.UIT.R, config={align = "cm", minh = 0.2, minw = 0.1}, nodes={}} or nil,'
position = "at"
payload = 'not show_win_cta and {n=G.UIT.R, config={align = "cm", minh = 0.1, minw = 0.1}, nodes={}} or nil,'
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "not show_win_cta and UIBox_button({button = 'go_to_menu', label = {localize('b_main_menu')}, minw = 2.5, maxw = 2.5, minh = 1, focus_args = {nav = 'wide'}}) or nil,"
position = "after"
payload = '{n=G.UIT.R, config={align = "cm", minw = rwidth}, nodes={{n=G.UIT.O, config={object = Cryptid.gameset_sprite()}}}},'
match_indent = true
# Gameset sprite in lose screen
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "show_lose_cta and"
position = "before"
payload = '{n=G.UIT.R, config={align = "cm"}, nodes={{n=G.UIT.C, config={align = "cm", minw = rwidth}, nodes={{n=G.UIT.O, config={object = Cryptid.gameset_sprite()}}}},'
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "{n=G.UIT.T, config={text = localize('b_main_menu'), scale = 0.5, colour = G.C.UI.TEXT_LIGHT}}"
position = "after"
payload = '}}'
match_indent = true
[[patches]]
[patches.regex]
target = "functions/UI_definitions.lua"
pattern = '''\{n=G\.UIT\.R, config=\{align = "cm", padding = 0\.1\}, nodes=\{\s+\{n=G\.UIT\.R, config=\{id = 'from_game_over','''
position = "at"
payload = '''{n=G.UIT.C, config={align = "cm", padding = 0.1}, nodes={
{n=G.UIT.R, config={id = 'from_game_over','''
# Disabled UI
# Show disabled tooltip
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "local info_queue = {}"
position = "after"
payload = '''if _c.cry_disabled or (_c.force_gameset and _c.force_gameset == 'disabled') then
if _c.cry_disabled then
if _c.cry_disabled.type == "card_dependency" then
local name = Cryptid.get_center(_c.cry_disabled.key) and localize{type = 'name_text', set = Cryptid.get_center(_c.cry_disabled.key).set, key = _c.cry_disabled.key} or _c.cry_disabled.key
info_queue[#info_queue+1] = {key = 'disabled_card_dependency', set = 'Other', specific_vars = {name}}
elseif _c.cry_disabled.type == "mod_dependency" then
local name = Cryptid.cross_mod_names[_c.cry_disabled.key] or _c.cry_disabled.key
info_queue[#info_queue+1] = {key = 'disabled_mod_dependency', set = 'Other', specific_vars = {name}}
elseif _c.cry_disabled.type == "mod_conflict" then
local name = SMODS.Mods[_c.cry_disabled.key].name
info_queue[#info_queue+1] = {key = 'disabled_mod_conflict', set = 'Other', specific_vars = {name}}
else
if not (_c.force_gameset and _c.force_gameset ~= 'disabled') then
info_queue[#info_queue+1] = {key = 'disabled', set = 'Other'}
end
end
else
info_queue[#info_queue+1] = {key = 'disabled', set = 'Other'}
end
end'''
match_indent = true
# replace rarity badge with gameset
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "card_type = (debuffed and AUT.card_type ~= 'Enhanced') and localize('k_debuffed') or card_type"
position = "after"
payload = '''
if AUT.card_type == "Back" then
card_type = localize('b_deck')
end
if AUT.card_type == "Tag" then
card_type = localize('b_tag')
end
if AUT.card_type == "Blind" then
card_type = localize('b_blind')
end
if AUT.card_type == "Content Set" then
card_type = localize('k_content_set')
end
if card.gameset_select then
card_type = localize('cry_gameset_'..card.config.center.force_gameset)
if card_type == "ERROR" then
card_type = localize('cry_gameset_custom')
end
end
if not card.gameset_select and card.config.center and card.config.center.cry_disabled then
card_type = localize('cry_gameset_disabled')
end
'''
match_indent = true
# Descriptions for Backs and Blinds in gameset UI
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "elseif _c.set == 'Tag' then"
position = "before"
payload = "elseif _c.set == 'Back' or _c.set == 'Blind' then localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = specific_vars or {}}"
match_indent = true

View file

@ -0,0 +1,74 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# hi it's me toneblock and i'm being stupid again! (Game:update inject)
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''if G.FILE_HANDLER and G.FILE_HANDLER and G.FILE_HANDLER.update_queued and ('''
position = "before"
payload = '''
if not Cryptid.member_count_delay then Cryptid.member_count_delay = 0 end
if (Cryptid.member_count_delay > 5) or not Cryptid.member_count then -- it doesn't need to update this frequently? but it also doesn't need to be higher tbh...
if Cryptid.update_member_count then Cryptid.update_member_count() end -- i honestly hate nil checks like this, wish there was a shorthand
Cryptid.member_count_delay = 0
else
Cryptid.member_count_delay = Cryptid.member_count_delay + dt
end
'''
match_indent = true
# call Cryptid.update_member_count() whenever the collection is opened to ensure it updates properly on title collection if it can (better than running it on loc_vars)
# it's not computationally intense at all, so whatever
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''G.FUNCS.your_collection = function(e)'''
position = "after"
payload = '''
if Cryptid.update_member_count then Cryptid.update_member_count() end
'''
match_indent = true
# notice if https is disabled (by default)
# also does some other things since this is patching in the same spot (SDM0 easter egg)
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "if _c.set == 'Other' then"
position = "before"
payload = '''
if _c.name == 'cry-membershipcard' or _c.name == 'cry-membershipcardtwo' then
if not Cryptid_config["HTTPS Module"] then
if G.localization.descriptions.Other.cry_https_disabled then
main_end = {}
localize{type = 'other', key = 'cry_https_disabled', nodes = main_end, vars = {}}
main_end = main_end[1]
end
end
end
if _c.name == 'cry-translucent Joker' then
if G.jokers and G.jokers.cards then
for k, v in ipairs(G.jokers.cards) do
if (v.edition and v.edition.negative) and (G.localization.descriptions.Other.remove_negative)then
main_end = {}
localize{type = 'other', key = 'remove_negative', nodes = main_end, vars = {}}
main_end = main_end[1]
break
end
end
end
end
if _c.name == 'cry-blurred Joker' then
if (SMODS.Mods["sdm0sstuff"] or {}).can_load then
if G.localization.descriptions.Other.blurred_sdm0 then
main_end = {}
localize{type = 'other', key = 'blurred_sdm0', nodes = main_end, vars = {}}
main_end = main_end[1]
end
end
end
'''
match_indent = true

View file

@ -0,0 +1,259 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Make the splash screen more jolly
# Requires "Custom Main Menu" config to be enabled
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "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_joker'])"
position = "after"
payload = '''
if ((Cryptid_config and Cryptid_config.menu) or false) then
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
'''
match_indent = true
# Make cards in splash screen CCD cards
# Disabling this because it caused fps drops on profiles with nothing discovered
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "if math.random() > 0.8 then card.sprite_facing = 'back'; card.facing = 'back' end"
position = "before"
payload = '''
--if Cryptid.random_consumable then card:set_ability(Cryptid.random_consumable('cry_splash',{"no_grc"},nil,nil,true), true, nil) end
'''
match_indent = true
# Show Glitched Edition to confirm Cryptid is Active if custom main menu is enabled
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "replace_card.states.visible = false"
position = "before"
payload = '''
if ((Cryptid_config and Cryptid_config.menu) or false) then
replace_card:set_edition(G.P_CENTERS.e_cry_glitched and 'e_cry_glitched' or 'e_negative',true,true)
end
'''
match_indent = true
# Patch related crash
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if not initial then G.GAME.blind:debuff_card(self) end"
position = "at"
payload = "if not initial and G.GAME and G.GAME.blind then G.GAME.blind:debuff_card(self) end"
match_indent = true
# Draw midground layer
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.config.center.soul_pos and (self.config.center.discovered or self.bypass_discovery_center) then"
position = "after"
payload = '''
if self.config.center.soul_pos and self.config.center.soul_pos.extra and (self.config.center.discovered or self.bypass_discovery_center) then
local scale_mod = 0.07-- + 0.02*math.cos(1.8*G.TIMERS.REAL) + 0.00*math.cos((G.TIMERS.REAL - math.floor(G.TIMERS.REAL))*math.pi*14)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^3
local rotate_mod = 0--0.05*math.cos(1.219*G.TIMERS.REAL) + 0.00*math.cos((G.TIMERS.REAL)*math.pi*5)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^2
self.children.floating_sprite2:draw_shader('dissolve',0, nil, nil, self.children.center,scale_mod, rotate_mod,nil, 0.1--[[ + 0.03*math.cos(1.8*G.TIMERS.REAL)--]],nil, 0.6)
self.children.floating_sprite2:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod)
end
'''
match_indent = true
# Custom variables in info queue
[[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 = "after"
payload = "if _c.specific_vars then specific_vars = _c.specific_vars end"
match_indent = true
# Fix not all cards returning to hand on big hands
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "{card_limit = 500, type = 'discard'})"
position = "at"
payload = "{card_limit = 1e308, type = 'discard'})"
match_indent = true
# When hand size exceeds deck size, space the cards as if the hand size was equal to the deck size
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "function CardArea:align_cards()"
position = "after"
payload = '''
if self.config.type == 'hand' then
self.config.temp_limit = math.min(self.config.card_limit, #G.playing_cards)
end
'''
match_indent = true
# Crash fix
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = "if not G.SAVED_GAME.VERSION or G.SAVED_GAME.VERSION < '0.9.2' then"
position = "at"
payload = "if not G.SAVED_GAME or not G.SAVED_GAME.VERSION or G.SAVED_GAME.VERSION < '0.9.2' then"
match_indent = true
# Register banned bosses for rush hour
# Also initializes disabled/enabled cards
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "set_profile_progress()"
position = "before"
payload = '''
for i = 1, #G.CHALLENGES do
if (G.CHALLENGES[i].id == 'c_cry_rush_hour' or G.CHALLENGES[i].id == 'c_cry_rush_hour_ii' or G.CHALLENGES[i].id == 'c_cry_rush_hour_iii') and #G.CHALLENGES[i].restrictions.banned_other == 0 then
for k, v in pairs(G.P_BLINDS) do
if k ~= "bl_cry_clock" and k ~= "bl_cry_lavender_loop" and v.boss then
G.CHALLENGES[i].restrictions.banned_other[#G.CHALLENGES[i].restrictions.banned_other+1] = {id = k, type = 'blind'}
end
end
end
end
'''
match_indent = true
# Prevent Jokers from spitting empty messages
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "text = extra.message or text"
position = "after"
payload = "if not text or text == '' then return end"
match_indent = true
# Add default pool value for Consumeables
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = 'else _pool[#_pool + 1] = "j_joker"'
position = "before"
payload = '''elseif _type == 'Consumeables' then _pool[#_pool + 1] = "c_ceres"'''
match_indent = true
# hand size forgiveness if playing negative or antimatter deck (someone please fix)
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "function Game:update_draw_to_hand(dt)"
position = "after"
payload = '''
if G.GAME.selected_back and (G.GAME.selected_back.name == 'cry--Negative Deck' or G.GAME.selected_back.name == 'cry-Antimatter') and G.hand.config.card_limit <= 0 then -- 'cry--Negative Deck'... sure
G.hand.config.card_limit = 1
end
'''
match_indent = true
# init Cryptid global through lovely
# so other mods can add things to obj pools
# and define some stub functions so that the game does not immediately crash when talisman isn't loaded
[[patches]]
[patches.pattern]
target = "main.lua"
pattern = '''function love.load()'''
position = "before"
payload = '''
Cryptid = {}
Cryptid.aliases = {}
function cry_format(...)
return ...
end
-- These ones are deprecated, they do not do anything and are just here to prevent crashes
Cryptid.memepack = {}
Cryptid.food = {}
Cryptid.M_jokers = {}
Cryptid.Megavouchers = {}
'''
match_indent = true
# Adds cry_creating_card event
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''
check_for_unlock({type = 'have_edition'})
end
'''
position = "after"
payload = '''
SMODS.calculate_context{cry_creating_card = true, card = card}
'''
match_indent = true
# plural handler (annoyingly fragile overwrite)
# also i pass the whole vars here, even though it's inefficient, just because it looks better
# whatever
[[patches]]
[patches.pattern]
target = "functions/misc_functions.lua"
pattern = '''
assembled_string = assembled_string..(type(subpart) == 'string' and subpart or format_ui_value(args.vars[tonumber(subpart[1])]) or 'ERROR')
'''
position = "at"
payload = '''
assembled_string = assembled_string..(type(subpart) == 'string' and subpart or (Cryptid.pluralize and Cryptid.pluralize(subpart[1], args.vars)) or format_ui_value(args.vars[tonumber(subpart[1])]) or 'ERROR')
'''
match_indent = true
# prevent misprint crashing when big
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''
for i = self.ability.extra.min, self.ability.extra.max do
r_mults[#r_mults+1] = tostring(i)
end
'''
position = "at"
payload = '''
if self.ability.extra.max - self.ability.extra.min < 500 then
for i = self.ability.extra.min, self.ability.extra.max do
r_mults[#r_mults+1] = tostring(i)
end
else
for i = 1, 50 do
r_mults[#r_mults+1] = tostring(math.random(self.ability.extra.min, self.ability.extra.max))
end
end
'''
match_indent = true
# handle banned playing cards
# this must patch into pseudorandom_element to not break Steamodded in_pool logic
[[patches]]
[patches.pattern]
target = "functions/misc_functions.lua"
pattern = "if keep then"
position = "before"
payload = '''
if G.GAME and G.GAME.cry_banned_pcards and G.GAME.cry_banned_pcards[k] then
keep = false
end
'''
match_indent = true
# Cross-Mod Content - allow Cryptid to load atlas/sound/shader files from other mods
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/game_object.lua"]'''
pattern = "self.full_path = (self.mod and self.mod.path or SMODS.path) .."
position = "at"
payload = "self.full_path = (self.mod_path or self.mod and self.mod.path or SMODS.path) .."
match_indent = true

View file

@ -0,0 +1,127 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Apply booster pack edition and stickers to contents - by Jen Walter
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "card.T.x = self.T.x"
position = "before"
payload = '''
local edi = self.edition or {}
if edi.type then
if card.ability.name ~= "cry-meteor"
and card.ability.name ~= "cry-exoplanet"
and card.ability.name ~= "cry-stardust" then
card:set_edition({[edi.type] = true})
end
end
local stickers = {'eternal', 'perishable', 'rental', 'banana'}
for _, v in ipairs(stickers) do
if self.ability[v] then
card.ability[v] = self.ability[v]
end
end
'''
match_indent = true
# save ability (to deal with re-misprinting)
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "G.vouchers:emplace(card_to_save)"
position = "before"
payload = '''
card_to_save.ability.extra = self and self.ability.extra or card_to_save.ability.extra
'''
match_indent = true
# patch for stickers in challenge ui
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "if v.eternal then card:set_eternal(true) end"
position = "before"
payload = '''
if v.stickers then
for i, _v in ipairs(v.stickers) do
SMODS.Stickers[_v]:apply(card, true)
end
end
'''
match_indent = true
# same deal for actual game
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "if v.eternal then _joker:set_eternal(true) end"
position = "before"
payload = '''
if v.stickers then
for i, _v in ipairs(v.stickers) do
SMODS.Stickers[_v]:apply(_joker, true)
end
end
'''
match_indent = true
# remove eternal badge
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.eternal then badges[#badges + 1] = 'eternal' end"
position = "at"
payload = '''
if not self.ability.cry_absolute then
if self.ability.eternal then badges[#badges + 1] = 'eternal' end
end
'''
match_indent = true
# remove old pinned badge
# i am fully aware that these badge removals may break stuff since they are good targets
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.pinned then badges[#badges + 1] = 'pinned_left' end"
position = "at"
payload = '''
-- if self.pinned then badges[#badges + 1] = 'pinned_left' end
'''
match_indent = true
# don't draw old perishable texture
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''if self.ability.perishable then'''
position = "at"
payload = '''if self.ability.perishable and not layer then'''
match_indent = true
# Adds cry_debuff_immune card modifier
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = 'if self.ability and self.ability.perma_debuff then self.debuff = true end'
position = "after"
payload = '''
if self.cry_debuff_immune then
self.debuff = false
end
'''
match_indent = true
# Removes cry_debuff_immune at the end of the round
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/utils.lua"]'''
pattern = '-- TARGET: effects after end of round evaluation'
position = "after"
payload = '''
card.cry_debuff_immune = false
'''
match_indent = true

101
Cryptid/lovely/lib_ui.toml Normal file
View file

@ -0,0 +1,101 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Antimatter Deck
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/card_draw.lua"]'''
pattern = "self.children.back:draw_shader('dissolve')"
position = "at"
payload = '''
local currentBack = self.params.viewed_back and G.GAME.viewed_back or G.GAME.selected_back
if currentBack and currentBack.effect.config.cry_antimatter or currentBack.effect.config.cry_force_edition == 'negative' then
self.children.back:draw_shader('negative', nil, self.ARGS.send_to_shader)
self.children.center:draw_shader('negative_shine', nil, self.ARGS.send_to_shader)
else
self.children.back:draw_shader('dissolve')
end
'''
match_indent = true
# render gameset as sticker
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/card_draw.lua"]'''
pattern = "if self.sticker and G.shared_stickers[self.sticker] then"
position = "before"
payload = '''
if not Cryptid.shared_gamesets and G.ASSET_ATLAS["cry_gameset"] then
Cryptid.shared_gamesets = {
modest = Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS["cry_gameset"], {x = 0,y = 0}),
mainline = Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS["cry_gameset"], {x = 1,y = 0}),
madness = Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS["cry_gameset"], {x = 2,y = 0}),
custom = Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS["cry_gameset"], {x = 3,y = 0}),
selected = Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS["cry_sticker"], {x = 0,y = 4}),
}
end
local gameset_key
if self.config.center.force_gameset then
gameset_key = self.config.center.force_gameset
if gameset_key ~= "disabled" and gameset_key ~= "modest" and gameset_key ~= "mainline" and gameset_key ~= "madness" then
gameset_key = "custom"
end
end
if self.gameset_select and Cryptid.shared_gamesets[gameset_key] then
Cryptid.shared_gamesets[gameset_key].role.draw_major = self
Cryptid.shared_gamesets[gameset_key]:draw_shader('dissolve', nil, nil, nil, self.children.center)
Cryptid.shared_gamesets[gameset_key]:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center)
end
'''
match_indent = true
# make disabled cards visually debuffed
# warning: this also patches a lot of extra stuff, but that shouldn't matter
# since you shouldn't be able to access them outside of the collection anyway
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/card_draw.lua"]'''
pattern = "if self.debuff then"
position = "at"
payload = "if self.debuff or (Cryptid.gameset and Cryptid.gameset(self) == 'disabled') or (self.config.center.gameset_config and self.config.center.gameset_config[Cryptid.gameset(self)] and self.config.center.gameset_config[Cryptid.gameset(self)].disabled) or (self.config.center.cry_disabled and not self.gameset_select) then"
match_indent = true
# Shine on Oversaturated to make it more noticable
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/card_draw.lua"]'''
pattern = "if (self.edition and self.edition.negative) or (self.ability.name == 'Antimatter' and (self.config.center.discovered or self.bypass_discovery_center)) then"
position = 'at'
match_indent = true
payload = "if (self.edition and (self.edition.negative or self.edition.cry_oversat)) or (self.ability.name == 'Antimatter' and (self.config.center.discovered or self.bypass_discovery_center)) then"
# Make description UI always appear if card is highlighted
[[patches]]
[patches.pattern]
target = "engine/node.lua"
pattern = "if self.children.h_popup then"
position = 'at'
match_indent = true
payload = '''
if self.children.h_popup and not (self.force_popup and self:force_popup() and Cryptid["force_tooltips"]) then
'''
# Let description tooltips work for any object
[[patches]]
[patches.pattern]
target = "functions/misc_functions.lua"
pattern = "detailed_tooltip = part.control.T and (G.P_CENTERS[part.control.T] or G.P_TAGS[part.control.T]) or nil,"
position = 'at'
match_indent = true
payload = "detailed_tooltip = part.control.T and (Cryptid.get_center(part.control.T) or (G.P_CENTERS[part.control.T] or G.P_TAGS[part.control.T])) or nil,"
# Remove consumable use UI in the collection
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.highlighted and self.area and self.area.config.type ~= 'shop' then"
position = 'at'
match_indent = true
payload = "if self.highlighted and self.area and self.area.config.type ~= 'shop' and not self.area.config.collection then"

494
Cryptid/lovely/misc.toml Normal file
View file

@ -0,0 +1,494 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Detect if edition comes from copy_card
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = '''new_card:set_edition(other.edition or {}, nil, true)'''
position = 'before'
payload = '''
new_card.from_copy = true
'''
match_indent = true
# Update value of Monsters created via copy_card
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = "if not strip_edition then"
position = 'before'
payload = '''
if new_card.ability.name == "cry-longboi" then new_card:set_ability(new_card.config.center) end
'''
match_indent = true
# Joker BigNum value support
[[patches]]
[patches.pattern]
target = "card.lua"
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"
position = "at"
payload = '''
if self.ability.name == 'Campfire' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and to_big(self.ability.x_mult) > to_big(1) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Hit the Road' and self.ability.x_mult > 1 then"
position = "at"
payload = '''
if self.ability.name == 'Hit the Road' and to_big(self.ability.x_mult) > to_big(1) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.x_mult > 1 then"
position = "at"
payload = '''
if to_big(self.ability.x_mult) > to_big(1) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name ~= 'Seeing Double' and self.ability.x_mult > 1 and (self.ability.type == '' or next(context.poker_hands[self.ability.type])) then"
position = "at"
payload = '''
if self.ability.name ~= 'Seeing Double' and to_big(self.ability.x_mult) > to_big(1) and (self.ability.type == '' or next(context.poker_hands[self.ability.type])) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Caino' and self.ability.caino_xmult > 1 then"
position = "at"
payload = '''
if self.ability.name == 'Caino' and to_big(self.ability.caino_xmult) > to_big(1) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.t_mult > 0 and next(context.poker_hands[self.ability.type]) then"
position = "at"
payload = '''
if to_big(self.ability.t_mult) > to_big(0) and next(context.poker_hands[self.ability.type]) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.t_chips > 0 and next(context.poker_hands[self.ability.type]) then"
position = "at"
payload = '''
if to_big(self.ability.t_chips) > to_big(0) and next(context.poker_hands[self.ability.type]) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Ceremonial Dagger' and self.ability.mult > 0 then"
position = "at"
payload = '''
if self.ability.name == 'Ceremonial Dagger' and to_big(self.ability.mult) > to_big(0) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Castle' and (self.ability.extra.chips > 0) then"
position = "at"
payload = '''
if self.ability.name == 'Castle' and (to_big(self.ability.extra.chips) > to_big(0)) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Swashbuckler' and self.ability.mult > 0 then"
position = "at"
payload = '''
if self.ability.name == 'Swashbuckler' and to_big(self.ability.mult) > to_big(0) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Spare Trousers' and self.ability.mult > 0 then"
position = "at"
payload = '''
if self.ability.name == 'Spare Trousers' and to_big(self.ability.mult) > to_big(0) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Ride the Bus' and self.ability.mult > 0 then"
position = "at"
payload = '''
if self.ability.name == 'Ride the Bus' and to_big(self.ability.mult) > to_big(0) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Flash Card' and self.ability.mult > 0 then"
position = "at"
payload = '''
if self.ability.name == 'Flash Card' and to_big(self.ability.mult) > to_big(0) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Popcorn' and self.ability.mult > 0 then"
position = "at"
payload = '''
if self.ability.name == 'Popcorn' and to_big(self.ability.mult) > to_big(0) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Green Joker' and self.ability.mult > 0 then"
position = "at"
payload = '''
if self.ability.name == 'Green Joker' and to_big(self.ability.mult) > to_big(0) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Red Card' and self.ability.mult > 0 then"
position = "at"
payload = '''
if self.ability.name == 'Red Card' and to_big(self.ability.mult) > to_big(0) then
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/misc_functions.lua"
pattern = "function localize(args, misc_cat)"
position = "after"
payload = '''
if args and args.vars then
local reset = {}
for i, j in pairs(args.vars) do
if type(j) == 'table' then
if (j.new and type(j.new) == "function") and ((j.m and j.e) or (j.array and j.sign and (type(j.array) == "table"))) then
reset[i] = number_format(j)
end
end
end
for i, j in pairs(reset) do
args.vars[i] = j
end
end
'''
match_indent = true
# Compat UI for Old Blueprint and Gemini
# I deleted the patches --Jevonn (test)
# calculate wheel fail (for Wheel of Hope)
[[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 = "after"
payload = '''
if self.ability.name == 'The Wheel of Fortune' then self.cry_wheel_success = true end
'''
match_indent = false
# no "Again!" text if a card will shatter
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = '''if reps[j] ~= 1 then'''
position = "at"
payload = '''if reps[j] ~= 1 and (not scoring_hand or not scoring_hand[i] or not scoring_hand[i].will_shatter) then'''
match_indent = true
# m
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''if self.ability.consumeable or self.ability.set == 'Joker' or (self.area and self.area == G.pack_cards) then'''
position = "at"
payload = '''if true then'''
match_indent = true
# Energia - detect blind skips from tag
# kitty printer - add cat tag
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''add_tag(_tag.config.ref_table)'''
position = "at"
payload = '''
add_tag( next(SMODS.find_card('j_cry_kittyprinter')) and Tag('tag_cry_cat') or _tag.config.ref_table, true)
'''
match_indent = true
# Energia - don't add tags from save load
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''add_tag(_tag)'''
position = "at"
payload = '''add_tag(_tag, nil, true)'''
match_indent = true
# Beta Deck - merge slots
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''self.consumeables = CardArea('''
position = "before"
payload = '''if not G.GAME.modifiers.cry_beta then'''
match_indent = true
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''self.discard = CardArea('''
position = "before"
payload = '''else
self.jokers = CardArea(
0, 0,
CAI.joker_W+CAI.consumeable_W,
CAI.joker_H,
{card_limit = self.GAME.starting_params.joker_slots+self.GAME.starting_params.consumable_slots-1, type = 'joker', highlight_limit = 1e100})
self.consumeables = self.jokers
end'''
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''G.consumeables.T.y = 0'''
position = "after"
payload = '''G.jokers.T.x = G.hand.T.x - 0.1
G.jokers.T.y = 0'''
match_indent = true
# Make Perkeo only copy consumables
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''if G.consumeables.cards[1] then'''
position = "at"
payload = '''local eligibleJokers = {}
for i = 1, #G.consumeables.cards do
if G.consumeables.cards[i].ability.consumeable then
eligibleJokers[#eligibleJokers + 1] = G.consumeables.cards[i]
end
end
if #eligibleJokers > 0 then'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''local card = copy_card(pseudorandom_element(G.consumeables.cards, pseudoseed('perkeo')), nil)'''
position = "at"
payload = '''local card = copy_card(pseudorandom_element(eligibleJokers, pseudoseed('perkeo')), nil)'''
match_indent = true
# More Beta Deck fixes
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = '''for i=1, #G.jokers.cards + #G.consumeables.cards do'''
position = "at"
payload = '''
local numcards = #G.jokers.cards + #G.consumeables.cards
if G.GAME.modifiers.cry_beta then numcards = #G.jokers.cards end
for i=1, numcards do'''
match_indent = true
# Poker Hand display can have enhancements
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '''local card = Card(0,0, 0.5*G.CARD_W, 0.5*G.CARD_H, G.P_CARDS[v[1]], G.P_CENTERS.c_base)'''
position = "at"
payload = '''local card = Card(0,0, 0.5*G.CARD_W, 0.5*G.CARD_H, G.P_CARDS[v[1]], G.P_CENTERS[v[3] or 'c_base'])'''
match_indent = true
# Adds G.GAME.modifiers.cry_forced_draw_amount
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "if G.GAME.blind.name == 'The Serpent' and"
position = "before"
payload = '''
if G.GAME.modifiers.cry_forced_draw_amount and (G.GAME.current_round.hands_played > 0 or G.GAME.current_round.discards_used > 0) then
hand_space = math.min(#G.deck.cards, G.GAME.modifiers.cry_forced_draw_amount)
end
'''
match_indent = true
# adds oldbp blueprint corruption
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = 'if _pool_size == 0 then'
position = "before"
payload = '''
if G.GAME.oldbpfactor and G.GAME.oldbpfactor >= 2 then
if _type == 'Joker' and (_rarity == nil or type(_rarity) ~= "string") and not _legendary and not (G.GAME.used_jokers["j_blueprint"] and not next(find_joker("Showman"))) then
for i = 1, math.floor(G.GAME.oldbpfactor - 1) do
_pool[#_pool + 1] = "j_blueprint"
end
end
end
'''
match_indent = true
# end of shop decrement
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = 'G.SHOP_SIGN.alignment.offset.y = -15'
position = "after"
payload = '''
if G.GAME.oldbpfactor then G.GAME.oldbpfactor = math.max(G.GAME.oldbpfactor - G.GAME.oldbpfactor/8, 1) end
'''
match_indent = true
# Make Loopy reset here so it retriggers everything before resetting regardless of position
# Makes Old Blueprint self-destruct after triggering other end of round effects
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = '''if G.GAME.round_resets.temp_reroll_cost then G.GAME.round_resets.temp_reroll_cost = nil; calculate_reroll_cost(true) end'''
position = "after"
payload = '''
for _, v in pairs(find_joker("cry-loopy")) do
if v.ability.extra.retrigger ~= 0 then
v.ability.extra.retrigger = 0
card_eval_status_text(v, 'extra', nil, nil, nil, {message = localize("k_reset"), colour = G.C.GREEN})
end
end
SMODS.calculate_context{end_of_round2 = true}
'''
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
# kitty printer 2 (for some reason i can't figure out how to not create another object here)
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "local _tag = Tag(G.GAME.round_resets.blind_tags[blind_choice], nil, blind_choice)"
position = "after"
payload = '''
if next(SMODS.find_card('j_cry_kittyprinter')) then
_tag = Tag('tag_cry_cat', nil, blind_choice)
end
'''
match_indent = true
# avoids a game-locking crash related to opened booster being nil
# remove this as soon as a fix is done
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "SMODS.OPENED_BOOSTER.config.center:update_pack(dt)"
position = "at"
payload = '''
if not SMODS.OPENED_BOOSTER then
G.STATE = G.STATES.SHOP
print('Error: SMODS.OPENED_BOOSTER is nil. Game recovered by setting game state to shop.')
else
SMODS.OPENED_BOOSTER.config.center:update_pack(dt)
end
'''
match_indent = true
# Created cards match suits of suit deck
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "card.playing_card = G.playing_card"
position = "after"
payload = '''
if G.GAME.modifiers.cry_force_suit then card:change_suit(G.GAME.modifiers.cry_force_suit) end
if G.GAME.modifiers.cry_force_enhancement then card:set_ability(G.P_CENTERS[G.GAME.modifiers.cry_force_enhancement]) end
if G.GAME.modifiers.cry_force_edition then card:set_edition({[G.GAME.modifiers.cry_force_edition]=true},true,true) end
if G.GAME.modifiers.cry_force_seal then card:set_seal(G.GAME.modifiers.cry_force_seal) end
'''
match_indent = true
# Remove G.cry_edeck_select on back
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = "G.FUNCS.setup_run = function(e)"
position = "after"
payload = '''
G.cry_edeck_select = nil
'''
match_indent = true
# Remove G.cry_edeck_select on escape key press
[[patches]]
[patches.pattern]
target = "engine/controller.lua"
pattern = '''if key == "escape" then'''
position = "after"
payload = '''
G.cry_edeck_select = nil
'''
match_indent = true
# Make vanilla edition tags Nope! if all jokers in shop have editions
[[patches]]
[patches.pattern]
target = "tag.lua"
pattern = "local _applied = nil"
position = "after"
payload = '''
if Cryptid.forced_edition() then self:nope() end
'''
match_indent = true

View file

@ -0,0 +1,22 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# LeBaron James - Calculate Steel effects when played
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "if context.cardarea == G.hand and context.main_scoring then"
position = "at"
payload = "if (context.cardarea == G.hand or context.cardarea == G.play and next(SMODS.find_card('j_cry_lebaron_james')) and Cryptid.safe_get(SMODS.Ranks,Cryptid.safe_get(card,'base','value') or 'm','key') == 'King') and context.main_scoring then"
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "ret.playing_card = {}"
position = "at"
payload = "ret.playing_card = ret.playing_card or {}"
match_indent = true

View file

@ -0,0 +1,504 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Randomize poker hands after RNG is set up
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "self.GAME.pseudorandom.hashed_seed = pseudohash(self.GAME.pseudorandom.seed)"
position = "after"
payload = '''
if G.GAME.modifiers.cry_misprint_min and not args.savetext then
for k, v in pairs(G.GAME.hands) do
v.chips = to_big(cry_format(v.chips * Cryptid.log_random(pseudoseed('cry_misprint'),G.GAME.modifiers.cry_misprint_min,G.GAME.modifiers.cry_misprint_max),"%.2g"))
v.mult = to_big(cry_format(v.mult * Cryptid.log_random(pseudoseed('cry_misprint'),G.GAME.modifiers.cry_misprint_min,G.GAME.modifiers.cry_misprint_max),"%.2g"))
v.l_chips = cry_format(v.l_chips * Cryptid.log_random(pseudoseed('cry_misprint'),G.GAME.modifiers.cry_misprint_min,G.GAME.modifiers.cry_misprint_max),"%.2g")
v.l_mult = cry_format(v.l_mult * Cryptid.log_random(pseudoseed('cry_misprint'),G.GAME.modifiers.cry_misprint_min,G.GAME.modifiers.cry_misprint_max),"%.2g")
v.s_chips = v.chips
v.s_mult = v.mult
end
end
'''
match_indent = true
# Packs
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "create_shop_card_ui(card, 'Booster', G.shop_booster)"
position = "before"
payload = '''
Cryptid.misprintize(card)
'''
match_indent = true
# Prevent pack softlocks
# Off by One Error effect
# Booster Tag effect
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "G.GAME.pack_choices = self.ability.choose or 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
self.ability.extra = G.GAME.pack_size
G.GAME.pack_choices = math.min(math.floor(G.GAME.pack_size), self.ability.choose)
--G.GAME.pack_choices = math.min(math.floor(G.GAME.pack_size),cry_format(G.GAME.pack_choices * Cryptid.log_random(pseudoseed('cry_misprint_p'..G.GAME.round_resets.ante),G.GAME.modifiers.cry_misprint_min,G.GAME.modifiers.cry_misprint_max),"%.2f"))
end
if G.GAME.cry_oboe then
self.ability.extra = self.ability.extra + G.GAME.cry_oboe
G.GAME.pack_choices = G.GAME.pack_choices + G.GAME.cry_oboe
G.GAME.cry_oboe = nil
end
if G.GAME.boostertag and G.GAME.boostertag > 0 then
self.ability.extra = self.ability.extra * 2
G.GAME.pack_choices = G.GAME.pack_choices * 2
G.GAME.boostertag = math.max(0, G.GAME.boostertag - 1)
end
self.ability.extra = math.min(self.ability.extra, 1000)
G.GAME.pack_choices = math.min(G.GAME.pack_choices, 1000)
G.GAME.pack_size = self.ability.extra
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name:find('Arcana') then"
position = "before"
payload = '''
if self.ability.extra < 1 then self.ability.extra = 1 end
'''
match_indent = true
# Vouchers
[[patches]]
[patches.pattern]
target = '''=[SMODS _ "src/utils.lua"]'''
pattern = "create_shop_card_ui(card, 'Voucher', G.shop_vouchers)"
position = "before"
payload = '''
Cryptid.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
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "tag.lua"
pattern = "create_shop_card_ui(card, 'Voucher', G.shop_vouchers)"
position = "before"
payload = '''
Cryptid.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
'''
match_indent = true
# Fractional Ante Bugs
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "G.GAME.round_resets.ante = G.GAME.round_resets.ante + mod"
position = "after"
payload = "G.GAME.round_resets.ante = Big and (to_number(math.floor(to_big(G.GAME.round_resets.ante)))) or math.floor(G.GAME.round_resets.ante)"
match_indent = true
# UI Bugs
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "_size*G.CARD_W,"
position = "at"
payload = "math.max(1,math.min(_size,5))*G.CARD_W,"
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "_size*G.CARD_W*1.1,"
position = "at"
payload = "math.max(1,math.min(_size,5))*G.CARD_W*1.1,"
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "_size*G.CARD_W*1.1 + 0.5,"
position = "at"
payload = "math.max(1,math.min(_size,5))*G.CARD_W*1.1 + 0.5,"
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "{card_limit = _size, type = 'consumeable', highlight_limit = 1})"
position = "at"
payload = "{card_limit = math.max(1,_size), type = 'consumeable', highlight_limit = 1})"
match_indent = true
# Death and a CCD Patch
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.consumeable.mod_num >= #G.hand.highlighted and #G.hand.highlighted >= (self.ability.consumeable.min_highlighted or 1) then"
position = "at"
payload = "if (self.ability.consumeable.mod_num - ((G.GAME.modifiers.cry_consumable_reduce and (self.ability.name ~= 'Death')) and (self.ability.consumeable.mod_num > 1) and 1 or 0)) >= #G.hand.highlighted + (self.area == G.hand and -1 or 0) and #G.hand.highlighted + (self.area == G.hand and -1 or 0) >= 1 then"
match_indent = true
# mod_num has no limit
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "self.ability.consumeable.mod_num = math.min(5, self.ability.consumeable.max_highlighted)"
position = "at"
payload = "self.ability.consumeable.mod_num = self.ability.consumeable.max_highlighted"
match_indent = true
# Infinite Deck
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "self.config.highlighted_limit = config.highlight_limit or 5"
position = "at"
payload = "self.config.highlighted_limit = config.highlight_limit or G.GAME.modifiers.cry_highlight_limit or 5"
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = "if #G.hand.highlighted <= 0 or G.GAME.blind.block_play or #G.hand.highlighted > 5 then"
position = "at"
payload = "if #G.hand.highlighted <= (G.GAME.stamp_mod and 1 or 0) or G.GAME.blind.block_play then"
match_indent = true
# Hieroglyph
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "ease_ante(-center_table.extra)"
position = "at"
payload = "ease_ante(math.floor(-center_table.extra))"
match_indent = true
# Get Cryptid to display and work with card selections
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "elseif _c.name == 'Cryptid' then loc_vars = {cfg.extra}"
position = "at"
payload = '''elseif _c.name == 'Cryptid' then loc_vars = {cfg.extra, cfg.max_highlighted}
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = 'local _card = copy_card(G.hand.highlighted[1], nil, nil, G.playing_card)'
position = "at"
payload = '''
for q = 1, #G.hand.highlighted do
local _card = copy_card(G.hand.highlighted[q], nil, nil, G.playing_card)
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "new_cards[#new_cards+1] = _card"
position = "after"
payload = "end"
match_indent = true
# Get seal spectrals to display and work with card selections
[[patches]]
[patches.regex]
target = "functions/common_events.lua"
pattern = '''
(?<indent>[\t ]*)elseif _c\.set == 'Spectral' then '''
position = 'after'
# match_indent = true
line_prepend = '$indent '
payload = '''
if _c.name == 'Talisman' or _c.name == 'Medium' or _c.name == 'Trance' or _c.name == 'Deja Vu' then
loc_vars = {cfg.max_highlighted}
end
'''
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = 'local conv_card = G.hand.highlighted[1]'
position = "at"
payload = '''
for q = 1, #G.hand.highlighted do
local conv_card = G.hand.highlighted[q]
G.E_MANAGER:add_event(Event({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()
conv_card:set_seal(self.ability.extra, nil, true)
return true end }))
end
delay(0.5)
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2,func = function() G.hand:unhighlight_all(); return true end }))
end--[[
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Aura' then"
position = "before"
payload = "--]]"
match_indent = true
# Fractional pricing
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "self.cost = math.max(1, math.floor((self.base_cost + self.extra_cost + 0.5)*(100-G.GAME.discount_percent)/100))"
position = "after"
payload = '''
if self.ability.set == 'Joker' then
self.cost = cry_format(self.cost * G.GAME.cry_shop_joker_price_modifier,'%.2f') end
if self.misprint_cost_fac then
self.cost = cry_format(self.cost * self.misprint_cost_fac,'%.2f')
if not G.GAME.modifiers.cry_misprint_min then self.cost = math.floor(self.cost) end end
'''
match_indent = true
# the d in disp stands for disparity (match internal values to display values)
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "function Card:apply_to_run(center)"
position = "after"
payload = '''
if (self and self.ability and self.ability.extra_disp) then -- redeeming through centers isn't misprinted
local self_disp = self.ability.extra_disp
local orig_disp = self.config.center.config.extra_disp
local self_extra = self.ability.extra
local orig_extra = self.config.center.config.extra
local new_fac = self_disp / orig_disp
self.ability.extra = new_fac*orig_extra
end
'''
match_indent = true
# I LOVE HARDCODING
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "G.hand:change_size(1)"
position = "at"
payload = '''
G.hand:change_size(center_table.extra)
'''
match_indent = true
# YOU LOVE HARDCODING
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "change_shop_size(1)"
position = "at"
payload = '''
change_shop_size(center_table.extra)
'''
match_indent = true
# WE ALL LOVE HARDCODING
[[patches]]
[patches.regex]
target = "card.lua"
pattern = '''if center_table\.name \=\= 'Antimatter' then\n\s+G\.E_MANAGER\:add_event\(Event\(\{func = function\(\)\n\s+if G\.jokers then \n\s+G\.jokers\.config\.card_limit \= G\.jokers\.config\.card_limit \+ 1\n\s+end\n\s+return true end \}\)\)\n\s+end'''
position = "at"
payload = '''
if center_table.name == 'Antimatter' then
G.E_MANAGER:add_event(Event({func = function()
if G.jokers then
G.jokers.config.card_limit = G.jokers.config.card_limit + center_table.extra
end
return true end }))
end
'''
# AAAA
[[patches]]
[patches.regex]
target = "card.lua"
pattern = '''if center_table\.name \=\= 'Crystal Ball' then\n\s+G\.E_MANAGER:add_event\(Event\(\{func \= function\(\)\n\s+G\.consumeables\.config\.card_limit \= G.consumeables\.config\.card_limit \+ 1\n\s+return true end }\)\)\n\s+end'''
position = "at"
payload = '''
if center_table.name == 'Crystal Ball' then
G.E_MANAGER:add_event(Event({func = function()
G.consumeables.config.card_limit = G.consumeables.config.card_limit + center_table.extra
return true end }))
end
'''
# anyway how's your day going?
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''elseif _c.name == "Clearance Sale" or _c.name == "Liquidation" then loc_vars = {cfg.extra}'''
position = "after"
payload = '''
elseif _c.name == "Crystal Ball" or _c.name == "Omen Globe" then loc_vars = {cfg.extra}
'''
match_indent = true
# doing pretty good myself
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''if _c.name == "Overstock" or _c.name == 'Overstock Plus' then'''
position = "at"
payload = '''
if _c.name == "Overstock" or _c.name == "Overstock Plus" then loc_vars = {cfg.extra}
'''
match_indent = true
# spent the whole day reviving misprinted vouchers
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''elseif _c.name == "Blank" or _c.name == "Antimatter" then'''
position = "at"
payload = '''
elseif _c.name == "Blank" or _c.name == "Antimatter" then loc_vars = {cfg.extra}
'''
match_indent = true
# but whatever, not like i was doing anything anyway
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = '''UIBox_button({label = {localize('b_reroll_boss'), localize('$')..'10'}, button = "reroll_boss", func = 'reroll_boss_button'}) or nil'''
position = "at"
payload = '''
UIBox_button({label = {localize('b_reroll_boss'), localize('$')..Cryptid.cheapest_boss_reroll()}, button = "reroll_boss", func = 'reroll_boss_button'}) or nil
'''
match_indent = true
# worth it in the end ig, it was bugging me
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if ((G.GAME.dollars-G.GAME.bankrupt_at) - 10 >= 0) and'''
position = "at"
payload = '''
if ((to_big(G.GAME.dollars)-to_big(G.GAME.bankrupt_at)) - to_big(Cryptid.cheapest_boss_reroll()) >= to_big(0)) and
'''
match_indent = true
# see you around
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if not G.from_boss_tag then ease_dollars(-10) end'''
position = "at"
payload = '''
if not G.from_boss_tag then ease_dollars(-Cryptid.cheapest_boss_reroll()) end
'''
match_indent = true
# hi i'm back and i'm fixing this thing that breaks sometimes for no reason (it really shouldn't)
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''v_overstock_norm = {order = 1, discovered = false, unlocked = true , available = true, cost = 10, name = "Overstock", pos = {x=0,y=0}, set = "Voucher", config = {}},'''
position = "at"
payload = '''
v_overstock_norm = {order = 1, discovered = false, unlocked = true , available = true, cost = 10, name = "Overstock", pos = {x=0,y=0}, set = "Voucher", config = {extra = 1}},
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''v_crystal_ball= {order = 9, discovered = false, unlocked = true , available = true, cost = 10, name = "Crystal Ball", pos = {x=2,y=2}, set = "Voucher", config = {extra = 3}},'''
position = "at"
payload = '''
v_crystal_ball= {order = 9, discovered = false, unlocked = true , available = true, cost = 10, name = "Crystal Ball", pos = {x=2,y=2}, set = "Voucher", config = {extra = 1}},
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''v_overstock_plus= {order = 2, discovered = false, unlocked = false, available = true, cost = 10, name = "Overstock Plus", pos = {x=0,y=1}, set = "Voucher", config = {}, requires = {'v_overstock_norm'},unlock_condition = {type = 'c_shop_dollars_spent', extra = 2500}},'''
position = "at"
payload = '''
v_overstock_plus= {order = 2, discovered = false, unlocked = false, available = true, cost = 10, name = "Overstock Plus", pos = {x=0,y=1}, set = "Voucher", config = {extra = 1}, requires = {'v_overstock_norm'},unlock_condition = {type = 'c_shop_dollars_spent', extra = 2500}},
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''v_antimatter= {order = 24, discovered = false, unlocked = false, available = true, cost = 10, name = "Antimatter", pos = {x=7,y=1}, set = "Voucher", config = {extra = 15}, requires = {'v_blank'},unlock_condition = {type = 'blank_redeems', extra = 10}},'''
position = "at"
payload = '''
v_antimatter= {order = 24, discovered = false, unlocked = false, available = true, cost = 10, name = "Antimatter", pos = {x=7,y=1}, set = "Voucher", config = {extra = 1}, requires = {'v_blank'},unlock_condition = {type = 'blank_redeems', extra = 10}},
'''
match_indent = true
# whyyyyyyyyy
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''G.GAME.tarot_rate = 4*center_table.extra'''
position = "at"
payload = '''
G.GAME.tarot_rate = G.GAME.tarot_rate*center_table.extra
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''G.GAME.planet_rate = 4*center_table.extra'''
position = "at"
payload = '''
G.GAME.planet_rate = G.GAME.planet_rate*center_table.extra
'''
match_indent = true
# keep vanilla rates by modifying tycoons
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''v_tarot_tycoon= {order = 18, discovered = false, unlocked = false, available = true,cost = 10, name = "Tarot Tycoon", pos = {x=1,y=1}, set = "Voucher", config = {extra = 32/4, extra_disp = 4}, requires = {'v_tarot_merchant'},unlock_condition = {type = 'c_tarots_bought', extra = 50}},'''
position = "at"
payload = '''
v_tarot_tycoon= {order = 18, discovered = false, unlocked = false, available = true,cost = 10, name = "Tarot Tycoon", pos = {x=1,y=1}, set = "Voucher", config = {extra = 32/9.6, extra_disp = 4}, requires = {'v_tarot_merchant'},unlock_condition = {type = 'c_tarots_bought', extra = 50}},
'''
match_indent = true
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''v_planet_tycoon= {order = 20, discovered = false, unlocked = false, available = true,cost = 10, name = "Planet Tycoon", pos = {x=2,y=1}, set = "Voucher", config = {extra = 32/4, extra_disp = 4}, requires = {'v_planet_merchant'},unlock_condition = {type = 'c_planets_bought', extra = 50}},'''
position = "at"
payload = '''
v_planet_tycoon= {order = 20, discovered = false, unlocked = false, available = true,cost = 10, name = "Planet Tycoon", pos = {x=2,y=1}, set = "Voucher", config = {extra = 32/9.6, extra_disp = 4}, requires = {'v_planet_merchant'},unlock_condition = {type = 'c_planets_bought', extra = 50}},
'''
match_indent = true

View file

@ -0,0 +1,27 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Lapio softlock mechanic
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "if (not v.config.softlock or G.GAME.hands[v.config.hand_type].played > 0) then"
position = "at"
payload = '''
local softlocked = true
if not v.config.softlock then
softlocked = false
elseif v.config.hand_type then
softlocked = G.GAME.hands[v.config.hand_type].played == 0
elseif v.config.hand_types then
for _, h in pairs(v.config.hand_types) do
if G.GAME.hands[h].played > 0 then
softlocked = false
end
end
end
if not softlocked then
'''
match_indent = true

20
Cryptid/lovely/seal.toml Normal file
View file

@ -0,0 +1,20 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 10
# Call Card:calculate_seal() with destroying_card context
[[patches]]
[patches.regex]
target = "functions/state_events.lua"
pattern = '(?<indent>[\t ]*)if destroyed then \n'
position = 'before'
line_prepend = '$indent'
payload = '''
if scoring_hand[i]:calculate_seal({destroying_card = scoring_hand[i], full_hand = G.play.cards}) and not scoring_hand[i].ability.eternal then
destroyed = true
end
'''

View file

@ -0,0 +1,60 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 10
# Haunted House - useless skips
[[patches]]
[patches.regex]
target = "functions/button_callbacks.lua"
pattern = 'if _tag then'
position = 'at'
line_prepend = '$indent'
payload = '''if _tag and not G.GAME.events.ev_cry_choco2 then'''
# Please Take One jank
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''ease_background_colour_blind(G.STATES.ROUND_EVAL)'''
position = "after"
payload = '''if G.GAME.events.ev_cry_choco6 and G.round_eval then return true end'''
match_indent = true
# Revered Antique - create legendary
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''if G.load_shop_booster then'''
position = "before"
payload = '''
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')
Cryptid.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
# hackfix for flickering thing
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''if not card then'''
position = "at"
payload = '''
if cfg and not card then
'''
match_indent = true

476
Cryptid/lovely/stake.toml Normal file
View file

@ -0,0 +1,476 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Yellow Stake - perishable and rental effects on consumable
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "if G.GAME.round_resets.ante == G.GAME.win_ante and G.GAME.blind:get_type() == 'Boss' then"
position = "before"
payload = '''
local i = 1
while i <= #G.jokers.cards do
local gone = G.jokers.cards[i]:calculate_banana()
if not gone then i = i + 1 end
end
'''
match_indent = true
# Yellow Stake - perishable and rental effects on cards held in hand
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "local effects = {[1] = {playing_card = G.hand.cards[i]:get_end_of_round_effect()}}"
position = "after"
payload = '''
-- these are already calculated
-- does mean this patch is pointless now, but i want to leave it here just so it's clear, maybe remove later
-- G.hand.cards[i]:calculate_rental()
-- G.hand.cards[i]:calculate_perishable()
'''
match_indent = true
# Yellow Stake - perishable and rental effects on cards in deck and discard pile
# Double Down
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "G.FUNCS.draw_from_hand_to_discard()"
position = "before"
payload = '''
local i = 1
while i <= #G.hand.cards do
local gone = G.hand.cards[i]:calculate_banana()
if not gone then i = i + 1 end
end
for i = 1, #G.discard.cards do
G.discard.cards[i]:calculate_perishable()
end
i = 1
while i <= #G.deck.cards do
G.deck.cards[i]:calculate_perishable()
local gone = G.deck.cards[i]:calculate_banana()
if not gone then i = i + 1 end
end
if G.GAME.used_vouchers.v_cry_double_down then
local function update_dbl(area)
for i = 1, #area.cards do
if area.cards[i].dbl_side then
--tweak to do deck effects with on the flip side
Cryptid.misprintize(area.cards[i].dbl_side, {min = 1.5, max = 1.5}, nil, true)
card_eval_status_text(area.cards[i], "extra", nil, nil, nil, { message = localize("k_upgrade_ex") })
end
end
end
update_dbl(G.jokers)
update_dbl(G.consumeables)
update_dbl(G.hand)
update_dbl(G.discard)
update_dbl(G.deck)
end
'''
match_indent = true
# Yellow Stake - Hanged Man can't be used on Eternal cards, Death can't remove Eternal
[[patches]]
[patches.pattern]
target = "card.lua"
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"
position = "before"
payload = '''
if self.ability.name == "The Hanged Man" then
for i = 1, #G.hand.highlighted do
if G.hand.highlighted[i].ability.eternal then return false end
end
end
if self.ability.name == "Death" then
local rightmost = G.hand.highlighted[1]
for i=1, #G.hand.highlighted-1 do if G.hand.highlighted[i].T.x > rightmost.T.x then rightmost = G.hand.highlighted[i] end end
for i=1, #G.hand.highlighted do if G.hand.highlighted[i].ability.eternal and rightmost ~= G.hand.highlighted[i] then return false end end
end
'''
match_indent = true
# Yellow Stake - Immolate can't be used on Eternal cards
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "for k, v in ipairs(G.hand.cards) do temp_hand[#temp_hand+1] = v end"
position = "at"
payload = '''
for k, v in ipairs(G.hand.cards) do
if not v.ability.eternal then
temp_hand[#temp_hand+1] = v
end
end
'''
match_indent = true
# Yellow Stake - Death can't modify Eternal cards (redundant, but may help if Death can be used on more cards)
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if G.hand.highlighted[i] ~= rightmost then"
position = "at"
payload = "if G.hand.highlighted[i] ~= rightmost and not G.hand.highlighted[i].ability.eternal then"
match_indent = true
# Yellow Stake - Trading Card can't destroy Eternals
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "G.GAME.current_round.discards_used <= 0 and #context.full_hand == 1 then"
position = "at"
payload = "G.GAME.current_round.discards_used <= 0 and #context.full_hand == 1 and not context.other_card.ability.eternal then"
match_indent = true
# Yellow Stake - Sixth Sense can't destroy Eternals
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Sixth Sense' and #context.full_hand == 1 and context.full_hand[1]:get_id() == 6 and G.GAME.current_round.hands_played == 0 then"
position = "at"
payload = "if self.ability.name == 'Sixth Sense' and #context.full_hand == 1 and context.full_hand[1]:get_id() == 6 and not context.full_hand[1].ability.eternal and G.GAME.current_round.hands_played == 0 then"
match_indent = true
# Yellow Stake - enhancement tarots don't remove stickers
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "perma_bonus = self.ability and self.ability.perma_bonus or 0,"
position = "after"
payload = '''
eternal = self.ability and self.ability.eternal,
perishable = self.ability and self.ability.perishable,
perish_tally = self.ability and self.ability.perish_tally,
rental = self.ability and self.ability.rental,
'''
match_indent = true
# Amber Stake - edit number of booster packs
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "for i = 1, 2 do"
position = "at"
payload = "for i = 1, G.GAME.modifiers.cry_no_boosters and 0 or G.GAME.modifiers.cry_booster_packs or 2 do"
match_indent = true
# Quartz Stake - pinned effect applies in every type of slot
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 < b.T.x + b.T.w/2 end)"
position = "at"
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)"
match_indent = true
# Quartz Stake - render pinned sticker
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "elseif self.sprite_facing == 'back' then"
position = "before"
payload = '''
if self.pinned then
G.shared_stickers['pinned'].role.draw_major = self
G.shared_stickers['pinned']:draw_shader('dissolve', nil, nil, nil, self.children.center)
G.shared_stickers['pinned']:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center)
end
'''
match_indent = true
# Ruby Stake - big blind bosses
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "self.GAME.round_resets.blind_choices.Boss = get_new_boss()"
position = "before"
payload = '''
if G.GAME.modifiers.cry_big_boss_rate and pseudorandom('cry_big_boss') < G.GAME.modifiers.cry_big_boss_rate then
self.GAME.round_resets.blind_choices.Big = get_new_boss()
elseif G.GAME.modifiers.cry_rush_hour_ii then
self.GAME.round_resets.blind_choices.Small = get_new_boss()
self.GAME.round_resets.blind_choices.Big = get_new_boss()
else
self.GAME.round_resets.blind_choices.Big = 'bl_big'
end
'''
match_indent = true
# Ruby Stake - big blind bosses
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "G.GAME.round_resets.blind_choices.Boss = get_new_boss()"
position = "before"
payload = '''
if G.GAME.modifiers.cry_big_boss_rate and pseudorandom('cry_big_boss') < G.GAME.modifiers.cry_big_boss_rate then
G.GAME.round_resets.blind_choices.Big = get_new_boss()
elseif G.GAME.modifiers.cry_rush_hour_ii then
G.GAME.round_resets.blind_choices.Small = get_new_boss()
G.GAME.round_resets.blind_choices.Big = get_new_boss()
else
G.GAME.round_resets.blind_choices.Big = 'bl_big'
end
'''
match_indent = true
# Ruby Stake - big blind doesn't increase ante
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "if G.GAME.blind:get_type() == 'Boss' then"
position = "at"
payload = "if G.GAME.blind_on_deck == 'Boss' then"
match_indent = true
# Ruby Stake - smaller showdown blinds don't win
# Win on any ante above win_ante
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "if G.GAME.round_resets.ante == G.GAME.win_ante and G.GAME.blind:get_type() == 'Boss' then"
position = "at"
payload = "if G.GAME.round_resets.ante >= G.GAME.win_ante and G.GAME.blind_on_deck == 'Boss' then"
match_indent = true
# Rush Hour - mark small blind as defeated
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "if G.GAME.round_resets.blind == G.P_BLINDS.bl_small then"
position = "at"
payload = "if G.GAME.blind_on_deck == 'Small' then"
match_indent = true
# Ruby Stake - mark big blind as defeated
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "elseif G.GAME.round_resets.blind == G.P_BLINDS.bl_big then"
position = "at"
payload = "elseif G.GAME.blind_on_deck == 'Big' then"
match_indent = true
# Sapphire Stake - ante tax
# The Joke boss effect
# Save game state for Revert
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "delay(0.4); ease_ante(1); delay(0.4); check_for_unlock({type = 'ante_up', ante = G.GAME.round_resets.ante + 1})"
position = "at"
payload = "delay(0.4); ease_ante(G.GAME.blind and G.GAME.blind:cry_calc_ante_gain() or 1); Cryptid.apply_ante_tax(); delay(0.4); check_for_unlock({type = 'ante_up', ante = G.GAME.round_resets.ante + 1})"
match_indent = true
# Emerald Stake - Permanently flipped cards
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "if card.facing == 'back' and self.config.type ~= 'discard' and self.config.type ~= 'deck' and not stay_flipped then"
position = "at"
payload = '''if card.cry_flipped then card.facing = 'back'; card.sprite_facing = 'back' end
if not (card.cry_flipped and (self == G.shop_jokers or self == G.shop_vouchers or self == G.shop_booster)) and card.facing == 'back' and self.config.type ~= 'discard' and self.config.type ~= 'deck' and not stay_flipped then'''
match_indent = true
# Emerald Stake - flipped packs
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "create_shop_card_ui(card, 'Booster', G.shop_booster)"
position = "before"
payload = '''
if G.GAME.modifiers.cry_enable_flipped_in_shop and pseudorandom('cry_flip_pack'..G.GAME.round_resets.ante) > 0.7 then
card.cry_flipped = true
end'''
match_indent = true
# Emerald Stake - flipped vouchers
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "create_shop_card_ui(card, 'Voucher', G.shop_vouchers)"
position = "before"
payload = '''
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'''
match_indent = true
# Platinum Stake - start with big blind ready to be selected
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "G.GAME.blind_on_deck = 'Small'"
position = "at"
payload = "G.GAME.blind_on_deck = G.GAME.modifiers.cry_no_small_blind and 'Big' or 'Small'"
match_indent = true
# Platinum Stake - start with big blind ready to be selected
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "G.GAME.blind_on_deck = 'Small'"
position = "at"
payload = "G.GAME.blind_on_deck = G.GAME.modifiers.cry_no_small_blind and 'Big' or 'Small'"
match_indent = true
# Platinum Stake - hide Small Blind
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "G.GAME.round_resets.blind_states.Small = 'Upcoming'"
position = "at"
payload = "G.GAME.round_resets.blind_states.Small = G.GAME.modifiers.cry_no_small_blind and 'Hide' or 'Upcoming'"
match_indent = true
# Ember Stake - grant no money on sell
# this is NOT ember stake grant no money on sell wtf
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then'''
position = "at"
payload = '''elseif v.boss.showdown and (((G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2) or G.GAME.modifiers.cry_big_showdown ) then'''
match_indent = true
# Ember Stake - give no money for selling
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''ease_dollars(self.sell_cost)'''
position = "at"
payload = '''if (not G.GAME.modifiers.cry_no_sell_value) and self.sell_cost ~= 0 then
ease_dollars(self.sell_cost)
end'''
match_indent = true
# Ember Stake - don't play coin sound
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''play_sound('coin2')'''
position = "at"
payload = '''if (not G.GAME.modifiers.cry_no_sell_value) and self.sell_cost ~= 0 then
play_sound('coin2')
end'''
match_indent = true
# Ember Stake - red dissolve for swag points
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''self:start_dissolve({G.C.GOLD})'''
position = "at"
payload = '''if G.GAME.modifiers.cry_no_sell_value or self.sell_cost == 0 then
self:start_dissolve({G.C.RED})
else
self:start_dissolve({G.C.GOLD})
end'''
match_indent = true
# Ember Stake - remove sell price visually
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''self.sell_cost_label = self.facing == 'back' and '?' or self.sell_cost'''
position = "at"
payload = '''self.sell_cost_label = (self.facing == 'back' and '?') or (G.GAME.modifiers.cry_no_sell_value and 0) or self.sell_cost'''
match_indent = true
# Dawn Stake - change maximum allowed highlights (i have no idea what this code is meant to be doing?? whatever it is, it doesn't seem to be working -toneblock)
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''local cfg = (card and card.ability) or _c['config']'''
position = "after"
payload = '''if cfg and G.GAME.modifiers.cry_consumable_reduce and cfg.max_highlighted and (cfg.max_highlighted > 1) then
local new_table = {}
for i0, j0 in pairs(cfg) do
new_table[i0] = j0
end
new_table.max_highlighted = new_table.max_highlighted - 1
cfg = new_table
end'''
match_indent = true
# Horizon Stake - create random card at start of blind
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = '''G.GAME.blind:set_blind(G.GAME.round_resets.blind)'''
position = "after"
payload = '''if G.GAME.modifiers.cry_card_each_round then
G.E_MANAGER:add_event(Event({
func = function()
local front = pseudorandom_element(G.P_CARDS, pseudoseed('cry_horizon'))
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
local edition = G.P_CENTERS.c_base
local card = 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})
card:start_materialize()
if G.GAME.selected_back.effect.config.cry_force_edition and G.GAME.selected_back.effect.config.cry_force_edition ~= "random" then
local edition = {}
edition[G.GAME.selected_back.effect.config.cry_force_edition] = true
card:set_edition(edition, true, true);
end
G.play:emplace(card)
table.insert(G.playing_cards, card)
playing_card_joker_effects({true})
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'''
match_indent = true
# Blossom Stake - showdown blinds before the winning ante
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = '''elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then'''
position = "at"
payload = '''elseif v.boss.showdown and (((G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2) or G.GAME.modifiers.cry_big_showdown ) then'''
match_indent = true
# inject into vanilla calculate_perishable to prevent nil index bug (i don't know where it fails so i'm just patching every part of it...)
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''if self.ability.perishable and self.ability.perish_tally > 0 then'''
position = "before"
payload = '''if self.ability.perishable and not self.ability.perish_tally then self.ability.perish_tally = G.GAME.perishable_rounds end'''
match_indent = true
# again in set_debuff
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''if self.ability.perishable and self.ability.perish_tally <= 0 then'''
position = "before"
payload = '''if self.ability.perishable and not self.ability.perish_tally then self.ability.perish_tally = G.GAME.perishable_rounds end'''
match_indent = true

156
Cryptid/lovely/sticker.toml Normal file
View file

@ -0,0 +1,156 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# initiate variables
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "rental_rate = 3,"
position = "after"
payload = '''
cry_voucher_perishable_rounds = 8,
cry_voucher_rental_rate = 2,
cry_consumeable_rental_rate = 2,
cry_voucher_banana_odds = 12,
cry_consumeable_banana_odds = 4,
cry_pinned_consumeables = 0,
cry_shop_joker_price_modifier = 1,
'''
match_indent = true
# check for pinned
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "G.GAME.current_round.voucher = get_next_voucher_key()"
position = "at"
payload = '''
if G.GAME.current_round.cry_voucher_stickers.pinned == false then
G.GAME.current_round.voucher = get_next_voucher_key()
end
'''
match_indent = true
# remove stickers if voucher is redeemed
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "self:apply_to_run()"
position = "before"
payload = '''
G.GAME.current_round.cry_voucher_edition = nil
G.GAME.current_round.cry_voucher_stickers = {eternal = false, perishable = false, rental = false, pinned = false, banana = false}
'''
match_indent = true
# consumeable sticker checking
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "local used_tarot = copier or self"
position = "after"
payload = '''
if self.ability.rental then
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
blocking = false,
blockable = false,
func = (function()
ease_dollars(-G.GAME.cry_consumeable_rental_rate)
return true
end)}))
end
local gone = false
if self.ability.banana then
if not self.ability.extinct then
if (pseudorandom('oops_it_banana') < G.GAME.probabilities.normal/G.GAME.cry_consumeable_banana_odds) then
local gone = true
self.ability.extinct = true
G.E_MANAGER:add_event(Event({
func = function()
play_sound('tarot1')
self.T.r = -0.2
self:juice_up(0.3, 0.4)
self.states.drag.is = true
self.children.center.pinch.x = true
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false,
func = function()
if self.area then self.area:remove_card(self) end
self:remove()
self = nil
return true; end}))
return true
end
}))
card_eval_status_text(self, 'jokers', nil, nil, nil, {message = localize('k_extinct_ex'), delay = 0.1})
return true
end
end
end
if gone == false then
'''
match_indent = true
# end the wrap
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "function Card:can_use_consumeable(any_state, skip_check)"
position = "before"
payload = '''
end
'''
match_indent = true
# check for pinned
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if G.STATE ~= G.STATES.HAND_PLAYED and G.STATE ~= G.STATES.DRAW_TO_HAND and G.STATE ~= G.STATES.PLAY_TAROT or any_state then"
position = "before"
payload = '''
if G.GAME.cry_pinned_consumeables > 0 and not self.pinned then
return false
end
'''
match_indent = true
# pinned consumeable remove, counterpart is in cryptid's create_card
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.queue_negative_removal then"
position = "before"
payload = '''
if self.ability.consumeable and self.pinned and (G.GAME.cry_pinned_consumeables > 0) then
G.GAME.cry_pinned_consumeables = G.GAME.cry_pinned_consumeables - 1
end
'''
match_indent = true
# rental jank
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.rental then self.cost = 1 end"
position = "at"
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
# apply stickers to packs
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "card.ability.booster_pos = i"
position = "before"
payload = '''
local stickers = Cryptid.next_voucher_stickers(true) -- don't mind the name
for k, v in pairs(stickers) do
card.ability[k] = v
end
'''
match_indent = true

View file

@ -0,0 +1,44 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Level up modifier
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "amount = amount or 1"
position = "after"
payload = "if not next(find_joker('cry-Universum')) then"
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "G.GAME.hands[hand].mult = math.max(G.GAME.hands[hand].s_mult + G.GAME.hands[hand].l_mult*(G.GAME.hands[hand].level - 1), 1)"
position = "at"
payload = "G.GAME.hands[hand].mult = math.max(G.GAME.hands[hand].mult + G.GAME.hands[hand].l_mult*amount, 1)"
match_indent = true
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "G.GAME.hands[hand].chips = math.max(G.GAME.hands[hand].s_chips + G.GAME.hands[hand].l_chips*(G.GAME.hands[hand].level - 1), 0)"
position = "at"
payload = '''
G.GAME.hands[hand].chips = math.max(G.GAME.hands[hand].chips + G.GAME.hands[hand].l_chips*amount, 1)
else
universum_mod = 1
local effects = {}
SMODS.calculate_context({cry_universum = true}, effects)
for i = 1, #effects do
universum_mod = universum_mod * (effects[i] and effects[i].jokers and effects[i].jokers.mod or 1)
end
G.GAME.hands[hand].level = math.max(0, G.GAME.hands[hand].level + 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
'''
match_indent = true

View file

@ -0,0 +1,61 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -1
# Remove voucher at start of run (also for Crimson Stake)
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "self.GAME.current_round.voucher = G.SETTINGS.tutorial_progress and G.SETTINGS.tutorial_progress.forced_voucher or SMODS.get_next_vouchers()"
position = "after"
payload = '''
if self.GAME.modifiers.cry_no_vouchers then
very_fair_quip = pseudorandom_element(G.localization.misc.very_fair_quips, pseudoseed("cry_very_fair"))
end
'''
match_indent = true
# Remove voucher when defeating boss (also for Crimson Stake)
[[patches]]
[patches.pattern]
target = "functions/state_events.lua"
pattern = "G.GAME.current_round.voucher = SMODS.get_next_vouchers()"
position = "after"
payload = '''
if G.GAME.modifiers.cry_no_vouchers then
very_fair_quip = pseudorandom_element(G.localization.misc.very_fair_quips, pseudoseed("cry_very_fair"))
end
'''
match_indent = true
# Change empty voucher text on Very Fair Deck
# This ain't localized, but that's a vanilla issue anyway
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "{n=G.UIT.T, config={text = 'DEFEAT', scale = 0.6, colour = G.C.WHITE}}"
position = "at"
payload = "{n=G.UIT.T, config={text = G.GAME.modifiers.cry_no_vouchers and (very_fair_quip[1] or '') or 'DEFEAT', scale = 0.6, colour = G.C.WHITE}}"
match_indent = true
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "{n=G.UIT.T, config={text = 'BOSS BLIND', scale = 0.4, colour = G.C.WHITE}}"
position = "at"
payload = "{n=G.UIT.T, config={text = G.GAME.modifiers.cry_no_vouchers and (very_fair_quip[2] or '') or G.GAME.modifiers.cry_voucher_restock_antes and G.GAME.round_resets.ante % G.GAME.modifiers.cry_voucher_restock_antes == 0 and 'TWO BOSS BLINDS' or 'BOSS BLIND', scale = 0.4, colour = G.C.WHITE}}"
match_indent = true
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "{n=G.UIT.T, config={text = 'TO RESTOCK', scale = 0.4, colour = G.C.WHITE}}"
position = "at"
payload = "{n=G.UIT.T, config={text = G.GAME.modifiers.cry_no_vouchers and (very_fair_quip[3] or '') or 'TO RESTOCK', scale = 0.4, colour = G.C.WHITE}}"
match_indent = true

View file

@ -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 = '''(?<indent>[\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'

View file

@ -0,0 +1,62 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -10
### Sprite API
# 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'''
## Set ability resizing fix
[[patches]]
[patches.pattern]
target = 'engine/moveable.lua'
pattern = '''Node.init(self, args)'''
position = 'after'
match_indent = true
payload = '''self.original_T = copy_table(self.T)'''
[[patches]]
[patches.pattern]
target = 'card.lua'
match_indent = true
position = 'before'
pattern = '''
local X, Y, W, H = self.T.x, self.T.y, self.T.w, self.T.h
'''
payload = '''
for key, _ in pairs(self.T) do
self.T[key] = self.original_T[key]
end
'''

193
Steamodded/lovely/back.toml Normal file
View file

@ -0,0 +1,193 @@
[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(self)
end'''
[[patches]]
[patches.pattern]
target = 'back.lua'
pattern = "if self.effect.config.randomize_rank_suit then"
position = 'before'
match_indent = true
payload = '''
G.E_MANAGER:add_event(Event({
func = function()
G.E_MANAGER:add_event(Event({
func = function()
save_run()
return true
end
}))
return true
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 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 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
# 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"
# 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
'''

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,467 @@
[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
(?<indent>[\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 = "if self.name == 'The Eye' and not reset then"
position = 'at'
payload = '''
if blind then
self.in_blind = true
end
local obj = self.config.blind
if not reset and obj.set_blind and type(obj.set_blind) == 'function' then
obj:set_blind()
elseif self.name == 'The Eye' and not reset then'''
match_indent = true
# 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 = "function Blind:stay_flipped(area, card)"
position = 'at'
match_indent = true
payload = '''function Blind:stay_flipped(area, card, from_area)'''
[[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, from_area)
end'''
[[patches]]
[patches.pattern]
target = 'cardarea.lua'
pattern = "local stay_flipped = G.GAME and G.GAME.blind and G.GAME.blind:stay_flipped(self, card)"
position = 'at'
match_indent = true
payload = '''local stay_flipped = G.GAME and G.GAME.blind and G.GAME.blind:stay_flipped(self, card, area)'''
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = "local stay_flipped = G.GAME and G.GAME.blind and G.GAME.blind:stay_flipped(to, card)"
position = 'at'
match_indent = true
payload = '''local stay_flipped = G.GAME and G.GAME.blind and G.GAME.blind:stay_flipped(to, card, from)'''
# Blind:drawn_to_hand()
[[patches]]
[patches.regex]
target = 'blind.lua'
pattern = "(?<indent>[\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'''
[[patches]]
[patches.pattern]
target = 'blind.lua'
pattern = "function Blind:modify_hand(cards, poker_hands, text, mult, hand_chips)"
position = 'at'
match_indent = true
payload = '''function Blind:modify_hand(cards, poker_hands, text, mult, hand_chips, scoring_hand)'''
[[patches]]
[patches.pattern]
target = 'functions/state_events.lua'
pattern = "mult, hand_chips, modded = G.GAME.blind:modify_hand(G.play.cards, poker_hands, text, mult, hand_chips)"
position = 'at'
match_indent = true
payload = '''mult, hand_chips, modded = G.GAME.blind:modify_hand(G.play.cards, poker_hands, text, mult, hand_chips, scoring_hand)'''
# 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 = "(?<indent>[\t ]*)blind_choice.animation = AnimatedSprite\\(0,0, 1.4, 1.4, (?<atlas>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 = "(?<indent>[\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))'''
# display blind descriptions in info_queue
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "elseif _c.set == 'Tarot' then"
position = "before"
match_indent = true
payload = '''elseif _c.set == 'Blind' then
local coll_loc_vars = (_c.collection_loc_vars and type(_c.collection_loc_vars) == 'function' and _c:collection_loc_vars()) or {}
loc_vars = coll_loc_vars.vars or _c.vars
localize{type = 'descriptions', key = coll_loc_vars.key or _c.key, set = _c.set, nodes = desc_nodes, vars = loc_vars}
'''
# 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)"
## elseif-ify some if chains
[[patches]]
[patches.regex]
target = 'blind.lua'
pattern = "end\n(?<indent>[\t ]*)if self.name == ['\"](?<ability>.*?)['\"]"
position = 'at'
payload = "elseif self.name == '$ability'"
# revert the change for The Pillar
[[patches]]
[patches.regex]
target = 'blind.lua'
pattern = "(?<indent>[\t ]*)elseif self.name == 'The Pillar' and card.ability.played_this_ante then"
position = 'at'
line_prepend = '$indent'
payload = '''end
if self.name == 'The Pillar' and card.ability.played_this_ante then'''
# revert the change for The Eye in debuff_hand
[[patches]]
[patches.regex]
target = 'blind.lua'
pattern = "(?<indent>[\t ]*)elseif self.name == 'The Eye' then"
position = 'at'
line_prepend = '$indent'
payload = '''end
if self.name == 'The Eye' then'''
# revert the change for The Arm in debuff_hand
[[patches]]
[patches.regex]
target = 'blind.lua'
pattern = "(?<indent>[\t ]*)elseif self.name == 'The Arm' then"
position = 'at'
line_prepend = '$indent'
payload = '''end
if self.name == 'The Arm' then'''
# revert the change for Crimson Heart in debuff_card
[[patches]]
[patches.regex]
target = 'blind.lua'
pattern = '''(?<indent>[\t ]*)elseif self\.name == 'Crimson Heart' and not self\.disabled'''
position = 'at'
line_prepend = '$indent'
payload = '''end
if self.name == 'Crimson Heart' and not self.disabled'''

View file

@ -0,0 +1,172 @@
[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 = '''
(?<indent>[\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 = '''
(?<indent>[\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 = """
(?<indent>[\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 = """
(?<indent>[\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 = '''
(?<indent>[\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 = '''
(?<indent>[\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 = '''hand_chips = mod_chips\(0\)(\n.*)*?\n[\t ]*(?<juice>SMODS.juice_up_blind\(\))'''
position = 'at'
root_capture = 'juice'
payload = 'if SMODS.hand_debuff_source then SMODS.hand_debuff_source:juice_up(0.3,0) else SMODS.juice_up_blind() end'
times = 1
[[patches]]
[patches.pattern]
target = 'game.lua'
pattern = 'G.GAME.blind.children.animatedSprite:juice_up(0.05, 0.02)'
position = 'at'
match_indent = true
payload = '''if SMODS.hand_debuff_source then
SMODS.hand_debuff_source:juice_up(0.05, 0.1)
else
G.GAME.blind.children.animatedSprite:juice_up(0.05, 0.02)
end
'''
# 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 = ''

View file

@ -0,0 +1,325 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -10
## Booster Pack API
# Card:open
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''
if self.ability.name:find('Arcana') then
G.STATE = G.STATES.TAROT_PACK
G.GAME.pack_size = self.ability.extra
elseif self.ability.name:find('Celestial') then
G.STATE = G.STATES.PLANET_PACK
G.GAME.pack_size = self.ability.extra
elseif self.ability.name:find('Spectral') then
G.STATE = G.STATES.SPECTRAL_PACK
G.GAME.pack_size = self.ability.extra
elseif self.ability.name:find('Standard') then
G.STATE = G.STATES.STANDARD_PACK
G.GAME.pack_size = self.ability.extra
elseif self.ability.name:find('Buffoon') then
G.STATE = G.STATES.BUFFOON_PACK
G.GAME.pack_size = self.ability.extra
end
G.GAME.pack_choices = self.config.center.config.choose or 1'''
match_indent = true
position = "at"
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
G.GAME.pack_choices = self.ability.choose or self.config.center.config.choose or 1
"""
# Card:open
[[patches]]
[patches.regex]
target = "card.lua"
pattern = '''(?<indent>[\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 = '''(?<indent>[\t ]*)self\.STATES = \{'''
position = "after"
payload = '''
SMODS_BOOSTER_OPENED = 999,'''
line_prepend = '$indent'
# Game:update
[[patches]]
[patches.regex]
target = "game.lua"
pattern = '''(?<indent>[\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 = '''(?<indent>[\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 and not select_to 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 = '''if prev_state == G.STATES.TAROT_PACK then inc_career_stat('c_tarot_reading_used', 1) end'''
position = 'at'
match_indent = true
payload = '''if prev_state == G.STATES.SMODS_BOOSTER_OPENED and booster_obj.name:find('Arcana') then inc_career_stat('c_tarot_reading_used', 1) end'''
# G.FUNC.use_card()
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if prev_state == G.STATES.PLANET_PACK then inc_career_stat('c_planetarium_used', 1) end'''
position = 'at'
match_indent = true
payload = '''if prev_state == G.STATES.SMODS_BOOSTER_OPENED and booster_obj.name:find('Celestial') then inc_career_stat('c_planetarium_used', 1) 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 = '''(?<indent>[\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 = '''(?<indent>[\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 card.area == G.pack_cards and booster_obj and booster_obj.select_card and card:selectable_from_pack(booster_obj) 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 select_to then
card:add_to_deck()
G[select_to]:emplace(card)
if card.config.center.on_select and type(card.config.center.on_select) == 'function' then
card.config.center:on_select(card)
end
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 = '''
for i = 1, #G.GAME.tags do
if G.GAME.tags[i]:apply_to_run({type = 'new_blind_choice'}) then break end
end
G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.2*delayfac,
func = function()
save_run()
return true
end}))
'''
payload = '''
booster_obj = nil
'''
# comment
[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
match_indent = true
position = 'before'
pattern = '''
G.FUNCS.end_consumeable(e)
'''
payload = '''
booster_obj = nil
'''
# G.FUNCS.can_select_card
# Support negative-ish on Jokers
[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
match_indent = true
position = 'at'
pattern = "if e.config.ref_table.ability.set ~= 'Joker' or (e.config.ref_table.edition and e.config.ref_table.edition.negative) or #G.jokers.cards < G.jokers.config.card_limit then"
payload = '''local card = e.config.ref_table
local card_limit = card.edition and card.edition.card_limit or 0
if card.ability.set ~= 'Joker' or #G.jokers.cards < G.jokers.config.card_limit + card_limit then'''

View file

@ -0,0 +1,25 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -5
# Add card_added context
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''if G.GAME.blind and G.GAME.blind.in_blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end'''
position = "after"
match_indent = true
payload = '''
if not from_debuff and G.hand then
local is_playing_card = self.ability.set == 'Default' or self.ability.set == 'Enhanced'
-- TARGET: calculate card_added
if not is_playing_card then
SMODS.calculate_context({card_added = true, card = self})
SMODS.enh_cache:clear()
end
end
'''
times = 1

View file

@ -0,0 +1,63 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -5
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''function Card:get_end_of_round_effect(context)
if self.debuff then return {} end'''
position = "at"
match_indent = true
payload = '''
function Card:get_end_of_round_effect(context)'''
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''function Card:calculate_dollar_bonus()
if self.debuff then return end'''
position = "at"
match_indent = true
payload = '''
function Card:calculate_dollar_bonus()
if not self:can_calculate() then return end'''
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''function Card:calculate_seal(context)
if self.debuff then return nil end'''
position = "at"
match_indent = true
payload = '''
function Card:calculate_seal(context)'''
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''function Card:calculate_joker(context)
if self.debuff then return nil end'''
position = "at"
match_indent = true
payload = '''
function Card:calculate_joker(context)'''
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''if self.ability.set == "Joker" and not self.debuff then'''
position = "at"
match_indent = true
payload = '''if self.ability.set == "Joker" then'''
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''if self.debuff then return 0 end'''
position = "at"
match_indent = true
payload = ''

View file

@ -0,0 +1,538 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -10
### Center API
# Card:set_ability()
[[patches]]
[patches.regex]
target = "card.lua"
pattern = "(?<indent>[\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>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 = "(?<indent>[\t ]+)if (?<rest>_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 = "(?<indent>[\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 = "(?<indent>[\t ]*)if(?<a> )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 = "(?<indent>[\t ]*)if(?<a> )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 = "(?<indent>[\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 = "(?<indent>[\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 = "(?<indent>[\t ]*)(?<if>if AUT.badges.card_type or AUT.badges.force_rarity then)\n[\t ]*(?<rest>.*)\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 = "(?<indent>[\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 = "(?<indent>[\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 = "(?<indent>[\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 = "(?<indent>[\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 = "(?<indent>[\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 = "(?<indent>[\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 = '(?<indent>[\t ]*)for _, v in ipairs\((?<li>\{\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'''
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = "{bypass_discovery_center = area==G.shop_jokers or area == G.pack_cards or area == G.shop_vouchers or (G.shop_demo and area==G.shop_demo) or area==G.jokers or area==G.consumeables,"
match_indent = true
position = 'at'
payload = '''
{bypass_discovery_center = SMODS.bypass_create_card_discovery_center or area==G.shop_jokers or area == G.pack_cards or area == G.shop_vouchers or (G.shop_demo and area==G.shop_demo) or area==G.jokers or area==G.consumeables,'''
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = "bypass_discovery_ui = area==G.shop_jokers or area == G.pack_cards or area==G.shop_vouchers or (G.shop_demo and area==G.shop_demo),"
match_indent = true
position = 'at'
payload = '''
bypass_discovery_ui = SMODS.bypass_create_card_discovery_center or area==G.shop_jokers or area == G.pack_cards or area==G.shop_vouchers or (G.shop_demo and area==G.shop_demo),'''
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = "discover = area==G.jokers or area==G.consumeables, "
match_indent = true
position = 'at'
payload = '''
discover = SMODS.bypass_create_card_discover or area==G.jokers or area==G.consumeables, '''
# Card:add_to_deck()
[[patches]]
[patches.regex]
target = 'card.lua'
pattern = '(?<indent>[\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 = '(?<indent>[\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
local select_to = card.area == G.pack_cards and booster_obj and booster_obj.select_card and card:selectable_from_pack(booster_obj)
if card.ability.consumeable and not select_to 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 not card.from_area then card.from_area = card.area 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'
match_indent = true
position = 'before'
pattern = '''
if area and area.cards[1] then
'''
payload = '''
if nc and not area then G.consumeables:emplace(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: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
'''
# 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
'''

View file

@ -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

View file

@ -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

View file

@ -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 = '(?<indent>[\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

View file

@ -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"

View file

@ -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",
]

View file

@ -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
'''

View file

@ -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.RED}, 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 = '''(?<indent>[\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

View file

@ -0,0 +1,281 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -10
# Fix debug mode edition cycling
[[patches]]
[patches.regex]
target = "engine/controller.lua"
pattern = '''
(?<indent>[\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 = '''
(?<indent>[\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'''
# 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 = '(?<indent>[\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 = '''(?<indent>[\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 = '''(?<indent>[\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 = '''(?<indent>[\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 not card.debuff and 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 not card.debuff and 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 + (not card.debuff and 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 = '''(?<indent>[\t ]*)(?<edi>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'''

View file

@ -0,0 +1,327 @@
[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 = '''
(?<indent>[\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 = '''(?<indent>[\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 self:can_calculate() 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 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"""
# Add the delayed property to sprites that are delayed
[[patches]]
[patches.pattern]
target = 'card.lua'
match_indent = true
position = 'at'
pattern = '''
if delay_sprites then
G.E_MANAGER:add_event(Event({
func = function()
if not self.REMOVED then
self:set_sprites(center)
end
return true
end
}))
'''
payload = '''
if delay_sprites == 'quantum' then
elseif delay_sprites then
self.ability.delayed = true
G.E_MANAGER:add_event(Event({
func = function()
if not self.REMOVED then
self:set_sprites(center)
self.ability.delayed = false
end
return true
end
}))
'''
# 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"
## 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 = "local effects = {G.hand.cards[i]:get_end_of_round_effect()}"
position = "at"
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.shatters(card) 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.shatters(G.hand.highlighted[i]) 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 cards_destroyed[i].shattered 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
# Reset enh cache on game update
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "modulate_sound(dt)"
position = "after"
payload = "SMODS.enh_cache:clear()"
match_indent = true
# Invalidate enhancement cache when card changes
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "function Card:set_ability(center, initial, delay_sprites)"
position = "after"
payload = "SMODS.enh_cache:write(self, nil)"
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "function Card:set_base(card, initial)"
position = "after"
payload = "SMODS.enh_cache:write(self, nil)"
match_indent = true
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "function Card:set_seal(_seal, silent, immediate)"
position = "after"
payload = "SMODS.enh_cache:write(self, nil)"
match_indent = true
# safeguards an infloop with debuff context
[[patches]]
[patches.pattern]
target = 'card.lua'
pattern = 'if not initial then G.GAME.blind:debuff_card(self) end'
position = 'at'
payload = 'if not initial and delay_sprites ~= "quantum" and G.GAME.blind then G.GAME.blind:debuff_card(self) end'
match_indent = true

View file

@ -0,0 +1,696 @@
[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 = "(?<indent>[\t ]*)if not \\(st.init and st:init\\(\\)\\) then\n[\t ]*(?<quit>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 = '''
(?<indent>[\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 = '''
(?<indent>[\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 = 'at'
match_indent = true
payload = '''
if delay_sprites == 'quantum' then self.from_quantum = true end
if self.added_to_deck and old_center and not self.debuff then
self:remove_from_deck()
self.added_to_deck = true
end
if type(center) == 'string' then
assert(G.P_CENTERS[center])
center = G.P_CENTERS[center]
end
self.config.center = center
'''
[[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
self.from_quantum = nil'''
## 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 = '''
(?<indent>[\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', 'perma_debuff'}
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.regex]
target = 'blind.lua'
pattern = "if self.name == 'Crimson Heart' and self.prepped and G.jokers.cards\\[1\\] then"
position = 'after'
payload = """
local prev_chosen_set = {}
local fallback_jokers = {}"""
# Fix bad logic if not enough choices for debuff
[[patches]]
[patches.regex]
target = 'blind.lua'
pattern = '''
(?<indent>[\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+
((?<indent>[\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.regex]
target = 'blind.lua'
pattern = "elseif self.name == 'The Water' then"
position = 'at'
payload = """
elseif self.name == 'Crimson Heart' then
for _, v in ipairs(G.jokers.cards) do
v.ability.crimson_heart_chosen = nil
end
elseif self.name == 'The Water' then"""
## Blind:defeat()
[[patches]]
[patches.regex]
target = 'blind.lua'
pattern = "elseif self.name == 'The Manacle' and not self.disabled then"
position = 'at'
payload = """
elseif self.name == 'Crimson Heart' then
for _, v in ipairs(G.jokers.cards) do
v.ability.crimson_heart_chosen = nil
end
elseif self.name == 'The Manacle' and not self.disabled then"""
## 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 and not self.from_quantum then"
# 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'
## 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 = ''' '''
# Fix prng calls on collection advancing seeds
# Keep vanilla behaviour for to-do list
[[patches]]
[patches.pattern]
target = "functions/misc_functions.lua"
pattern = "if key == 'seed' then return math.random() end"
position = "after"
payload = """
if G.SETTINGS.paused and key ~= 'to_do' then return math.random() end
"""
overwrite = true
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, "LuaSteam"); st = {} end"""
overwrite = true
match_indent = true
# copy_card edition config
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
position = 'after'
match_indent = true
pattern = 'new_card:set_edition(other.edition or {}, nil, true)'
payload = '''for k,v in pairs(other.edition or {}) do
if type(v) == 'table' then
new_card.edition[k] = copy_table(v)
else
new_card.edition[k] = v
end
end'''
# fix Smeared Joker compat issues with modded suits
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if next(find_joker('Smeared Joker')) and (self.base.suit == 'Hearts' or self.base.suit == 'Diamonds') == (suit == 'Hearts' or suit == 'Diamonds') then"
position = "at"
payload = "if next(find_joker('Smeared Joker')) and SMODS.smeared_check(self, suit) then"
overwrite = true
match_indent = true
# fix Seeing Double compat issues with modded suits
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = """local suits = {
['Hearts'] = 0,
['Diamonds'] = 0,
['Spades'] = 0,
['Clubs'] = 0
}
for i = 1, #context.scoring_hand do
if not SMODS.has_any_suit(context.scoring_hand[i]) then
if context.scoring_hand[i]:is_suit('Hearts') then suits["Hearts"] = suits["Hearts"] + 1 end
if context.scoring_hand[i]:is_suit('Diamonds') then suits["Diamonds"] = suits["Diamonds"] + 1 end
if context.scoring_hand[i]:is_suit('Spades') then suits["Spades"] = suits["Spades"] + 1 end
if context.scoring_hand[i]:is_suit('Clubs') then suits["Clubs"] = suits["Clubs"] + 1 end
end
end
for i = 1, #context.scoring_hand do
if SMODS.has_any_suit(context.scoring_hand[i]) then
if context.scoring_hand[i]:is_suit('Clubs') and suits["Clubs"] == 0 then suits["Clubs"] = suits["Clubs"] + 1
elseif context.scoring_hand[i]:is_suit('Diamonds') and suits["Diamonds"] == 0 then suits["Diamonds"] = suits["Diamonds"] + 1
elseif context.scoring_hand[i]:is_suit('Spades') and suits["Spades"] == 0 then suits["Spades"] = suits["Spades"] + 1
elseif context.scoring_hand[i]:is_suit('Hearts') and suits["Hearts"] == 0 then suits["Hearts"] = suits["Hearts"] + 1 end
end
end
if (suits["Hearts"] > 0 or
suits["Diamonds"] > 0 or
suits["Spades"] > 0) and
suits["Clubs"] > 0 then
return {
message = localize{type='variable',key='a_xmult',vars={self.ability.extra}},
Xmult_mod = self.ability.extra
}
end"""
position = "at"
payload = """if SMODS.seeing_double_check(context.scoring_hand, 'Clubs') then
return {
message = localize{type='variable',key='a_xmult',vars={self.ability.extra}},
Xmult_mod = self.ability.extra
}
end"""
overwrite = true
match_indent = true

View file

@ -0,0 +1,16 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -10
# 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 _,v in pairs(SMODS.Gradients) do
v:update(dt)
end'''
match_indent = true

View file

@ -0,0 +1,364 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -10
# Luchador
[[patches]]
[patches.regex]
target = "card.lua"
pattern = '''[ \t]*G\.GAME\.blind:disable\(\)
(?<indent>[ \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]*\}\)\)
(?<indent>[ \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\(\)
(?<indent>[ \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
(?<indent>[ \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\)\}\)\)
(?<indent>[ \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'\)\}\)
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \t]*)\}\)\)'''
position = "after"
line_prepend = '$indent'
payload = "return nil, true"
[[patches]]
[patches.regex]
target = "card.lua"
pattern = '''
[ \t]*end
[ \t]*return
[ \t]*end
(?<indent>[ \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
(?<indent>[ \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
(?<indent>[ \t]*)elseif context.debuffed_hand'''
position = "before"
line_prepend = '$indent'
payload = "nil, true"
# Burnt Joker
[[patches]]
[patches.regex]
target = "card.lua"
pattern = '''
[ \t]*end
(?<indent>[ \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
(?<indent>[ \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,'''

View file

@ -0,0 +1,73 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -5
[[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

View file

@ -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
'''

View file

@ -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'), '=[localization "'..G.SETTINGS.language..'.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

View file

@ -0,0 +1,34 @@
[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"
[[patches]]
[patches.module]
source = "libs/https/luajit-curl.lua"
before = "main.lua"
name = "luajit-curl"
[[patches]] # Ensure the thread can also load this
[patches.module]
source = "libs/https/luajit-curl.lua"
before = '=[SMODS _ "smods-https-thread.lua"]'
name = "luajit-curl"
[[patches]]
[patches.module]
source = "libs/https/smods-https.lua"
before = "main.lua"
name = "SMODS.https"

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,72 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -5
### Per-mod functions
# end_round()
[[patches]]
[patches.regex]
target = 'functions/state_events.lua'
pattern = '''(?<indent>[\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 = '''(?<indent>[\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
'''

View file

@ -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\((?<param>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 = '(?<param>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)"

View file

@ -0,0 +1,337 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -5
### Permanent card values implementations
## Adapted from AMM (https://github.com/AutumnMood924/AutumnMoodMechanics)
# generate_card_ui(): mult card special case
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "if _c.effect == 'Mult Card' then loc_vars = {cfg.mult}"
position = "at"
payload = "if _c.effect == 'Mult Card' then loc_vars = {SMODS.signed(cfg.mult + (specific_vars and specific_vars.bonus_mult or 0))}"
match_indent = true
# generate_card_ui(): gold card special case
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "elseif _c.effect == 'Gold Card' then loc_vars = {cfg.h_dollars}"
position = "at"
payload = "elseif _c.effect == 'Gold Card' then loc_vars = {specific_vars and SMODS.signed_dollars(specific_vars.total_h_dollars) or cfg.h_dollars and SMODS.signed_dollars(cfg.h_dollars) or 0}"
match_indent = true
# generate_card_ui(): stone card special case
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "elseif _c.effect == 'Stone Card' then loc_vars = {((specific_vars and specific_vars.bonus_chips) or cfg.bonus)}"
position = "at"
payload = "elseif _c.effect == 'Stone Card' then loc_vars = {((specific_vars and SMODS.signed(specific_vars.bonus_chips)) or cfg.bonus and SMODS.signed(cfg.bonus) or 0)}"
match_indent = true
# generate_card_ui(): show permanent bonuses on default playing cards
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "elseif _c.set == 'Enhanced' then"
position = "before"
payload = '''
if specific_vars and specific_vars.bonus_x_chips then
localize{type = 'other', key = 'card_x_chips', nodes = desc_nodes, vars = {specific_vars.bonus_x_chips}}
end
if specific_vars and specific_vars.bonus_mult then
localize{type = 'other', key = 'card_extra_mult', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_mult)}}
end
if specific_vars and specific_vars.bonus_x_mult then
localize{type = 'other', key = 'card_x_mult', nodes = desc_nodes, vars = {specific_vars.bonus_x_mult}}
end
if specific_vars and specific_vars.bonus_h_chips then
localize{type = 'other', key = 'card_extra_h_chips', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_h_chips)}}
end
if specific_vars and specific_vars.bonus_h_x_chips then
localize{type = 'other', key = 'card_h_x_chips', nodes = desc_nodes, vars = {specific_vars.bonus_h_x_chips}}
end
if specific_vars and specific_vars.bonus_h_mult then
localize{type = 'other', key = 'card_extra_h_mult', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_h_mult)}}
end
if specific_vars and specific_vars.bonus_h_x_mult then
localize{type = 'other', key = 'card_h_x_mult', nodes = desc_nodes, vars = {specific_vars.bonus_h_x_mult}}
end
if specific_vars and specific_vars.bonus_p_dollars then
localize{type = 'other', key = 'card_extra_p_dollars', nodes = desc_nodes, vars = {SMODS.signed_dollars(specific_vars.bonus_p_dollars)}}
end
if specific_vars and specific_vars.bonus_h_dollars then
localize{type = 'other', key = 'card_extra_h_dollars', nodes = desc_nodes, vars = {SMODS.signed_dollars(specific_vars.bonus_h_dollars)}}
end'''
match_indent = true
overwrite = false
# generate_card_ui(): signed(extra_chips)
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "localize{type = 'other', key = 'card_extra_chips', nodes = desc_nodes, vars = {specific_vars.bonus_chips}}"
position = "at"
match_indent = true
payload = "localize{type = 'other', key = 'card_extra_chips', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_chips)}}"
# generate_card_ui(): signed(extra_chips)
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "localize{type = 'other', key = 'card_extra_chips', nodes = desc_nodes, vars = {((specific_vars and specific_vars.bonus_chips) or cfg.bonus)}}"
position = "at"
match_indent = true
payload = "localize{type = 'other', key = 'card_extra_chips', nodes = desc_nodes, vars = {SMODS.signed((specific_vars and specific_vars.bonus_chips) or cfg.bonus)}}"
# generate_card_ui(): show permanent bonuses on enhanced playing cards
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "elseif _c.set == 'Booster' then"
position = "before"
payload = '''
if specific_vars and specific_vars.bonus_x_chips then
localize{type = 'other', key = 'card_x_chips', nodes = desc_nodes, vars = {specific_vars.bonus_x_chips}}
end
if specific_vars and specific_vars.bonus_mult and _c.effect ~= 'Mult Card' then
localize{type = 'other', key = 'card_extra_mult', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_mult)}}
end
if specific_vars and specific_vars.bonus_x_mult then
localize{type = 'other', key = 'card_x_mult', nodes = desc_nodes, vars = {specific_vars.bonus_x_mult}}
end
if specific_vars and specific_vars.bonus_h_chips then
localize{type = 'other', key = 'card_extra_h_chips', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_h_chips)}}
end
if specific_vars and specific_vars.bonus_h_x_chips then
localize{type = 'other', key = 'card_h_x_chips', nodes = desc_nodes, vars = {specific_vars.bonus_h_x_chips}}
end
if specific_vars and specific_vars.bonus_h_mult then
localize{type = 'other', key = 'card_extra_h_mult', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_h_mult)}}
end
if specific_vars and specific_vars.bonus_h_x_mult then
localize{type = 'other', key = 'card_h_x_mult', nodes = desc_nodes, vars = {specific_vars.bonus_h_x_mult}}
end
if specific_vars and specific_vars.bonus_p_dollars then
localize{type = 'other', key = 'card_extra_p_dollars', nodes = desc_nodes, vars = {SMODS.signed_dollars(specific_vars.bonus_p_dollars)}}
end
if specific_vars and specific_vars.bonus_h_dollars and _c.effect ~= 'Gold Card' then
localize{type = 'other', key = 'card_extra_h_dollars', nodes = desc_nodes, vars = {SMODS.signed_dollars(specific_vars.bonus_h_dollars)}}
end'''
match_indent = true
overwrite = false
# generate_UIBox_ability_table(): prime locals for easier boolean magic
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "loc_vars = { playing_card = not not self.base.colour, value = self.base.value, suit = self.base.suit, colour = self.base.colour,"
position = "before"
payload = '''local bonus_chips = self.ability.bonus + (self.ability.perma_bonus or 0)
local total_h_dollars = self:get_h_dollars()'''
match_indent = true
overwrite = false
# generate_UIBox_ability_table(): prime specific_vars for playing cards
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "bonus_chips = (self.ability.bonus + (self.ability.perma_bonus or 0)) > 0 and (self.ability.bonus + (self.ability.perma_bonus or 0)) or nil,"
position = "at"
payload = '''
bonus_x_chips = self.ability.perma_x_chips ~= 0 and (self.ability.perma_x_chips + 1) or nil,
bonus_mult = self.ability.perma_mult ~= 0 and self.ability.perma_mult or nil,
bonus_x_mult = self.ability.perma_x_mult ~= 0 and (self.ability.perma_x_mult + 1) or nil,
bonus_h_chips = self.ability.perma_h_chips ~= 0 and self.ability.perma_h_chips or nil,
bonus_h_x_chips = self.ability.perma_h_x_chips ~= 0 and (self.ability.perma_h_x_chips + 1) or nil,
bonus_h_mult = self.ability.perma_h_mult ~= 0 and self.ability.perma_h_mult or nil,
bonus_h_x_mult = self.ability.perma_h_x_mult ~= 0 and (self.ability.perma_h_x_mult + 1) or nil,
bonus_p_dollars = self.ability.perma_p_dollars ~= 0 and self.ability.perma_p_dollars or nil,
bonus_h_dollars = self.ability.perma_h_dollars ~= 0 and self.ability.perma_h_dollars or nil,
total_h_dollars = total_h_dollars ~= 0 and total_h_dollars or nil,
bonus_chips = bonus_chips ~= 0 and bonus_chips or nil,'''
match_indent = true
overwrite = false
# set_ability: set defaults for temporary bonuses
# Also add conformance with SMODS documentation.
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "x_mult = center.config.Xmult or 1,"
position = "at"
payload = '''
x_mult = center.config.Xmult or center.config.x_mult or 1,
h_chips = center.config.h_chips or 0,
x_chips = center.config.x_chips or 1,
h_x_chips = center.config.h_x_chips or 1,
'''
match_indent = true
overwrite = false
# set_ability: set defaults for permanent bonuses
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "perma_bonus = self.ability and self.ability.perma_bonus or 0,"
position = "after"
payload = '''
perma_x_chips = self.ability and self.ability.perma_x_chips or 0,
perma_mult = self.ability and self.ability.perma_mult or 0,
perma_x_mult = self.ability and self.ability.perma_x_mult or 0,
perma_h_chips = self.ability and self.ability.perma_h_chips or 0,
perma_h_x_chips = self.ability and self.ability.perma_h_x_chips or 0,
perma_h_mult = self.ability and self.ability.perma_hmult or 0,
perma_h_x_mult = self.ability and self.ability.perma_h_x_mult or 0,
perma_p_dollars = self.ability and self.ability.perma_p_dollars or 0,
perma_h_dollars = self.ability and self.ability.perma_h_dollars or 0,
'''
match_indent = true
overwrite = false
# Card:get_chip_mult
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''if self.ability.effect == "Lucky Card" then
if pseudorandom('lucky_mult') < G.GAME.probabilities.normal/5 then
self.lucky_trigger = true
return self.ability.mult
else
return 0
end
else
return self.ability.mult
end'''
position = "at"
match_indent = true
payload = '''local ret = self.ability.perma_mult or 0
if self.ability.effect == "Lucky Card" then
if pseudorandom('lucky_mult') < G.GAME.probabilities.normal/5 then
self.lucky_trigger = true
ret = ret + self.ability.mult
end
else
ret = ret + self.ability.mult
end
-- TARGET: get_chip_mult
return ret'''
# Card:get_chip_x_mult
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''if self.ability.x_mult <= 1 then return 0 end
return self.ability.x_mult'''
position = "at"
match_indent = true
payload = '''local ret = SMODS.multiplicative_stacking(self.ability.x_mult or 1, self.ability.perma_x_mult or 0)
-- TARGET: get_chip_x_mult
return ret
'''
# Card:get_chip_h_mult
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = 'return self.ability.h_mult'
position = "at"
match_indent = true
payload = '''local ret = (self.ability.h_mult or 0) + (self.ability.perma_h_mult or 0)
-- TARGET: get_chip_h_mult
return ret
'''
# Card:get_chip_h_x_mult
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = 'return self.ability.h_x_mult'
position = "at"
match_indent = true
payload = '''local ret = SMODS.multiplicative_stacking(self.ability.h_x_mult or 1, self.ability.perma_h_x_mult or 0)
-- TARGET: get_chip_h_x_mult
return ret
'''
# Card:get_chip_x_bonus
# Card:get_chip_h_bonus
# Card:get_chip_h_x_bonus
# Card:get_h_dollars
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = 'function Card:get_edition()'
position = "before"
match_indent = true
payload = '''
function Card:get_chip_x_bonus()
if self.debuff then return 0 end
local ret = SMODS.multiplicative_stacking(self.ability.x_chips or 1, self.ability.perma_x_chips or 0)
-- TARGET: get_chip_x_bonus
return ret
end
function Card:get_chip_h_bonus()
if self.debuff then return 0 end
local ret = (self.ability.h_chips or 0) + (self.ability.perma_h_chips or 0)
-- TARGET: get_chip_h_bonus
return ret
end
function Card:get_chip_h_x_bonus()
if self.debuff then return 0 end
local ret = SMODS.multiplicative_stacking(self.ability.h_x_chips or 1, self.ability.perma_h_x_chips or 0)
-- TARGET: get_chip_h_x_bonus
return ret
end
function Card:get_h_dollars()
if self.debuff then return 0 end
local ret = (self.ability.h_dollars or 0) + (self.ability.perma_h_dollars or 0)
-- TARGET: get_h_dollars
return ret
end
'''
# Card:get_p_dollars
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''end
if ret > 0 then
G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + ret'''
position = "at"
match_indent = true
payload = '''elseif self.ability.p_dollars < 0 then
ret = ret + self.ability.p_dollars
end
ret = ret + (self.ability.perma_p_dollars) or 0
-- TARGET: get_p_dollars
if ret ~= 0 then
G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + ret'''
# Card:get_end_of_round_effect
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''
if self.ability.h_dollars > 0 then
ret.h_dollars = self.ability.h_dollars
ret.card = self
end
'''
position = "at"
match_indent = true
payload = '''
local h_dollars = self:get_h_dollars()
if h_dollars ~= 0 then
ret.h_dollars = h_dollars
ret.card = self
end
'''
times = 1

View file

@ -0,0 +1,302 @@
[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 = '(?<indent>[\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.Gradient.obj_buffer) do
G.ARGS.LOC_COLOURS[v:lower()] = SMODS.Gradients[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 = '(?<indent>[\t ]*)local suits = \{\n[\t ]*"Spades",\n[\t ]*"Hearts",\n[\t ]*"Clubs",\n[\t ]*"Diamonds"\n[\t ]*\}\n[\t ]*if #hand > 5 or (?<restcond>#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 = "(?<indent>[\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 = "(?<indent>[\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 = "(?<indent>[\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 = "(?<indent>[\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 = '(?<start>[\t ]*local t_s = Sprite\(0,0,0.5,0.5,)G.ASSET_ATLAS\[.*?\](?<rest>.*?\))'
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 = "(?<indent>[\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 = '(?<indent>[\t ]*)for j = 1, 4 do\n[\t ]*(?<mid>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
'''

View file

@ -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

185
Steamodded/lovely/pool.toml Normal file
View file

@ -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 = "self.config.center = 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 = '''
(?<indent>[\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 = '''
(?<indent>[\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"

View file

@ -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 = '''(?<indent>[\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

224
Steamodded/lovely/seal.toml Normal file
View file

@ -0,0 +1,224 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -10
### Seal API
# Card:open()
[[patches]]
[patches.regex]
target = 'card.lua'
pattern = '''
(?<indent>[\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 = '''
(?<indent>[\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(?<indent>[\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 = '''(?<indent>[\t ]*)if (?<cond>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 = (?<badge>'.*?_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 = '''(?<indent>[\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
'''

237
Steamodded/lovely/shop.toml Normal file
View file

@ -0,0 +1,237 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = -10
# Set defaults
[[patches]]
[patches.pattern]
target = 'functions/misc_functions.lua'
match_indent = true
position = 'after'
pattern = '''
erratic_suits_and_ranks = false,
'''
payload = '''
boosters_in_shop = 2,
vouchers_in_shop = 1,
'''
# Allow booster count to be controlled by G.GAME.modifiers.extra_boosters
[[patches]]
[patches.pattern]
target = 'game.lua'
match_indent = true
position = 'at'
pattern = '''
for i = 1, 2 do
G.GAME.current_round.used_packs = G.GAME.current_round.used_packs or {}
'''
payload = '''
for i=1, G.GAME.starting_params.boosters_in_shop + (G.GAME.modifiers.extra_boosters or 0) do
G.GAME.current_round.used_packs = G.GAME.current_round.used_packs or {}
'''
# Custom deck functionality
[[patches]]
[patches.pattern]
target = 'back.lua'
match_indent = true
position = 'before'
pattern = '''
if self.effect.config.no_interest then
'''
payload = '''
if self.effect.config.boosters_in_shop then
G.GAME.starting_params.boosters_in_shop = self.effect.config.boosters_in_shop
end
'''
# Allow voucher count to be controlled by G.GAME.modifiers.extra_vouchers
[[patches]]
[patches.pattern]
target = 'game.lua'
match_indent = true
position = 'at'
pattern = '''
if G.GAME.current_round.voucher and G.P_CENTERS[G.GAME.current_round.voucher] 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.voucher],{bypass_discovery_center = true, bypass_discovery_ui = true})
card.shop_voucher = true
create_shop_card_ui(card, 'Voucher', G.shop_vouchers)
card:start_materialize()
G.shop_vouchers:emplace(card)
end
'''
payload = '''
local vouchers_to_spawn = 0
for _,_ in pairs(G.GAME.current_round.voucher.spawn) do vouchers_to_spawn = vouchers_to_spawn + 1 end
if vouchers_to_spawn < G.GAME.starting_params.vouchers_in_shop + (G.GAME.modifiers.extra_vouchers or 0) then
SMODS.get_next_vouchers(G.GAME.current_round.voucher)
end
for _, key in ipairs(G.GAME.current_round.voucher or {}) do
if G.P_CENTERS[key] and G.GAME.current_round.voucher.spawn[key] then
SMODS.add_voucher_to_shop(key)
end
end
'''
# Modify generating vouchers
[[patches]]
[patches.pattern]
target = 'functions/state_events.lua'
match_indent = true
position = 'at'
pattern = '''
G.GAME.current_round.voucher = get_next_voucher_key()
'''
payload = '''
G.GAME.current_round.voucher = SMODS.get_next_vouchers()
'''
[[patches]]
[patches.pattern]
target = 'game.lua'
match_indent = true
position = 'at'
pattern = '''
self.GAME.current_round.voucher = G.SETTINGS.tutorial_progress and G.SETTINGS.tutorial_progress.forced_voucher or get_next_voucher_key()
'''
payload = '''
local forced_voucher = (G.SETTINGS.tutorial_progress or {}).forced_voucher
self.GAME.current_round.voucher = forced_voucher and {forced_voucher, spawn = {[forced_voucher] = true }} or SMODS.get_next_vouchers()
'''
# Stop redeeming vouchers deleting the table of vouchers
[[patches]]
[patches.pattern]
target = 'card.lua'
match_indent = true
position = 'at'
pattern = '''
if self.shop_voucher then G.GAME.current_round.voucher = nil end
'''
payload = '''
if self.shop_voucher then G.GAME.current_round.voucher.spawn[self.config.center_key] = false end
if self.from_tag then G.GAME.current_round.voucher.spawn[G.GAME.current_round.voucher[1]] = false end
'''
[[patches]]
[patches.pattern]
target = 'card.lua'
match_indent = true
position = 'at'
pattern = '''
G.GAME.current_round.voucher = nil
'''
payload = '''
--G.GAME.current_round.voucher = nil
'''
# Add voucher restock message
[[patches]]
[patches.pattern]
target = 'functions/button_callbacks.lua'
match_indent = true
position = 'at'
pattern = '''
if (G.shop_vouchers and G.shop_vouchers.cards and (G.shop_vouchers.cards[1] or G.GAME.current_round.voucher)) then
'''
payload = '''
if (G.shop_vouchers and G.shop_vouchers.cards and G.shop_vouchers.cards[1]) then
'''
# Maintain voucher tag jank interaction
[[patches]]
[patches.pattern]
target = 'tag.lua'
match_indent = true
position = 'before'
pattern = '''
create_shop_card_ui(card, 'Voucher', G.shop_vouchers)
'''
payload = '''
card.from_tag = true
'''
# Free Rerolls
[[patches]]
[patches.pattern]
target = 'functions/state_events.lua'
match_indent = true
position = 'at'
pattern = '''
local chaos = find_joker('Chaos the Clown')
G.GAME.current_round.free_rerolls = #chaos
'''
payload = '''
G.GAME.current_round.free_rerolls = G.GAME.round_resets.free_rerolls
'''
# G.GAME.round_resets.free_rerolls
[[patches]]
[patches.pattern]
target = 'game.lua'
match_indent = true
position = 'after'
pattern = '''
reroll_cost = 1,
'''
payload = '''
free_rerolls = 0,
'''
# Adjust Chaos the Clown
[[patches]]
[patches.pattern]
target = 'card.lua'
match_indent = true
position = 'at'
pattern = '''
G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls + 1
'''
payload = '''
SMODS.change_free_rerolls(1)
'''
[[patches]]
[patches.pattern]
target = 'card.lua'
match_indent = true
position = 'at'
pattern = '''
G.GAME.current_round.free_rerolls = G.GAME.current_round.free_rerolls - 1
'''
payload = '''
SMODS.change_free_rerolls(-1)
'''
## Shop Card Area Width
[[patches]]
[patches.pattern]
target = 'functions/UI_definitions.lua'
pattern = '''G.GAME.shop.joker_max*1.02*G.CARD_W,'''
position = 'at'
match_indent = true
payload = '''math.min(G.GAME.shop.joker_max*1.02*G.CARD_W,4.08*G.CARD_W),'''
[[patches]]
[patches.pattern]
target = 'functions/common_events.lua'
pattern = '''G.shop_jokers.T.w = G.GAME.shop.joker_max*1.01*G.CARD_W'''
position = 'at'
match_indent = true
payload = '''G.shop_jokers.T.w = math.min(G.GAME.shop.joker_max*1.02*G.CARD_W,4.08*G.CARD_W)'''
# for some reason shop_voucher is not saved/loaded so... that's what's gonna happen
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = '''ability = self.ability,'''
position = "before"
payload = '''
shop_voucher = self.shop_voucher,
'''
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
'''
match_indent = true

View file

@ -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 = """(?<indent>[\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'''

View file

@ -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

View file

@ -0,0 +1,111 @@
[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'''
# 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)'''

139
Steamodded/lovely/tag.toml Normal file
View file

@ -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 = "(?<indent>[\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 = '''(?<indent>[\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 = '''(?<indent>[\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'''

View file

@ -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

251
Steamodded/lovely/ui.toml Normal file
View file

@ -0,0 +1,251 @@
[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 = '''(?<indent>[\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 = '''(?<indent>[\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 = '''
(?<indent>[\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 = '(?<indent>[\t ]*)(?<start>for _, v in pairs\(G\.P_[BT].*)(?<rest>(\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"
## Description controls
# localize
[[patches]]
[patches.pattern]
target = 'functions/misc_functions.lua'
match_indent = true
position = 'at'
pattern = 'final_line[#final_line+1] = {n=G.UIT.O, config={'
payload = '''
final_line[#final_line+1] = {n=G.UIT.C, config={align = "m", colour = part.control.B and args.vars.colours[tonumber(part.control.B)] or part.control.X and loc_colour(part.control.X) or nil, r = 0.05, padding = 0.03, res = 0.15}, nodes={}}
final_line[#final_line].nodes[1] = {n=G.UIT.O, config={
'''
[[patches]]
[patches.pattern]
target = 'functions/misc_functions.lua'
match_indent = true
position = 'at'
pattern = 'elseif part.control.X then'
payload = 'elseif part.control.X or part.control.B then'
[[patches]]
[patches.regex]
target = 'functions/misc_functions.lua'
position = 'at'
pattern = 'colour = loc_colour\(part.control.X\)'
payload = 'colour = part.control.B and args.vars.colours[tonumber(part.control.B)] or loc_colour(part.control.X)'
[[patches]]
[patches.pattern]
target = 'functions/misc_functions.lua'
match_indent = true
position = 'at'
pattern = 'colour = loc_colour(part.control.C or nil),'
payload = 'colour = part.control.V and args.vars.colours[tonumber(part.control.V)] or loc_colour(part.control.C or nil),'

View file

@ -0,0 +1,130 @@
[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
# remove hardcoded shop selection limit
[[patches]]
[patches.pattern]
target = "cardarea.lua"
pattern = "if self.highlighted[1] then"
position = "at"
payload = "if #self.highlighted >= self.config.highlighted_limit then"
match_indent = true

View file

@ -0,0 +1,90 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 0
# Fix the nominal sorting (Suit for high ranks)
[[patches]]
[patches.regex]
target = 'card.lua'
pattern = '''if mod == 'suit' (.*)'''
position = 'at'
payload = '''
if mod == 'suit' then mult = 30000 end'''
# Fix the nominal sorting (For low ranks)
[[patches]]
[patches.regex]
target = 'card.lua'
pattern = '''return 10\*self.base.nominal\*rank_mult(.*)'''
position = 'at'
payload = '''
--Temporary fix so the card with the lowest nominal can still be sorted properly
local nominal = self.base.nominal
if self.base.value == 'unstb_???' then
nominal = 0.3
elseif nominal < 0.4 then
nominal = 0.31 + nominal*0.1
end
--Hardcode this so it's sorted properly
if self.base.value == 'unstb_161' then
nominal = 30
end
return 10*(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'''
# Adds ability text for decimal ranks
# function generate_card_ui()
[[patches]]
[patches.pattern]
target = "functions/common_events.lua"
pattern = "if main_end then"
position = "before"
match_indent = true
payload = """
local isCollection = (card and card.area and card.area.config.collection) or false
if not isCollection and (_c.set == 'Default' or _c.set == 'Enhanced') and card and card.base and card.base.value and SMODS.Ranks[card.base.value].is_decimal and not card.config.center.no_rank and not card.debuff then
local rank_act = SMODS.Ranks[card.base.value].rank_act or {'0', '0', '0'}
if rank_act[3] then
localize{type = 'other', key = 'decimal_rank_ability', nodes = desc_nodes, vars = {rank_act[1], rank_act[2], rank_act[3]}}
else
localize{type = 'other', key = 'decimal_rank_ability_2', nodes = desc_nodes, vars = {rank_act[1], rank_act[2]}}
end
end"""
# Adds 'No Chips' text for certain ranks
# function generate_card_ui()
[[patches]]
[patches.regex]
target = "functions/common_events.lua"
pattern = "specific_vars.nominal_chips then \n(.*)"
position = "at"
payload = """
specific_vars.nominal_chips or (specific_vars.value == 'unstb_0' or specific_vars.value == 'unstb_???') then
if (specific_vars.value == 'unstb_0' or specific_vars.value == 'unstb_???') and not specific_vars.nominal_chips then
localize{type = 'other', key = 'no_chip', nodes = desc_nodes, vars = {}}
else
localize{type = 'other', key = 'card_chips', nodes = desc_nodes, vars = {specific_vars.nominal_chips}}
end
"""
# Ranks unlocks from Booster Pack
# function generate_card_ui()
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = "elseif card.ability.set == 'Enhanced' or card.ability.set == 'Default' then "
position = "after"
match_indent = true
payload = """
if G.STATE == G.STATES.STANDARD_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED then
local rank = card.base.value
--Check if it's UnStable rank, if so then flips the flag
if rank:find('unstb_') then
setPoolRankFlagEnable(rank, true);
end
end
"""

View file

@ -0,0 +1,21 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 0
# Auxiliary Cards undiscovered sprite, based on Polyminoes undiscovered sprite from Bunco
[[patches]]
[patches.pattern]
target = 'card.lua'
pattern = '''local shared_sprite = (self.ability.set == 'Edition' or self.ability.set == 'Joker') and G.shared_undiscovered_joker or G.shared_undiscovered_tarot'''
position = 'after'
match_indent = true
payload = '''
if not G.shared_undiscovered_auxiliary then G.shared_undiscovered_auxiliary = Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS['unstb_auxiliary_undiscovered'], {x = 1, y = 0}) end
if self.ability.set == 'Auxiliary' then
shared_sprite = G.shared_undiscovered_auxiliary
end
'''

View file

@ -0,0 +1,16 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 0
# Adds rank blacklist functionality for deck
# function generate_card_ui()
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "if self.GAME.starting_params.no_faces and SMODS.Ranks[v.value].face then keep = false end"
position = "before"
match_indent = true
payload = """
if self.GAME.starting_params.blacklisted_ranks and self.GAME.starting_params.blacklisted_ranks[v.value] then keep = false end
"""

View file

@ -0,0 +1,39 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 0
# Adds triggers for destroyable enhancement after-play
[[patches]]
[patches.pattern]
target = 'functions/state_events.lua'
pattern = '''-- context.remove_playing_cards calculations'''
position = 'before'
match_indent = true
payload = '''
for i=1, #scoring_hand do
if scoring_hand[i].config.center.after_play and not scoring_hand[i].debuff and not unstb_global.table_has_value(cards_destroyed, scoring_hand[i]) then
local effect = scoring_hand[i].config.center:after_play(scoring_hand[i], {scoring_hand = scoring_hand})
if effect and effect.to_destroy then
cards_destroyed[#cards_destroyed+1] = scoring_hand[i]
end
end
end
'''
# Enhancement Discard Overrides
[[patches]]
[patches.pattern]
target = 'functions/state_events.lua'
pattern = "draw_card(G.hand, G.discard, i*100/highlighted_count, 'down', false, G.hand.highlighted[i])"
position = 'at'
match_indent = true
payload = '''
if G.hand.highlighted[i].config.center.discard_override and not G.hand.highlighted[i].debuff then
G.hand.highlighted[i].config.center:discard_override(G.hand.highlighted[i], {delay = i*100/highlighted_count})
else
draw_card(G.hand, G.discard, i*100/highlighted_count, 'down', false, G.hand.highlighted[i])
end
'''

View file

@ -0,0 +1,82 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 0
# Blueprint Compat Jokers Part 1
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "elseif self.ability.name == 'Blueprint' then"
position = "before"
payload = '''
elseif self.config.center.key == 'j_unstb_plagiarism' then
self.ability.blueprint_compat_ui_l = self.ability.blueprint_compat_ui_l or '';
self.ability.blueprint_compat_check_l = nil
self.ability.blueprint_compat_ui_r = self.ability.blueprint_compat_ui_r or '';
self.ability.blueprint_compat_check_r = nil
main_end = (self.area and self.area == G.jokers) and {
{n=G.UIT.C, config={align = "bm", minh = 0.4, padding = 0.06}, nodes={
{n=G.UIT.R, config={ref_table = self, align = "m", colour = G.C.JOKER_GREY, r = 0.05, padding = 0.06, func = 'blueprint_compat_dside_l'}, nodes={
{n=G.UIT.T, config={ref_table = self.ability, ref_value = 'blueprint_compat_ui_l',colour = G.C.UI.TEXT_LIGHT, scale = 0.32*0.8}},
}},
{n=G.UIT.R, config={ref_table = self, align = "m", colour = G.C.JOKER_GREY, r = 0.05, padding = 0.06, func = 'blueprint_compat_dside_r'}, nodes={
{n=G.UIT.T, config={ref_table = self.ability, ref_value = 'blueprint_compat_ui_r',colour = G.C.UI.TEXT_LIGHT, scale = 0.32*0.8}},
}}
}}
} or nil
'''
match_indent = true
# Blueprint Compat Jokers Part 2
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "if self.ability.name == 'Blueprint' or self.ability.name == 'Brainstorm' then"
position = "before"
payload = '''
if self.config.center.key == 'j_unstb_plagiarism' then
local other_joker_l = nil
local other_joker_r = nil
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == self then
other_joker_l = G.jokers.cards[i-1]
other_joker_r = G.jokers.cards[i+1]
end
end
if other_joker_l and other_joker_l ~= self and other_joker_l.config.center.blueprint_compat then
self.ability.blueprint_compat_l = 'compatible'
else
self.ability.blueprint_compat_l = 'incompatible'
end
if other_joker_r and other_joker_r ~= self and other_joker_r.config.center.blueprint_compat then
self.ability.blueprint_compat_r = 'compatible'
else
self.ability.blueprint_compat_r = 'incompatible'
end
end
'''
match_indent = true
# Adds support for Virtual Money (used for IC Card)
[[patches]]
[patches.regex]
target = 'functions/button_callbacks.lua'
pattern = '''G.GAME.dollars[ ]*-[ ]*G.GAME.bankrupt_at'''
position = 'at'
payload = '''G.GAME.dollars + (G.GAME.virtual_dollars or 0) - G.GAME.bankrupt_at'''
# Adds support for Virtual Money (used for IC Card)
# (Talisman Variant)
[[patches]]
[patches.regex]
target = 'functions/button_callbacks.lua'
pattern = '''to_big\(G.GAME.dollars\)[ ]*-[ ]*to_big\(G.GAME.bankrupt_at\)'''
position = 'at'
payload = '''to_big(G.GAME.dollars) + to_big(G.GAME.virtual_dollars or 0) - to_big(G.GAME.bankrupt_at)'''

View file

@ -0,0 +1,15 @@
[manifest]
version = "1.0.0"
dump_lua = true
priority = 0
# Shiny Seal
[[patches]]
[patches.pattern]
target = 'card.lua'
pattern = "if self.seal == 'Gold' then G.shared_seals[self.seal]:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center) end"
position = "before"
match_indent = true
payload = '''
if SMODS.Seals[self.seal] and SMODS.Seals[self.seal].shiny then G.shared_seals[self.seal]:draw_shader('voucher', nil, self.ARGS.send_to_shader, nil, self.children.center) end
'''

0
lovely/hello Normal file
View file