• 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!

[TFS 0.4] Exceptional Auto Looting System on opening corpse

Gomgom

Member
Joined
Oct 1, 2009
Messages
135
Reaction score
18
Location
Egypt
Hello, I wrote a system that got an idea and I know that the hole thing could’ve been written in c++ but I’d rather have it written in lua than edit source files which makes it easy for a lot of people to install systems, though, many people have been using that all new versions of tibia and I stick with 8.6, so you wouldn’t like this one unless you were into 8.6, I found a couple of auto looting systems here on forums, the ones I found don’t differ from each other that much so I wanted to share an exceptional one with you, guys, as I had spare time to write some codes.

Using this makes you have to have a parchment written on it the items you want to auto loot to a certain backpack, it is writable which means you can edit it anytime, certainly, but with a 10 second cooldown or whatever you want it to be, if the backpack is full or you do not have such a backpack to loot to, it loots anywhere, I know some people would notice that I didn’t use the regular function that adds items to players and automatically stacks them, I simply could’ve got ride of some loops freeing memory, so I have to tell you that, in some servers “doPlayerAddItemEx” function doesn’t update players’ capacity if you have 1 of that stackable item, though, it stacks but it doesn’t update the cap unless the function creates a new stack or you move, remove or add an item to the inventory/backpack, I guess that happens ‘cause the function lacks the part of the code that updates players’ capacity on stacking items that’s why I tended to use loops that update items to their new amount using transfer function instead, anyway, I hope you guys like the idea, and of course, I wouldn’t mind considering any suggestions.

Here are the codes:

1. Go to data/lib, place the lua file I attached there.

2. Go to data/creaturescripts/scripts, create a new lua file, name it as "autolooting.lua", copy the code below and paste it there.

