• 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!
  • If you're using Gesior 2012 or MyAAC, please review this thread for information about a serious security vulnerability and a fix.

Action [TFS 1.x] Item 'loot seller'

Gesior.pl

Mega Noob&LOL 2012
Senator
Premium User
Joined
Sep 18, 2007
Messages
2,743
Solutions
86
Reaction score
2,740
Location
Poland
GitHub
gesior
TFS 1.x version of Action - item 'item seller'/'fast loot' (use npc items list config!) (https://otland.net/threads/item-item-seller-fast-loot-use-npc-items-list-config.51076/)
How it works?
Player uses 'loot seller item' (ex. some rune - item that player can 'Use with...') on other item and if that other item is sellable, script removes it and gives player money.
It's easy to configure, as you can copy item lists from NPC. Items configuration is at bottom of script.

New features in 1.x version:
  • support for items list from .xml file
  • limit range to 1 SQM
  • block possibility to sell item in house, otherwise someone could sell item that lays in house doors
  • block possibility to sell items with actionID or uniqueID
data/actions.xml:
XML:
<action actionid="36282" event="script" value="other/item_seller.lua"/>
data/actions/scripts/other/item_seller.lua:
Lua:
-- rest of config (item prices) is under function, paste there your items list from npc
local config = {
    price_percent = 90, -- how many % of shop price player receive when sell by 'item seller'
    cash_to_bank = true -- send money to bank, not add to player BP
}

local shopItems = {}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if toPosition.x ~= 65535 and getDistanceBetween(player:getPosition(), toPosition) > 1 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'This item is too far away.')
        return true
    end

    local targetTile = Tile(toPosition)
    if targetTile then
        -- this is to prevent selling item that lays in house doors
        local targetHouse = targetTile:getHouse()
        if targetHouse then
            -- this blocks only selling items laying on house floor
            -- if player open BP that lays on house floor, he can sell items inside it
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'You cannot sell items in house.')
            return true
        end
    end

    local itemEx = Item(target.uid)
    if not itemEx then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'This is not an item.')
        return true
    end

    if itemEx:getUniqueId() < 65535 or itemEx:getActionId() > 0 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'You cannot sell quest item.')
        return true
    end

    if not shopItems[itemEx.itemid] then
        player:sendTextMessage(MESSAGE_INFO_DESCR, 'This is not sellable item.')
        return true
    end

    local itemCount = 1
    local itemType = ItemType(itemEx.itemid)
    if itemType:isStackable() then
        itemCount = itemEx.type
    end

    local itemName = itemEx:getName()
    local itemValue = math.ceil(shopItems[itemEx.itemid] * itemCount / 100 * config.price_percent)
    if itemValue > 0 then
        itemEx:getPosition():sendMagicEffect(CONST_ME_GIFT_WRAPS)
        itemEx:remove()

        local message = 'You sold ' .. itemCount .. ' ' .. itemName .. ' for ' .. itemValue .. ' gold coins.'
        if config.cash_to_bank then
            player:setBankBalance(player:getBankBalance() + itemValue)
            message = message .. ' Money was added to your bank account.'
        else
            player:addMoney(itemValue)
        end
        player:sendTextMessage(MESSAGE_INFO_DESCR, message)
    else
        player:sendTextMessage(MESSAGE_INFO_DESCR, itemName .. ' is worthless.')
    end

    return true
end

local shopModule = {}
function shopModule:addBuyableItemContainer()
end
function shopModule:addBuyableItem()
end
function shopModule:addSellableItem(names, itemid, cost, realName)
    shopItems[itemid] = cost
end

function shopModule:parseList(data)
    for item in string.gmatch(data, "[^;]+") do
        local i = 1
        local itemid = -1
        local cost = 0
        for temp in string.gmatch(item, "[^,]+") do
            if i == 2 then
                itemid = tonumber(temp)
            elseif i == 3 then
                cost = tonumber(temp)
            end
            i = i + 1
        end

        shopItems[itemid] = cost
    end
end

-- here paste list of items from NPC lua file
shopModule:addSellableItem({ 'poison arrow' }, 2545, 5, 'poison arrow')
shopModule:addSellableItem({ 'hota' }, 2342, 500, 'helmet of the ancients')

-- here paste list from .xml file
shopModule:parseList('crossbow,2455,150;bow,2456,130')
shopModule:parseList('knight armor, 2476, 10000')
 
Last edited:

Roddet

Boo!
Premium User
Joined
May 1, 2013
Messages
684
Solutions
70
Reaction score
432
Location
Mexico
Little optimization on parse func
Lua:
function shopModule:parseList(data)
    for item in string.gmatch(data, "[^;]+") do
        item:gsub("(%d+).(%d+)$", function(itemid, cost)
            shopItems[itemid] = cost
        end)
    end
end

Nice script : )
 
Last edited:
OP
OP
Gesior.pl

Gesior.pl

Mega Noob&LOL 2012
Senator
Premium User
Joined
Sep 18, 2007
Messages
2,743
Solutions
86
Reaction score
2,740
Location
Poland
GitHub
gesior
Little optimization on parse func
Lua:
function parseList(data)
    for item in string.gmatch(data, "[^;]+") do
        item:gsub("(%d+),(%d+)$", function(itemid, cost)
            shopItems[itemid] = cost
        end)
    end
