• 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/OTXServer3] Custom function NPC for buy/sell items.

whiteblXK

Active Member
Joined
Apr 20, 2011
Messages
315
Solutions
9
Reaction score
32
Location
Poland
Hello, I have idiotic problem, I have custom function for NPC trade and don't know why not working. Here is how it looks in game:
rUefcKsZQWqnD6bhb6mhhg.png


Function, with NPC
Lua:
local function getItemList(items, i, itemTable)
    v = items[i]
 
    itemTable[v.id] = {id = v.id, buy = v.buy, sell = v.sell, subType = v.subType or 0, name = v.name}
    return itemTable
end

function openTradeWindow(cid, items)
    local itemTable = {}
 
    if #items > 1 then
        for i = #items, 1, -1 do
            itemTable = getItemList(items, i, itemTable)
        end
    else
        itemTable = getItemList(items, 1, itemTable)
    end
 
    local function doNpcSellItem(cid, itemid, amount, subType, ignoreCap, inBackpacks, backpack)
        local amount = amount or 1
        local subType = subType or 0
        local item = 0
     
        if not itemTable[itemid].buy then
            return print("Error with traders table")
        end     
     
        if isItemStackable(itemid) then
            if inBackpacks then
                stuff = doCreateItemEx(backpack, 1)
                item = doAddContainerItem(stuff, itemid, math.min(100, amount))
            else
                stuff = doCreateItemEx(itemid, math.min(100, amount))
            end
            return doPlayerAddItemEx(cid, stuff, ignoreCap) ~= RETURNVALUE_NOERROR and 0 or amount, 0
        end

        local a = 0
        if inBackpacks then
            local container, b = doCreateItemEx(backpack, 1), 1
            for i = 1, amount do
                local item = doAddContainerItem(container, itemid, subType)
                if table.contains({(getContainerCapById(backpack) * b), amount}, i) then
                    if doPlayerAddItemEx(cid, container, ignoreCap) ~= RETURNVALUE_NOERROR then
                        b = b - 1
                        break
                    end

                    a = i
                    if amount > i then
                        container = doCreateItemEx(backpack, 1)
                        b = b + 1
                    end
                end
            end
            return a, b
        end

        for i = 1, amount do -- normal method for non-stackable items
            local item = doCreateItemEx(itemid, subType)
            if doPlayerAddItemEx(cid, item, ignoreCap) ~= RETURNVALUE_NOERROR then
                break
            end
            a = i
        end
     
        local price = amount * itemTable[item].buy
        doPlayerRemoveMoney(cid, price)
     
        local withPrice, hasText = '', false
        if price >= 10000 then
            local itemCoin = math.floor(price / 10000)
            withPrice = withPrice .. itemCoin .. ' gold' .. (itemCoin > 1 and 's' or '')
            price = price % 10000
            hasText = true
        end
        if price >= 100 then
            local itemCoin = math.floor(price / 100)
            withPrice = withPrice .. (hasText and ', ' or '') .. itemCoin .. ' dollar' .. (itemCoin > 1 and 's' or '')
            price = price % 100
            hasText = true
        end
        if price > 0 then
            withPrice = withPrice .. (hasText and ' and ' or '') .. price .. ' zeni' .. (price > 1 and 's' or '')
        end
     
        return npcHandler:say({'You bought '.. (amount > 1 and (amount .. 'x ') or '') .. itemTable[item].name .. (amount > 1 and 's' or '') ..' for '.. withPrice .. '.'}) 
     
    end 
 
 
    local function doPlayerSellItem(cid, itemid, count, cost)
        if not itemTable[itemid].sell then
            return
        end     
        if doPlayerTakeItem(cid, itemid, count) == true then
            local price = itemTable[item].sell * amount
         
            local withPrice, hasText = '', false
            if price >= 10000 then
                local itemCoin = math.floor(price / 10000)
                withPrice = withPrice .. itemCoin .. ' gold' .. (itemCoin > 1 and 's' or '')
                price = price % 10000
                hasText = true
            end
            if price >= 100 then
                local itemCoin = math.floor(price / 100)
                withPrice = withPrice .. (hasText and ', ' or '') .. itemCoin .. ' dollar' .. (itemCoin > 1 and 's' or '')
                price = price % 100
                hasText = true
            end
            if price > 0 then
                withPrice = withPrice .. (hasText and ' and ' or '') .. price .. ' zeni' .. (price > 1 and 's' or '')
            end
         
            if not doPlayerAddMoney(cid, price) then
                error('Could not add money to ' .. getPlayerName(cid) .. '(' .. cost .. 'gp)')
            end
            return npcHandler:say({'You sold '.. (amount > 1 and (amount .. 'x ') or '') .. itemTable[item].name .. (amount > 1 and 's' or '') ..' for '.. withPrice .. '.'}) 
        end
    end 
 
    return openShopWindow(cid, itemTable, doNpcSellItem, doPlayerSellItem)
