file = {}
nextSaveLoadPlayer = -1 -- used to queue up the players when saving/loading
function file:load(player, _file_slot, _timeout)
local file_slot = _file_slot or 0
if file_slot <= file.capacity then
if not file.in_progress then
file.player = player
local timeout = _timeout or 1.5
local pid = pnum(player)
file.in_progress = true
file:reset_abils(player)
debug(function()
timed(timeout, function()
if not udg_save_load_hero[pid] and file.in_progress then
file.in_progress = false
if is_local(player) then
print("Load Timeout: Failed to load character from file slot "..tostring(file_slot)..". File is corrupt.")
end
end
end)
if is_local(player) then
Preloader(file.folder.."\\"..file.name..tostring(file_slot)..".pld")
if file:read(player) then
file:sync()
else
file.data = ""
end
end
file.in_progress = false
GetNextSaveLoadPlayer(false) -- true = save / false = load
end)
elseif is_local(player) then
print(msg.on_conflict)
end
elseif is_local(player) then
print(msg.over_capacity)
end
end
function file:save(player, _file_slot)
local file_slot = _file_slot or 0
if file_slot <= file.capacity then
if not file.in_progress then
file.in_progress = true
local seed = ""
for _ = 1,12 do
seed = seed..tostring(math.random(1,5)) -- running this locally causes a desync.
end
if is_local(player) then
save_char = char:save(player, udg_save_load_hero[pnum(player)])
file:reset_abils(player)
-- because of the 259 character limit in a preload line, we must break each string into groups.
save_char:save_data()
local data, _, sum = encrypt:basic(save_char.data, seed, true)
save_char.metadata = save_char.metadata..seed..","..tostring(sum)..file.meta_delimiter
local chunk_size, pos, posend = 200, 0, 0
local chunk_count = math.ceil(string.len(data)/chunk_size)
PreloadGenClear()
PreloadGenStart()
Preload("\")\ncall BlzSetAbilityTooltip('"..file.abil[1].."',\""..save_char.metadata.."\",".."0"..")\n//")
if chunk_count > 1 then
for chunk = 2,chunk_count do
pos = 1 + ((chunk-1)*chunk_size)
posend = chunk*chunk_size
if chunk < chunk_count then
Preload("\")\ncall BlzSetAbilityTooltip('"..file.abil[chunk].."',\""..string.sub(data, pos, posend).."\",".."0"..")\n//")
elseif chunk == chunk_count then
Preload("\")\ncall BlzSetAbilityTooltip('"..file.abil[chunk].."',\""..string.sub(data, pos, posend).."\",".."0"..")\n//")
end
end
else
Preload("\")\ncall BlzSetAbilityTooltip('"..file.abil[2].."',\""..data.."\",".."0"..")\n//")
end
Preload("\" )\nendfunction\nfunction a takes nothing returns nothing\n //")
PreloadGenEnd(file.folder.."\\"..file.name..tostring(file_slot)..".pld")
--print(msg.on_save)
save_char = nil
end
seed = nil
file.in_progress = false
GetNextSaveLoadPlayer(true) -- true = save / false = load
elseif is_local(player) then
print(msg.on_conflict)
end
elseif is_local(player) then
print(msg.over_capacity)
end
end
-- this will run inside the file:save / file:load functions
function GetNextSaveLoadPlayer(saveGame)
nextSaveLoadPlayer = nextSaveLoadPlayer + 1
local p = Player(nextSaveLoadPlayer)
if GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(p) == MAP_CONTROL_USER then
local t1 = CreateTimer()
TimerStart(t1, 1.0, false, function()
PauseTimer(t1)
DestroyTimer(t1)
if saveGame then
file:save(p, 0)
else
file:load(p, 0, 1.5)
end
end)
elseif nextSaveLoadPlayer < 3 then
-- try again if that player didn't exist
GetNextSaveLoadPlayer(saveGame)
end
end
-- call these from your GUI triggers to start the save/load process
function SaveTheGame()
nextSaveLoadPlayer = -1
GetNextSaveLoadPlayer(true) -- save
end
function LoadTheGame()
nextSaveLoadPlayer = -1
GetNextSaveLoadPlayer(false) -- load
end