Lua:
function onTextEdit(cid, item, newtext)
    if item.itemid == AUTOLOOTITEMID then
        if os.time() < getPlayerStorageValue(cid, "AUTOLOOTD") then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "["..string.upper(AUTOLOOTSYSTEMNAME).."]: " .. (getPlayerStorageValue(cid, "AUTOLOOTD") - os.time() > 0 and "You can edit "..getItemNameById(item.itemid).." only once per "..AUTOLOOTDELAY.." seconds. " .. getPlayerStorageValue(cid, "AUTOLOOTD") - os.time() .. " second"..(getPlayerStorageValue(cid, "AUTOLOOTD") - os.time() == 1 and "" or "s").." left" or "Just wait awhile") .. ".")
            return false
        end
 
        if getItemAttribute(item.uid, 'text') and string.lower(newtext) == getItemAttribute(item.uid, 'text') then
            return false
        end
 
        local newtitems, tablecount, itemtable, notfounditems, bitems, msgs = string.explode(newtext:lower(), "\n"), 0, {}, {}, {}, ""
        if #newtitems > 0 then
            for iitem = 1, #newtitems do
                local newitc = string.explode(newtitems[iitem], ",")
                local itemname, citemname = newitc[1] or '', newitc[2] or ''
                local itemid, citemid = getItemIdByName(itemname, false), getItemIdByName(citemname, false)
                if itemname ~= '' and not itemtable[itemname] and not isInArray(notfounditems, itemname) and #newitc < 3 then
                    if tablecount == MAXAUTOLOOTITEMS then
                        msgs = msgs..(msgs ~= '' and ', y' or 'Y').."ou can only write "..MAXAUTOLOOTITEMS.." item names that you can auto loot"
                        break
                    end
                    if itemid then
                        if getItemInfo(itemid).weight ~= 0 then
                            if not isItemBackpack(itemid) then
                                if not isInArray(AUTOLOOTBLOCKEDITEM, itemid) then
                                    itemtable[itemname] = isItemBackpack(citemid) and citemname or ''
                                    tablecount = tablecount+1
                                else
                                    table.insert(bitems, itemname)
                                end
                            else
                                msgs = msgs..(msgs ~= '' and ', y' or 'Y').."ou can't auto loot bags nor backpacks"
                            end
                        else
                            msgs = msgs..(msgs ~= '' and ', y' or 'Y').."ou can't auto loot weightless items"
                        end
                    else
                        table.insert(notfounditems, itemname)
                    end
                end
            end
        end
 
        local founditemtext, count = "", 0
        if tablecount > 0 then
            for item, backpack in pairs(itemtable) do
                count = count+1
                founditemtext = founditemtext..(count == 1 and "" or "\n")..item..(backpack ~= '' and ", "..backpack or '')
            end
        end
 
        if founditemtext ~= '' then
            doItemSetAttribute(item.uid, 'text', founditemtext)
        else
            doItemEraseAttribute(item.uid, 'text')
        end
 
        if #bitems > 0 then
            local bitemtext = ""
            for bitem = 1, #bitems do
                bitemtext = bitemtext..(bitem > 1 and (bitem == #bitems and " & " or ", ") or "")..bitems[bitem]
            end
            msgs = msgs..(msgs ~= '' and ', t' or 'T').."he following item"..(#bitems == 1 and " is" or "s are").." blocked \" "..bitemtext.." \""
        end
                        
        if #notfounditems > 0 then
            local wrongitemtext = ""
            for nitem = 1, #notfounditems do
                wrongitemtext = wrongitemtext..(nitem > 1 and (nitem == #notfounditems and " & " or ", ") or "")..notfounditems[nitem]
            end
            msgs = msgs..(msgs ~= '' and ', t' or 'T')..'he following item'..(#notfounditems == 1 and ' doesn\'t' or 's don\'t')..' exist " '..wrongitemtext..' "'
        end
 
        if msgs ~= '' then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "["..string.upper(AUTOLOOTSYSTEMNAME).."]: "..msgs..".")
        end
        setPlayerStorageValue(cid, "AUTOLOOTD", os.time() + AUTOLOOTDELAY)
        return false
    end
    return true
end

3. Create a new lua file in the same folder, name it as "autolootingkill.lua", copy the code below and paste it there.

Lua:
function onKill(cid, target)
    if not isMonster(target) or isSummon(target) then
        return true
    end

    local v = getMonsterInfo(getCreatureName(target))
    if v and v.lookCorpse ~= 0 and #v.loot > 0 then
        addEvent(doSetAutoLootCorpseAid, 0, cid, getThingPos(target), v.lookCorpse)
    end
    return true
end

4. Open "login.lua" which is also in the same folder, register the 2 previous files above by copying and pasting the code below anywhere.

Lua:
registerCreatureEvent(cid, "AutoLooting")
registerCreatureEvent(cid, "AutoLootingKill")

5. Open "creaturescripts.xml" which is located in data/creaturescripts, copy the code below and paste it there.

XML:
<event type="textedit" name="AutoLooting" event="script" value="autolooting.lua"/>
<event type="kill" name="AutoLootingKill" event="script" value="autolootingkill.lua"/>

6. Go to data/actions/scripts, create a new lua file, name it as "autolooting.lua", copy the code below and paste it there.

Lua:
function onUse(cid, item)
    if item.actionid == AUTOLOOTCORPSEAID and isCorpse(item.uid) then
        local corpseowner = getItemAttribute(item.uid, 'corpseowner')
        if (corpseowner and getPlayerByGUID(corpseowner) == cid) or not corpseowner then
            doPlayerAutoLoot(cid, item)
            if AUTOLOOTONLYONCE then --- once corpse is opened it can't be auto looted anymore
                doItemEraseAttribute(item.uid, 'aid')
            end --- once corpse is opened it can't be auto looted anymore
        end
        return false
    end
    return true
end

This "AUTOLOOTONLYONCE" condition here forces the script to rest item aid attribute on opening corpse even if you don’t call the autoloot function, in other words, if you open the corpse without having the parchment in your inventory/backpack or the parchment is empty you won’t be able to autoloot this corpse anymore, I had to use it that way to prevent people from adding a lot of items to the corpse which would probably cause lag if there are a lot of containers, you could simply move that part of script inside autoloot function after checking out whether or not the player is having the parchment which means it would only reset the aid if you executed autoloot function but keep in mind, that will allow players to have a chance to put items inside corpse, though.

7. Open "actions.xml" which is located in data/actions, copy the code below and paste it there.

XML:
<action actionid="87078" event="script" value="autolooting.lua"/>

8. Open "items.xml" which is located in data/items, search for an item with id "1951" and replace all item elements with the code below.

XML:
<item id="1951" article="the" name="auto looting parchment">
   <attribute key="weight" value="200" />
   <attribute key="writeable" value="1" />
   <attribute key="maxTextLen" value="620" />
   <attribute key="description" value="Write items you want to auto loot followed by loot backpack, if loot backpack is not written you will loot to anywhere. (e.g., gold coin, yellow backpack)" />
</item>

The more items you want the parchment to have, the more max text length you have to have, which means you need to increase "maxTextLen" in case you want to increase "MAXAUTOLOOTITEMS"

How to use?


Simply write the item you want to loot followed by loot backpack, if loot backpack is not written you will loot to anywhere. (e.g., gold coin, yellow backpack), take a look at this image.
autolooting.png
 

Attachments

Last edited:
im having a problem, when i try to add an item to 1951 i have this error always

[AUTO LOOTING SYSTEM]: The following item doesn't exist "ham".
Hello, I wrote a system that got an idea and I know that the hole thing could’ve been written in c++ but I’d rather have it written in lua than edit source files which makes it easy for a lot of people to install systems, though, many people have been using that all new versions of tibia and I stick with 8.6, so you wouldn’t like this one unless you were into 8.6, I found a couple of auto looting systems here on forums, the ones I found don’t differ from each other that much so I wanted to share an exceptional one with you, guys, as I had spare time to write some codes.

Using this makes you have to have a parchment written on it the items you want to auto loot to a certain backpack, it is writable which means you can edit it anytime, certainly, but with a 10 second cooldown or whatever you want it to be, if the backpack is full or you do not have such a backpack to loot to, it loots anywhere, I know some people would notice that I didn’t use the regular function that adds items to players and automatically stacks them, I simply could’ve got ride of some loops freeing memory, so I have to tell you that, in some servers “doPlayerAddItemEx” function doesn’t update players’ capacity if you have 1 of that stackable item, though, it stacks but it doesn’t update the cap unless the function creates a new stack or you move, remove or add an item to the inventory/backpack, I guess that happens ‘cause the function lacks the part of the code that updates players’ capacity on stacking items that’s why I tended to use loops that update items to their new amount using transfer function instead, anyway, I hope you guys like the idea, and of course, I wouldn’t mind considering any suggestions.

Here are the codes:

1. Go to data/lib, place the lua file I attached there.

2. Go to data/creaturescripts/scripts, create a new lua file, name it as "autolooting.lua", copy the code below and paste it there.

Lua:
function onTextEdit(cid, item, newtext)
    if item.itemid == AUTOLOOTITEMID then
        if os.time() < getPlayerStorageValue(cid, "AUTOLOOTD") then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "["..string.upper(AUTOLOOTSYSTEMNAME).."]: " .. (getPlayerStorageValue(cid, "AUTOLOOTD") - os.time() > 0 and "You can edit "..getItemNameById(item.itemid).." only once per "..AUTOLOOTDELAY.." seconds. " .. getPlayerStorageValue(cid, "AUTOLOOTD") - os.time() .. " second"..(getPlayerStorageValue(cid, "AUTOLOOTD") - os.time() == 1 and "" or "s").." left" or "Just wait awhile") .. ".")
            return false
        end
 
        if getItemAttribute(item.uid, 'text') and string.lower(newtext) == getItemAttribute(item.uid, 'text') then
            return false
        end
 
        local newtitems, tablecount, itemtable, notfounditems, bitems, msgs = string.explode(newtext:lower(), "\n"), 0, {}, {}, {}, ""
        if #newtitems > 0 then
            for iitem = 1, #newtitems do
                local newitc = string.explode(newtitems[iitem], ",")
                local itemname, citemname = newitc[1] or '', newitc[2] or ''
                local itemid, citemid = getItemIdByName(itemname, false), getItemIdByName(citemname, false)
                if itemname ~= '' and not itemtable[itemname] and not isInArray(notfounditems, itemname) and #newitc < 3 then
                    if tablecount == MAXAUTOLOOTITEMS then
                        msgs = msgs..(msgs ~= '' and ', y' or 'Y').."ou can only write "..MAXAUTOLOOTITEMS.." item names that you can auto loot"
                        break
                    end
                    if itemid then
                        if getItemInfo(itemid).weight ~= 0 then
                            if not isItemBackpack(itemid) then
                                if not isInArray(AUTOLOOTBLOCKEDITEM, itemid) then
                                    itemtable[itemname] = isItemBackpack(citemid) and citemname or ''
                                    tablecount = tablecount+1
                                else
                                    table.insert(bitems, itemname)
                                end
                            else
                                msgs = msgs..(msgs ~= '' and ', y' or 'Y').."ou can't auto loot bags nor backpacks"
                            end
                        else
                            msgs = msgs..(msgs ~= '' and ', y' or 'Y').."ou can't auto loot weightless items"
                        end
                    else
                        table.insert(notfounditems, itemname)
                    end
                end
            end
        end
 
        local founditemtext, count = "", 0
        if tablecount > 0 then
            for item, backpack in pairs(itemtable) do
                count = count+1
                founditemtext = founditemtext..(count == 1 and "" or "\n")..item..(backpack ~= '' and ", "..backpack or '')
            end
        end
 
        if founditemtext ~= '' then
            doItemSetAttribute(item.uid, 'text', founditemtext)
        else
            doItemEraseAttribute(item.uid, 'text')
        end
 
        if #bitems > 0 then
            local bitemtext = ""
            for bitem = 1, #bitems do
                bitemtext = bitemtext..(bitem > 1 and (bitem == #bitems and " & " or ", ") or "")..bitems[bitem]
            end
            msgs = msgs..(msgs ~= '' and ', t' or 'T').."he following item"..(#bitems == 1 and " is" or "s are").." blocked \" "..bitemtext.." \""
        end
                       
        if #notfounditems > 0 then
            local wrongitemtext = ""
            for nitem = 1, #notfounditems do
                wrongitemtext = wrongitemtext..(nitem > 1 and (nitem == #notfounditems and " & " or ", ") or "")..notfounditems[nitem]
            end
            msgs = msgs..(msgs ~= '' and ', t' or 'T')..'he following item'..(#notfounditems == 1 and ' doesn\'t' or 's don\'t')..' exist " '..wrongitemtext..' "'
        end
 
        if msgs ~= '' then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "["..string.upper(AUTOLOOTSYSTEMNAME).."]: "..msgs..".")
        end
        setPlayerStorageValue(cid, "AUTOLOOTD", os.time() + AUTOLOOTDELAY)
        return false
    end
    return true
end

3. Create a new lua file in the same folder, name it as "autolootingkill.lua", copy the code below and paste it there.

Lua:
function onKill(cid, target)
    if not isMonster(target) or isSummon(target) then
        return true
    end

    local v = getMonsterInfo(getCreatureName(target))
    if v and v.lookCorpse ~= 0 and #v.loot > 0 then
        addEvent(doSetAutoLootCorpseAid, 0, cid, getThingPos(target), v.lookCorpse)
    end
    return true
end

4. Open "login.lua" which is also in the same folder, register the 2 previous files above by copying and pasting the code below anywhere.

Lua:
registerCreatureEvent(cid, "AutoLooting")
registerCreatureEvent(cid, "AutoLootingKill")

5. Open "creaturescripts.xml" which is located in data/creaturescripts, copy the code below and paste it there.

XML:
<event type="textedit" name="AutoLooting" event="script" value="autolooting.lua"/>
<event type="kill" name="AutoLootingKill" event="script" value="autolootingkill.lua"/>

6. Go to data/actions/scripts, create a new lua file, name it as "autolooting.lua", copy the code below and paste it there.

Lua:
function onUse(cid, item)
    if item.actionid == AUTOLOOTCORPSEAID and isCorpse(item.uid) then
        local corpseowner = getItemAttribute(item.uid, 'corpseowner')
        if (corpseowner and getPlayerByGUID(corpseowner) == cid) or not corpseowner then
            doPlayerAutoLoot(cid, item)
            if AUTOLOOTONLYONCE then --- once corpse is opened it can't be auto looted anymore
                doItemEraseAttribute(item.uid, 'aid')
            end --- once corpse is opened it can't be auto looted anymore
        end
        return false
    end
    return true
end

This "AUTOLOOTONLYONCE" condition here forces the script to rest item aid attribute on opening corpse even if you don’t call the autoloot function, in other words, if you open the corpse without having the parchment in your inventory/backpack or the parchment is empty you won’t be able to autoloot this corpse anymore, I had to use it that way to prevent people from adding a lot of items to the corpse which would probably cause lag if there are a lot of containers, you could simply move that part of script inside autoloot function after checking out whether or not the player is having the parchment which means it would only reset the aid if you executed autoloot function but keep in mind, that will allow players to have a chance to put items inside corpse, though.

7. Open "actions.xml" which is located in data/actions, copy the code below and paste it there.

XML:
<action actionid="87078" event="script" value="autolooting.lua"/>

8. Open "items.xml" which is located in data/items, search for an item with id "1951" and replace all item elements with the code below.

XML:
<item id="1951" article="the" name="auto looting parchment">
   <attribute key="weight" value="200" />
   <attribute key="writeable" value="1" />
   <attribute key="maxTextLen" value="620" />
   <attribute key="description" value="Write items you want to auto loot followed by loot backpack, if loot backpack is not written you will loot to anywhere. (e.g., gold coin, yellow backpack)" />
</item>

The more items you want the parchment to have, the more max text length you have to have, which means you need to increase "maxTextLen" in case you want to increase "MAXAUTOLOOTITEMS"

How to use?


Simply write the item you want to loot followed by loot backpack, if loot backpack is not written you will loot to anywhere. (e.g., gold coin, yellow backpack), take a look at this image.
View attachment 59407
 
im having a problem, when i try to add an item to 1951 i have this error always

[AUTO LOOTING SYSTEM]: The following item doesn't exist "ham".
Would you mind sharing your “item.xml” as long as “autolooting.lua” which is located in data/creaturescripts/scripts

Edit:
Are you getting any errors?
You might as well replace “getItemIdByName(itemname, false), getItemIdByName(citemname, false)” with “getItemIdByName(itemname), getItemIdByName(citemname)”
 
Last edited:
Hi, I managed to make the modification and the parchment works. But every time the Player takes the loot the following error appears.

[Error - Action Interface]
data/actions/scripts/autolooting.lua:eek:nUse
Description:
(luaGetItemIdByName) Item not found

[Error - Action Interface]
data/actions/scripts/autolooting.lua:eek:nUse
Description:
(luaGetItemIdByName) Item not found
 
You can either replace all "getItemIdByName(...., false)" functions with "getItemIdByName(....) just without the second parameter and it will work just fine, you will still get the error though without any issues, an error will just show up, or you can leave it as it is but you will need a source edit

in " luascripts.cpp " replace this

C++:
int32_t LuaInterface::luaGetItemIdByName(lua_State* L)
{
    //getItemIdByName(name)
    int32_t itemId = Item::items.getItemIdByName(popString(L));
    if(itemId == -1)
    {
        errorEx(getError(LUA_ERROR_ITEM_NOT_FOUND));
        lua_pushboolean(L, false);
    }
    else
        lua_pushnumber(L, itemId);

    return 1;
}

with that


C++:
int32_t LuaInterface::luaGetItemIdByName(lua_State* L)
{
    //getItemIdByName(name[, displayError = true])
    bool displayError = true;
    if(lua_gettop(L) >= 2)
        displayError = popBoolean(L);

    int32_t itemId = Item::items.getItemIdByName(popString(L));
    if(itemId == -1)
    {
        if(displayError)
            errorEx(getError(LUA_ERROR_ITEM_NOT_FOUND));

        lua_pushboolean(L, false);
    }
    else
        lua_pushnumber(L, itemId);

    return 1;
}
 
Last edited:
Good morning, I play on server 7.6, which has a built-in autoloot command (you can add an item and just open the body and the item appears in the backpack). I wonder if it is possible to make a macro in OTClient in which the character runs to the monster's body and opens it. I tried to do something like that, but I don't know how to make it so that after opening the same body once, it doesn't open it a second time, but moves to the next body.
 
Back
Top