• 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 1.3] Small Autoloot

Well, I tested it on rats and added cheese to the autoloot and it only collects one. and where does the money go?
 
My friend, to be honest, I don't know anything, I've never used it and I don't even know where to look. Could you guide me or refer me to a website with an explanation?
 
My friend, to be honest, I don't know anything, I've never used it and I don't even know where to look. Could you guide me or refer me to a website with an explanation?
If it's your TFS 1.5 Nekiro, then the default NPC bank already exists. Take a look here.
or
There is also a command available to check your bank balance.

See which one you prefer more: NPC bank or talkaction bank.
 
If it's your TFS 1.5 Nekiro, then the default NPC bank already exists. Take a look here.
or
There is also a command available to check your bank balance.

See which one you prefer more: NPC bank or talkaction bank.
I prefer talkactions, but I don't know why only the !balance command works and !withdraw all doesn't throw any errors, but it doesn't pay out money except for the !balance command, nothing happens, it's a pity I have to figure it out because the conversation with the NPC is too long
Post automatically merged:

I solved the problem, the changes from this link were needed:
[TalkAction.onSay] Fix pass the correct parameter by MillhioreBT · Pull Request #3518 · otland/forgottenserver (https://github.com/otland/forgottenserver/pull/3518/files)
 
Last edited:
I really like how simple and effective it is! How easy is it possible to change the looting to when the body is opened instead of when it's killed?
Don't want to make things to easy. ;)
Hi,
Raikou question still actually.
Possibile to change this ?

Next question - this script working with TFS 1.4.2 ?
 
For those who want to use Sarah's system? I was added and tested it, and noticed that there were errors, so I had to make changes to the source. After that, I corrected the script, which is very simple. I tested it on TFS 1.4.2 1098 and it worked perfectly, 100% Ok.

Here are the commits that need necessary alterations.

look for this line:
Lua:
function ec.onDropLoot(monster, corpse)
change to:
Lua:
function ec.onDropLoot(monster, corpse)
    if not corpse:getType():isContainer() then
        return
    end

    local corpseOwner = Player(corpse:getCorpseOwner())
    local items = corpse:getItems()
    local warningCapacity = false
    for _, item in pairs(items) do
        if item then
            local itemId = item:getId()
            if hasPlayerAutolootItem(corpseOwner, itemId) then
                if currencyItems[itemId] then
                    local worth = item:getCount()
                    local playerBankBalance = corpseOwner:getBankBalance()
                    corpseOwner:setBankBalance(playerBankBalance + worth)
                    corpseOwner:sendTextMessage(MESSAGE_STATUS_SMALL, string.format("Your balance increases by %d gold coins.", worth))
                    item:remove()
                elseif not item:moveTo(corpseOwner, 0) then
                    warningCapacity = true
                end
            end
        end
    end

    if warningCapacity then
        corpseOwner:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have no capacity.")
    end
end
 
Last edited:
For those who want to use Sarah's system? I was added and tested it, and noticed that there were errors, so I had to make changes to the source. After that, I corrected the script, which is very simple. I tested it on TFS 1.4.2 1098 and it worked perfectly, 100% Ok.

Here are the commits that need necessary alterations.

look for this line:
Lua:
function ec.onDropLoot(monster, corpse)
change to:
Lua:
function ec.onDropLoot(monster, corpse)
    if not corpse:getType():isContainer() then
        return
    end

    local corpseOwner = Player(corpse:getCorpseOwner())
    local items = corpse:getItems()
    local warningCapacity = false
    for _, item in pairs(items) do
        if item then
            local itemId = item:getId()
            if hasPlayerAutolootItem(corpseOwner, itemId) then
                if currencyItems[itemId] then
                    local worth = item:getCount()
                    local playerBankBalance = corpseOwner:getBankBalance()
                    corpseOwner:setBankBalance(playerBankBalance + worth)
                    corpseOwner:sendTextMessage(MESSAGE_STATUS_SMALL, string.format("Your balance increases by %d gold coins.", worth))
                    item:remove()
                elseif not item:moveTo(corpseOwner, 0) then
                    warningCapacity = true
                end
            end
        end
    end

    if warningCapacity then
        corpseOwner:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have no capacity.")
    end
end
Perfect working! Good job.
 
For those who want to use Sarah's system? I was added and tested it, and noticed that there were errors, so I had to make changes to the source. After that, I corrected the script, which is very simple. I tested it on TFS 1.4.2 1098 and it worked perfectly, 100% Ok.

Here are the commits that need necessary alterations.

