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
31 changes: 6 additions & 25 deletions lovely/history.toml
Original file line number Diff line number Diff line change
@@ -1,44 +1,31 @@
[manifest]
version = "1.0"
version = "1.1"
dump_lua = true
priority = 5

[[patches]]
[patches.copy]
target = "globals.lua"
position = "append"
sources = [
"src/Init.lua"
]
sources = [ "src/Init.lua" ]

[[patches]]
[patches.copy]
target = "main.lua"
position = "append"
sources = [
"src/RunHistory.lua",
"src/RunStorage.lua",
"src/Utils.lua"
]
sources = [ "src/RunHistory.lua", "src/RunStorage.lua", "src/Utils.lua" ]

[[patches]]
[patches.copy]
target = "functions/UI_definitions.lua"
position = "append"
sources = [
"src/UI/BaseUI.lua",
"src/UI/RunHistoryUI.lua",
"src/UI/RunStorageUI.lua"
]
sources = [ "src/UI/BaseUI.lua", "src/UI/RunHistoryUI.lua", "src/UI/RunStorageUI.lua" ]

[[patches]]
[patches.copy]
target = "functions/button_callbacks.lua"
position = "append"
sources = [
"src/UI/ButtonCallbacks.lua"
]

sources = [ "src/UI/ButtonCallbacks.lua" ]
[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
Expand All @@ -57,23 +44,17 @@ match_indent = true
overwrite = false
payload = "DV.HIST.queue_save_manager()"

# Below are extensions to engine/save_manager.lua;
# special considerations are needed, because the save manager runs on a thread.

[[patches]]
[patches.module]
source = "src/SaveManager.lua"
before = "engine/save_manager.lua"
name = "DV"
load_now = true

# TODO: `load_now` above is a stopgap solution to the lazy module loading introduced in Lovely v0.6.0
# My hunch is that lazy loading breaks something due to the fact that save manager runs on a thread.

[[patches]]
[patches.pattern]
target = "engine/save_manager.lua"
pattern = "compress_and_save(prefix_profile..'save.jkr', request.save_table)"
pattern = "tal_compress_and_save(prefix_profile..'save.jkr', request.save_table, request.talisman)"
position = "after"
match_indent = true
overwrite = false
Expand Down
29 changes: 2 additions & 27 deletions lovely/settings.toml
Original file line number Diff line number Diff line change
@@ -1,38 +1,13 @@
[manifest]
version = "1.0"
version = "1.1"
dump_lua = true
priority = 10

[[patches]]
[patches.copy]
target = "game.lua"
position = "append"
sources = [
"lib/Balatro-Settings/src/Settings.lua"
]

[[patches]]
[patches.pattern]
target = "functions/UI_definitions.lua"
pattern = "local t = create_UIBox_generic_options({back_func = 'options',contents = {create_tabs("
position = "before"
match_indent = true
overwrite = false
payload = '''
if not DV.settings_tab then
tabs[#tabs+1] = DV.create_settings_tab()
DV.settings_tab = true
end
'''

[[patches]]
[patches.regex]
target = "functions/UI_definitions.lua"
pattern = '''tab_alignment = 'tm',\n\s+snap_to_nav = true}\n\s+\)}}\)\n'''
position = "after"
match_indent = true
overwrite = false
# Reset for next UI create/update
payload = '''
DV.settings_tab = false
'''
payload = "tabs[#tabs+1] = DV.create_settings_tab(#tabs)"
35 changes: 18 additions & 17 deletions metadata.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
{
"id": "DVHistory",
"name": "Divvy's History",
"author": ["Divvy C."],
"description": "Save and load any number of runs! Also, view the history of your played hands and shop purchases!",
"prefix": "dvhistory",
"main_file": "lib/steamodded.lua",
"priority": 0,
"badge_colour": "6495ED",
"badge_text_colour": "FFFFFF",
"version": "3.0.0",
"dependencies": [
"Lovely (>=0.6)"
],
"conflicts": [
"Talisman (>=0.0)"
],
"dump_loc": false
"id": "DVHistory",
"name": "Divvy's History (Fixed Update)",
"author": [
"Divvy C.",
"Community"
],
"description": "Save and load any number of runs! Also, view the history of your played hands and shop purchases! Fixed for Talisman and modern Lovely.",
"prefix": "dvhistory",
"main_file": "lib/steamodded.lua",
"priority": 0,
"badge_colour": "6495ED",
"badge_text_colour": "FFFFFF",
"version": "1.1",
"dependencies": [
"Lovely (>=0.15)"
],
"conflicts": [],
"dump_loc": false
}
96 changes: 89 additions & 7 deletions src/Init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

if not DV then DV = {} end

if DV.HIST then error("Cannot load Divvy's History multiple times!") end

DV.HIST = {
-- TODO: Move key data into `G.GAME.DV`?
history = {},
Expand Down Expand Up @@ -40,19 +38,83 @@ DV.HIST._start_up = Game.start_up
function Game:start_up()
DV.HIST._start_up(self)

-- Initialize settings framework (from DVSettings)
if not G.SETTINGS.DV then G.SETTINGS.DV = {} end
if not G.DV then G.DV = {} end
if not G.DV.options then G.DV.options = {} end

if not G.SETTINGS.DV.HIST then
G.SETTINGS.DV.HIST = true

G.SETTINGS.DV.autosave = true
G.SETTINGS.DV.autosaves_per_run = 5
G.SETTINGS.DV.autosaves_total = 10
end

if not DV.settings then error("Divvy's History requires Divvy's Setting tools; re-install Divvy's History mod and double-check that there is a 'DVSettings' folder") end
DV.settings = true
G.DV.options["Autosaves"] = "get_history_settings_page"

-- Settings UI callback (from DVSettings)
function G.FUNCS.dv_settings_change(args)
if not args or not args.cycle_config then return end
local callback_args = args.cycle_config.opt_args
local page_object = callback_args.ui
local page_wrap = page_object.parent
local new_option_idx = args.to_key
local new_option_def = callback_args.indexed_options[new_option_idx]
page_wrap.config.object:remove()
page_wrap.config.object = UIBox({
definition = DV[G.DV.options[new_option_def]](),
config = { parent = page_wrap, type = "cm" }
})
page_wrap.UIBox:recalculate()
end
end

-- Settings Tab Logic (from DVSettings)
function DV.create_settings_tab(num_tabs)
if num_tabs > 4 then return nil end
return {
label = "Other",
tab_definition_function = DV.get_settings_tab,
}
end

function DV.get_settings_tab()
local options = {}
local first_option_def = nil
for option_name, option_def in pairs(G.DV.options) do
if #options == 0 then first_option_def = option_def end
table.insert(options, option_name)
end
local first_page = UIBox({
definition = DV[first_option_def](),
config = {type = "cm"}
})
if #options == 1 then
return
{n=G.UIT.ROOT, config={align="cm", padding = 0.1, r = 0.1, colour = G.C.CLEAR}, nodes={
{n=G.UIT.O, config={object = first_page}}
}}
end
return
{n=G.UIT.ROOT, config={align = "cm", padding = 0.1, r = 0.1, colour = G.C.CLEAR}, nodes={
{n=G.UIT.C, config={align = "cm"}, nodes={
{n=G.UIT.R, config={align = "tm", minh = 5.5}, nodes={
{n=G.UIT.O, config={object = first_page}}
}},
{n=G.UIT.R, config={align = "bm"}, nodes={
create_option_cycle({
options = options,
current_option = 1,
opt_callback = "dv_settings_change",
opt_args = {ui = first_page, indexed_options = options},
w = 5, colour = G.C.RED, cycle_shoulders = false})
}}
}}
}}
end


DV.HIST._start_run = Game.start_run
function Game:start_run(args)
DV.HIST._start_run(self, args)
Expand All @@ -70,14 +132,34 @@ function Game:start_run(args)
ante = 0,
}
else
-- Loaded run, so extract mod data from loaded data:
DV.HIST.history = G.GAME.DV.history
DV.HIST.latest = G.GAME.DV.latest
-- Loaded run -- G.GAME.DV may be absent if the save predates DVHistory:
if not G.GAME.DV then G.GAME.DV = {} end
-- Generate a run_id if missing (needed by SaveManager to avoid a thread crash):
if not G.GAME.DV.run_id then G.GAME.DV.run_id = DV.HIST.simple_uuid() end
DV.HIST.history = G.GAME.DV.history or {}
DV.HIST.latest = G.GAME.DV.latest or { rel_round = 0, abs_round = 0, ante = 0 }

-- If history is empty the current blind slot was never recorded (select_blind already
-- fired before this continue). Build a minimal slot from the live game state so that
-- shop hooks (get_shop_entry) don't crash on history[ante][round] = nil:
if DV.HIST.latest.ante == 0 then
local ante = (G.GAME.round_resets and G.GAME.round_resets.ante) or 1
local states = (G.GAME.round_resets and G.GAME.round_resets.blind_states) or {}
local rel_round = (states["Small"] == "Current" and 1)
or (states["Big"] == "Current" and 2)
or 3
DV.HIST.latest.ante = ante
DV.HIST.latest.rel_round = rel_round
DV.HIST.latest.abs_round = (ante - 1) * 3 + rel_round
if not DV.HIST.history[ante] then DV.HIST.history[ante] = {} end
if not DV.HIST.history[ante][rel_round] then DV.HIST.history[ante][rel_round] = {} end
end
end
end

DV.HIST._save_run = save_run
function save_run()
if not G.GAME.DV then G.GAME.DV = {} end
G.GAME.DV.history = DV.HIST.history
G.GAME.DV.latest = DV.HIST.latest
DV.HIST._save_run()
Expand Down
6 changes: 0 additions & 6 deletions src/RunHistory.lua
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,6 @@ function G.FUNCS.buy_from_shop(e)
elseif card.ability.set == "Tarot" or card.ability.set == "Planet" or card.ability.set == "Spectral" then
table.insert(shop_entry.consumables, DV.HIST.get_consumable_data(card))
elseif card.ability.set == "Default" or card.ability.set == "Enhanced" then
-- If player bought the Magic Trick voucher and a playing card
-- *in the same shop*, then there would be no `play_cards` field.
-- TODO: Consider a better place/way of doing this:
if not shop_entry.play_cards and G.GAME.playing_card_rate > 0 then
shop_entry.play_cards = {}
end
table.insert(shop_entry.play_cards, DV.HIST.get_card_data(card))
end
end
Expand Down
38 changes: 26 additions & 12 deletions src/RunStorage.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ function DV.HIST.store_run(store_type)
STATE = G.STATE,
ACTION = G.action or nil,
BLIND = G.GAME.blind:save(),
SCORING_CALC = G.GAME.current_scoring_calculation and G.GAME.current_scoring_calculation:save() or nil,
BACK = G.GAME.selected_back:save(),
HISTORY = history_data,
VERSION = G.VERSION
Expand All @@ -58,7 +59,8 @@ function DV.HIST.queue_save_manager()
profile_num = G.SETTINGS.profile,
dv_settings = G.SETTINGS.DV,
dv_paths = DV.HIST.PATHS,
dv_types = DV.HIST.STORAGE_TYPE
dv_types = DV.HIST.STORAGE_TYPE,
talisman = (Talisman and Talisman.config_file and Talisman.config_file.break_infinity)
})
end

