• 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 [MOD] tfs 0.4 error attempt to index local (a number value)

Svira

Active Member
Joined
Jan 27, 2008
Messages
267
Solutions
11
Reaction score
36
Hello, for a few days I have been trying to make an item to improve the equipment, today I managed to create a correctly loaded mod but I have a bug in the onuse function.

Do you have an idea how to correctly write it?

my mod:
XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<mod name="upgradeslots" version="1.0.0" author="Svira" enabled="yes">
    <config name="itemstats_confslot">
        <![CDATA[
            -- //
    extra_loot_key = 890456 --: optional storage for higher loot rate
    vocation_base_attackspeed = getVocationInfo(1).attackSpeed --: used for attackSpeed stat
-- //

tiers, attr = {}, {}

tiers['rare'] = {
    color = 66, -- color of 'RARE' text
    extra = {0, 15},
    attrNames = true, -- show attribute names instead of rare
    chance = {
        [1] = 30000,
        [2] = 15000 -- chance for 2nd stat
    }
}
tiers['epic'] = {
    color = 35,
    extra = {15, 35}, -- additional percent bonus
    chance = {
        [1] = 10000,
        [2] = 35000
    }
}
tiers['legendary'] = {
    color = 149,
    extra = {35, 55},
    chance = {
        [1] = 5000,
        [2] = 100000 -- 2 bonuses always
    }
}

MELEE = 0
DISTANCE = 1
ARMOR = 2
SHIELD = 3
WAND = 4
DURATION_RING = 5
CHARGES = 6

--! attributes
attr['quick'] = {
    attr = 'attackSpeed',
    name = 'Attack Speed',
    percent = {25, 45},
    types = {MELEE, DISTANCE, WAND}
}
attr['fortified'] = {
    attr = 'extraDefense',
    base = 'defense',
    name = 'Defense',
    percent = {25, 35},
    types = {MELEE, SHIELD}
}
attr['deadly'] = {
    attr = 'extraAttack',
    base = 'attack',
    name = 'Attack',
    types = {MELEE},
    percent = {25, 50}
}
attr['strong'] = {
    attr = 'armor',
    name = 'Armor',
    percent = {25, 50},
    types = {ARMOR}
}
attr['hawkeye\'s'] = {
    attr = 'hitChance',
    name = 'Hit Chance',
    percent = {35, 55},
    types = {DISTANCE}
}
--[[ // not available without source edit
attr['farsight'] = {
    attr = 'shootRange',
    name = 'Shoot Range',
    percent = {10, 20},
    types = {DISTANCE, WAND}
}
]]
attr['charged'] = {
    attr = 'charges',
    name = 'Charges',
    percent = {40, 80},
    types = {CHARGES}
}
attr['divine'] = {
    attr = 'duration',
    name = 'Duration',
    percent = {40, 80},
    types = {DURATION_RING}
}
--/ attributes

rate = getConfigInfo('rateLoot')

if( getConfigInfo('monsterLootMessage') ~= 0 )then
    print('[Notice] Set monsterLootMessage = 0 to prevent duplicate loot messages')
end
]]></config>

   
   

    <action itemid="8299" event="script">
        <![CDATA[
            domodlib('itemstats_confslot')
function round(n, s)
    return tonumber(('%.' .. (s or 0) .. 'f'):format(n))
end

function getContentDescription(uid, sep)
    local ret, i, containers = '', 0, {}
    while( i < getContainerSize(uid) )do
        local v, s = getContainerItem(uid, i), ''
        local k = getItemInfo(v.itemid)
        k.name = getItemAttribute(v.uid, 'name') or k.name
        if( k.name ~= '' )then
            if( v.type > 1 and k.stackable and k.showCount )then
                s = v.type .. ' ' .. k.plural
            else
                local article = getItemAttribute(v.uid, 'article') or k.article
                s = (article == '' and '' or article .. ' ') .. k.name
            end
            ret = ret .. (i == 0 and not sep and '' or ', ') .. s
            if( isContainer(v.uid) and getContainerSize(v.uid) ~= 0 )then
                table.insert(containers, v.uid)
            end
        else
            ret = ret .. (i == 0 and not sep and '' or ', ') .. 'an item of type ' .. v.itemid .. ', please report it to gamemaster'
        end
        i = i + 1
    end
    for i = 1, #containers do
        ret = ret .. getContentDescription(containers[i], true)
    end
    return ret
end

local function send(cid, corpse, monster)
    if( isPlayer(cid) )then
        local ret = corpse and isContainer(corpse) and getContentDescription(corpse)
        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, 'Loot of ' .. monster .. ': ' .. (ret ~= '' and ret or 'nothing'))
        local party = getPlayerParty(cid)
        if( party )then
            for _, pid in ipairs(getPartyMembers(party)) do
                doPlayerSendChannelMessage(pid, '', 'Loot of ' .. monster .. ': ' .. (ret ~= '' and ret or 'nothing'), TALKTYPE_CHANNEL_W, CHANNEL_PARTY)
            end
        end
    end
end
           
           
function onUse(i, ext)
    local item = type(i.id) == 'table' and i.id[math.random(#i.id)] or i.id
    local random = math.ceil(math.random(100000) / ext)
    local tmpItem, f

    if( random < i.chance )then
        if i.subType == -1 then
            f = getItemInfo(item)
        end
        tmpItem = doCreateItemEx(item,
            i.subType ~= -1 and i.subType or
            f.stackable and random % i.count + 1 or
            f.charges ~= 0 and f.charges or
            1
        )
    end

    if( not tmpItem )then
        return
    end

    if( i.actionId ~= -1 )then
        doItemSetAttribute(tmpItem, 'aid', i.actionId)
    end

    if( i.uniqueId ~= -1 )then
        doItemSetAttribute(tmpItem, 'uid', i.uniqueId)
    end

    if( i.text ~= '' )then
        doItemSetAttribute(tmpItem, 'text', i.text)
    end

    local ret, done

    for k, v in pairs(tiers) do
        local cur, used = {}, {}
        for i = 1, #v.chance do
            if( math.random(100000) <= v.chance[i] )then
                if( f )then
                    f = getItemInfo(item)
                end
                if( not f.stackable )then
                    for m, n in pairs(attr) do
                        if( not table.find(used, m) and
                        (
                            ( table.find(n.types, MELEE) and table.find({WEAPON_SWORD, WEAPON_CLUB, WEAPON_AXE}, f.weaponType) ) or
                            ( table.find(n.types, DISTANCE) and f.weaponType == WEAPON_DIST and f.ammoType ~= 0 ) or
                            ( table.find(n.types, ARMOR) and f.armor ~= 0 and f.wieldPosition ~= CONST_SLOT_NECKLACE ) or
                            ( table.find(n.types, SHIELD) and f.defense ~= 0 and f.weaponType == WEAPON_SHIELD ) or
                            ( table.find(n.types, WAND) and f.weaponType == WEAPON_WAND ) or
                            ( table.find(n.types, DURATION_RING) and f.wieldPosition == CONST_SLOT_RING and f.transformEquipTo ~= 0 ) or
                            ( table.find(n.types, CHARGES) and table.find({CONST_SLOT_RING, CONST_SLOT_NECKLACE}, f.wieldPosition) and f.charges ~= 0 )
                        ) )then
                            table.insert(cur, m)
                        end
                    end

                    if( #cur ~= 0 )then
                        local n = cur[math.random(#cur)]
                        table.insert(used, n)

                        n = attr[n]
                        local percent, new, tmp = math.random(n.percent[1] + (v.extra[1] or 0), n.percent[2] + (v.extra[2] or 0))
                        -- hacks
                        if( n.attr == 'duration' )then
                            tmp = getItemInfo(f.transformEquipTo)
                            if tmp.transformDeEquipTo ~= item then
                                break
                            end
                            new = round( tmp.decayTime * (1 + percent / 100) * 1000 )
                        elseif( n.attr == 'attackSpeed' )then
                            new = round( vocation_base_attackspeed / (1 + percent / 100) )
                        elseif( n.attr == 'hitChance' ) then
                            new = round(
                                f.hitChance == -1 and
                                    percent
                                or
                                    f.hitChance * (1 + percent / 100)
                            )
                        else
                            new = round(
                                n.base and
                                    f[n['attr']] + f[n['base']] * (percent / 100)
                                or
                                    f[n['attr']] * (1 + percent / 100)
                            )

                            if( new == f[n[n.base and 'base' or 'attr']] )then -- no improvement
                                break
                            end
                        end

                        doItemSetAttribute(tmpItem, n.attr:lower(), new)

                        local name = getItemAttribute(tmpItem, 'name')
                        if( v.attrNames or not name )then
                            local name = (v.attrNames and used[#used] or k) .. ' ' .. (name or f.name)
                            doItemSetAttribute(tmpItem, 'name', name)

                            if( f.article ~= '' )then
                                local article = getArticle(name)
                                if( article ~= f.article )then
                                    doItemSetAttribute(tmpItem, 'article', article)
                                end
                            end
                        end

                        local desc = getItemAttribute(tmpItem, 'description') or f.description
                        doItemSetAttribute(tmpItem, 'description', '[' .. n.name .. ': +' .. percent .. '%]' .. (desc == '' and '' or '\n' .. desc))

                        ret = k
                    end
                    cur = {}
                    if( #v.chance == i )then
                        done = true
                    end
                end
            else
                done = i ~= 1
                break
            end
        end
        if( done )then
            break
        end
    end

    return tmpItem, ret
end
        ]]>
    </action>
</mod>

edit, lol & Error xD

Lua:
[11:5:11.342] [Error - Action Interface]
[11:5:11.342]                   domodlib('itemstats_confslot')
[11:5:11.342] function round(n, s)
[11:5:11.342]   return tonumber(('%.' .. (s or 0) .. 'f'):format(n))
[11:5:11.342] end
[11:5:11.342]
[11:5:11.342] function getContentDescription(uid, sep)
[11:5:11.342]   local ret, i, containers = '', 0, {}
[11:5:11.342]   while( i < getContainerSize(uid) )do
[11:5:11.342]           local v, s = getContainerItem(uid, i), ''
[11:5:11.342]           local k = getItemInfo(v.itemid)
[11:5:11.342]           k.name = getItemAttribute(v.uid, 'name') or k.name
[11:5:11.342]           if( k.name ~= '' )then
[11:5:11.342]                   if( v.type > 1 and k.stackable and k.showCount )then
[11:5:11.342]                           s = v.type .. ' ' .. k.plural
[11:5:11.342]                   else
[11:5:11.342]                           local article = getItemAttribute(v.uid, 'article') or k.article
[11:5:11.342]                           s = (article == '' and '' or article .. ' ') .. k.name
[11:5:11.342]                   end
[11:5:11.342]                   ret = ret .. (i == 0 and not sep and '' or ', ') .. s
[11:5:11.342]                   if( isContainer(v.uid) and getContainerSize(v.uid) ~= 0 )then
[11:5:11.342]                           table.insert(containers, v.uid)
[11:5:11.342]                   end
[11:5:11.342]           else
[11:5:11.342]                   ret = ret .. (i == 0 and not sep and '' or ', ') .. 'an item of type ' .. v.itemid .. ', please report it to gamemaster'
[11:5:11.342]           end
[11:5:11.342]           i = i + 1
[11:5:11.342]   end
[11:5:11.342]   for i = 1, #containers do
[11:5:11.342]           ret = ret .. getContentDescription(containers[i], true)
[11:5:11.342]   end
[11:5:11.342]   return ret
[11:5:11.342] end
[11:5:11.342]
[11:5:11.343] local function send(cid, corpse, monster)
[11:5:11.343]   if( isPlayer(cid) )then
[11:5:11.343]           local ret = corpse and isContainer(corpse) and getContentDescription(corpse)
[11:5:11.343]           doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, 'Loot of ' .. monster .. ': ' .. (ret ~= '' and ret or 'nothing'))
[11:5:11.343]           local party = getPlayerParty(cid)
[11:5:11.343]           if( party )then
[11:5:11.343]                   for _, pid in ipairs(getPartyMembers(party)) do
[11:5:11.343]                           doPlayerSendChannelMessage(pid, '', 'Loot of ' .. monster .. ': ' .. (ret ~= '' and ret or 'nothing'), TALKTYPE_CHANNEL_W, CHANNEL_PARTY)
[11:5:11.343]                   end
[11:5:11.343]           end
[11:5:11.343]   end
[11:5:11.343] end
[11:5:11.343]
[11:5:11.343]
[11:5:11.343] function onUse(i, ext)
[11:5:11.343]   local item = type(i.id) == 'table' and i.id[math.random(#i.id)] or i.id
[11:5:11.343]   local random = math.ceil(math.random(100000) / ext)
[11:5:11.343]   local tmpItem, f
[11:5:11.343]
[11:5:11.343]   if( random < i.chance )then
[11:5:11.343]           if i.subType == -1 then
[11:5:11.343]                   f = getItemInfo(item)
[11:5:11.343]           end
[11:5:11.343]           tmpItem = doCreateItemEx(item,
[11:5:11.343]                   i.subType ~= -1 and i.subType or
[11:5:11.343]                   f.stackable and random % i.count + 1 or
[11:5:11.343]                   f.charges ~= 0 and f.charges or
[11:5:11.343]                   1
[11:5:11.343]           )
[11:5:11.343]   end
[11:5:11.343]
[11:5:11.343]   if( not tmpItem )then
[11:5:11.343]           return
[11:5:11.343]   end
[11:5:11.343]
[11:5:11.343]   if( i.actionId ~= -1 )then
[11:5:11.343]           doItemSetAttribute(tmpItem, 'aid', i.actionId)
[11:5:11.343]   end
[11:5:11.343]
[11:5:11.343]   if( i.uniqueId ~= -1 )then
[11:5:11.343]           doItemSetAttribute(tmpItem, 'uid', i.uniqueId)
[11:5:11.343]   end
[11:5:11.343]
[11:5:11.343]   if( i.text ~= '' )then
[11:5:11.343]           doItemSetAttribute(tmpItem, 'text', i.text)
[11:5:11.343]   end
[11:5:11.343]
[11:5:11.343]   local ret, done
[11:5:11.343]
[11:5:11.343]   for k, v in pairs(tiers) do
[11:5:11.343]           local cur, used = {}, {}
[11:5:11.343]           for i = 1, #v.chance do
[11:5:11.343]                   if( math.random(100000) <= v.chance[i] )then
[11:5:11.343]                           if( f )then
[11:5:11.343]                                   f = getItemInfo(item)
[11:5:11.343]                           end
[11:5:11.343]                           if( not f.stackable )then
[11:5:11.343]                                   for m, n in pairs(attr) do
[11:5:11.343]                                           if( not table.find(used, m) and
[11:5:11.343]                                           (
[11:5:11.343]                                                   ( table.find(n.types, MELEE) and table.find({WEAPON_SWORD, WEAPON_CLUB, WEAPON_AXE}, f.weaponType) ) or
[11:5:11.343]                                                   ( table.find(n.types, DISTANCE) and f.weaponType == WEAPON_DIST and f.ammoType ~= 0 ) or
[11:5:11.343]                                                   ( table.find(n.types, ARMOR) and f.armor ~= 0 and f.wieldPosition ~= CONST_SLOT_NECKLACE ) or
[11:5:11.343]                                                   ( table.find(n.types, SHIELD) and f.defense ~= 0 and f.weaponType == WEAPON_SHIELD ) or
[11:5:11.343]                                                   ( table.find(n.types, WAND) and f.weaponType == WEAPON_WAND ) or
[11:5:11.343]                                                   ( table.find(n.types, DURATION_RING) and f.wieldPosition == CONST_SLOT_RING and f.transformEquipTo ~= 0 ) or
[11:5:11.343]                                                   ( table.find(n.types, CHARGES) and table.find({CONST_SLOT_RING, CONST_SLOT_NECKLACE}, f.wieldPosition) and f.charges ~= 0 )
[11:5:11.343]                                           ) )then
[11:5:11.343]                                                   table.insert(cur, m)
[11:5:11.343]                                           end
[11:5:11.343]                                   end
[11:5:11.343]
[11:5:11.343]                                   if( #cur ~= 0 )then
[11:5:11.343]                                           local n = cur[math.random(#cur)]
[11:5:11.343]                                           table.insert(used, n)
[11:5:11.343]
[11:5:11.343]                                           n = attr[n]
[11:5:11.343]                                           local percent, new, tmp = math.random(n.percent[1] + (v.extra[1] or 0), n.percent[2] + (v.extra[2] or 0))
[11:5:11.343]                                           -- hacks
[11:5:11.343]                                           if( n.attr == 'duration' )then
[11:5:11.343]                                                   tmp = getItemInfo(f.transformEquipTo)
[11:5:11.343]                                                   if tmp.transformDeEquipTo ~= item then
[11:5:11.343]                                                           break
[11:5:11.343]                                                   end
[11:5:11.343]                                                   new = round( tmp.decayTime * (1 + percent / 100) * 1000 )
[11:5:11.343]                                           elseif( n.attr == 'attackSpeed' )then
[11:5:11.343]                                                   new = round( vocation_base_attackspeed / (1 + percent / 100) )
[11:5:11.343]                                           elseif( n.attr == 'hitChance' ) then
[11:5:11.343]                                                   new = round(
[11:5:11.343]                                                           f.hitChance == -1 and
[11:5:11.344]                                                                   percent
[11:5:11.344]                                                           or
[11:5:11.344]                                                                   f.hitChance * (1 + percent / 100)
[11:5:11.344]                                                   )
[11:5:11.344]                                           else
[11:5:11.344]                                                   new = round(
[11:5:11.344]                                                           n.base and
[11:5:11.344]                                                                   f[n['attr']] + f[n['base']] * (percent / 100)
[11:5:11.344]                                                           or
[11:5:11.344]                                                                   f[n['attr']] * (1 + percent / 100)
[11:5:11.344]                                                   )
[11:5:11.344]
[11:5:11.344]                                                   if( new == f[n[n.base and 'base' or 'attr']] )then -- no improvement
[11:5:11.344]                                                           break
[11:5:11.344]                                                   end
[11:5:11.344]                                           end
[11:5:11.344]
[11:5:11.344]                                           doItemSetAttribute(tmpItem, n.attr:lower(), new)
[11:5:11.344]
[11:5:11.344]                                           local name = getItemAttribute(tmpItem, 'name')
[11:5:11.344]                                           if( v.attrNames or not name )then
[11:5:11.344]                                                   local name = (v.attrNames and used[#used] or k) .. ' ' .. (name or f.name)
[11:5:11.344]                                                   doItemSetAttribute(tmpItem, 'name', name)
[11:5:11.344]
[11:5:11.344]                                                   if( f.article ~= '' )then
[11:5:11.344]                                                           local article = getArticle(name)
[11:5:11.344]                                                           if( article ~= f.article )then
[11:5:11.344]                                                                   doItemSetAttribute(tmpItem, 'article', article)
[11:5:11.344]                                                           end
[11:5:11.344]                                                   end
[11:5:11.344]                                           end
[11:5:11.344]
[11:5:11.344]                                           local desc = getItemAttribute(tmpItem, 'description') or f.description
[11:5:11.344]                                           doItemSetAttribute(tmpItem, 'description', '[' .. n.name .. ': +' .. percent .. '%]' .. (desc == '' and '' or '\n' .. desc))
[11:5:11.344]
[11:5:11.344]                                           ret = k
[11:5:11.344]                                   end
[11:5:11.344]                                   cur = {}
[11:5:11.344]                                   if( #v.chance == i )then
[11:5:11.344]                                           done = true
[11:5:11.344]                                   end
[11:5:11.344]                           end
[11:5:11.344]                   else
[11:5:11.344]                           done = i ~= 1
[11:5:11.344]                           break
[11:5:11.344]                   end
[11:5:11.344]           end
[11:5:11.344]           if( done )then
[11:5:11.344]                   break
[11:5:11.344]           end
[11:5:11.344]   end
[11:5:11.344]
[11:5:11.344]   return tmpItem, ret
[11:5:11.344] end
[11:5:11.344]           :onUse
[11:5:11.344] Description:
[11:5:11.344] [string "LuaInterface::loadBuffer"]:49: attempt to index local 'i' (a number value)
[11:5:11.344] stack traceback:
[11:5:11.344]   [string "LuaInterface::loadBuffer"]:49: in function <[string "LuaInterface::loadBuffer"]:48>
 
Solution
Wait.. why is your onUse like this?
Lua:
function onUse(i, ext)

Normally onUse looks like this..
Lua:
function onUse(cid, item, fromPosition, itemEx, toPosition)

idk if that helps or not, cuz I'm not touching that script with a 10 ft pole. xD
Wait.. why is your onUse like this?
Lua:
function onUse(i, ext)

Normally onUse looks like this..
Lua:
function onUse(cid, item, fromPosition, itemEx, toPosition)

idk if that helps or not, cuz I'm not touching that script with a 10 ft pole. xD
 
Solution
Back
Top