look for this line:
Lua:
function ec.onDropLoot(monster, corpse)
change to:
Lua:
function ec.onDropLoot(monster, corpse)
    if not corpse:getType():isContainer() then
        return
    end

    local corpseOwner = Player(corpse:getCorpseOwner())
    local items = corpse:getItems()
    local warningCapacity = false
    for _, item in pairs(items) do
        if item then
            local itemId = item:getId()
            if hasPlayerAutolootItem(corpseOwner, itemId) then
                if currencyItems[itemId] then
                    local worth = item:getCount()
                    local playerBankBalance = corpseOwner:getBankBalance()
                    corpseOwner:setBankBalance(playerBankBalance + worth)
                    corpseOwner:sendTextMessage(MESSAGE_STATUS_SMALL, string.format("Your balance increases by %d gold coins.", worth))
                    item:remove()
                elseif not item:moveTo(corpseOwner, 0) then
                    warningCapacity = true
                end
            end
        end
    end

    if warningCapacity then
        corpseOwner:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have no capacity.")
    end
end

What would need to be changed to make the autoloot work only after the corpse is opened ?
 
I tried to modify it to add !autoloot money - so that I don't have to add each currency separately, but there is no chance, I can't manage to do it myself, help anyone?

BUG - If on corpose gold coin and currencyToBank = true, all is OK, but od platinum coins or crystal, Item on corpose remove but not going to bank.
 
Last edited:
Lua:
 if action == "add" then
        local itemType = ItemType(split[2])
        if not itemType or itemType:getId() == 0 then
            itemType = ItemType(math.max(tonumber(split[2]) or 0), 0)
            if not itemType or itemType:getId() == 0 then
                player:sendCancelMessage(string.format("The item %s does not exist!", split[2]))
                return false
            end
        end

        local itemName = itemType:getName()
        local itemID = itemType:getId()

        if addPlayerAutolootItem(player, itemID) then
            local message = string.format("Added %s to autoloot list.", itemName)
            player:sendCancelMessage(message)
            local monster = Monster(player:getPosition())
            if monster then
                monster:say(message, TALKTYPE_MONSTER_SAY)
            end
        else
            player:sendCancelMessage(string.format("The item %s is already in the autoloot list.", itemName))
        end

        return false
    end

if anybody want me to generate other functionalities into this code let me know
 
For those who want to use Sarah's system? I was added and tested it, and noticed that there were errors, so I had to make changes to the source. After that, I corrected the script, which is very simple. I tested it on TFS 1.4.2 1098 and it worked perfectly, 100% Ok.

Here are the commits that need necessary alterations.

look for this line:
Lua:
function ec.onDropLoot(monster, corpse)
change to:
Lua:
function ec.onDropLoot(monster, corpse)
    if not corpse:getType():isContainer() then
        return
    end

    local corpseOwner = Player(corpse:getCorpseOwner())
    local items = corpse:getItems()
    local warningCapacity = false
    for _, item in pairs(items) do
        if item then
            local itemId = item:getId()
            if hasPlayerAutolootItem(corpseOwner, itemId) then
                if currencyItems[itemId] then
                    local worth = item:getCount()
                    local playerBankBalance = corpseOwner:getBankBalance()
                    corpseOwner:setBankBalance(playerBankBalance + worth)
                    corpseOwner:sendTextMessage(MESSAGE_STATUS_SMALL, string.format("Your balance increases by %d gold coins.", worth))
                    item:remove()
                elseif not item:moveTo(corpseOwner, 0) then
                    warningCapacity = true
                end
            end
        end
    end

    if warningCapacity then
        corpseOwner:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have no capacity.")
    end
end

No have errors in console, but sometimes get item.
Crown Legs sometimes going to backpack, sometimes not.

EDIT: I found problem:


!autoloot add, crown legs (in newer versions have two names "cown legs")
ID 2488 and ID27189

It is possible to add items by name, but retrieve from the lowest indexes?
 
Last edited:
I tested with some normal items, however, this ID 'crown legs' doesn't work at all. I found it strange. Later, I'll study the case. I don't know the reason why this 'crown legs' ID doesn't work while other normal ones do.
They work, but add it like this.

!autoloot add, 2488

If you type a name, it picks up another index.
This happens not only with crown legs.
If you have duplicate names in items.xml, and the higher the protocol the more of them, it will pull up a random ID or the highest one available.


EDIT: +++ Console Problems:

