• 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.X+ Trying to add storage and mission to Trader

SixNine

Active Member
Joined
Dec 12, 2018
Messages
452
Reaction score
41
Hey trying to create NPC that basically he wont be able to type Trade to him until he brings the required stuff, once he brings it he can see what he sells. Tried this code but didnt worked at all
Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

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

local shopModule = ShopModule:new()
npcHandler:addModule(shopModule)
 
shopModule:addBuyableItem({'secret chest'}, 19105, 1000000, 1, 'secret chest')
--The rest of items

 
local config = {
    minLevel = 50, 
    needItems = {
        {id = 1234, count = 5},
        {id = 5678, count = 3},
    },
}

function creatureSayCallback(cid, type, msg)
    local player = Player(cid)

    if not npcHandler:isFocused(cid) then
        if msg == "hi" or msg == "hello" then
            npcHandler:addFocus(cid)

            npcHandler:say("Hey, I'm the owner, and I can trade you some furniture. Are you interested in a trade?", cid)
            npcHandler.topic[cid] = 1
        else
            return false
        end
    elseif msgcontains(msg, "trade") and npcHandler.topic[cid] == 1 then
        npcHandler:say("Great! Please type 'items' to see the list of items I need.", cid)
        npcHandler.topic[cid] = 2
    elseif msgcontains(msg, "items") and npcHandler.topic[cid] == 2 then
        local itemsNeeded = {}

        for _, v in ipairs(config.needItems) do
            local info = ItemType(v.id)
            table.insert(itemsNeeded, (v.count > 1 and v.count or info:getArticle()) .. " " .. (v.count > 1 and info:getPluralName() or info:getName()))
        end

        local neededItemsString = table.concat(itemsNeeded, ", ")

        npcHandler:say(string.format("Do you have the following items: %s?", neededItemsString), cid)
        npcHandler.topic[cid] = 3
    elseif msgcontains(msg, "yes") and npcHandler.topic[cid] == 3 then
        local amount = 0
        local items = {}

        for _, v in ipairs(config.needItems) do
            local playerCount = player:getItemCount(v.id)
            if playerCount >= v.count then
                amount = amount + 1
            else
                local info = ItemType(v.id)
                table.insert(items, (v.count > 1 and v.count or info:getArticle()) .. " " .. (v.count > 1 and info:getPluralName() or info:getName()))
            end
        end

        if amount ~= #config.needItems then
            local needItems = table.concat(items, ", ")
            npcHandler:say(string.format("Sorry, you don't have the required items: %s.", needItems), cid)
            npcHandler.topic[cid] = 0
            npcHandler:releaseFocus(cid)
            return true
        end

        for _, v in ipairs(config.needItems) do
            player:removeItem(v.id, v.count)
        end

        npcHandler:say("Thank you for the items! You can now see the list of items I sell.", cid)
        player:setStorageValue(123, 1)
        npcHandler.topic[cid] = 0
        npcHandler:releaseFocus(cid)
    elseif msgcontains(msg, "no") and npcHandler.topic[cid] == 3 then
        npcHandler:say("No problem! If you change your mind, feel free to come back.", cid)
        npcHandler.topic[cid] = 0
        npcHandler:releaseFocus(cid)
    elseif msgcontains(msg, "bye") then
        npcHandler:say("Goodbye!", cid)
        npcHandler:releaseFocus(cid)
    end

    return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
 
Solution
I went and looked at your script to understand, it took me 20 minutes, and now I get what you wanted. If a player doesn't have storage, they can't initiate a trade with the NPC, right? Then, they just need to say 'hi' and 'items,' and they need the items to confirm 'yes' to receive storage and unlock the ability to talk to the trade NPC. So, I copied another NPC function that has 'onBuy,' made some changes, and now it's easier. Give it a try, and then give me some feedback..

Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}
local needItems = {}

function onCreatureAppear(cid)
    npcHandler:onCreatureAppear(cid)
end

function...
So
- You want the NPC to only be able to trade with if player has X storage?

You could add this before the trading~


Lua:
function onCreatureSay(cid, type, msg)
    if getPlayerStorageValue(cid, 1001) == 1 then

The 1001 is the Quest Storage that needs to be completed before anything will done after this function
 
So
- You want the NPC to only be able to trade with if player has X storage?

You could add this before the trading~


Lua:
function onCreatureSay(cid, type, msg)
    if getPlayerStorageValue(cid, 1001) == 1 then

The 1001 is the Quest Storage that needs to be completed before anything will done after this function
Something aint right with my overall code probably after adding this, it doesnt even respond to "hi"
 
I noticed that some scripts were incorrect, so I decided to remove those that were unnecessary. For example, there's no need to add 'hi' or 'hello' within the Lua script, only in the XML. I made small adjustments, tested it, and it's working perfectly.

