feat: add Durability.ensure and Durability.isBroken
This commit is contained in:
1 parent
fc02e0fe8d
commit
142051057b
1 file changed
+127
@@ -0,0 +1,127 @@
|
|||||||
|
-- Weapon, armor and bow wear: unlike digging.lua's pick, a single limited-use
|
||||||
|
-- tool discarded outright once spent, a piece of gear wears down from
|
||||||
|
-- ordinary use but survives reaching zero - it just stops contributing to
|
||||||
|
-- combat until repaired, exactly like disenchanting a rune off a weapon
|
||||||
|
-- strips its bonus without destroying the weapon itself (see crafting.lua).
|
||||||
|
-- A weapon or armor's power is baked straight into the wielder's
|
||||||
|
-- attack/defense the instant it is equipped (see items.lua's
|
||||||
|
-- Items.equipWeapon/equipArmor), so breaking or repairing one here adjusts
|
||||||
|
-- that same baked total by the identical delta swapping gear already uses -
|
||||||
|
-- never a separate "effective power" read live in combat. A bow is the one
|
||||||
|
-- exception: its power is read live at the point of firing (see
|
||||||
|
-- ranged.lua's Ranged.fire), so Durability.effectivePower covers that
|
||||||
|
-- instead. Only the player's own gear wears at all - monsters have no
|
||||||
|
-- inventory management or repair access, so wear is never applied to theirs.
|
||||||
|
|
||||||
|
local Durability = {}
|
||||||
|
|
||||||
|
Durability.MAX = 30
|
||||||
|
Durability.WEAR_PER_HIT = 1
|
||||||
|
Durability.REPAIR_COST_PER_POINT = 2
|
||||||
|
|
||||||
|
-- Lazily stamps a fresh durability pair onto `item` the moment anything
|
||||||
|
-- first asks about it, so an item built before this field existed on it
|
||||||
|
-- (a raw table assembled somewhere this module cannot see) still gets a
|
||||||
|
-- sensible default rather than an error.
|
||||||
|
function Durability.ensure(item)
|
||||||
|
if not item.durability then
|
||||||
|
item.durability = Durability.MAX
|
||||||
|
item.maxDurability = Durability.MAX
|
||||||
|
end
|
||||||
|
return item
|
||||||
|
end
|
||||||
|
|
||||||
|
function Durability.isBroken(item)
|
||||||
|
Durability.ensure(item)
|
||||||
|
return item.durability <= 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- A broken bow contributes nothing to a shot's damage; read live in
|
||||||
|
-- Ranged.fire in place of a bare `bow.power`.
|
||||||
|
function Durability.effectivePower(item)
|
||||||
|
if not item then return 0 end
|
||||||
|
if Durability.isBroken(item) then return 0 end
|
||||||
|
return item.power or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local function isPlayerOwned(entity)
|
||||||
|
return entity.kind == "player"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Wears one point off `entity.weapon`, subtracting its power out of
|
||||||
|
-- entity.attack the instant it actually breaks (never before, and never
|
||||||
|
-- twice for the same break). A no-op, nil return, for an unarmed entity or
|
||||||
|
-- one whose weapon already sits at zero.
|
||||||
|
function Durability.wearWeapon(entity)
|
||||||
|
local item = entity.weapon
|
||||||
|
if not item then return nil end
|
||||||
|
Durability.ensure(item)
|
||||||
|
if item.durability <= 0 then return nil end
|
||||||
|
item.durability = item.durability - Durability.WEAR_PER_HIT
|
||||||
|
if item.durability <= 0 then
|
||||||
|
entity.attack = entity.attack - item.power
|
||||||
|
return isPlayerOwned(entity) and ("your " .. item.name .. " breaks apart from wear")
|
||||||
|
or (entity.name .. "'s " .. item.name .. " breaks apart from wear")
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function Durability.wearArmor(entity)
|
||||||
|
local item = entity.armor
|
||||||
|
if not item then return nil end
|
||||||
|
Durability.ensure(item)
|
||||||
|
if item.durability <= 0 then return nil end
|
||||||
|
item.durability = item.durability - Durability.WEAR_PER_HIT
|
||||||
|
if item.durability <= 0 then
|
||||||
|
entity.defense = entity.defense - item.power
|
||||||
|
return isPlayerOwned(entity) and ("your " .. item.name .. " is battered to uselessness")
|
||||||
|
or (entity.name .. "'s " .. item.name .. " is battered to uselessness")
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- A bow's power is never baked into attack, so breaking one touches no stat
|
||||||
|
-- - Ranged.fire simply stops reading any power out of it via
|
||||||
|
-- Durability.effectivePower.
|
||||||
|
function Durability.wearBow(entity)
|
||||||
|
local item = entity.bow
|
||||||
|
if not item then return nil end
|
||||||
|
Durability.ensure(item)
|
||||||
|
if item.durability <= 0 then return nil end
|
||||||
|
item.durability = item.durability - Durability.WEAR_PER_HIT
|
||||||
|
if item.durability <= 0 then
|
||||||
|
return isPlayerOwned(entity) and ("your " .. item.name .. " snaps from wear")
|
||||||
|
or (entity.name .. "'s " .. item.name .. " snaps from wear")
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function Durability.missing(item)
|
||||||
|
Durability.ensure(item)
|
||||||
|
return item.maxDurability - item.durability
|
||||||
|
end
|
||||||
|
|
||||||
|
function Durability.repairCost(item)
|
||||||
|
return Durability.missing(item) * Durability.REPAIR_COST_PER_POINT
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Spends `entity.gold` to restore `entity`'s gear in `slotName` (one of
|
||||||
|
-- "weapon", "armor", "bow") fully, folding its power back into attack or
|
||||||
|
-- defense if the break had already stripped it out. Fails without spending
|
||||||
|
-- anything for an empty slot, an already-pristine item, or too thin a purse.
|
||||||
|
function Durability.repair(entity, slotName)
|
||||||
|
local item = entity[slotName]
|
||||||
|
if not item then return false, "nothing equipped there" end
|
||||||
|
Durability.ensure(item)
|
||||||
|
if item.durability >= item.maxDurability then return false, "already in perfect condition" end
|
||||||
|
local cost = Durability.repairCost(item)
|
||||||
|
if entity.gold < cost then return false, "not enough gold" end
|
||||||
|
local wasBroken = item.durability <= 0
|
||||||
|
entity.gold = entity.gold - cost
|
||||||
|
item.durability = item.maxDurability
|
||||||
|
if wasBroken and slotName == "weapon" then entity.attack = entity.attack + item.power end
|
||||||
|
if wasBroken and slotName == "armor" then entity.defense = entity.defense + item.power end
|
||||||
|
return true, cost
|
||||||
|
end
|
||||||
|
|
||||||
|
return Durability
|
||||||
Reference in new issue
Block a user