Lua:
2024-03-07_01-00-28.255530 Lua Script Error: [Event Interface]
2024-03-07_01-00-28.255595 data/events/scripts/monster.lua:Monster@onDropLoot
2024-03-07_01-00-28.255632 /var/www/tfs_old/data/scripts/auto_loot/auto_loot.lua:21: attempt to index local 'player' (a nil value)
2024-03-07_01-00-28.255667 stack traceback:
2024-03-07_01-00-28.255701     [C]: in function '__index'
2024-03-07_01-00-28.255736     /var/www/tfs_old/data/scripts/auto_loot/auto_loot.lua:21: in function 'getPlayerLimit'
2024-03-07_01-00-28.256337     /var/www/tfs_old/data/scripts/auto_loot/auto_loot.lua:25: in function 'getPlayerAutolootItems'
2024-03-07_01-00-28.256385     /var/www/tfs_old/data/scripts/auto_loot/auto_loot.lua:87: in function 'hasPlayerAutolootItem'
2024-03-07_01-00-28.256459     /var/www/tfs_old/data/scripts/auto_loot/auto_loot.lua:107: in function </var/www/tfs_old/data/scripts/auto_loot/auto_loot.lua:97>
2024-03-07_01-00-28.256633     /var/www/tfs_old/data/scripts/lib/event_callbacks.lua:127: in function 'EventCallback'
2024-03-07_01-00-28.256774     data/events/scripts/monster.lua:3: in function <data/events/scripts/monster.lua:1>
 
Last edited:
Hello, here is a small, totally local autoloot system that is easy to configure ;)

Required version: TFS 1.5 last version
*** If you are using an alternate version such as: TFS-1.5-Downgrades, maybe you should merge these changes: A new way to manage player storages.

data/scripts/small_autoloot.lua
Here I will leave the version with money to the bank:
These small changes are required: A new way to manage player storages
Lua:
local autoloot = {
    talkaction = "!autoloottest",
    storageBase = 50000,
    freeAccountLimit = 10,
    premiumAccountLimit = 20,
    currencyToBank = true
}

local currencyItems = {}
if autoloot.currencyToBank then
    for index, item in pairs(Game.getCurrencyItems()) do
        currencyItems[item:getId()] = true
    end
end

local autolootCache = {}
local textEditRequests = {}

local function getPlayerLimit(player)
    return player:isPremium() and autoloot.premiumAccountLimit or autoloot.freeAccountLimit
end

