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

Solved Umar npc index local message nil value and others

Thorn

Spriting since 2013
Joined
Sep 24, 2012
Messages
2,203
Solutions
1
Reaction score
922
Location
Chile
Hello guys, i use a tfs 1.3 and i took Umar from orts datapack, but this npc is giving me trouble everytime i talk to him...i tried everything i know to make him work, compared to other npcs, tried multiple times multiple variables, but nothing, so im posting here begging for help plz!! this is the error it shows up in console everytime i talk to him


Code:
Lua Script Error: [Npc interface]
data/npc/scripts/Umar.lua:onCreatureSay
data/npc/lib/npc.lua:6: attempt to index local 'message' (a nil value)
stack traceback:
        [C]: in function '__index'
        data/npc/lib/npc.lua:6: in function 'msgcontains'
        data/npc/scripts/Umar.lua:12: in function 'callback'
        data/npc/lib/npcsystem/npchandler.lua:340: in function 'greet'
        data/npc/lib/npcsystem/npchandler.lua:519: in function 'onGreet'
        data/npc/lib/npcsystem/modules.lua:322: in function 'callback'
        data/npc/lib/npcsystem/keywordhandler.lua:26: in function 'processMessage'
        data/npc/lib/npcsystem/keywordhandler.lua:136: in function 'processNodeMessage'
        data/npc/lib/npcsystem/keywordhandler.lua:104: in function 'processMessage'
        data/npc/lib/npcsystem/npchandler.lua:408: in function 'onCreatureSay'
        data/npc/scripts/Umar.lua:7: in function <data/npc/scripts/Umar.lua:7>


this is the file that is giving error:
LUA:
-- Including the Advanced NPC System
dofile('data/npc/lib/npcsystem/npcsystem.lua')
dofile('data/npc/lib/npcsystem/customModules.lua')

function msgcontains(message, keyword)
    local message, keyword = message:lower(), keyword:lower()
    if message == keyword then
        return true
    end

    return message:find(keyword) and not message:find('(%w+)' .. keyword)
end

function doNpcSellItem(cid, itemid, amount, subType, ignoreCap, inBackpacks, backpack)
    local amount = amount or 1
    local subType = subType or 0
    local item = 0
    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
    return a, 0
end

local func = function(cid, text, type, e, pcid)
    if isPlayer(pcid) then
        doCreatureSay(cid, text, type, false, pcid, getCreaturePosition(cid))
        e.done = TRUE
    end
end

function doCreatureSayWithDelay(cid, text, type, delay, e, pcid)
    if isPlayer(pcid) then
        e.done = FALSE
        e.event = addEvent(func, delay < 1 and 1000 or delay, cid, text, type, e, pcid)
    end
end

function doPlayerTakeItem(cid, itemid, count)
    if getPlayerItemCount(cid,itemid) < count then
        return false
    end

    while count > 0 do
        local tempcount = 0
        if isItemStackable(itemid) then
            tempcount = math.min (100, count)
        else
            tempcount = 1
        end

        local ret = doPlayerRemoveItem(cid, itemid, tempcount)
        if ret ~= false then
            count = count - tempcount
        else
            return false
        end
    end

    if count ~= 0 then
        return false
    end
    return true
end

function doPlayerSellItem(cid, itemid, count, cost)
    if doPlayerTakeItem(cid, itemid, count) == true then
        if not doPlayerAddMoney(cid, cost) then
            error('Could not add money to ' .. getPlayerName(cid) .. '(' .. cost .. 'gp)')
        end
        return true
    end
    return false
end

function doPlayerBuyItemContainer(cid, containerid, itemid, count, cost, charges)
    if not doPlayerRemoveMoney(cid, cost) then
        return false
    end

    for i = 1, count do
        local container = doCreateItemEx(containerid, 1)
        for x = 1, getContainerCapById(containerid) do
            doAddContainerItem(container, itemid, charges)
        end

        if doPlayerAddItemEx(cid, container, true) ~= RETURNVALUE_NOERROR then
            return false
        end
    end
    return true
end

function getCount(string)
    local b, e = string:find("%d+")
    return b and e and tonumber(string:sub(b, e)) or -1
end


