feat: extend horde with Horde.essenceFor and Horde.pool
This commit is contained in:
1 parent
58994a6132
commit
1f4ea71a1f
3 files changed
+198
-1
No files matched your search
@@ -157,3 +157,88 @@ function Horde.countFor(wave)
|
||||
return count
|
||||
end
|
||||
|
||||
function Horde.essenceFor(wave)
|
||||
return wave * Horde.ESSENCE_PER_WAVE
|
||||
end
|
||||
|
||||
-- Species eligible for wave `wave`, drawn from Monsters.forDepth at
|
||||
-- Horde.depthFor(wave) exactly like a real floor's population, minus the
|
||||
-- passive vend-behaviour shopkeeper - a wave the player can never provoke
|
||||
-- into fighting back would leave Horde.cleared permanently false.
|
||||
function Horde.pool(wave)
|
||||
local eligible = {}
|
||||
for _, spec in ipairs(Monsters.forDepth(Horde.depthFor(wave))) do
|
||||
if spec.ai ~= "vend" then eligible[#eligible + 1] = spec end
|
||||
end
|
||||
return eligible
|
||||
end
|
||||
|
||||
-- True once every hostile monster the arena has ever placed is dead -
|
||||
-- vacuously true against a still-empty arena too, which is exactly what
|
||||
-- lets Horde.tick reuse the same check to bootstrap wave 1 as it does to
|
||||
-- clear every wave after it (see Horde.tick's own comment). Filtered to
|
||||
-- entity.kind == "monster", the same "hostile" tag every other module
|
||||
-- (companions.lua/mercenaries.lua/reanimation.lua/abilities.lua...) uses:
|
||||
-- Game:startHorde can now carry a bonded companion/hireling/thrall into the
|
||||
-- arena, and an ally that never dies to the wave itself would otherwise
|
||||
-- keep this permanently false, freezing the arena on wave 0 forever.
|
||||
function Horde.cleared(level)
|
||||
for _, entity in ipairs(level.entities) do
|
||||
if entity.kind == "monster" and entity:isAlive() then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Populates `game.level` with wave `wave`'s monsters, drawn from
|
||||
-- Horde.pool and placed one to a cell along Horde.spawnPoints's queue -
|
||||
-- never doubling two monsters onto the same cell, the one-entity-per-cell
|
||||
-- invariant every other spawn path in game.lua already relies on. Every
|
||||
-- spawn is already hunting, exactly like Game:spawnMinion's own summons -
|
||||
-- an arena has no stealth approach to sneak past. Returns the spawned
|
||||
-- entities.
|
||||
function Horde.spawnWave(game, wave)
|
||||
local level = game.level
|
||||
local points = Horde.spawnPoints(level.map)
|
||||
local pool = Horde.pool(wave)
|
||||
local count = math.min(Horde.countFor(wave), #points)
|
||||
local depth = Horde.depthFor(wave)
|
||||
local spawned = {}
|
||||
for i = 1, count do
|
||||
local point = points[i]
|
||||
local spec = game.rng:pick(pool)
|
||||
local entity = Monsters.create(spec, game:nextMonsterId(), point.x, point.y, depth)
|
||||
entity.awareness = Stealth.HUNTING
|
||||
Elites.maybePromote(game.rng, entity, depth)
|
||||
level.entities[#level.entities + 1] = entity
|
||||
spawned[#spawned + 1] = entity
|
||||
end
|
||||
return spawned
|
||||
end
|
||||
|
||||
-- Advances horde state by one player turn, called from Game:endPlayerTurn
|
||||
-- behind a `game.horde` check. A no-op while the current wave still has a
|
||||
-- living monster in it; the instant it does not - including the very first
|
||||
-- call, against the still-empty arena Game:startHorde just built, since
|
||||
-- Horde.cleared reads that the same way as a genuinely finished wave - it
|
||||
-- banks Horde.essenceFor(wave) essence (zero the first time, wave still
|
||||
-- being 0), heals Horde.REST_HEAL, advances the wave counter, and spawns
|
||||
-- the new wave outright, so the arena is never left standing empty for
|
||||
-- even a single turn. Returns a log line, or nil when nothing happened.
|
||||
function Horde.tick(game)
|
||||
local horde = game.horde
|
||||
if not horde then return nil end
|
||||
if not Horde.cleared(game.level) then return nil end
|
||||
local reward = Horde.essenceFor(horde.wave)
|
||||
if reward > 0 then
|
||||
game.player.essence = game.player.essence + reward
|
||||
end
|
||||
game.player.hp = math.min(game.player.maxHp, game.player.hp + Horde.REST_HEAL)
|
||||
horde.wave = horde.wave + 1
|
||||
Horde.spawnWave(game, horde.wave)
|
||||
if horde.wave == 1 then
|
||||
return "the horde arena falls silent - wave 1 begins"
|
||||
end
|
||||
return string.format("the arena falls silent - wave %d begins (+%d essence)", horde.wave, reward)
|
||||
end
|
||||
|
||||
return Horde
|
||||
Reference in new issue
Block a user