• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Lua Error on a upgrade system: attempt to index field '?' (a nil value)

1268995

Member
Joined
Sep 9, 2010
Messages
422
Reaction score
13
Hello, i am having this error on this upgrade system:

Code:
[13/07/2015 16:00:09] [Error - Action Interface]
[13/07/2015 16:00:09] data/actions/scripts/upgrade.lua:onUse
[13/07/2015 16:00:09] Description:
[13/07/2015 16:00:09] data/lib/upgradesystem.lua:60: attempt to index field '?' (a nil value)
[13/07/2015 16:00:09] stack traceback:
[13/07/2015 16:00:09]     data/lib/upgradesystem.lua:60: in function 'chance'
[13/07/2015 16:00:09]     data/lib/upgradesystem.lua:122: in function 'refine'
[13/07/2015 16:00:09]     data/actions/scripts/upgrade.lua:12: in function <data/actions/scripts/upgrade.lua:1>

upgrade.lua:
Code:
function onUse(cid, item, fromPosition, itemEx, toPosition)
    if isCreature(itemEx.uid) then 
        return doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTPOSSIBLE)
    end

    local obj = UpgradeHandler:new(itemEx)

    if(obj == false) then
        return doPlayerSendCancel(cid, UpgradeHandler.message.notupgradeable)
    end

    local status = obj:refine(cid, item)
    if status == "success" then
        --doSendAnimatedText(toPosition, "Success!", COLOR_GREEN)
        doSendMagicEffect(toPosition, CONST_ME_MAGIC_GREEN)
    elseif status == "fail" then
        --doSendAnimatedText(toPosition, "Fail!", COLOR_RED)
        doSendMagicEffect(toPosition, CONST_ME_POFF)
    else
        doSendMagicEffect(toPosition, CONST_ME_POFF)
    end
    return true
end

upgradesystem.lua: (this is a lib)
Code:
--[[

    PERFECT UPGRADE SYSTEM
                2.0

    Criado por Oneshot

    É proibido a venda ou a cópia sem os devidos créditos desse script.

]]--

UpgradeHandler = {
    levels = {
        [1] = {100, false, false},
        [2] = {90, false, false},
        [3] = {75, false, false},
        [4] = {60, true, false},
        [5] = {45, true, false},
        [6] = {30, true, false},
        [7] = {25, true, false},
        [8] = {20, true, true},
        [9] = {15, true, true},
        [10] = {10, true, true},
        [11] = {10, true, true},
        [12] = {5, true, true}
    },
    broadcast = 7,
    attributes = {
        ["attack"] = 2,
        ["defense"] = 1,
        ["armor"] = 1
    },
    message = {
        console = "Trying to refine %s to level +%s with %s%% success rate.",
        success = "You have upgraded %s to level +%s",
        fail = "You have failed in upgrade of %s to level +%s",
        downgrade = "The upgrade level of %s has downgraded to +%s",
        erase = "The upgrade level of %s has been erased.",
        maxlevel = "The targeted %s is already on max upgrade level.",
        notupgradeable = "This item is not upgradeable.",
        broadcast = "The player %s was successful in upgrading %s to level +%s.\nCongratulations!!",
        invalidtool = "This is not a valid upgrade tool.",
        toolrange = "This upgrade tool can only be used in items with level between +%s and +%s"
    },
    tools = {
        [8306] = {range = {0, 10}, info = {chance = 0, removeable = true}},
    },

    isEquipment = function(self)
        local weaponType = self:getItemWeaponType()
        return ((weaponType > 0 and weaponType < 7) or self.item.armor ~= 0)
    end,

    setItemName = function(self, name)
        return doItemSetAttribute(self.item.uid, "name", name)
    end,

    chance = function(self)
        local chances = {}
        chances.upgrade = (self.levels[self.item.level + 1][1] or 100)
        chances.downgrade = (self.item.level * 5)
        chances.erase = (self.item.level * 3)

        return chances
    end
}

function UpgradeHandler:new(item)
    local obj, ret = {}
    obj.item = {}

    obj.item.level = 0
    obj.item.uid = item.uid
    for key, value in pairs(getItemInfo(item.itemid)) do
        obj.item[key] = value
    end

    ret = setmetatable(obj, {__index = function(self, index)
        if _G[index] then
            return (setmetatable({callback = _G[index]}, {__call = function(self, ...)
                return self.callback(item.uid, ...)
            end}))
        else
            return UpgradeHandler[index]
        end
    end})

    if ret:isEquipment() then
        ret:update()
        return ret
    end
    return false
end

function UpgradeHandler:update()
    self.item.level = (tonumber(self:getItemName():match("%+(%d+)")) or 0)
end