and this is the npc

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 function greetCallback(cid, message)
    local player = Player(cid)
    if not msgcontains(message, 'djanni\'hah') and player:getStorageValue(Storage.DjinnWar.Faction.Marid) ~= 1 then
        npcHandler:say('Whoa! A human! This is no place for you, |PLAYERNAME|. Go and play somewhere else.', cid)
        return false
    end

    if player:getStorageValue(Storage.DjinnWar.Faction.Greeting) == -1 then
        npcHandler:say({
            'Hahahaha! ...',
            '|PLAYERNAME|, that almost sounded like the word of greeting. Humans - cute they are!'
        }, cid)
        return false
    end

    if player:getStorageValue(Storage.DjinnWar.Faction.Marid) ~= 1 then
        npcHandler:setMessage(MESSAGE_GREET, {
            'Whoa? You know the word! Amazing, |PLAYERNAME|! ...',
            'I should go and tell Fa\'hradin. ...',
            'Well. Why are you here anyway, |PLAYERNAME|?'
        })
    else
        npcHandler:setMessage(MESSAGE_GREET, '|PLAYERNAME|! How\'s it going these days? What brings you {here}?')
    end
    return true
end

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

    local player = Player(cid)
    if msgcontains(msg, 'passage') then
        if player:getStorageValue(Storage.DjinnWar.Faction.Marid) ~= 1 then
            npcHandler:say({
                'If you want to enter our fortress you have to become one of us and fight the Efreet. ...',
                'So, are you willing to do so?'
            }, cid)
            npcHandler.topic[cid] = 1
        else
            npcHandler:say('You already have the permission to enter Ashta\'daramai.', cid)
        end

    elseif npcHandler.topic[cid] == 1 then
        if msgcontains(msg, 'yes') then
            if player:getStorageValue(Storage.DjinnWar.Faction.Efreet) ~= 1 then
                npcHandler:say('Are you sure? You pledge loyalty to king Gabel, who is... you know. And you are willing to never ever set foot on Efreets\' territory, unless you want to kill them? Yes?', cid)
                npcHandler.topic[cid] = 2
            else
                npcHandler:say('I don\'t believe you! You better go now.', cid)
                npcHandler.topic[cid] = 0
            end

        elseif msgcontains(msg, 'no') then
            npcHandler:say('This isn\'t your war anyway, human.', cid)
            npcHandler.topic[cid] = 0
        end

    elseif npcHandler.topic[cid] == 2 then
        if msgcontains(msg, 'yes') then
            npcHandler:say({
                'Oh. Ok. Welcome then. You may pass. ...',
                'And don\'t forget to kill some Efreets, now and then.'
            }, cid)
            player:setStorageValue(Storage.DjinnWar.Faction.Marid, 1)
            player:setStorageValue(Storage.DjinnWar.Faction.Greeting, 0)

        elseif msgcontains(msg, 'no') then
            npcHandler:say('This isn\'t your war anyway, human.', cid)
        end
        npcHandler.topic[cid] = 0
    end
    return true
end

npcHandler:setMessage(MESSAGE_FAREWELL, '<salutes>Aaaa -tention!')
npcHandler:setMessage(MESSAGE_WALKAWAY, '<salutes>Aaaa -tention!')

npcHandler:setCallback(CALLBACK_GREET, greetCallback)
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)

local focusModule = FocusModule:new()
focusModule:addGreetMessage('hi')
focusModule:addGreetMessage('hello')
focusModule:addGreetMessage('djanni\'hah')
npcHandler:addModule(focusModule)
 
Last edited:
Solution
You should learn to read error messages because they tell you exactly what the problem is. Start at the top; the first line tells you that this is a Lua script error, specifically within the Npc interface. The second line tells you in what file, and the method name, in which the error originated (head of the call stack). The third line is the most important, it tells you the file, line number, and reason for the error. Next is the stack trace, this is the series of method calls that led to the error. The stack trace is in reverse order, so the first line is the instruction where the error occurred, and the last line is where the instruction originated from. So, if you wanted to follow the stack trace, start at line 15 and work your way...
Not sure of the issue, as it appears to be focused on this one line..
But everywhere else in your script you've been using 'msg' and on that line you are using 'message'
Try changing that?
yeah i also tried that, it looks like the npc is fine, the problem is in lib D:
 
