I'm working on a game in Corona/Lua, and implementing a class called "Item" which represents an in game weapon, armor, amulet, etc. And I'm new to object-oriented Lua.
After creating a new instance of the class, I'm finding that setting certain properties of the object seems to set them in the class metatable, not in the object itself.
Here is the class and constructor:
local Item = {
name = nil,
itemType = nil,
scarcity = "basic",
baseDamage = 0, -- Bow only
bonuses = {
damageBonus = 0,
speedBonus = 0,
critBonus = 0,
dropBonus = 0,
rechargeBonus = 0,
xpBonus = 0
}
}
-- Creates a simple blank instance of the Item class.
function Item:new(o)
local item = o or {}
setmetatable(item, self)
self.__index = self
return item
end
Now let's say I create two objects based on this prototype:
local bow = Item:new()
bow.itemType = "bow"
starterBow.baseDamage = 5
local ring = Item:new()
ring.itemType = "ring"
ring.bonuses.damageBonus = 0.25
To my dismay, the "bonuses.damageBonus" property seems to be getting set inside the metatable and therefore applying to every item (i.e. the bow also gets the damage bonus, and stacking with the ring). However the behavior seems limited to the "bonus" properties. If I set the "itemType" property, it is attached to the object, not the class, as expected.
The behavior I'd like to see is that the fields of the "bonuses" table can be set for individual items. Any idea what I'm doing wrong? Thanks!
The __index metafield is triggered when you try to 'get' a field from your table the doesn't exist.
ring.bonuses.damageBonus = 0.25 is trying to 'get' bonuses from ring, and since it doesn't exist, goes to the metatable and returns your bonuses table, and then its damageBonus index is set to 0.25.
Understand that just declaring variables in the Item table doesn't mean your Item instances will inherit them as instance variables. For that, you would need to declare/initialize them in your Item:new() function:
function Item:new(o)
local item = o or {}
setmetatable(item, self)
self.__index = self
item.bonuses={} -- create instance bonuses table and give default values
for k,v in pairs(self.bonuses) do
item.bonuses[k]=v
end
return item
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With