function UpgradeHandler:refine(uid, item)
    if not self.item then
        doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_BLUE, self.message.notupgradeable)
        return "miss"
    end 

    local tool = self.tools[item.itemid]

    if(tool == nil) then
        doPlayerSendTextMessage(uid, MESSAGE_EVENT_DEFAULT, self.message.invalidtool)
        return "miss"
    end

    if(self.item.level > #self.levels) then
        doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_RED, self.message.maxlevel:format(self.item.name))
        return "miss"
    end

    if(self.item.level < tool.range[1] or self.item.level >= tool.range[2]) then
        doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_RED, self.message.toolrange:format(unpack(tool.range)))
        return "miss"
    end

    local chance = (self:chance().upgrade + tool.info.chance)
    doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_BLUE, self.message.console:format(self.item.name, (self.item.level + 1), math.min(100, chance)))

    if(tool.info.removeable == true) then
        doRemoveItem(item.uid, 1)
    end

    if chance * 100 > math.random(1, 10000) then
        doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_ORANGE, self.message.success:format(self.item.name, (self.item.level + 1)))
        if (self.item.level + 1) >= self.broadcast then
            doBroadcastMessage(self.message.broadcast:format(getCreatureName(uid), self.item.name, (self.item.level + 1)))
        end

        self:setItemName((self.item.level > 0 and self:getItemName():gsub("%+(%d+)", "+".. (self.item.level + 1)) or (self:getItemName() .." +1")))
        for key, value in pairs(self.attributes) do
            if getItemAttribute(self.item.uid, key) ~= nil or self.item[key] ~= 0 then
                doItemSetAttribute(self.item.uid, key, (self.item.level > 0 and getItemAttribute(self.item.uid, key) or self.item[key]) + value)
            end
        end
        return "success"
    else
        if(self.levels[self.item.level][3] == true and (self:chance().erase * 100) > math.random(1, 10000)) then
            doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_RED, self.message.erase:format(self.item.name))
            self:setItemName(self.item.name)
            for key, value in pairs(self.attributes) do
                if self.item[key] > 0 then
                    doItemSetAttribute(self.item.uid, key, self.item[key])
                end
            end
        elseif(self.levels[self.item.level][2] == true and (self:chance().downgrade * 100) > math.random(1, 10000)) then
            doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_RED, self.message.downgrade:format(self.item.name, (self.item.level - 1)))
            self:setItemName((self.item.level == 1 and self.item.name or self:getItemName():gsub("%+(%d+)", "+".. (self.item.level - 1))))
            for key, value in pairs(self.attributes) do
                if getItemAttribute(self.item.uid, key) ~= nil or self.item[key] ~= 0 then
                    doItemSetAttribute(self.item.uid, key, (self.item[key] + value * (self.item.level - 1)))
                end
            end
        else
            doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_RED, self.message.fail:format(self.item.name, (self.item.level + 1)))
        end
        return "fail"
    end
end
 
Last edited:
razor solved your problem, but you did not change you code.

your
self.levels[self.item.level + 1]
is not table value.

now remove the prints and replace the error line with this.
(im not sure does value 0 means it will be 100% hopefully it does)

chances.upgrade = (self.levels[self.item.level] or 100)
self.item.level + 1 = 1. That's a table value. It's checking the chance of upgrading to the NEXT level.
 
mm..
then I want to see table.

for k,v in pairs(self.levels) do
print("key = "..tostring(k))
print("value = "..tostring(v))
end
return false --no need to see error again
 
mm..
then I want to see table.

for k,v in pairs(self.levels) do
print("key = "..tostring(k))
print("value = "..tostring(v))
end
return false --no need to see error again
Code:
levels = {
[1] = {100, false, false},
[2] = {90, false, false},
[3] = {75, false, false},
[4] = {60, true, false},
[5] = {45, true, false},
[6] = {30, true, false},
[7] = {25, true, false},
[8] = {20, true, true},
[9] = {15, true, true},
[10] = {10, true, true},
[11] = {10, true, true},
[12] = {5, true, true}
},

You can see the table by reading the script. It's not a complicated script, just uses metatables before metatables were cool. It's hipster TFS.

self.levels will never change because it is not modified in the script.
 
Code:
levels = {
[1] = {100, false, false},
[2] = {90, false, false},
[3] = {75, false, false},
[4] = {60, true, false},
[5] = {45, true, false},
[6] = {30, true, false},
[7] = {25, true, false},
[8] = {20, true, true},
[9] = {15, true, true},
[10] = {10, true, true},
[11] = {10, true, true},
[12] = {5, true, true}
},

You can see the table by reading the script. It's not a complicated script, just uses metatables before metatables were cool. It's hipster TFS.

self.levels will never change because it is not modified in the script.
Yes, but I don't trust this metatable. I want to see what he finds.
 
razor solved your problem, but you did not change you code.

your
self.levels[self.item.level + 1]
is not table value.

now remove the prints and replace the error line with this.
(im not sure does value 0 means it will be 100% hopefully it does)

chances.upgrade = (self.levels[self.item.level] or 100)

I changed
Code:
chances.upgrade = (self.levels[self.item.level + 1][1] or 100)
to
Code:
chances.upgrade = (self.levels[self.item.level] or 100)

and all workeeeed!!!!!!! THANKSSSSSSS

EDIT: not work, read down!
 
Last edited:
Yes, but I don't trust this metatable. I want to see what he finds.
Code:
levels = {
[1] = {100, false, false},
[2] = {90, false, false},
[3] = {75, false, false},
[4] = {60, true, false},
[5] = {45, true, false},
[6] = {30, true, false},
[7] = {25, true, false},
[8] = {20, true, true},
[9] = {15, true, true},
[10] = {10, true, true},
[11] = {10, true, true},
[12] = {5, true, true}
},

You can see the table by reading the script. It's not a complicated script, just uses metatables before metatables were cool. It's hipster TFS.

self.levels will never change because it is not modified in the script.

Wait, i have a new problem... I can only upgrade a item +1. It was supposed to be possible to upgrate until +10, right?
When item are +1, appear: The targeted spike sword is already on max upgrade level.
 
Back
Top Bottom