Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
b5293f9
Moved over `SMODS.GameState` API from #1055.
AllUniversal Apr 4, 2026
13a051f
More WIP moving.
AllUniversal Apr 4, 2026
1a37766
Also moved over Blind types
AllUniversal Apr 4, 2026
2beaffd
More moving.
AllUniversal Apr 4, 2026
42f50c2
More
AllUniversal Apr 4, 2026
d2f28ca
Still WIP
AllUniversal Apr 4, 2026
fcc7317
Made stuff functional
AllUniversal Apr 4, 2026
504e904
Refactored `on_enter` and `on_exit` for `SMODS.GameState`s and change…
AllUniversal Apr 4, 2026
86aaa7b
More refactoring + WIP Per-instance state stuff (e.g. to allow creati…
AllUniversal Apr 4, 2026
75a7384
Moved `SMODS.GameStates` to new file and removed `SMODS.clear_states()`
AllUniversal Apr 4, 2026
0816bab
Forgot to load the new file
AllUniversal Apr 4, 2026
4f07bff
Minor refactoring
AllUniversal Apr 4, 2026
852b932
Readded `G.FUNCS.use_card()` patches
AllUniversal Apr 4, 2026
7d8997c
Added `G.FUNCS.use_card()` `GameState` patches
AllUniversal Apr 4, 2026
c695f38
Removed `G.FUNCS.end_consumeable()` override in favor of patches
AllUniversal Apr 4, 2026
e266c02
Merge remote-tracking branch 'upstream/main' into smods-game-states
AllUniversal Apr 6, 2026
fa584de
Added more `SMODS.state_stack` utility functions + polished `from_hol…
AllUniversal Apr 6, 2026
0432c5b
Minor refactor + fix
AllUniversal Apr 6, 2026
c6eaeb4
Minor refactor^2
AllUniversal Apr 6, 2026
2da4e78
Added `SMODS.state_queue`
AllUniversal Apr 6, 2026
dc400d1
Added missing clean-up function + refactored
AllUniversal Apr 6, 2026
8fc368a
Removed relic from AntePath PR
AllUniversal Apr 6, 2026
d648009
Fix crash
AllUniversal Apr 6, 2026
9a3cc4d
Removed unnecessary override
AllUniversal Apr 6, 2026
9be6b7e
Fixed Showdown Blinds crashing / being missing
AllUniversal Apr 7, 2026
d2c2bbd
Implemented holding `SMODS.STATES.BLIND` + saving and loading the `SM…
AllUniversal Apr 7, 2026
121bbb6
Fixed / Improved saving and loading `BLIND` and `SHOP` states.
AllUniversal Apr 7, 2026
afc238b
Removed Todo marker
AllUniversal Apr 7, 2026
a8e2636
Restored `end_round()` and `G.FUNCS.evaluate_round()` patches
AllUniversal Apr 7, 2026
fae6f61
Missing patch
AllUniversal Apr 7, 2026
5a35ba3
Updated `SMODS.get_new_blind()` and according `weight` function
AllUniversal Apr 7, 2026
35236c4
Minor refactor
AllUniversal Apr 7, 2026
4b325c7
Fixed Blind related crash + added `args.leave_sign` to `SHOP` state's…
AllUniversal Apr 8, 2026
91a899d
Moved `blind_types` and related over to new PR
AllUniversal Apr 8, 2026
1775810
Moved patches
AllUniversal Apr 8, 2026
4ffae2a
Readded missing `Blind` patch
AllUniversal Apr 8, 2026
e5bbe16
Added `args.leave_HUD_blind` to `BLIND`'s `on_exit()`
AllUniversal Apr 8, 2026
daedeb2
Merge remote-tracking branch 'upstream/main' into smods-game-states
AllUniversal Apr 10, 2026
040423b
Merge remote-tracking branch 'upstream/main' into smods-game-states
AllUniversal Apr 20, 2026
f46bdcf
Merge remote-tracking branch 'upstream/main' into smods-game-states
AllUniversal May 1, 2026
5f390f1
Merge remote-tracking branch 'upstream/main' into smods-game-states
AllUniversal May 6, 2026
d8ab74b
Merge remote-tracking branch 'upstream/main' into smods-game-states
AllUniversal May 17, 2026
bcae37d
Generalized `SMODS.get_card_by_sort_id` to find any card.
AllUniversal May 17, 2026
6d1df45
Merge remote-tracking branch 'upstream/main' into smods-game-states
AllUniversal Jun 1, 2026
a15ddcd
Added `SMODS.STATES.USE_CONSUMABLE` + refactored a bunch
AllUniversal Jun 2, 2026
757099b
WIP Fix for double `end_round()` call
AllUniversal Jun 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lovely/better_calc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2154,7 +2154,7 @@ table.sort(G.playing_cards, function (a, b) return a.playing_card > b.playing_ca
'''
payload = '''
if saveTable then
if saveTable.SMODS then
if saveTable.SMODS and saveTable.SMODS.last_hand then
SMODS.last_hand = {scoring_hand = {}, full_hand = {}, scoring_name = saveTable.SMODS.last_hand.scoring_name}
for _, v in ipairs({'scoring_hand','full_hand'}) do
for _, card in ipairs(G.playing_cards) do
Expand Down
117 changes: 55 additions & 62 deletions lovely/booster.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,53 @@ priority = -10
[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
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

G.GAME.pack_choices = self.config.center.config.choose or 1'''
if self.cost > 0 then
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function()
inc_career_stat('c_shop_dollars_spent', self.cost)
self:juice_up()
return true end }))
ease_dollars(-self.cost)
else
delay(0.2)
end'''
match_indent = true
position = "at"
payload = """
G.GAME.pack_choices = math.min((self.ability.choose or self.config.center.config.choose or 1) + (G.GAME.modifiers.booster_choice_mod or 0), self.ability.extra and math.max(1, self.ability.extra + (G.GAME.modifiers.booster_size_mod or 0)) or self.config.center.extra and math.max(1, self.config.center.extra + (G.GAME.modifiers.booster_size_mod or 0)) or 1)
if self.cost > 0 then
G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.2, func = function()
inc_career_stat('c_shop_dollars_spent', self.cost)
self:juice_up()
return true end }))
ease_dollars(-self.cost)
else
delay(0.2)
end
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
SMODS.enter_state(SMODS.STATES.BOOSTER_OPENED, nil, {from_hold = true, leave_shop_sign = true, leave_HUD_blind = true})
end
G.GAME.pack_choices = math.min((self.ability.choose or self.config.center.config.choose or 1) + (G.GAME.modifiers.booster_choice_mod or 0), self.ability.extra and math.max(1, self.ability.extra + (G.GAME.modifiers.booster_size_mod or 0)) or self.config.center.extra and math.max(1, self.config.center.extra + (G.GAME.modifiers.booster_size_mod or 0)) or 1)
"""
""" # Reordered to maintain vanilla timing

# Card:open
# Adds modifier for size of booster
Expand Down Expand Up @@ -89,40 +108,14 @@ payload = '''
SMODS.calculate_context({modify_booster_card = true, booster = self, card = card, index = i})
'''

# Game:set_globals
[[patches]]
[patches.regex]
target = "globals.lua"
pattern = '''(?<indent>[\t ]*)self\.STATES = \{'''
position = "after"
payload = '''

SMODS_BOOSTER_OPENED = 999,
SMODS_REDEEM_VOUCHER = 998,'''
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
# G.FUNCS.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'''
payload = '''(G.STATE == SMODS.STATES.BOOSTER_OPENED or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.STANDARD_PACK'''

# CardArea:draw()
[[patches]]
Expand All @@ -131,7 +124,7 @@ 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'''
(self.config.type == 'hand' and SMODS.in_booster()) or'''
match_indent = true

# G.FUNCS.use_card
Expand All @@ -141,7 +134,7 @@ 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'''
prev_state == SMODS.STATES.BOOSTER_OPENED or'''
match_indent = true

# CardArea:align_cards()
Expand All @@ -150,7 +143,7 @@ match_indent = true
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"
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 SMODS.in_booster()) then"
match_indent = true

# CardArea:align_cards()
Expand All @@ -159,7 +152,7 @@ match_indent = true
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"
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 SMODS.in_booster()) then"
match_indent = true

# Card:can_use_consumable()
Expand All @@ -168,7 +161,7 @@ match_indent = true
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"
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 == SMODS.STATES.BOOSTER_OPENED then"
match_indent = true

# G.FUNCS.use_card()
Expand All @@ -183,7 +176,7 @@ if nc then
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"""
if (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.SPECTRAL_PACK or SMODS.in_booster()) then"""
match_indent = true

# G.FUNC.use_card()
Expand All @@ -203,7 +196,7 @@ 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'''
payload = '''if prev_state == SMODS.STATES.BOOSTER_OPENED and booster_obj.name:find('Arcana') then inc_career_stat('c_tarot_reading_used', 1) end'''

# G.FUNC.use_card()
[[patches]]
Expand All @@ -212,24 +205,24 @@ 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'''
payload = '''if prev_state == SMODS.STATES.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"
payload = "(G.STATE == SMODS.STATES.BOOSTER_OPENED and SMODS.STATES.BOOSTER_OPENED) or"
match_indent = true

# G.FUNC.use_card()
# G.FUNC.draw_from_deck_to_hand()
[[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"
payload = "if not (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == SMODS.STATES.BOOSTER_OPENED) and"
match_indent = true

# Card:use_consumeable()
Expand All @@ -239,8 +232,8 @@ 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},'''
align = (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or SMODS.in_booster()) and 'tm' or 'cm',
offset = {x = 0, y = (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or SMODS.in_booster()) and -0.2 or 0},'''
line_prepend = '$indent'

# G.FUNCS.use_card()
Expand Down Expand Up @@ -462,7 +455,7 @@ target = 'card.lua'
match_indent = true
position = 'after'
pattern = '''if self.shop_voucher then G.GAME.current_round.voucher = nil end'''
payload = '''G.STATE = G.STATES.SMODS_REDEEM_VOUCHER'''
payload = '''SMODS.enter_state(SMODS.STATES.REDEEM_VOUCHER, nil, {from_hold = true, leave_shop_sign = true, leave_HUD_blind = true, leave_data = true, no_sound = true})'''

# G.FUNCS.use_card()
# Consumables in areas other than the consumable don't count
Expand Down
2 changes: 1 addition & 1 deletion lovely/center.toml
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,6 @@ if G.booster_pack and not G.booster_pack.alignment.offset.py and ((not select_to

'''


# G.FUNCS.use_card()
[[patches]]
[patches.pattern]
Expand All @@ -534,6 +533,7 @@ position = 'at'
payload = '''
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'
Expand Down
2 changes: 1 addition & 1 deletion lovely/fixes.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ target = 'functions/misc_functions.lua'
pattern = "function save_run()"
position = "after"
payload = """ 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.BUFFOON_PACK or G.STATE == G.STATES.STANDARD_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED then return end"""
or G.STATE == G.STATES.BUFFOON_PACK or G.STATE == G.STATES.STANDARD_PACK or G.STATE == SMODS.STATES.BOOSTER_OPENED then return end"""
match_indent = true

## Set `G.your_collection.config.collection` to true in all cases
Expand Down
Loading