The problem is that you are setting greetCallback() as your greet callback, and the NPC greet callback handler only passes one argument; the cid. You should be able to just add the message as another argument there, then update the onGreet method in npchandler.lua to have the message parameter as well, then passing it as a second argument to self:greet(cid) inside of the NpcHandler onGreet() method.
 
The problem is that you are setting greetCallback() as your greet callback, and the NPC greet callback handler only passes one argument; the cid. You should be able to just add the message as another argument there, then update the onGreet method in npchandler.lua to have the message parameter as well, then passing it as a second argument to self:greet(cid) inside of the NpcHandler onGreet() method.
damn, is there any way you could tell me exactly what to edit there? this is beyond my knowledge and libs are delicate :S plzz
 
FocusModule.onGreet
First, add message to the onGreet call. Change this:
LUA:
-- Greeting callback function.
function FocusModule.onGreet(cid, message, keywords, parameters)
    parameters.module.npcHandler:onGreet(cid)
    return true
end
To this:
LUA:
-- Greeting callback function.
function FocusModule.onGreet(cid, message, keywords, parameters)
    parameters.module.npcHandler:onGreet(cid, message)
    return true
end

NpcHandler.onGreet
Next, you'll need to update that method to handle that new argument, and pass it on to the greet method. Change this:
LUA:
-- Tries to greet the player with the given cid.
function NpcHandler:onGreet(cid)
    if self:isInRange(cid) then
        if not self:isFocused(cid) then
            self:greet(cid)
            return
        end
    end
end
To this:
LUA:
-- Tries to greet the player with the given cid.
function NpcHandler:onGreet(cid, message)
    if self:isInRange(cid) then
        if not self:isFocused(cid) then
            self:greet(cid, message)
            return
        end
    end
end

NpcHandler:greet
Then, add message to the parameters of the greet method, and to the call to the callback. Change this:
LUA:
-- Greets a new player.
function NpcHandler:greet(cid)
    if cid ~= 0 then
        local callback = self:getCallback(CALLBACK_GREET)
        if callback == nil or callback(cid) then
            if self:processModuleCallback(CALLBACK_GREET, cid) then
                local msg = self:getMessage(MESSAGE_GREET)
                local player = Player(cid)
                local playerName = player and player:getName() or -1
                local parseInfo = { [TAG_PLAYERNAME] = playerName }
                msg = self:parseMessage(msg, parseInfo)
                self:say(msg, cid, true)
            else
                return
            end
        else
            return
        end
    end
    self:addFocus(cid)
end
To this:
LUA:
-- Greets a new player.
function NpcHandler:greet(cid, message)
    if cid ~= 0 then
        local callback = self:getCallback(CALLBACK_GREET)
        if callback == nil or callback(cid, message) then
            if self:processModuleCallback(CALLBACK_GREET, cid) then
                local msg = self:getMessage(MESSAGE_GREET)
                local player = Player(cid)
                local playerName = player and player:getName() or -1
                local parseInfo = { [TAG_PLAYERNAME] = playerName }
                msg = self:parseMessage(msg, parseInfo)
                self:say(msg, cid, true)
            else
                return
            end
        else
            return
        end
    end
    self:addFocus(cid)
end
If I'm not mistaken, in LUA your method definitions and the calls to them don't have to have matching argument/parameter counts. Basically, you shouldn't have to update all of your onGreetCallback methods to include the new message parameter.
 
FocusModule.onGreet
First, add message to the onGreet call. Change this:
LUA:
-- Greeting callback function.
function FocusModule.onGreet(cid, message, keywords, parameters)
    parameters.module.npcHandler:onGreet(cid)
    return true
end
To this:
LUA:
-- Greeting callback function.
function FocusModule.onGreet(cid, message, keywords, parameters)
    parameters.module.npcHandler:onGreet(cid, message)
    return true
end

NpcHandler.onGreet
Next, you'll need to update that method to handle that new argument, and pass it on to the greet method. Change this:
LUA:
-- Tries to greet the player with the given cid.
function NpcHandler:onGreet(cid)
    if self:isInRange(cid) then
        if not self:isFocused(cid) then
            self:greet(cid)
            return
        end
    end
