Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
54 changes: 52 additions & 2 deletions lovely/fixes.toml
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,7 @@ target = 'card.lua'
match_indent = true
position = 'after'
pattern = '''
if v ~= chosen_joker then
if v ~= chosen_joker then
'''
payload = '''
v.getting_sliced = true
Expand All @@ -812,4 +812,54 @@ function pseudoshuffle(list, seed)
'''
payload = '''
if seed and type(seed) == "string" then seed = pseudoseed(seed) end
'''
'''

# Update Save Actions to use the inputted function
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = '''for k, v in pairs(G.I.CARD) do
if v.sort_id == saveTable.ACTION.card then
G.FUNCS.use_card({config = {ref_table = v}}, nil, true)
end
end'''
position = 'at'
payload = '''local action_card = nil
for _, card in pairs(G.I.CARD) do
if card.sort_id == saveTable.ACTION.card then
action_card = card
end
if saveTable.ACTION.highlights then
for k, v in pairs(saveTable.ACTION.highlights) do
if card.area and G[k] == card.area and v[card.sort_id] then
card.area:add_to_highlighted(card, true)
end
end
end
end
if action_card then
SMODS.action_nosave = true
G.FUNCS[saveTable.ACTION.type]({config = {ref_table = action_card}}, saveTable.ACTION.args and unpack(saveTable.ACTION.args))
SMODS.action_nosave = nil
end'''
match_indent = true

# added arguments for save actions
[[patches]]
[patches.pattern]
target = "functions/button_callbacks.lua"
pattern = '''if card.ability.set == 'Booster' and not nosave and G.STATE == G.STATES.SHOP then
save_with_action({
type = 'use_card',
card = card.sort_id,
})
end'''
position = 'at'
payload = '''if card.ability.set == 'Booster' and not SMODS.action_nosave and G.STATE == G.STATES.SHOP then
save_with_action({
type = 'use_card',
args = {mute},
card = card.sort_id,
})
end'''
match_indent = true
6 changes: 6 additions & 0 deletions lsp_def/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -747,3 +747,9 @@ function SMODS.check_looping_context(eval_object) end
---@param k? number Index of challenge in G.CHALLENGES. Only relevant for challenges defined outside SMODS
---@return boolean
function SMODS.challenge_is_unlocked(challenge, k) end

---@param cardareas table | nil a map of cardarea keys to access them from the global G table. Passing nil saves all global cardarea highights
---@return table
--- Saves highlighted cards for saved actions that require them
--- Returns a table of sort_id maps, indexed by the keys of their cardareas
function SMODS.save_action_highights(cardareas) end
92 changes: 53 additions & 39 deletions src/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ function SMODS.modify_rank(card, amount, manual_sprites)
rank_data = SMODS.Ranks[rank_key]
end
end

return SMODS.change_base(card, nil, rank_key, manual_sprites)
end

Expand Down Expand Up @@ -1029,7 +1029,7 @@ function SMODS.calculate_quantum_enhancements(card, effects, context)
local old_center = card.config.center
local old_center_key = card.config.center_key
-- Note: For now, just trigger extra enhancements in order.
-- Future work: combine enhancements during
-- Future work: combine enhancements during
-- playing card scoring (ex. Mult comes before Glass because +_mult
-- naturally comes before x_mult)
local extra_enhancements_list = {}
Expand Down Expand Up @@ -1245,7 +1245,7 @@ SMODS.calculate_individual_effect = function(effect, scored_card, key, amount, f
if (key == 'p_dollars' or key == 'dollars' or key == 'h_dollars') and amount then
if effect.card and effect.card ~= scored_card then juice_card(effect.card) end
SMODS.ease_dollars_calc = true
ease_dollars(amount)
ease_dollars(amount)
SMODS.ease_dollars_calc = nil
if not effect.remove_default_message then
if effect.dollar_message then
Expand Down Expand Up @@ -1305,7 +1305,7 @@ SMODS.calculate_individual_effect = function(effect, scored_card, key, amount, f
blockable = false,
blocking = false,
delay = 0.8,
func = (function()
func = (function()
ease_colour(G.C.UI_CHIPS, G.C.BLUE, 0.8)
ease_colour(G.C.UI_MULT, G.C.RED, 0.8)
return true
Expand All @@ -1317,7 +1317,7 @@ SMODS.calculate_individual_effect = function(effect, scored_card, key, amount, f
blocking = false,
no_delete = true,
delay = 1.3,
func = (function()
func = (function()
G.C.UI_CHIPS[1], G.C.UI_CHIPS[2], G.C.UI_CHIPS[3], G.C.UI_CHIPS[4] = G.C.BLUE[1], G.C.BLUE[2], G.C.BLUE[3], G.C.BLUE[4]
G.C.UI_MULT[1], G.C.UI_MULT[2], G.C.UI_MULT[3], G.C.UI_MULT[4] = G.C.RED[1], G.C.RED[2], G.C.RED[3], G.C.RED[4]
return true
Expand Down Expand Up @@ -1358,16 +1358,16 @@ SMODS.calculate_individual_effect = function(effect, scored_card, key, amount, f
if key == 'effect' then
return true
end

if key == 'prevent_debuff' or key == 'add_to_hand' or key == 'remove_from_hand' or key == 'stay_flipped' or key == 'prevent_stay_flipped' or key == 'prevent_trigger' then
return key
end

if key == 'remove' or key == 'debuff_text' or key == 'cards_to_draw' or key == 'numerator' or key == 'denominator' or key == 'no_destroy' or
if key == 'remove' or key == 'debuff_text' or key == 'cards_to_draw' or key == 'numerator' or key == 'denominator' or key == 'no_destroy' or
key == 'replace_scoring_name' or key == 'replace_display_name' or key == 'replace_poker_hands' or key == 'modify' then
return { [key] = amount }
end

if key == 'debuff' then
return { [key] = amount, debuff_source = scored_card }
end
Expand Down Expand Up @@ -1536,20 +1536,20 @@ SMODS.calculate_repetitions = function(card, context, reps)
-- After each inserted repetition we insert the post effects
local new_size = #reps
for i = curr_size + 1, new_size do
if not first then
if not first then
post = {}
if not context.post_trigger and SMODS.optional_features.post_trigger then
SMODS.calculate_context({blueprint_card = context.blueprint_card, post_trigger = true, other_card = _card, other_context = context, other_ret = eval}, post)
end
end
first = nil
if next(post) then
if next(post) then
reps[#reps - new_size + i].retriggers.retrigger_flag = true
else break end
-- index from behind since that doesn't change
for idx, eff in ipairs(post) do
if next(eff) then
select(2, next(eff)).retrigger_flag = true
select(2, next(eff)).retrigger_flag = true
table.insert(reps, #reps + 1 - new_size + i, eff)
end
end
Expand Down Expand Up @@ -1648,7 +1648,7 @@ function Card:calculate_edition(context)
end
end
end
end
end

function SMODS.calculate_card_areas(_type, context, return_table, args)
local flags = {}
Expand All @@ -1669,7 +1669,7 @@ function SMODS.calculate_card_areas(_type, context, return_table, args)

local effects = {eval}
for _,v in ipairs(post) do effects[#effects+1] = v end

if context.other_joker then
for k, v in pairs(effects[1]) do
v.other_card = _card
Expand Down Expand Up @@ -1834,7 +1834,7 @@ SMODS.current_evaluated_object = nil
-- Joker B calls SMODS.pseudorandom_probability() to check whether it should trigger
-- A loop is caused (ignore the fact that Joker B would be the trigger_obj and not a playing card) (I'd write a Quantum Ranks example, If I had any!!)
-- To avoid this; Check before evaluating any object, whether the current getter context type (if it's a getter context) has previously caused said object to create a getter context,
-- if yes, don't evaluate the object.
-- if yes, don't evaluate the object.
function SMODS.is_getter_context(context)
if context.mod_probability or context.fix_probability then return "probability" end
if context.check_enhancement then return "enhancement" end
Expand All @@ -1861,7 +1861,7 @@ end
-- SMODS.context_stack = {1: {context = [unique context 1], count = [number of times it was added consecutively], caller = [the SMODS.current_evaluated_object when the context was added]}, ...}
-- (Contexts may repeat non-consecutively, though I don't think they ever should..)
-- Allows some advanced effects, like:
-- Individual playing cards modifying probabilities checked during individual scoring, only when they're the context.other_card
-- Individual playing cards modifying probabilities checked during individual scoring, only when they're the context.other_card
-- (-> By checking the context in the stack PRIOR to the mod_probability context for the .individual / .other_card flags)
SMODS.context_stack = {}

Expand Down Expand Up @@ -1906,16 +1906,16 @@ function SMODS.calculate_context(context, return_table, no_resolve)
context.main_eval = true
flags[#flags+1] = SMODS.calculate_card_areas('jokers', context, return_table, { joker_area = true, has_area = has_area })
context.main_eval = nil

flags[#flags+1] = SMODS.calculate_card_areas('playing_cards', context, return_table, { has_area = has_area })
context.main_eval = true
flags[#flags+1] = SMODS.calculate_card_areas('individual', context, return_table)
context.main_eval = nil

if SMODS.no_resolve then SMODS.no_resolve = nil end

SMODS.pop_from_context_stack(context, "utils.lua : SMODS.calculate_context")

if not return_table then
local ret = {}
for i,f in ipairs(flags) do
Expand All @@ -1938,8 +1938,8 @@ function SMODS.score_card(card, context)
while j <= #reps do
if reps[j] ~= 1 then
local _, eff = next(reps[j])
while eff.retrigger_flag do
SMODS.calculate_effect(eff, eff.card); j = j+1; _, eff = next(reps[j])
while eff.retrigger_flag do
SMODS.calculate_effect(eff, eff.card); j = j+1; _, eff = next(reps[j])
end
SMODS.calculate_effect(eff, eff.card)
percent = percent + percent_delta
Expand Down Expand Up @@ -1985,7 +1985,7 @@ function SMODS.calculate_main_scoring(context, scoring_hand)
end
--if card is debuffed
if scoring_hand and card.debuff then
if in_scoring then
if in_scoring then
G.GAME.blind.triggered = true
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
Expand Down Expand Up @@ -2051,7 +2051,7 @@ function SMODS.calculate_destroying_cards(context, cards_destroyed, scoring_hand
local destroyed = nil
--un-highlight all cards
local in_scoring = scoring_hand and SMODS.in_scoring(card, context.scoring_hand)
if scoring_hand and in_scoring and not card.destroyed then
if scoring_hand and in_scoring and not card.destroyed then
-- Use index of card in scoring hand to determine pitch
local m = 1
for j, _card in pairs(scoring_hand) do
Expand Down Expand Up @@ -2145,7 +2145,7 @@ function SMODS.get_card_areas(_type, _context)
{ object = G.GAME.selected_back, scored_card = G.deck.cards[1] or G.deck },
}
if G.GAME.blind then t[#t + 1] = { object = G.GAME.blind, scored_card = G.GAME.blind.children.animatedSprite } end
if G.GAME.challenge then t[#t + 1] = { object = SMODS.Challenges[G.GAME.challenge], scored_card = G.deck.cards[1] or G.deck } end
if G.GAME.challenge then t[#t + 1] = { object = SMODS.Challenges[G.GAME.challenge], scored_card = G.deck.cards[1] or G.deck } end
for _, stake in ipairs(SMODS.get_stake_scoring_targets()) do
t[#t + 1] = { object = stake, scored_card = G.deck.cards[1] or G.deck }
end
Expand Down Expand Up @@ -2576,9 +2576,9 @@ function SMODS.destroy_cards(cards, bypass_eternal, immediate, skip_anim)
card.skip_destroy_animation = skip_anim
end
end

check_for_unlock{type = 'shatter', shattered = glass_shattered}

if next(playing_cards) then SMODS.calculate_context({scoring_hand = cards, remove_playing_cards = true, removed = playing_cards}) end

for i = 1, #cards do
Expand Down Expand Up @@ -2630,8 +2630,8 @@ end

function SMODS.draw_cards(hand_space)
if not (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) and
G.hand.config.card_limit <= 0 and #G.hand.cards == 0 then
G.STATE = G.STATES.GAME_OVER; G.STATE_COMPLETE = false
G.hand.config.card_limit <= 0 and #G.hand.cards == 0 then
G.STATE = G.STATES.GAME_OVER; G.STATE_COMPLETE = false
return true
end

Expand All @@ -2640,7 +2640,7 @@ function SMODS.draw_cards(hand_space)
delay(0.3)
SMODS.drawn_cards = {}
for i=1, hand_space do --draw cards from deckL
if G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK then
if G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK then
draw_card(G.deck,G.hand, i*100/hand_space,'up', true)
else
draw_card(G.deck,G.hand, i*100/hand_space,'up', true)
Expand Down Expand Up @@ -2691,7 +2691,7 @@ function SMODS.merge_effects(...)
local t = {}
for _, v in ipairs({...}) do
for _, vv in ipairs(v) do
if vv == true or (type(vv) == "table" and next(vv)) then
if vv == true or (type(vv) == "table" and next(vv)) then
table.insert(t, vv)
end
end
Expand Down Expand Up @@ -2786,7 +2786,7 @@ function Game:start_run(args)
game_start_run(self, args)
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
func = function()
func = function()
SMODS.refresh_score_UI_list()
return true
end
Expand All @@ -2805,14 +2805,14 @@ G.FUNCS.SMODS_scoring_calculation_function = function(e)
else
e.children[1].UIBox:add_child(SMODS.GUI.hand_chips_container(scale), e.children[1])
end
e.config.current_scoring_calculation = G.GAME.current_scoring_calculation.key
e.config.current_scoring_calculation = G.GAME.current_scoring_calculation.key
end

local container = e.children[1].children[2]
local chip_display = container.UIBox:get_UIE_by_ID('hand_chips_container')
local operator = container.UIBox:get_UIE_by_ID('hand_operator_container')
local mult_display = container.UIBox:get_UIE_by_ID('hand_mult_container')

if G.GAME.current_scoring_calculation.update_ui then
G.GAME.current_scoring_calculation:update_ui(container, chip_display, mult_display, operator)
else
Expand Down Expand Up @@ -2879,7 +2879,7 @@ function SMODS.scale_card(card, args)
end
end
end

if type(args.operation) == 'function' then
args.operation(args.ref_table, args.ref_value, initial, scalar_value)
elseif args.operation == 'X' then
Expand All @@ -2889,7 +2889,7 @@ function SMODS.scale_card(card, args)
else
SMODS.additive_scaling(args.ref_table, args.ref_value, initial, scalar_value)
end

scaling_message = scaling_message or {
message = localize(args.message_key and {type='variable',key=args.message_key,vars={args.message_key =='a_xmult' and args.ref_table[args.ref_value] or scalar_value}} or 'k_upgrade_ex'),
colour = args.message_colour or G.C.FILTER,
Expand Down Expand Up @@ -3072,7 +3072,7 @@ function UIElement:draw_pixellated_under(_type, _parallax, _emboss, _progress)
self.pixellated_rect.sw ~= self.shadow_parrallax.x or
self.pixellated_rect.sh ~= self.shadow_parrallax.y or
self.pixellated_rect.progress ~= (_progress or 1)
then
then
self.pixellated_rect = {
w = self.VT.w,
h = self.VT.h,
Expand Down Expand Up @@ -3189,7 +3189,7 @@ function CardArea:handle_card_limit()
self.config.card_limits.total_slots = self.config.card_limits.extra_slots + (self.config.card_limits.base or 0) + (self.config.card_limits.mod or 0)
self.config.card_limits.extra_slots_used = self:count_property('extra_slots_used')
self.config.card_count = #self.cards + self.config.card_limits.extra_slots_used

if G.hand and self == G.hand and self.config.card_count + (SMODS.cards_to_draw or 0) < self.config.card_limits.total_slots then
if G.STATE == G.STATES.DRAW_TO_HAND and not SMODS.blind_modifies_draw(G.GAME.blind.config.blind.key) and not SMODS.draw_queued then
SMODS.draw_queued = true
Expand All @@ -3201,7 +3201,7 @@ function CardArea:handle_card_limit()
trigger = 'immediate',
func = function()
if (self.config.card_limits.total_slots - self.config.card_count - (SMODS.cards_to_draw or 0)) > 0 and #G.deck.cards > (SMODS.cards_to_draw or 0) then
G.FUNCS.draw_from_deck_to_hand(self.config.card_limits.total_slots - self.config.card_count - (SMODS.cards_to_draw or 0))
G.FUNCS.draw_from_deck_to_hand(self.config.card_limits.total_slots - self.config.card_count - (SMODS.cards_to_draw or 0))
end
return true
end
Expand All @@ -3225,4 +3225,18 @@ end
-- Function used to determine whether the current blind modifies the number of cards drawn
function SMODS.blind_modifies_draw(key)
if SMODS.Blinds.modifies_draw[key] then return true end
end
end

-- saving highights for any card actions you might want saved between runs, similar to boosters
function SMODS.save_action_highights(cardareas)
local highlights = {}
for k, v in pairs(G) do
if (type(v) == "table") and v.is and v:is(CardArea) and (not cardareas or cardareas[k]) and #v.highlighted > 0 then
highlights[k] = {}
for _, highlight in ipairs(v.highlighted) do
highlights[k][highlight.sort_id] = true
end
end
end
return next(highlights) and highlights or nil
end