133 lines
4.2 KiB
Lua
133 lines
4.2 KiB
Lua
-- 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
|