end
To this:
LUA:
-- Tries to greet the player with the given cid.
function NpcHandler:onGreet(cid, message)
    if self:isInRange(cid) then
        if not self:isFocused(cid) then
            self:greet(cid, message)
            return
        end
    end
end

NpcHandler:greet
Then, add message to the parameters of the greet method, and to the call to the callback. Change this:
LUA:
-- Greets a new player.
function NpcHandler:greet(cid)
    if cid ~= 0 then
        local callback = self:getCallback(CALLBACK_GREET)
        if callback == nil or callback(cid) then
            if self:processModuleCallback(CALLBACK_GREET, cid) then
                local msg = self:getMessage(MESSAGE_GREET)
                local player = Player(cid)
                local playerName = player and player:getName() or -1
                local parseInfo = { [TAG_PLAYERNAME] = playerName }
                msg = self:parseMessage(msg, parseInfo)
                self:say(msg, cid, true)
            else
                return
            end
        else
            return
        end
    end
    self:addFocus(cid)
end
To this:
LUA:
-- Greets a new player.
function NpcHandler:greet(cid, message)
    if cid ~= 0 then
        local callback = self:getCallback(CALLBACK_GREET)
        if callback == nil or callback(cid, message) then
            if self:processModuleCallback(CALLBACK_GREET, cid) then
                local msg = self:getMessage(MESSAGE_GREET)
                local player = Player(cid)
                local playerName = player and player:getName() or -1
                local parseInfo = { [TAG_PLAYERNAME] = playerName }
                msg = self:parseMessage(msg, parseInfo)
                self:say(msg, cid, true)
            else
                return
            end
        else
            return
        end
    end
    self:addFocus(cid)
end
If I'm not mistaken, in LUA your method definitions and the calls to them don't have to have matching argument/parameter counts. Basically, you shouldn't have to update all of your onGreetCallback methods to include the new message parameter.
Thanks man!! now it responds, but it sends a new error D:


Code:
Lua Script Error: [Npc interface]
data/npc/scripts/Umar.lua:onCreatureSay
data/npc/lib/npcsystem/npchandler.lua:310: bad argument #1 to 'gsub' (string expected, got table)
stack traceback:
        [C]: in ?
        [C]: in function 'gsub'
        data/npc/lib/npcsystem/npchandler.lua:310: in function 'parseMessage'
        data/npc/lib/npcsystem/npchandler.lua:346: in function 'greet'
        data/npc/lib/npcsystem/npchandler.lua:519: in function 'onGreet'
        data/npc/lib/npcsystem/modules.lua:322: in function 'callback'
        data/npc/lib/npcsystem/keywordhandler.lua:26: in function 'processMessage'
        data/npc/lib/npcsystem/keywordhandler.lua:136: in function 'processNodeMessage'
        data/npc/lib/npcsystem/keywordhandler.lua:111: in function 'processMessage'
        data/npc/lib/npcsystem/npchandler.lua:408: in function 'onCreatureSay'
        data/npc/scripts/Umar.lua:7: in function <data/npc/scripts/Umar.lua:7>

