feat: extend game with Graves.record and Graves.eligibleFor
This commit is contained in:
1 parent
5f13d7012e
commit
cb01478890
2 files changed
+183
-4
No files matched your search
+106
@@ -0,0 +1,106 @@
|
||||
-- Cross-run bones: the moment a run ends in death (see warren.lua's --meta
|
||||
-- path and Game:graveEntry), a grave entry is appended to meta.lua's
|
||||
-- persistent save - what the fallen was still carrying, and how deep they
|
||||
-- got. From the very next run on, Builder.build may roll one of those
|
||||
-- graves onto a floor at or shallower than where it was dug (bones drift
|
||||
-- upward over time, never down - see Graves.eligibleFor) as an inert
|
||||
-- floorItem, drawn dead last of all so a run without any recorded deaths
|
||||
-- (or one played without --meta at all) makes no extra rng draw and its
|
||||
-- floor layouts stay byte-identical to before this module existed.
|
||||
--
|
||||
-- Unlike mimics.lua's disguise, a grave marker is honest about what it is -
|
||||
-- disturbing it (Game:pickupHere, mirroring Game:triggerMimic) wakes a
|
||||
-- vengeful shade rather than pretending to be ordinary loot. The shade's
|
||||
-- hp and attack scale with how much the fallen was carrying at death, and
|
||||
-- felling it in turn pays out a fraction of that same hoard - a richer
|
||||
-- death makes for a tougher fight and a richer reward, but always strictly
|
||||
-- less than what was actually lost.
|
||||
|
||||
local Entity = require("entity")
|
||||
local Factions = require("factions")
|
||||
|
||||
local Graves = {}
|
||||
|
||||
-- Oldest graves fall off once a save accumulates more than this many, so a
|
||||
-- long-lived meta file never grows without bound.
|
||||
Graves.MAX_RECORDED = 20
|
||||
|
||||
-- Appends `entry` (see Game:graveEntry) to meta.graves, most recent first,
|
||||
-- trimming anything past Graves.MAX_RECORDED.
|
||||
function Graves.record(meta, entry)
|
||||
meta.graves = meta.graves or {}
|
||||
table.insert(meta.graves, 1, entry)
|
||||
while #meta.graves > Graves.MAX_RECORDED do
|
||||
table.remove(meta.graves)
|
||||
end
|
||||
end
|
||||
|
||||
-- Graves eligible to be rolled onto `depth`: any dug at that depth or
|
||||
-- deeper. A grave dug on floor 7 can still turn up waiting on floor 4, but
|
||||
-- a floor 2 grave never surfaces on floor 7 - bones drift shallower with
|
||||
-- time, never the other way around.
|
||||
function Graves.eligibleFor(graves, depth)
|
||||
local eligible = {}
|
||||
if not graves then return eligible end
|
||||
for _, grave in ipairs(graves) do
|
||||
if grave.depth >= depth then eligible[#eligible + 1] = grave end
|
||||
end
|
||||
return eligible
|
||||
end
|
||||
|
||||
-- The inert floorItem a builder drops for a rolled grave: visibly a grave
|
||||
-- from the moment it is seen (no disguise to unmask), carrying just enough
|
||||
-- of the fallen's own data for Graves.reveal to build their shade later.
|
||||
function Graves.floorItem(grave)
|
||||
return {
|
||||
kind = "grave", grave = true, name = "a weathered grave marker", glyph = "b",
|
||||
graveClass = grave.className, graveGold = grave.gold, graveEssence = grave.essence,
|
||||
}
|
||||
end
|
||||
|
||||
-- The hostile shade a grave marker becomes the instant it is disturbed:
|
||||
-- hp and attack both scale with the wealth it is guarding, capped so even
|
||||
-- the richest grave never spawns something the player cannot fight back
|
||||
-- against. Mirrors Mimics.reveal's shape (a fresh monster entity, tagged so
|
||||
-- awardKill and corpses.lua both know to treat it specially).
|
||||
function Graves.reveal(id, x, y, ground)
|
||||
local gold = ground.graveGold or 0
|
||||
local essence = ground.graveEssence or 0
|
||||
local wealth = gold + essence * 2
|
||||
local bonusHp = math.min(20, wealth // 8)
|
||||
local bonusAttack = math.min(6, wealth // 30)
|
||||
local entity = Entity.new({
|
||||
id = id, x = x, y = y,
|
||||
glyph = "G", name = "vengeful shade", kind = "monster",
|
||||
species = "shade", ai = "chase",
|
||||
hp = 10 + bonusHp, maxHp = 10 + bonusHp,
|
||||
attack = 4 + bonusAttack, defense = 1, speed = 105,
|
||||
})
|
||||
entity.cooldown = 0
|
||||
entity.faction = Factions.UNDEAD
|
||||
entity.grave = true
|
||||
entity.graveClass = ground.graveClass
|
||||
entity.graveGold = gold
|
||||
entity.graveEssence = essence
|
||||
return entity
|
||||
end
|
||||
|
||||
-- Flat xp reward for felling a revealed shade - kept separate from
|
||||
-- Monsters.xpFor exactly like Mimics.xpFor, since a shade is never a
|
||||
-- member of the wild bestiary Monsters.forDepth draws its per-floor
|
||||
-- population from.
|
||||
function Graves.xpFor()
|
||||
return 12
|
||||
end
|
||||
|
||||
-- What a felled shade actually leaves behind: half the gold and a third of
|
||||
-- the essence the fallen was carrying at the moment of death - the rest is
|
||||
-- gone for good, so a grave is always a net loss across the two runs it
|
||||
-- touches, never a way to launder wealth forward.
|
||||
function Graves.lootFor(entity)
|
||||
local gold = (entity.graveGold or 0) // 2
|
||||
local essence = (entity.graveEssence or 0) // 3
|
||||
return gold, essence
|
||||
end
|
||||
|
||||
return Graves
|
||||
Reference in new issue
Block a user