npc LUA.
Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

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

local shopModule = ShopModule:new()
npcHandler:addModule(shopModule)

shopModule:addBuyableItem({'secret chest'}, 2400, 1000, 1, 'secret chest')
-- Add other items to the store as needed

local config = {
    minLevel = 50,
    needItems = {
        {id = 2140, count = 5},
        {id = 5678, count = 3},
    },
    requiredStorageValue = 10510, -- Replace with the required storage value
}

function creatureSayCallback(cid, type, msg)
    local player = Player(cid)

-- Checks if the player meets the minimum requirements
    if player:getLevel() < config.minLevel then
        npcHandler:say("You need to be at least level " .. config.minLevel .. " to trade with me.", cid)
        npcHandler:releaseFocus(cid)
        return true
    elseif player:getStorageValue(config.requiredStorageValue) ~= 1 then
        npcHandler:say("You must complete a certain task before trading with me.", cid)
        npcHandler:releaseFocus(cid)
        return true
    elseif msgcontains(msg, "trade") and npcHandler.topic[cid] == 1 then
        npcHandler:say("Great! Please type 'items' to see the list of items I need.", cid)
        npcHandler.topic[cid] = 2
    elseif msgcontains(msg, "items") and npcHandler.topic[cid] == 2 then
    local itemsNeeded = {}

    for _, v in ipairs(config.needItems) do
        local info = ItemType(v.id)
        table.insert(itemsNeeded, (v.count > 1 and v.count or info:getArticle()) .. " " .. (v.count > 1 and info:getPluralName() or info:getName()))
    end

    local neededItemsString = table.concat(itemsNeeded, ", ")

    npcHandler:say(string.format("Do you have the following items: %s?", neededItemsString), cid)
    npcHandler.topic[cid] = 3

    elseif msgcontains(msg, "yes") and npcHandler.topic[cid] == 3 then
        local amount = 0
        local items = {}

        for _, v in ipairs(config.needItems) do
            local playerCount = player:getItemCount(v.id)
            if playerCount >= v.count then
                amount = amount + 1
            else
                local info = ItemType(v.id)
                table.insert(items, (v.count > 1 and v.count or info:getArticle()) .. " " .. (v.count > 1 and info:getPluralName() or info:getName()))
            end
        end

        if amount ~= #config.needItems then
            local needItems = table.concat(items, ", ")
            npcHandler:say(string.format("Sorry, you don't have the required items: %s.", needItems), cid)
            npcHandler.topic[cid] = 0
            npcHandler:releaseFocus(cid)
            return true
        end

        for _, v in ipairs(config.needItems) do
            player:removeItem(v.id, v.count)
        end

        npcHandler:say("Thank you for the items! You can now see the list of items I sell.", cid)
        player:setStorageValue(config.requiredStorageValue, 1)
        npcHandler.topic[cid] = 0
        npcHandler:releaseFocus(cid)
    elseif msgcontains(msg, "no") and npcHandler.topic[cid] == 3 then
        npcHandler:say("No problem! If you change your mind, feel free to come back.", cid)
        npcHandler.topic[cid] = 0
        npcHandler:releaseFocus(cid)
    elseif msgcontains(msg, "bye") then
        npcHandler:say("Goodbye!", cid)
        npcHandler:releaseFocus(cid)
    end

    return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

npc xml.
Lua:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="test" script="test.lua" walkinterval="2000" floorchange="0">
    <health now="150" max="150"/>
    <look type="142" head="17" body="54" legs="114" feet="0" addons="0" corpse="3128"/>
    <parameters>
  <parameter key="message_greet" value="Hey, |PLAYERNAME|. I'm the owner, and I can trade you some furniture. Are you interested in a trade?" />
  </parameters>
</npc>
 
I noticed that some scripts were incorrect, so I decided to remove those that were unnecessary. For example, there's no need to add 'hi' or 'hello' within the Lua script, only in the XML. I made small adjustments, tested it, and it's working perfectly.

npc LUA.
Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

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

local shopModule = ShopModule:new()
npcHandler:addModule(shopModule)

shopModule:addBuyableItem({'secret chest'}, 2400, 1000, 1, 'secret chest')
-- Add other items to the store as needed

local config = {
    minLevel = 50,
    needItems = {
        {id = 2140, count = 5},
        {id = 5678, count = 3},
    },
    requiredStorageValue = 10510, -- Replace with the required storage value
}

function creatureSayCallback(cid, type, msg)
    local player = Player(cid)

