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:
edit, lol & Error xD
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>