end

Nice script : )
Nice. I just copied part of modules.lua from npc/lib.

NPC item lists in public datapacks have different formats. Some authors add space before/after ,.
How to make it handle spaces before and after ,? Like these 4 cases:
Code:
knight armor, 2476,10000
knight armor, 2476, 10000
knight armor, 2476 ,10000
knight armor, 2476 , 10000
I hope there are no items with number at end of name :p

Test code (you can run it on Lua: demo (https://www.lua.org/cgi-bin/demo) ):
Lua:
function parseListOld(data)
    for item in string.gmatch(data, "[^;]+") do
        local i = 1
        local itemid = -1
        local cost = 0
        for temp in string.gmatch(item, "[^,]+") do
            if i == 2 then
                itemid = tonumber(temp)
            elseif i == 3 then
                cost = tonumber(temp)
            end
            i = i + 1
        end
        shopItems[itemid] = cost
    end
end

function parseListNew(data)
    for item in string.gmatch(data, "[^;]+") do
        item:gsub("(%d+),(%d+)$", function(itemid, cost)
            shopItems[itemid] = cost
        end)
    end
end

shopItems = {}
parseListOld('a armor, 2476,10001');
parseListOld('b armor, 2477, 10002');
parseListOld('c armor, 2478 ,10003');
parseListOld('d armor, 2479 ,10004');
print('old')
for k, v in pairs(shopItems) do
    print(k, v)
end

shopItems = {}
parseListNew('a armor, 2476,10001');
parseListNew('b armor, 2477, 10002');
parseListNew('c armor, 2478 ,10003');
parseListNew('d armor, 2479 ,10004');
print('new')
for k, v in pairs(shopItems) do
    print(k, v)
end
 
Last edited:

Roddet

Boo!
Premium User
Joined
May 1, 2013
Messages
684
Solutions
70
Reaction score
432
Location
Mexico
Ahh you right, a weird way but this could be a workaround
Lua:
function shopModule:parseList(data)
    for item in string.gmatch(data, "[^;]+") do
        item:gsub("[^,]+", "", 1):gsub("(%d+).-(%d+)", function(itemid, cost)
            shopItems[itemid] = cost
        end)
    end
end
 
OP
OP
Gesior.pl

Gesior.pl

Mega Noob&LOL 2012
Senator
Premium User
Joined
Sep 18, 2007
Messages
2,743
Solutions
86
Reaction score
2,740
Location
Poland
GitHub
gesior
Ahh you right, a weird way but this could be a workaround
Lua:
function shopModule:parseList(data)
    for item in string.gmatch(data, "[^;]+") do
        item:gsub("[^,]+", "", 1):gsub("(%d+).-(%d+)", function(itemid, cost)
            shopItems[itemid] = cost
        end)
    end
end
Lua:
function shopModule:parseList(data)
    for item in string.gmatch(data, "[^;]+") do
        item:gsub("[^,]+", "", 1):gsub("(%d+).-(%d+)", function(itemid, cost)
            if tonumber(itemid) > 0 and tonumber(cost) > 0 then
                shopItems[tonumber(itemid)] = tonumber(cost)
            end
        end)
    end
end
Added conversion to number. Somehow (%d+) returns string, not number.

Anyway, it still works wrong somehow. WTF.
New edge case "someone typed some string in place of cost":
Lua:
parseListNew('b armor, 2477, b armor');
returns:
Code:
itemid = 247
cost = 7
I must say I'm not a fan of regex. Results are hard to predict and in some cases it's very unefficient.
In simple cases like spliting by ; and , I prefere few loops and simple string split.
 

Roddet

Boo!
Premium User
Joined
May 1, 2013
Messages
684
Solutions
70
Reaction score
432
Location
Mexico
I think this is the one, instead of looking for numbers we better explode , as you mention and then we capture their content
Lua:
function shopModule:parseList(data)
    for item in string.gmatch(data, "[^;]+") do
        item:gsub("[^,]+", "", 1):gsub("([^,]+).-([^,]+)", function(itemid, cost)
            itemid = tonumber(itemid)
            if itemid then -- only true if itemid is number
                shopItems[itemid] = tonumber(cost) -- if cost is not a number, then new index wont be added to the list
            end
        end)
    end
end
 
Last edited:

VagosClubTM

Member
Joined
Aug 16, 2019
Messages
168
Reaction score
22
Location
Chile
Is it possible to change the type of money it gives you for a specific item used as a token?
 

moekl

Member
Joined
Aug 25, 2014
Messages
124
Reaction score
14
Location
Sweden
hello havent tinkerd with a distro for a while totally forgot,
but can you fill in where i put the item id wich will be the shop
 
OP
OP
Gesior.pl

Gesior.pl

Mega Noob&LOL 2012
Senator
Premium User
Joined
Sep 18, 2007
Messages
2,743
Solutions
86
Reaction score
2,740
Location
Poland
GitHub
gesior
hello havent tinkerd with a distro for a while totally forgot,
but can you fill in where i put the item id wich will be the shop
It will be any item with ActionID set to 36282:
XML:
<action actionid="36282" event="script" value="other/item_seller.lua"/>
You can change it to:
XML:
<action itemid="2400" event="script" value="other/item_seller.lua"/>
to make item ID 2400 (Magic Sword) work as item seller.
 
Top