feat: add Shrines.costFor and Shrines.curseChance
This commit is contained in:
1 parent
3fe3f21de4
commit
23fdd0245e
1 file changed
+111
+111
@@ -0,0 +1,111 @@
|
||||
-- Wayside altars the player can pray at for a permanent boon at a gold price.
|
||||
-- A shrine's favor wears thin with use: each prayer at the same altar is more
|
||||
-- likely to backfire into a curse than the last, so greedily re-praying at a
|
||||
-- single shrine is a real risk rather than a free stat pump. Shrines are plain
|
||||
-- data on level.shrines, keyed by position, so they serialize like traps and
|
||||
-- hazards do with no special save-format handling.
|
||||
|
||||
local Status = require("status")
|
||||
local Curses = require("curses")
|
||||
|
||||
local Shrines = {}
|
||||
|
||||
Shrines.WAR = "war"
|
||||
Shrines.VITALITY = "vitality"
|
||||
Shrines.WISDOM = "wisdom"
|
||||
Shrines.FORTUNE = "fortune"
|
||||
|
||||
-- Fixed order so a given rng draw always names the same kind.
|
||||
Shrines.order = { Shrines.WAR, Shrines.VITALITY, Shrines.WISDOM, Shrines.FORTUNE }
|
||||
|
||||
Shrines.names = {
|
||||
[Shrines.WAR] = "shrine of war",
|
||||
[Shrines.VITALITY] = "shrine of vitality",
|
||||
[Shrines.WISDOM] = "shrine of wisdom",
|
||||
[Shrines.FORTUNE] = "shrine of fortune",
|
||||
}
|
||||
|
||||
local BASE_COST = 20
|
||||
local COST_STEP = 10
|
||||
|
||||
-- Prayer cost climbs with prior use at this specific altar, the same shape as
|
||||
-- its rising curse risk: the shrine asks more and gives worse odds once its
|
||||
-- patience with the petitioner is spent.
|
||||
function Shrines.costFor(shrine)
|
||||
return BASE_COST + shrine.uses * COST_STEP
|
||||
end
|
||||
|
||||
-- Numerator over a denominator of 6: the first prayer risks 1-in-6, climbing
|
||||
-- by one for every prior use, capped at a certainty of 6-in-6.
|
||||
function Shrines.curseChance(shrine)
|
||||
return math.min(shrine.uses + 1, 6), 6
|
||||
end
|
||||
|
||||
local function grantBlessing(player, kind)
|
||||
if kind == Shrines.WAR then
|
||||
player.attack = player.attack + 1
|
||||
player.baseAttack = player.baseAttack + 1
|
||||
return "your grip tightens with martial favor"
|
||||
elseif kind == Shrines.VITALITY then
|
||||
player.maxHp = player.maxHp + 5
|
||||
player.hp = player.hp + 5
|
||||
return "vigor floods through you"
|
||||
elseif kind == Shrines.WISDOM then
|
||||
player.maxMana = player.maxMana + 3
|
||||
player.mana = player.maxMana
|
||||
return "arcane insight fills your mind"
|
||||
else
|
||||
local cleansed = false
|
||||
local kept = {}
|
||||
for _, active in ipairs(player.statuses) do
|
||||
if active.kind == Status.POISON or active.kind == Status.BURNING
|
||||
or active.kind == Status.WEAKEN or active.kind == Status.SLOW then
|
||||
cleansed = true
|
||||
else
|
||||
kept[#kept + 1] = active
|
||||
end
|
||||
end
|
||||
player.statuses = kept
|
||||
Status.apply(player, Status.SHIELD, 10, 1)
|
||||
if Curses.cleanseWorn(player) > 0 then cleansed = true end
|
||||
if cleansed then
|
||||
return "fortune cleanses your ailments and wards you"
|
||||
end
|
||||
return "fortune wards you against harm"
|
||||
end
|
||||
end
|
||||
|
||||
local function inflictCurse(player)
|
||||
Status.apply(player, Status.WEAKEN, 8, 1)
|
||||
Status.apply(player, Status.SLOW, 8, 1)
|
||||
return "the shrine's favor turns against you"
|
||||
end
|
||||
|
||||
-- Attempts a prayer at `shrine` for `game.player`. When the price cannot be
|
||||
-- met nothing is spent and this returns (false, lines). Otherwise the gold is
|
||||
-- always spent, the shrine's use count always advances (so its price and
|
||||
-- curse odds keep climbing), and this returns (true, lines) describing
|
||||
-- whichever of a blessing or a curse landed.
|
||||
function Shrines.pray(game, shrine)
|
||||
local player = game.player
|
||||
local cost = Shrines.costFor(shrine)
|
||||
if player.gold < cost then
|
||||
return false, { "you cannot afford " .. Shrines.names[shrine.kind] .. "'s price" }
|
||||
end
|
||||
player.gold = player.gold - cost
|
||||
local numerator, denominator = Shrines.curseChance(shrine)
|
||||
local cursed = game.rng:chance(numerator, denominator)
|
||||
shrine.uses = shrine.uses + 1
|
||||
local line
|
||||
if cursed then
|
||||
line = inflictCurse(player)
|
||||
else
|
||||
line = grantBlessing(player, shrine.kind)
|
||||
end
|
||||
return true, {
|
||||
string.format("you pray at the %s for %d gold", Shrines.names[shrine.kind], cost),
|
||||
line,
|
||||
}
|
||||
end
|
||||
|
||||
return Shrines
|
||||
Reference in new issue
Block a user