-- Checks if the player meets the minimum requirements
    if player:getLevel() < config.minLevel then
        npcHandler:say("You need to be at least level " .. config.minLevel .. " to trade with me.", cid)
        npcHandler:releaseFocus(cid)
        return true
    elseif player:getStorageValue(config.requiredStorageValue) ~= 1 then
        npcHandler:say("You must complete a certain task before trading with me.", cid)
        npcHandler:releaseFocus(cid)
        return true
    elseif msgcontains(msg, "trade") and npcHandler.topic[cid] == 1 then
        npcHandler:say("Great! Please type 'items' to see the list of items I need.", cid)
        npcHandler.topic[cid] = 2
    elseif msgcontains(msg, "items") and npcHandler.topic[cid] == 2 then
    local itemsNeeded = {}

    for _, v in ipairs(config.needItems) do
        local info = ItemType(v.id)
        table.insert(itemsNeeded, (v.count > 1 and v.count or info:getArticle()) .. " " .. (v.count > 1 and info:getPluralName() or info:getName()))
    end

    local neededItemsString = table.concat(itemsNeeded, ", ")

    npcHandler:say(string.format("Do you have the following items: %s?", neededItemsString), cid)
    npcHandler.topic[cid] = 3

    elseif msgcontains(msg, "yes") and npcHandler.topic[cid] == 3 then
        local amount = 0
        local items = {}

        for _, v in ipairs(config.needItems) do
            local playerCount = player:getItemCount(v.id)
            if playerCount >= v.count then
                amount = amount + 1
            else
                local info = ItemType(v.id)
                table.insert(items, (v.count > 1 and v.count or info:getArticle()) .. " " .. (v.count > 1 and info:getPluralName() or info:getName()))
            end
        end

        if amount ~= #config.needItems then
            local needItems = table.concat(items, ", ")
            npcHandler:say(string.format("Sorry, you don't have the required items: %s.", needItems), cid)
            npcHandler.topic[cid] = 0
            npcHandler:releaseFocus(cid)
            return true
        end

        for _, v in ipairs(config.needItems) do
            player:removeItem(v.id, v.count)
        end

        npcHandler:say("Thank you for the items! You can now see the list of items I sell.", cid)
        player:setStorageValue(config.requiredStorageValue, 1)
        npcHandler.topic[cid] = 0
        npcHandler:releaseFocus(cid)
    elseif msgcontains(msg, "no") and npcHandler.topic[cid] == 3 then
        npcHandler:say("No problem! If you change your mind, feel free to come back.", cid)
        npcHandler.topic[cid] = 0
        npcHandler:releaseFocus(cid)
    elseif msgcontains(msg, "bye") then
        npcHandler:say("Goodbye!", cid)
        npcHandler:releaseFocus(cid)
    end

    return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

npc xml.
Lua:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="test" script="test.lua" walkinterval="2000" floorchange="0">
    <health now="150" max="150"/>
    <look type="142" head="17" body="54" legs="114" feet="0" addons="0" corpse="3128"/>
    <parameters>
  <parameter key="message_greet" value="Hey, |PLAYERNAME|. I'm the owner, and I can trade you some furniture. Are you interested in a trade?" />
  </parameters>
</npc>
Indeed its better now but noticed a flaw, task part doesnt work where he should ask him to bring the items in the table. Another issue you can just type hi/trade and it opens trade menu without completing his requirements
 
I went and looked at your script to understand, it took me 20 minutes, and now I get what you wanted. If a player doesn't have storage, they can't initiate a trade with the NPC, right? Then, they just need to say 'hi' and 'items,' and they need the items to confirm 'yes' to receive storage and unlock the ability to talk to the trade NPC. So, I copied another NPC function that has 'onBuy,' made some changes, and now it's easier. Give it a try, and then give me some feedback..

Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}
local needItems = {}

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

local function hasTradePermission(player)
    local requiredStorage = 10510
    return player:getStorageValue(requiredStorage) == 1
end