Expand All @@ -77,15 +79,8 @@ function Game:update_shop(dt)
if DV.HIST.autosave then
G.E_MANAGER:add_event(Event({
-- This event is queued after all shop events;
-- however, shop events queue more (nested) events, so triggering
-- a save in this event will actually run before most shop events!
trigger = "after",
-- The delay in only necessary to allow some shop events to take place, such as the Coupon tag
-- TODO: Figure out a better way to do this:
-- either combine some shop condition with top-level `if` here,
-- or trigger run storage at a slightly different time?
delay = 1.5,
--
-- however, shop events queue more events, so triggering a save
-- in this event will actually run before most shop events!
func = function()
G.E_MANAGER:add_event(Event({
-- Hence, this event is queued after all shop events are queued:
Expand Down Expand Up @@ -128,13 +123,32 @@ end

function DV.HIST.is_game_over()
local round_beat = false
if G.GAME.chips - G.GAME.blind.chips >= 0 then

local function _compare(a, b)
if to_big then
a = to_big(a)
b = to_big(b)
return a >= b
end
return a >= b
end

local function _compare_ratio(a, b, ratio)
if to_big then
a = to_big(a)
b = to_big(b)
return a / b >= to_big(ratio)
end
return a / b >= ratio
end

if _compare(G.GAME.chips, G.GAME.blind.chips) then
round_beat = true
else
-- Check for any saving graces:
-- TODO: Need a more generic way that doesn't have side-effects (for other mod effects)
for _, joker_obj in ipairs(G.jokers.cards) do
if joker_obj.ability.name == "Mr. Bones" and G.GAME.chips/G.GAME.blind.chips >= 0.25 then
if joker_obj.ability.name == "Mr. Bones" and _compare_ratio(G.GAME.chips, G.GAME.blind.chips, 0.25) then
round_beat = true
end
end
Expand Down
4 changes: 2 additions & 2 deletions src/SaveManager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function DV.HIST.execute_save_manager(request)
save_path = DV.HIST.manage_save(request, history_dir, file_name)
end

compress_and_save(save_path, request.save_table)
tal_compress_and_save(save_path, request.save_table, request.talisman)
end

function DV.HIST.manage_save(request, history_dir, file_name)
Expand Down Expand Up @@ -114,7 +114,7 @@ end

function DV.HIST.get_run_name(save_table)
local seed = save_table.GAME.pseudorandom.seed
local runid = save_table.GAME.DV.run_id
local runid = save_table.GAME.DV.run_id or "unknown"
return seed .."_".. runid
end

Expand Down
1 change: 1 addition & 0 deletions src/UI/BaseUI.lua
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,4 @@ function create_popup_UIBox_tooltip(tooltip)
end
return DV.HIST._create_tooltip(tooltip)
end

Loading