and here is my npcHandler in case you need to see it! :(
-- Advanced NPC System by Jiddo if NpcHandler == nil then -- Constant talkd - Pastebin.com
 
Last edited:
You should learn to read error messages because they tell you exactly what the problem is. Start at the top; the first line tells you that this is a Lua script error, specifically within the Npc interface. The second line tells you in what file, and the method name, in which the error originated (head of the call stack). The third line is the most important, it tells you the file, line number, and reason for the error. Next is the stack trace, this is the series of method calls that led to the error. The stack trace is in reverse order, so the first line is the instruction where the error occurred, and the last line is where the instruction originated from. So, if you wanted to follow the stack trace, start at line 15 and work your way up. Each line in the stack trace has the file name, function name, and line number, so it's really, really easy to follow.

Looking back at the third line, the error is very clear:
LUA:
-- The error happened in npchandler.lua, on line 310, and the error was because the first argument
-- passed to the gsub method (this is part of the Lua string library, and it's use is to replace any
-- instance of a string inside of a string with another string) was a table and not a string.
data/npc/lib/npcsystem/npchandler.lua:310: bad argument #1 to 'gsub' (string expected, got table)

Here's what that method looks like in your npchandler.lua:
LUA:
-- Translates all message tags found in msg using parseInfo
function NpcHandler:parseMessage(msg, parseInfo)
    local ret = msg
    for search, replace in pairs(parseInfo) do
        ret = string.gsub(ret, search, replace)
    end
    return ret
end

What's happening is that the argument being passed to the msg parameter is a table and not a string, and the method assumes it's always a string.

So, to fix your problem, you need to check if the argument being passed to the msg parameter is a string or a table:
LUA:
-- Translates all message tags found in msg using parseInfo
function NpcHandler:parseMessage(msg, parseInfo)
    local ret = msg
    if type(ret) == 'string' then
        for search, replace in pairs(parseInfo) do
            ret = string.gsub(ret, search, replace)
        end
    else
        for i = 1, #ret do
            for search, replace in pairs(parseInfo) do
                -- Note that this assumes it's a table of strings.
                -- If the table contains anything other than a string, you'll get an error here.
                ret[i] = string.gsub(ret[i], search, replace)
            end
        end
    end
    return ret
end

One thing to note about languages like Lua is variables (local, global, parameters, etc.) don't have a defined type. Unlike languages like C++ where everything is defined.
LUA:
local i = 0
i = 'zero' -- this is valid
Code:
int i = 0;
i = "zero"; // this is not valid
 
Solution
You should learn to read error messages because they tell you exactly what the problem is. Start at the top; the first line tells you that this is a Lua script error, specifically within the Npc interface. The second line tells you in what file, and the method name, in which the error originated (head of the call stack). The third line is the most important, it tells you the file, line number, and reason for the error. Next is the stack trace, this is the series of method calls that led to the error. The stack trace is in reverse order, so the first line is the instruction where the error occurred, and the last line is where the instruction originated from. So, if you wanted to follow the stack trace, start at line 15 and work your way up. Each line in the stack trace has the file name, function name, and line number, so it's really, really easy to follow.

Looking back at the third line, the error is very clear:
LUA:
-- The error happened in npchandler.lua, on line 310, and the error was because the first argument
-- passed to the gsub method (this is part of the Lua string library, and it's use is to replace any
-- instance of a string inside of a string with another string) was a table and not a string.
data/npc/lib/npcsystem/npchandler.lua:310: bad argument #1 to 'gsub' (string expected, got table)

Here's what that method looks like in your npchandler.lua:
LUA:
-- Translates all message tags found in msg using parseInfo
function NpcHandler:parseMessage(msg, parseInfo)
    local ret = msg
    for search, replace in pairs(parseInfo) do
        ret = string.gsub(ret, search, replace)
    end
    return ret
end

What's happening is that the argument being passed to the msg parameter is a table and not a string, and the method assumes it's always a string.

So, to fix your problem, you need to check if the argument being passed to the msg parameter is a string or a table:
LUA:
-- Translates all message tags found in msg using parseInfo
function NpcHandler:parseMessage(msg, parseInfo)
    local ret = msg
    if type(ret) == 'string' then
        for search, replace in pairs(parseInfo) do
            ret = string.gsub(ret, search, replace)
        end
    else
        for i = 1, #ret do
            for search, replace in pairs(parseInfo) do
                -- Note that this assumes it's a table of strings.
                -- If the table contains anything other than a string, you'll get an error here.
                ret[i] = string.gsub(ret[i], search, replace)
            end
        end
    end
    return ret
end

One thing to note about languages like Lua is variables (local, global, parameters, etc.) don't have a defined type. Unlike languages like C++ where everything is defined.
LUA:
local i = 0
i = 'zero' -- this is valid
Code:
int i = 0;
i = "zero"; // this is not valid
thank you so much and thanks for teaching! tbh i understand a little about the problems, but i couldn't fix them, dont have that expertise yet, at least with npcs
 
thank you so much and thanks for teaching! tbh i understand a little about the problems, but i couldn't fix them, dont have that expertise yet, at least with npcs
No worries. That’s why I took the time to explain instead of just giving you code; so that it may help you understand and solve an issue you may run into in the future.
 
Back
Top