Files
warren/src/compendium.lua
T

94 lines
4.3 KiB
Lua

-- Cross-run bestiary: which species the player has ever laid eyes on, and how
-- many of each they have slain. A compendium lives inside meta.lua's
-- persistent save (see game.lua's Game.new, which reuses options.meta's own
-- table by reference so every sighting and kill recorded mid-run is already
-- sitting in the very table warren.lua writes back out with Meta.save) so it
-- survives death exactly like renown and perks; a run started without
-- --meta still gets a fresh, un-persisted one so every code path exercises
-- the same bookkeeping either way.
local Monsters = require("monsters")
local Bosses = require("bosses")
local Compendium = {}
-- One evocative line per species, keyed the same as monsters.lua's species
-- key or, for a boss, its bosses.lua catalog key (without the "boss_"
-- prefix game.lua stamps onto the actual entity's `species` field).
Compendium.FLAVOR = {
rat = "Bold enough to bite an ankle, never bold enough to fight fair.",
bat = "Flits erratically through the dark on a course only it can hear.",
kobold = "Travels in twos and threes; alone it barely has the nerve to bite.",
goblin = "Quick with a rusty blade, quicker to run once its pack scatters.",
archer = "A skeleton archer, more patient dead than most men are living.",
orc = "Broad-shouldered muscle with no plan beyond the next swing.",
wretch = "Something that used to be a person, now just hungry and afraid.",
troll = "Wounds close almost as fast as they open; fire is the only argument it respects.",
mage = "A dark mage who traded caution for whatever is behind that door.",
dragon = "Young enough to still be reckless, old enough to already breathe fire.",
zombie = "Shambles forward on rot and spite alone.",
slime = "Splits when struck; killing one carelessly just makes two problems.",
footpad = "Light-fingered and lighter on its feet - it wants your purse, not a fight.",
shaman = "Chants curses from a safe distance and flees the moment that fails.",
necromancer = "Would rather raise a friend from your kills than make one of its own.",
cleric = "Keeps its allies standing longer than they have any right to.",
chieftain = "Rallies its kin with a bellow that carries through the whole floor.",
shopkeeper = "Minds its own business and its stock, right up until you take both.",
warlord = "The Orc Warlord, whose rage only sharpens the longer a fight runs.",
lich = "The Lich, a will that outlasted its own body decades ago.",
bonequeen = "The Bone Queen, who never lacks for company - the dead keep answering her call.",
}
function Compendium.new()
return { seen = {}, kills = {} }
end
-- Marks `speciesKey` as sighted. Returns true only the first time it is ever
-- seen, so a caller can choose whether to make anything of that moment; a
-- repeat sighting is silently a no-op.
function Compendium.noteSighting(compendium, speciesKey)
if not speciesKey or compendium.seen[speciesKey] then return false end
compendium.seen[speciesKey] = true
return true
end
function Compendium.noteKill(compendium, speciesKey)
if not speciesKey then return end
compendium.kills[speciesKey] = (compendium.kills[speciesKey] or 0) + 1
end
function Compendium.killCount(compendium, speciesKey)
return compendium.kills[speciesKey] or 0
end
function Compendium.hasSeen(compendium, speciesKey)
return compendium.seen[speciesKey] == true
end
-- Every species named in the wild bestiary or the boss catalog, in a fixed
-- order (wild species first, then bosses), each row carrying its catalogued
-- name, flavor line and this compendium's own seen/kill tally. `key` here
-- matches exactly what an actual entity's `species` field would hold, so a
-- caller can cross-reference the two without re-deriving the "boss_" prefix.
function Compendium.entries(compendium)
local rows = {}
for _, spec in ipairs(Monsters.species) do
rows[#rows + 1] = {
key = spec.key, name = spec.name, flavor = Compendium.FLAVOR[spec.key],
seen = Compendium.hasSeen(compendium, spec.key),
kills = Compendium.killCount(compendium, spec.key),
}
end
for _, spec in ipairs(Bosses.catalog) do
local key = "boss_" .. spec.key
rows[#rows + 1] = {
key = key, name = spec.name, flavor = Compendium.FLAVOR[spec.key],
seen = Compendium.hasSeen(compendium, key),
kills = Compendium.killCount(compendium, key),
}
end
return rows
end
return Compendium