end

NPC:
Code:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}
function onCreatureAppear(cid)            npcHandler:onCreatureAppear(cid)            end
function onCreatureDisappear(cid)         npcHandler:onCreatureDisappear(cid)         end
function onCreatureSay(cid, type, msg)  npcHandler:onCreatureSay(cid, type, msg)     end
function onThink()                        npcHandler:onThink()                         end
function creatureSayCallback(cid, type, msg)
  
    if(not npcHandler:isFocused(cid)) then
        return false
    end
    local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid 
    if isInArray({'trade','offer'}, msg:lower()) then
        openTradeWindow(cid, TRADE_WINDOW[getNpcName():lower()])
        return npcHandler:say({'He, he, he!'}, cid, 2000)
    end
return true
end
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
TRADE_WINDOW = {
    ['karin'] = {
        {id=2673, buy=20000, sell=0, name='Senzu Bean'},
        {id=2796, buy=1000, sell=0, name='Senzu Root'},
        {id=2795, buy=100, sell=0, name='Senzu Leaf'},
    },
}
 
Last edited:
I dont know much about scripting but you could just copy/paste Xodet.lua(or any other shopkeepernpc) and renamet to (your =npcname.lua)
Then that same npc (xodet) xml and add the custom items with the same functions. and then change the name to that xodet.xml to the name of your preference, and then the script pointing to you edited npcname.lua file, then go to your remeres map and do import monsters and select your npcname.xml file and done! :D! thats how i managed to get my custom items all into a full working npc seller (sells and buys everything)
 
Hello, I have idiotic problem, I have custom function for NPC trade and don't know why not working. Here is how it looks in game:
rUefcKsZQWqnD6bhb6mhhg.png


Function, with NPC
Lua:
local function getItemList(items, i, itemTable)
    v = items[i]
 
    itemTable[v.id] = {id = v.id, buy = v.buy, sell = v.sell, subType = v.subType or 0, name = v.name}
    return itemTable
end

