feat: extend encumbrance with Encumbrance.itemWeight
This commit is contained in:
1 parent
f4c8fcd5fc
commit
7fa20d459d
2 files changed
+187
-3
No files matched your search
@@ -0,0 +1,123 @@
|
|||||||
|
-- Carry weight. Every item kind has a physical weight (gear scales a little
|
||||||
|
-- with its power, the way a heavier blade hits harder); a carrier's capacity
|
||||||
|
-- grows with level, the same knob progression.lua turns for hp. Exceeding
|
||||||
|
-- capacity does not block a pickup outright - it slows the carrier down
|
||||||
|
-- instead (see Entity:effectiveSpeed), and a wide overage on top of that also
|
||||||
|
-- costs defense, the same shape a status.lua debuff takes (see
|
||||||
|
-- Entity:effectiveDefense). Nothing here is persisted: weight is entirely a
|
||||||
|
-- function of entity.inventory and entity.level, both already serialized, so
|
||||||
|
-- a save/load round trip recomputes the identical tier for free.
|
||||||
|
--
|
||||||
|
-- Monsters are never excluded from these checks (there is no species flag to
|
||||||
|
-- opt out), but their inventory is always empty in practice - abilities.lua
|
||||||
|
-- and combat.lua never stash loot on a monster - so in play this only ever
|
||||||
|
-- matters for the player.
|
||||||
|
|
||||||
|
local Items = require("items")
|
||||||
|
|
||||||
|
local Encumbrance = {}
|
||||||
|
|
||||||
|
Encumbrance.BASE_CAPACITY = 12
|
||||||
|
Encumbrance.CAPACITY_PER_LEVEL = 4
|
||||||
|
Encumbrance.BURDENED_MULT = 1.5
|
||||||
|
|
||||||
|
Encumbrance.LIGHT = "light"
|
||||||
|
Encumbrance.BURDENED = "burdened"
|
||||||
|
Encumbrance.OVERLOADED = "overloaded"
|
||||||
|
|
||||||
|
Encumbrance.BURDENED_SPEED_PENALTY = -20
|
||||||
|
Encumbrance.OVERLOADED_SPEED_PENALTY = -45
|
||||||
|
Encumbrance.OVERLOADED_DEFENSE_PENALTY = -2
|
||||||
|
|
||||||
|
-- Base weight per item kind, before any power-scaling below. Kinds absent
|
||||||
|
-- here (gold, keys) default to a flat 1 rather than 0: even a featherweight
|
||||||
|
-- trinket takes up some of the pack, and a strictly-zero-weight kind would
|
||||||
|
-- let a hoard of them carry for free.
|
||||||
|
local BASE_WEIGHT = {
|
||||||
|
[Items.POTION] = 2,
|
||||||
|
[Items.SCROLL] = 1,
|
||||||
|
[Items.WEAPON] = 6,
|
||||||
|
[Items.ARMOR] = 9,
|
||||||
|
[Items.RING] = 1,
|
||||||
|
[Items.FOOD] = 3,
|
||||||
|
[Items.KEY] = 1,
|
||||||
|
[Items.TOME] = 4,
|
||||||
|
[Items.AMULET] = 2,
|
||||||
|
[Items.BOW] = 7,
|
||||||
|
[Items.AMMO] = 1,
|
||||||
|
[Items.GOLD] = 0,
|
||||||
|
[Items.GEM] = 1,
|
||||||
|
[Items.CHARM] = 2,
|
||||||
|
[Items.KIT] = 3,
|
||||||
|
[Items.HERB] = 1,
|
||||||
|
[Items.CONTRACT] = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Kinds whose power rating (a straightforward proxy for how much metal went
|
||||||
|
-- into them) adds a little extra weight on top of the flat base.
|
||||||
|
local POWER_SCALES = {
|
||||||
|
[Items.WEAPON] = true,
|
||||||
|
[Items.ARMOR] = true,
|
||||||
|
[Items.BOW] = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Kinds that stack into one inventory slot via a `count`/`amount` field, so
|
||||||
|
-- their weight must scale with the stack rather than being charged once.
|
||||||
|
local STACK_FIELD = {
|
||||||
|
[Items.AMMO] = "count",
|
||||||
|
[Items.GOLD] = "amount",
|
||||||
|
}
|
||||||
|
|
||||||
|
function Encumbrance.itemWeight(item)
|
||||||
|
local weight = BASE_WEIGHT[item.kind] or 1
|
||||||
|
if POWER_SCALES[item.kind] then
|
||||||
|
weight = weight + (item.power or 0) // 3
|
||||||
|
end
|
||||||
|
local stackField = STACK_FIELD[item.kind]
|
||||||
|
if stackField then
|
||||||
|
weight = weight * (item[stackField] or 1)
|
||||||
|
end
|
||||||
|
return weight
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Loose inventory plus whatever is currently worn or wielded: a sword on
|
||||||
|
-- your belt weighs exactly as much as one in your pack.
|
||||||
|
function Encumbrance.carriedWeight(entity)
|
||||||
|
local total = 0
|
||||||
|
for _, item in ipairs(entity.inventory) do
|
||||||
|
total = total + Encumbrance.itemWeight(item)
|
||||||
|
end
|
||||||
|
for _, slot in ipairs({ "weapon", "armor", "ring", "bow" }) do
|
||||||
|
local equipped = entity[slot]
|
||||||
|
if equipped then total = total + Encumbrance.itemWeight(equipped) end
|
||||||
|
end
|
||||||
|
return total
|
||||||
|
end
|
||||||
|
|
||||||
|
function Encumbrance.capacityFor(entity)
|
||||||
|
return Encumbrance.BASE_CAPACITY + (entity.level or 1) * Encumbrance.CAPACITY_PER_LEVEL
|
||||||
|
end
|
||||||
|
|
||||||
|
function Encumbrance.tierFor(entity)
|
||||||
|
local carried = Encumbrance.carriedWeight(entity)
|
||||||
|
local capacity = Encumbrance.capacityFor(entity)
|
||||||
|
if carried <= capacity then return Encumbrance.LIGHT end
|
||||||
|
if carried <= capacity * Encumbrance.BURDENED_MULT then return Encumbrance.BURDENED end
|
||||||
|
return Encumbrance.OVERLOADED
|
||||||
|
end
|
||||||
|
|
||||||
|
function Encumbrance.speedPenalty(entity)
|
||||||
|
local tier = Encumbrance.tierFor(entity)
|
||||||
|
if tier == Encumbrance.BURDENED then return Encumbrance.BURDENED_SPEED_PENALTY end
|
||||||
|
if tier == Encumbrance.OVERLOADED then return Encumbrance.OVERLOADED_SPEED_PENALTY end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function Encumbrance.defensePenalty(entity)
|
||||||
|
if Encumbrance.tierFor(entity) == Encumbrance.OVERLOADED then
|
||||||
|
return Encumbrance.OVERLOADED_DEFENSE_PENALTY
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
return Encumbrance
|
||||||
+64
-3
@@ -3,6 +3,11 @@
|
|||||||
-- and speed drive the turn scheduler; statuses layer temporary modifiers on top.
|
-- and speed drive the turn scheduler; statuses layer temporary modifiers on top.
|
||||||
|
|
||||||
local Status = require("status")
|
local Status = require("status")
|
||||||
|
local Encumbrance = require("encumbrance")
|
||||||
|
local Momentum = require("momentum")
|
||||||
|
local Sanity = require("sanity")
|
||||||
|
local Proficiency = require("proficiency")
|
||||||
|
local Hunger = require("hunger")
|
||||||
|
|
||||||
local Entity = {}
|
local Entity = {}
|
||||||
Entity.__index = Entity
|
Entity.__index = Entity
|
||||||
@@ -30,6 +35,8 @@ function Entity.new(spec)
|
|||||||
weapon = nil,
|
weapon = nil,
|
||||||
armor = nil,
|
armor = nil,
|
||||||
ring = nil,
|
ring = nil,
|
||||||
|
bow = nil,
|
||||||
|
pick = nil,
|
||||||
}, Entity)
|
}, Entity)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -38,19 +45,25 @@ function Entity:isAlive()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Entity:effectiveAttack()
|
function Entity:effectiveAttack()
|
||||||
return self.attack + Status.attackModifier(self)
|
return self.attack + Status.attackModifier(self) + Momentum.attackBonus(self) + Sanity.attackPenalty(self)
|
||||||
|
+ Proficiency.attackBonus(self) + Hunger.attackPenalty(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Entity:effectiveDefense()
|
function Entity:effectiveDefense()
|
||||||
return self.defense
|
return self.defense + Status.defenseModifier(self) + Encumbrance.defensePenalty(self) + Sanity.defensePenalty(self)
|
||||||
|
+ Hunger.defensePenalty(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Entity:effectiveSpeed()
|
function Entity:effectiveSpeed()
|
||||||
local speed = self.speed + Status.speedModifier(self)
|
local speed = self.speed + Status.speedModifier(self) + Encumbrance.speedPenalty(self)
|
||||||
if speed < 10 then speed = 10 end
|
if speed < 10 then speed = 10 end
|
||||||
return speed
|
return speed
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Entity:encumbranceTier()
|
||||||
|
return Encumbrance.tierFor(self)
|
||||||
|
end
|
||||||
|
|
||||||
function Entity:toData()
|
function Entity:toData()
|
||||||
return {
|
return {
|
||||||
id = self.id,
|
id = self.id,
|
||||||
@@ -66,6 +79,54 @@ function Entity:toData()
|
|||||||
weapon = self.weapon,
|
weapon = self.weapon,
|
||||||
armor = self.armor,
|
armor = self.armor,
|
||||||
ring = self.ring,
|
ring = self.ring,
|
||||||
|
bow = self.bow,
|
||||||
|
pick = self.pick,
|
||||||
|
regen = self.regen,
|
||||||
|
onDeath = self.onDeath,
|
||||||
|
breath = self.breath,
|
||||||
|
ability = self.ability,
|
||||||
|
summonSpecies = self.summonSpecies,
|
||||||
|
summonedBy = self.summonedBy,
|
||||||
|
cooldown = self.cooldown,
|
||||||
|
fleeing = self.fleeing,
|
||||||
|
stolen = self.stolen,
|
||||||
|
splitGen = self.splitGen,
|
||||||
|
hostile = self.hostile,
|
||||||
|
isBoss = self.isBoss,
|
||||||
|
bossKey = self.bossKey,
|
||||||
|
enraged = self.enraged,
|
||||||
|
desperate = self.desperate,
|
||||||
|
channeling = self.channeling,
|
||||||
|
novaSpent = self.novaSpent,
|
||||||
|
resist = self.resist,
|
||||||
|
faction = self.faction,
|
||||||
|
provoked = self.provoked,
|
||||||
|
elite = self.elite,
|
||||||
|
eliteAffixes = self.eliteAffixes,
|
||||||
|
eliteTier = self.eliteTier,
|
||||||
|
mimic = self.mimic,
|
||||||
|
grave = self.grave,
|
||||||
|
graveClass = self.graveClass,
|
||||||
|
graveGold = self.graveGold,
|
||||||
|
graveEssence = self.graveEssence,
|
||||||
|
proficiency = self.proficiency,
|
||||||
|
awareness = self.awareness,
|
||||||
|
lastKnownX = self.lastKnownX,
|
||||||
|
lastKnownY = self.lastKnownY,
|
||||||
|
lostTurns = self.lostTurns,
|
||||||
|
searchTurns = self.searchTurns,
|
||||||
|
combo = self.combo,
|
||||||
|
decay = self.decay,
|
||||||
|
wage = self.wage,
|
||||||
|
loyalty = self.loyalty,
|
||||||
|
wet = self.wet,
|
||||||
|
nemesis = self.nemesis,
|
||||||
|
nemesisGrudge = self.nemesisGrudge,
|
||||||
|
disease = self.disease,
|
||||||
|
biteDisease = self.biteDisease,
|
||||||
|
companionXp = self.companionXp,
|
||||||
|
companionLevel = self.companionLevel,
|
||||||
|
companionHealBonus = self.companionHealBonus,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user