local function getPlayerAutolootItems(player)
    local limits = getPlayerLimit(player)
    local guid = player:getGuid()
    local itemsCache = autolootCache[guid]
    if itemsCache then
        if #itemsCache > limits then
            local newChache = {unpack(itemsCache, 1, limits)}
            autolootCache[guid] = newChache
            return newChache
        end
        return itemsCache
    end

    local items = {}
    for i = 1, limits do
        local itemType = ItemType(math.max(player.storage[autoloot.storageBase + i], 0))
        if itemType and itemType:getId() ~= 0 then
            items[#items +1] = itemType:getId()
        end
    end

    autolootCache[guid] = items
    return items
end

local function setPlayerAutolootItems(player, newItems)
    local items = getPlayerAutolootItems(player)
    for i = getPlayerLimit(player), 1, -1 do
        local itemId = newItems[i]
        if itemId then
            player.storage[autoloot.storageBase + i] = itemId
            items[i] = itemId
        else
            player.storage[autoloot.storageBase + i] = -1
            table.remove(items, i)
        end
    end
    return true
end

local function addPlayerAutolootItem(player, itemId)
    local items = getPlayerAutolootItems(player)
    for _, id in pairs(items) do
        if itemId == id then
            return false
        end
    end
    items[#items +1] = itemId
    return setPlayerAutolootItems(player, items)
end

local function removePlayerAutolootItem(player, itemId)
    local items = getPlayerAutolootItems(player)
    for i, id in pairs(items) do
        if itemId == id then
            table.remove(items, i)
            return setPlayerAutolootItems(player, items)
        end
    end
    return false
end

local function hasPlayerAutolootItem(player, itemId)
    for _, id in pairs(getPlayerAutolootItems(player)) do
        if itemId == id then
            return true
        end
    end
    return false
end

local ec = EventCallback

function ec.onDropLoot(monster, corpse)
    if not corpse:getType():isContainer() then
        return
    end

    local corpseOwner = Player(corpse:getCorpseOwner())
    local items = corpse:getItems()
    local warningCapacity = false
    for _, item in pairs(items) do
        local itemId = item:getId()
        if hasPlayerAutolootItem(corpseOwner, itemId) then
            if currencyItems[itemId] then
                local worth = item:getWorth()
                corpseOwner:setBankBalance(corpseOwner:getBankBalance() + worth)
                corpseOwner:sendTextMessage(MESSAGE_STATUS_SMALL, string.format("Your balance increases by %d gold coins.", worth))
                item:remove()
            elseif not item:moveTo(corpseOwner, 0) then
                warningCapacity = true
            end
        end
    end

    if warningCapacity then
        corpseOwner:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You no have capacity.")
    end
end

ec:register(3)

local talkAction = TalkAction(autoloot.talkaction)

function talkAction.onSay(player, words, param, type)
    local split = param:splitTrimmed(",")
    local action = split[1]
    if not action then
        player:showTextDialog(2160, string.format("Examples of use:\n%s add,gold coin\n%s remove,gold coin\n%s clear\n%s show\n%s edit\n\n~Available slots~\nfreeAccount: %d\npremiumAccount: %d\ncurrency to bank: %s", words, words, words, words, words, autoloot.freeAccountLimit, autoloot.premiumAccountLimit, autoloot.currencyToBank and "yes" or "no"), false)
        return false
    end

    if action == "clear" then
        setPlayerAutolootItems(player, {})
        player:sendCancelMessage("Autoloot list cleaned.")
        return false
    elseif action == "show" then
        local items = getPlayerAutolootItems(player)
        local description = {string.format('~ Your autoloot list, capacity: %d/%d ~\n', #items, getPlayerLimit(player))}
        for i, itemId in pairs(items) do
            description[#description +1] = string.format("%d) %s", i, ItemType(itemId):getName())
        end
        player:showTextDialog(2160, table.concat(description, '\n'), false)
        return false
    elseif action == "edit" then
        local items = getPlayerAutolootItems(player)
        if #items == 0 then
            -- Example
            items = {2160,2672,2432}
        end
        local description = {}
        for i, itemId in pairs(items) do
            description[#description +1] = ItemType(itemId):getName()
        end
        player:registerEvent("autolootTextEdit")
        player:showTextDialog(1948, string.format("To add articles you just have to write their IDs or names on each line\nfor example:\n\n%s", table.concat(description, '\n')), true, 666)
        textEditRequests[player:getGuid()] = true
        return false
    end

    local function getItemType()
        local itemType = ItemType(split[2])
        if not itemType or itemType:getId() == 0 then
            itemType = ItemType(math.max(tonumber(split[2]) or 0), 0)
            if not itemType or itemType:getId() == 0 then
                player:sendCancelMessage(string.format("The item %s does not exists!", split[2]))
                return false
            end
        end
        return itemType
    end

    if action == "add" then
        local itemType = getItemType()
        if itemType then
            local limits = getPlayerLimit(player)
            if #getPlayerAutolootItems(player) >= limits then
                player:sendCancelMessage(string.format("Your auto loot only allows you to add %d items.", limits))
                return false
            end

            if addPlayerAutolootItem(player, itemType:getId()) then
                player:sendCancelMessage(string.format("Perfect you have added to the list: %s", itemType:getName()))
            else
                player:sendCancelMessage(string.format("The item %s already exists!", itemType:getName()))
            end
        end
        return false
    elseif action == "remove" then
        local itemType = getItemType()
        if itemType then
            if removePlayerAutolootItem(player, itemType:getId()) then
                player:sendCancelMessage(string.format("Perfect you have removed to the list the article: %s", itemType:getName()))
            else
                player:sendCancelMessage(string.format("The item %s does not exists in the list.", itemType:getName()))
            end
        end
        return false
    end

    return false
end

talkAction:separator(" ")
talkAction:register()

local creatureEvent = CreatureEvent("autolootCleanCache")

function creatureEvent.onLogout(player)
    setPlayerAutolootItems(player, getPlayerAutolootItems(player))
    autolootCache[player:getGuid()] = nil
    return true
end

creatureEvent:register()

creatureEvent = CreatureEvent("autolootTextEdit")

function creatureEvent.onTextEdit(player, item, text)
    player:unregisterEvent("autolootTextEdit")

    local split = text:splitTrimmed("\n")
    local items = {}
    for index, name in pairs(split) do repeat
        local itemType = ItemType(name)
        if not itemType or itemType:getId() == 0 then
            itemType = ItemType(tonumber(name))
            if not itemType or itemType:getId() == 0 then
                break
            end

            break
        end

        items[#items +1] = itemType:getId()
    until true end
    setPlayerAutolootItems(player, items)
    player:sendCancelMessage(string.format("Perfect, you have modified the list of articles manually."))
    return true
end

creatureEvent:register()

Note: Fixed the issues I was having clear and added a new command: !autoloot edit this works for manually editing the item list
View attachment 65760

loved it, but i have a problem, it doesnt let me edit the list manually only shows the list & adds by command
 
Back
Top