feat: add tierFrom, Resistances.tierOf and wordKey
This commit is contained in:
1 parent
63a9fb5f90
commit
cf286f9da3
2 files changed
+144
No files matched your search
@@ -0,0 +1,67 @@
|
||||
-- Elemental damage typing. Every hit that lands - melee, a bolt, a thrown
|
||||
-- weapon, a hazard tick, a status effect's damage-over-time - is tagged with
|
||||
-- one of the types below, and this module decides how much of it actually
|
||||
-- gets through. A defender's tier for a type comes from up to two places: its
|
||||
-- own base profile (bestiary data, e.g. a dragon's own hide) and whatever it
|
||||
-- has equipped (weapon/armor/ring/bow, e.g. a ring of cold resistance). The
|
||||
-- single best (most protective) tier across those sources wins - immune beats
|
||||
-- resist beats weak beats the normal default - so a found ring can cancel out
|
||||
-- an innate vulnerability, but nothing ever stacks two resists into a second
|
||||
-- discount or two weaknesses into a bigger penalty.
|
||||
|
||||
local Resistances = {}
|
||||
|
||||
Resistances.PHYSICAL = "physical"
|
||||
Resistances.FIRE = "fire"
|
||||
Resistances.COLD = "cold"
|
||||
Resistances.POISON = "poison"
|
||||
Resistances.LIGHTNING = "lightning"
|
||||
Resistances.ARCANE = "arcane"
|
||||
|
||||
Resistances.TYPES = {
|
||||
Resistances.PHYSICAL, Resistances.FIRE, Resistances.COLD,
|
||||
Resistances.POISON, Resistances.LIGHTNING, Resistances.ARCANE,
|
||||
}
|
||||
|
||||
Resistances.IMMUNE = "immune"
|
||||
Resistances.RESIST = "resist"
|
||||
Resistances.WEAK = "weak"
|
||||
Resistances.NORMAL = "normal"
|
||||
|
||||
local RANK = { immune = 3, resist = 2, weak = 1, normal = 0 }
|
||||
|
||||
-- Slots checked alongside an entity's own `resist` table, in a fixed order so
|
||||
-- the result never depends on Lua's unspecified pairs() iteration order.
|
||||
local EQUIP_SLOTS = { "weapon", "armor", "ring", "bow" }
|
||||
|
||||
local function tierFrom(source, damageType)
|
||||
return source and source.resist and source.resist[damageType]
|
||||
end
|
||||
|
||||
-- The single tier that governs `damageType` incoming against `entity`, folding
|
||||
-- in its own base profile and every equipped slot that carries one.
|
||||
function Resistances.tierOf(entity, damageType)
|
||||
local best = tierFrom(entity, damageType) or Resistances.NORMAL
|
||||
for _, slot in ipairs(EQUIP_SLOTS) do
|
||||
local tier = tierFrom(entity[slot], damageType)
|
||||
if tier and RANK[tier] > RANK[best] then
|
||||
best = tier
|
||||
end
|
||||
end
|
||||
return best
|
||||
end
|
||||
|
||||
-- Scales a already-computed `amount` of `damageType` damage by `entity`'s
|
||||
-- tier for that type. Immune drops it to nothing outright rather than merely
|
||||
-- halving it, so it can floor damage below the "always at least 1" guarantee
|
||||
-- combat.lua's own minimum otherwise enforces.
|
||||
function Resistances.apply(entity, amount, damageType)
|
||||
if amount <= 0 then return amount end
|
||||
local tier = Resistances.tierOf(entity, damageType or Resistances.PHYSICAL)
|
||||
if tier == Resistances.IMMUNE then return 0 end
|
||||
if tier == Resistances.RESIST then return math.floor(amount / 2) end
|
||||
if tier == Resistances.WEAK then return math.floor(amount * 1.5) end
|
||||
return amount
|
||||
end
|
||||
|
||||
return Resistances
|
||||
Reference in new issue
Block a user