local function creatureSayCallback(cid, type, msg)
    if not npcHandler:isFocused(cid) then
        return false
    end

    local player = Player(cid)

    if msgcontains(msg, 'trade') then
        if hasTradePermission(player) then
            local t = {
                [19105] = { price = 1000000 },
            }

            local onBuy = function(cid, item, subType, amount, ignoreCap, inBackpacks)
                local player = Player(cid)

                if t[item] and not player:removeMoney(t[item].price) then
                    selfSay("You do not have enough money.", cid)
                else
                    player:addItem(item)
                    selfSay("Here it is.", cid)
                end

                return true
            end

            local shopWindow = {}
            for var, ret in pairs(t) do
                local itemType = ItemType(var)
                local itemName = itemType:getName()
                table.insert(shopWindow, { id = var, subType = 0, buy = ret.price, sell = 0, name = itemName })
            end

            openShopWindow(cid, shopWindow, onBuy, onSell)
        else
            selfSay("Great! Please type 'items' to see the list of items I need..", cid)
        end
        return true
    elseif msgcontains(msg, 'items') or msgcontains(msg, 'item') then
        if player:getStorageValue(10510) ~= 1 then
            selfSay("I am in need of the following items:", cid)
            needItems = {
                {id = 2140, count = 5, name = "Small Health Potion"},
                {id = 5678, count = 3, name = "Some Other Item"},
            }
            for _, item in ipairs(needItems) do
                local itemName = ItemType(item.id):getName()
                selfSay(itemName .. " x " .. item.count, cid)
            end
            talkState[cid] = 8
        else
            selfSay("You already have permission to trade with me", cid)
        end
    elseif msgcontains(msg, 'yes') and talkState[cid] == 8 then
        if player:getStorageValue(10510) == 1 then
            selfSay("You already have the permission", cid)
            return true
        end

        local playerItems = {}
        for _, item in ipairs(needItems) do
            local itemCount = player:getItemCount(item.id)
            table.insert(playerItems, {id = item.id, count = itemCount, name = item.name})
        end

        local hasItems = true
        for _, item in ipairs(playerItems) do
            if item.count < needItems[_].count then
                hasItems = false
                break
            end
        end

        if hasItems then
            for _, item in ipairs(needItems) do
                player:removeItem(item.id, item.count)
            end

            player:setStorageValue(10510, 1)
            player:getPosition():sendMagicEffect(49)
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You have received permission to trade with me")
            selfSay("Thank you for the items! You can now see the list of items I sell.", cid)
        else
            selfSay("Sorry, you don't have the required items.", cid)
        end

        talkState[cid] = 0
    end

    return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
 
Last edited:
Solution
I went and looked at your script to understand, it took me 20 minutes, and now I get what you wanted. If a player doesn't have storage, they can't initiate a trade with the NPC, right? Then, they just need to say 'hi' and 'items,' and they need the items to confirm 'yes' to receive storage and unlock the ability to talk to the trade NPC. So, I copied another NPC function that has 'onBuy,' made some changes, and now it's easier. Give it a try, and then give me some feedback..

Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}
local needItems = {}

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

local function hasTradePermission(player)
    local requiredStorage = 10510
    return player:getStorageValue(requiredStorage) == 1
end

local function creatureSayCallback(cid, type, msg)
    if not npcHandler:isFocused(cid) then
        return false
    end

    local player = Player(cid)

    if msgcontains(msg, 'trade') then
        if hasTradePermission(player) then
            local t = {
                [19105] = { price = 1000000 },
            }

            local onBuy = function(cid, item, subType, amount, ignoreCap, inBackpacks)
                local player = Player(cid)

                if t[item] and not player:removeMoney(t[item].price) then
                    selfSay("You do not have enough money.", cid)
                else
                    player:addItem(item)
                    selfSay("Here it is.", cid)
                end

                return true
            end

            local shopWindow = {}
            for var, ret in pairs(t) do
                local itemType = ItemType(var)
                local itemName = itemType:getName()
                table.insert(shopWindow, { id = var, subType = 0, buy = ret.price, sell = 0, name = itemName })
            end

            openShopWindow(cid, shopWindow, onBuy, onSell)
        else
            selfSay("Great! Please type 'items' to see the list of items I need..", cid)
        end
        return true
    elseif msgcontains(msg, 'items') or msgcontains(msg, 'item') then
        if player:getStorageValue(10510) ~= 1 then
            selfSay("I am in need of the following items:", cid)
            needItems = {
                {id = 2140, count = 5, name = "Small Health Potion"},
                {id = 5678, count = 3, name = "Some Other Item"},
            }
            for _, item in ipairs(needItems) do
                local itemName = ItemType(item.id):getName()
                selfSay(itemName .. " x " .. item.count, cid)
            end
            talkState[cid] = 8
        else
            selfSay("You already have permission to trade with me", cid)
        end
    elseif msgcontains(msg, 'yes') and talkState[cid] == 8 then
        if player:getStorageValue(10510) == 1 then
            selfSay("You already have the permission", cid)
            return true
        end

        local playerItems = {}
        for _, item in ipairs(needItems) do
            local itemCount = player:getItemCount(item.id)
            table.insert(playerItems, {id = item.id, count = itemCount, name = item.name})
        end

        local hasItems = true
        for _, item in ipairs(playerItems) do
            if item.count < needItems[_].count then
                hasItems = false
                break
            end
        end

        if hasItems then
            for _, item in ipairs(needItems) do
                player:removeItem(item.id, item.count)
            end

            player:setStorageValue(10510, 1)
            player:getPosition():sendMagicEffect(49)
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You have received permission to trade with me")
            selfSay("Thank you for the items! You can now see the list of items I sell.", cid)
        else
            selfSay("Sorry, you don't have the required items.", cid)
        end

        talkState[cid] = 0
    end

    return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
O wow top tier stuff my dude
 
Back
Top