feat(items): add item catalog and equipment stats

This commit is contained in:
dualfroz committed 2026-08-25 11:44:00 +02:00
1 parent ec5c8277a0
commit a2f25d7917
1 file changed
+132
+132
View File
@@ -0,0 +1,132 @@
-- Items are plain data tables so they serialize without metatable handling.
-- Potions and scrolls carry an effect key resolved by the effects module; gear
-- modifies effective stats when equipped and may carry an affix. Potion and
-- scroll type catalogs drive the identification system.
local Items = {}
Items.POTION = "potion"
Items.SCROLL = "scroll"
Items.WEAPON = "weapon"
Items.ARMOR = "armor"
Items.RING = "ring"
Items.FOOD = "food"
Items.KEY = "key"
-- Catalogs list every distinct type in a fixed order; identification assigns a
-- random appearance to each entry, so the order here must stay stable.
Items.potionTypes = {
{ effect = "heal", name = "potion of healing", power = 10 },
{ effect = "poison", name = "potion of poison", power = 3 },
{ effect = "strength", name = "potion of strength", power = 0 },
{ effect = "haste", name = "potion of speed", power = 0 },
}
Items.scrollTypes = {
{ effect = "teleport", name = "scroll of teleportation" },
{ effect = "identify", name = "scroll of identify" },
{ effect = "mapping", name = "scroll of magic mapping" },
{ effect = "fireball", name = "scroll of fireball" },
}
function Items.typeId(item)
return item.kind .. "/" .. (item.effect or "")
end
function Items.potion(power)
return { kind = Items.POTION, effect = "heal", name = "potion of healing", glyph = "!", power = power }
end
function Items.potionOf(effect, power)
local spec
for _, entry in ipairs(Items.potionTypes) do
if entry.effect == effect then spec = entry end
end
return { kind = Items.POTION, effect = effect, name = spec.name, glyph = "!", power = power or spec.power }
end
function Items.scroll(effect)
local spec
for _, entry in ipairs(Items.scrollTypes) do
if entry.effect == effect then spec = entry end
end
return { kind = Items.SCROLL, effect = effect, name = spec.name, glyph = "?" }
end
function Items.weapon(name, power)
return { kind = Items.WEAPON, name = name, glyph = "/", power = power }
end
function Items.armor(name, power)
return { kind = Items.ARMOR, name = name, glyph = "[", power = power }
end
function Items.ring(name, attack, defense)
return { kind = Items.RING, name = name, glyph = "=", attack = attack or 0, defense = defense or 0 }
end
function Items.food(name, nutrition)
return { kind = Items.FOOD, name = name, glyph = "%", nutrition = nutrition }
end
function Items.key(name)
return { kind = Items.KEY, name = name or "iron key", glyph = "*" }
end
function Items.equipWeapon(item, entity)
if entity.weapon then
entity.attack = entity.attack - entity.weapon.power
entity.inventory[#entity.inventory + 1] = entity.weapon
end
entity.weapon = item
entity.attack = entity.attack + item.power
return item.power
end
function Items.equipArmor(item, entity)
if entity.armor then
entity.defense = entity.defense - entity.armor.power
entity.inventory[#entity.inventory + 1] = entity.armor
end
entity.armor = item
entity.defense = entity.defense + item.power
return item.power
end
function Items.equipRing(item, entity)
if entity.ring then
entity.attack = entity.attack - entity.ring.attack
entity.defense = entity.defense - entity.ring.defense
entity.inventory[#entity.inventory + 1] = entity.ring
end
entity.ring = item
entity.attack = entity.attack + item.attack
entity.defense = entity.defense + item.defense
return item.attack + item.defense
end
-- Applies a self-contained item to an entity and returns the magnitude of its
-- effect. Effects that need the wider world (teleport, mapping, fireball) are
-- routed through the effects module by the game instead.
function Items.use(item, entity)
if item.kind == Items.POTION and item.effect == "heal" then
local before = entity.hp
entity.hp = math.min(entity.maxHp, entity.hp + item.power)
return entity.hp - before
elseif item.kind == Items.WEAPON then
return Items.equipWeapon(item, entity)
elseif item.kind == Items.ARMOR then
return Items.equipArmor(item, entity)
elseif item.kind == Items.RING then
return Items.equipRing(item, entity)
end
return 0
end
function Items.useFromInventory(entity, index)
local item = table.remove(entity.inventory, index)
local effect = Items.use(item, entity)
return item, effect
end
return Items