function openTradeWindow(cid, items)
    local itemTable = {}
 
    if #items > 1 then
        for i = #items, 1, -1 do
            itemTable = getItemList(items, i, itemTable)
        end
    else
        itemTable = getItemList(items, 1, itemTable)
    end
 
    local function doNpcSellItem(cid, itemid, amount, subType, ignoreCap, inBackpacks, backpack)
        local amount = amount or 1
        local subType = subType or 0
        local item = 0
 
        if not itemTable[itemid].buy then
            return print("Error with traders table")
        end 
 
        if isItemStackable(itemid) then
            if inBackpacks then
                stuff = doCreateItemEx(backpack, 1)
                item = doAddContainerItem(stuff, itemid, math.min(100, amount))
            else
                stuff = doCreateItemEx(itemid, math.min(100, amount))
            end
            return doPlayerAddItemEx(cid, stuff, ignoreCap) ~= RETURNVALUE_NOERROR and 0 or amount, 0
        end

        local a = 0
        if inBackpacks then
            local container, b = doCreateItemEx(backpack, 1), 1
            for i = 1, amount do
                local item = doAddContainerItem(container, itemid, subType)
                if table.contains({(getContainerCapById(backpack) * b), amount}, i) then
                    if doPlayerAddItemEx(cid, container, ignoreCap) ~= RETURNVALUE_NOERROR then
                        b = b - 1
                        break
                    end

                    a = i
                    if amount > i then
                        container = doCreateItemEx(backpack, 1)
                        b = b + 1
                    end
                end
            end
            return a, b
        end

        for i = 1, amount do -- normal method for non-stackable items
            local item = doCreateItemEx(itemid, subType)
            if doPlayerAddItemEx(cid, item, ignoreCap) ~= RETURNVALUE_NOERROR then
                break
            end
            a = i
        end
 
        local price = amount * itemTable[item].buy
        doPlayerRemoveMoney(cid, price)
 
        local withPrice, hasText = '', false
        if price >= 10000 then
            local itemCoin = math.floor(price / 10000)
            withPrice = withPrice .. itemCoin .. ' gold' .. (itemCoin > 1 and 's' or '')
            price = price % 10000
            hasText = true
        end
        if price >= 100 then
            local itemCoin = math.floor(price / 100)
            withPrice = withPrice .. (hasText and ', ' or '') .. itemCoin .. ' dollar' .. (itemCoin > 1 and 's' or '')
            price = price % 100
            hasText = true
        end
        if price > 0 then
            withPrice = withPrice .. (hasText and ' and ' or '') .. price .. ' zeni' .. (price > 1 and 's' or '')
        end
 
        return npcHandler:say({'You bought '.. (amount > 1 and (amount .. 'x ') or '') .. itemTable[item].name .. (amount > 1 and 's' or '') ..' for '.. withPrice .. '.'})
 
    end
 
 
    local function doPlayerSellItem(cid, itemid, count, cost)
        if not itemTable[itemid].sell then
            return
        end 
        if doPlayerTakeItem(cid, itemid, count) == true then
            local price = itemTable[item].sell * amount
     
            local withPrice, hasText = '', false
            if price >= 10000 then
                local itemCoin = math.floor(price / 10000)
                withPrice = withPrice .. itemCoin .. ' gold' .. (itemCoin > 1 and 's' or '')
                price = price % 10000
                hasText = true
            end
            if price >= 100 then
                local itemCoin = math.floor(price / 100)
                withPrice = withPrice .. (hasText and ', ' or '') .. itemCoin .. ' dollar' .. (itemCoin > 1 and 's' or '')
                price = price % 100
                hasText = true
            end
            if price > 0 then
                withPrice = withPrice .. (hasText and ' and ' or '') .. price .. ' zeni' .. (price > 1 and 's' or '')
            end
     
            if not doPlayerAddMoney(cid, price) then
                error('Could not add money to ' .. getPlayerName(cid) .. '(' .. cost .. 'gp)')
            end
            return npcHandler:say({'You sold '.. (amount > 1 and (amount .. 'x ') or '') .. itemTable[item].name .. (amount > 1 and 's' or '') ..' for '.. withPrice .. '.'})
        end
    end
 
    return openShopWindow(cid, itemTable, doNpcSellItem, doPlayerSellItem)
end

NPC:
Code:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}
function onCreatureAppear(cid)            npcHandler:onCreatureAppear(cid)            end
function onCreatureDisappear(cid)         npcHandler:onCreatureDisappear(cid)         end
function onCreatureSay(cid, type, msg)  npcHandler:onCreatureSay(cid, type, msg)     end
function onThink()                        npcHandler:onThink()                         end
function creatureSayCallback(cid, type, msg)
 
    if(not npcHandler:isFocused(cid)) then
        return false
    end
    local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid
    if isInArray({'trade','offer'}, msg:lower()) then
        openTradeWindow(cid, TRADE_WINDOW[getNpcName():lower()])
        return npcHandler:say({'He, he, he!'}, cid, 2000)
    end
return true
end
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
TRADE_WINDOW = {
    ['karin'] = {
        {id=2673, buy=20000, sell=0, name='Senzu Bean'},
        {id=2796, buy=1000, sell=0, name='Senzu Root'},
        {id=2795, buy=100, sell=0, name='Senzu Leaf'},
    },
}
Here is the 1st part of your script... getItemList is pointless to have because it is extra steps that do nothing for the script.
Lua:
function openTradeWindow(cid, items)
    local itemTable = {}
    if items and next(items) then
        for k, v in pairs(items) do
           if type(v) == 'table' then
               itemTable[v.id] = {id = v.id, buy = v.buy, sell = v.sell, subType = v.subType or 0, name = v.name}
           end
        end
    end
    if not itemTable or not next(itemTable) then
        return print("Error nothing to buy or sell")
    end
    local function doNpcSellItem(cid, itemid, amount, subType, ignoreCap, inBackpacks, backpack)
        local amount = amount or 1
        local subType = subType or 0
        local item = 0
 
        if not itemTable[itemid] or not itemTable[itemid].buy then
            return print("Error with traders table")
        end
 
Last edited:
Back
Top