feat: extend game with Graves.record and Graves.eligibleFor

This commit is contained in:
dualfroz committed 2026-09-06 20:02:24 +02:00
1 parent 5f13d7012e
commit cb01478890
2 files changed
+183 -4

No files matched your search

+77 -4
View File
@@ -2638,35 +2638,108 @@ function Game:toData()
identify = self.identify,
dungeon = self.dungeon:toData(),
player = self.player:toData(),
playerExtra = { satiation = self.player.satiation, light = self.player.light },
playerExtra = {
satiation = self.player.satiation, sanity = self.player.sanity, light = self.player.light,
level = self.player.level, xp = self.player.xp, xpNext = self.player.xpNext,
mana = self.player.mana, maxMana = self.player.maxMana, spellsKnown = self.player.spellsKnown,
gold = self.player.gold, essence = self.player.essence,
class = self.player.class, skills = self.player.skills,
skillPoints = self.player.skillPoints, skillCooldowns = self.player.skillCooldowns,
quest = self.player.quest, reputation = self.player.reputation,
pendingPoisonBlade = self.player.pendingPoisonBlade,
},
log = self.log:toData(),
compendium = self.compendium,
ascension = self.ascension,
nemesis = self.nemesis,
rift = self.rift or false,
riftLevels = Branches.levelsToData(self.riftLevels),
riftReturn = self.riftReturn and {
depth = self.riftReturn.depth, x = self.riftReturn.x, y = self.riftReturn.y,
} or nil,
-- The arena itself lives outside self.dungeon (see Game:startHorde), so
-- without its own snapshot here a mid-arena save would resume from
-- self.dungeon:get(self.depth) instead - the ordinary floor the arena
-- replaced, abandoned but still cached. horde.wave rides along in the
-- same field, since a restored arena with no wave counter would strand
-- the player once the surviving wave dies with nothing left to trigger
-- the next one.
horde = self.horde,
hordeLevel = self.horde and self.level:toData() or nil,
}
end
-- Expects a complete, current-shape snapshot: every field GameSave's
-- migration chain owns (essence, the skill-tree fields, reputation, sanity,
-- stats.vaultsOpened/setPiecesFound - see the migrations above) must already
-- be present. Game.load guarantees that by running GameSave.load first;
-- Game:toData()'s own output always has them too. A handful of unversioned
-- fields (won, monsterSeq, deepestDepth, the whole stats table) keep their
-- own "or" defaults here since they can be missing outright rather than just
-- missing individual leaves, which the migration chain does not model.
function Game.fromData(snapshot)
local game = setmetatable({}, Game)
game.seed = snapshot.seed
game.depth = snapshot.depth
game.turn = snapshot.turn
game.won = snapshot.won or false
game.monsterSeq = snapshot.monsterSeq or 0
game.deepestDepth = snapshot.deepestDepth or snapshot.depth
game.stats = snapshot.stats or {
kills = 0, bossKills = 0, questsCompleted = 0, artifactsFound = 0, vaultsOpened = 0,
setPiecesFound = 0,
}
game.rng = Rng.deserialize(snapshot.rng)
game.identify = snapshot.identify
game.dungeon = Dungeon.fromData(snapshot.dungeon)
game.level = game.dungeon:get(game.depth)
game.maxDepth = Builder.maxDepth(game.dungeon.options)
game.rift = snapshot.rift or false
game.riftLevels = Branches.levelsFromData(snapshot.riftLevels)
game.riftReturn = snapshot.riftReturn and {
depth = snapshot.riftReturn.depth, x = snapshot.riftReturn.x, y = snapshot.riftReturn.y,
level = game.dungeon:get(snapshot.riftReturn.depth),
} or nil
game.horde = snapshot.horde
game.level = game.horde and Level.fromData(snapshot.hordeLevel)
or (game.rift and game.riftLevels[game.depth] or game.dungeon:get(game.depth))
game.player = Entity.fromData(snapshot.player)
game.player.satiation = snapshot.playerExtra.satiation
game.player.sanity = snapshot.playerExtra.sanity
game.player.light = snapshot.playerExtra.light
game.player.level = snapshot.playerExtra.level
game.player.xp = snapshot.playerExtra.xp
game.player.xpNext = snapshot.playerExtra.xpNext
game.player.mana = snapshot.playerExtra.mana
game.player.maxMana = snapshot.playerExtra.maxMana
game.player.spellsKnown = snapshot.playerExtra.spellsKnown
game.player.gold = snapshot.playerExtra.gold
game.player.essence = snapshot.playerExtra.essence
game.player.class = snapshot.playerExtra.class
game.player.skills = snapshot.playerExtra.skills
game.player.skillPoints = snapshot.playerExtra.skillPoints
game.player.skillCooldowns = snapshot.playerExtra.skillCooldowns
game.player.quest = snapshot.playerExtra.quest
game.player.reputation = snapshot.playerExtra.reputation
game.player.pendingPoisonBlade = snapshot.playerExtra.pendingPoisonBlade
game.log = MessageLog.fromData(snapshot.log)
game.compendium = snapshot.compendium or Compendium.new()
game.ascension = snapshot.ascension or {}
game.nemesis = snapshot.nemesis
game.visible = {}
game:computeVisible()
return game
end
function Game:save(path)
Serialize.saveFile(path, self:toData())
GameSave.save(path, self:toData())
end
function Game.load(path)
return Game.fromData(Serialize.loadFile(path))
local data, err = GameSave.load(path)
if not data then
error("cannot load save " .. path .. ": " .. err)
end
return Game.fromData(data)
end
return Game