• 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+ [LUA] [npcHandler] How to: doNpcTalkALot()

krafttomten

Well-Known Member
Joined
Jul 23, 2017
Messages
103
Solutions
1
Reaction score
75
Location
Sweden
Hello fellow person!

I've looked through the forum for hours now but cannot seem to find an answer.

How are doNpcTalkALot to be used properly? No matter how I use it, it either doesn't work at all, or it gives me warning messages about being "Unsafe"

I have three working ways of using this code, but all of them are giving me this "unsafe" warning

Lua:
local player = Player(cid) -- (cid is taken from the above local function creatureSayCallback(cid, type, msg) )
local msgs = {"First msg","Second msg", "Third message"}
        --First working but unsafe usage
        for aux = 1, #msgs do
            doCreatureSayWithDelay(getNpcCid(), msgs[aux], TALKTYPE_PRIVATE_NP, ((aux-1) * (2000)) + 700, msgs, player)
        end
       
        --Second working but unsafe usage
        npcHandler:doNPCTalkALot(msgs, 6000, player)
       
       
        --Third working but unsafe usage (too long script, [URL='https://otland.net/threads/how-to-make-npcs-tell-stories.157308/']here's a link to the thread where I found it[/URL])

Does anyone have a working (and safe, whatever that means) implementation of the doNPCTalkALot() function that I can copy? Or better yet, could someone take the time to explain what I am doing wrong, I would appreciate it a lot!

(using TFS 1.41, 10.98 version)

(Line 82 in function is doCreatureSayWithDelay(getNpcCid(), msgs[aux], TALKTYPE_PRIVATE_NP, ((aux-1) * (2000)) + 700, msgs, player)
unsafe_doCreatureSayWithDelay.png

(I didn't post full script because it's much more than the relevant code there, but I'll post it here inside a spoiler too, if it for any reason would help)
Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local states = {
    look_for_aurora = {}

    }

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 greetCallback(cid)
    -- Standard greetings
    local player = Player(cid)
    local name = player:getName()
    local unStartedQuest = (player:getStorageValue(50025) == -1)
    local searching = (player:getStorageValue(50025) == 1 or player:getStorageValue(50025) == 2)
    local greet = "Welcome to my shop "

    if player:getSex() == PLAYERSEX_FEMALE then
        greet = "Madame!"
    else
        greet = "Good Sir."
    end

    if unStartedQuest then
        selfSay("Oh my!", cid)
        greet = "Sorry, my mind was elsewhere.. " .. greet
    elseif searching then
        greet = "Oh hello again " .. name .. "! Please tell me you have {found} Aurora! Or.. Oh forgive me."
    end
    greet = greet .. " Are you here to purchase {furniture}?"
    npcHandler:setMessage(MESSAGE_GREET, greet)
    return true
end

-- Don't forget npcHandler = npcHandler in the parameters. It is required for all StdModule functions!
keywordHandler:addKeyword({'chairs'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I sell wooden, sofa, red cushioned, green cushioned, tusk and ivory chairs.'})
keywordHandler:addKeyword({'tables'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I sell big, square, round, small, stone, tusk, bamboo tables.'})
keywordHandler:addKeyword({'plants'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I sell pink and green flowers, also christmas trees.'})
keywordHandler:addKeyword({'furniture'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I sell large trunks, boxes, drawers, dressers, lockers and troughs.'})
keywordHandler:addKeyword({'more'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I sell coal basins, birdcages, harps, pianos, globes, clocks and lamps.'})
keywordHandler:addKeyword({'destination'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I sell blue, green, orange, pink, red, white and yellow tapestries.'})
keywordHandler:addKeyword({'small'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I sell small purple, small green, small red, small blue, small orange, small turquiose and small white pillows.'})
keywordHandler:addKeyword({'round'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I sell round blue, round red, round purple and round turquiose pillows.'})
keywordHandler:addKeyword({'square'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I sell blue, red, green and yellow pillows.'})
keywordHandler:addKeyword({'pillows'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I sell heart, small, sqare and round pillows.'})
keywordHandler:addKeyword({'beds'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I sell {green}, {red} and {yellow} {beds} for {5000}gp. I can sell you too standard bed (to remove modification)'})




local function creatureSayCallback(cid, type, msg)
    if not npcHandler:isFocused(cid) then
        return false
    end
    local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid
    local player = Player(cid)
    local config = {
        searchForAurora = 50025,
        playerLevel = player:getLevel(),
        playerName = player:getName()
    }
    if msgcontains(msg, "girl") then
        selfSay("No no no no no... My girl, my only child Aurora disappeared and hasn't come home in four days!", cid)
        states.look_for_aurora[talkUser] = 1
    end
    if states.look_for_aurora[talkUser] == 1 then
        if msgcontains(msg, "disappeared") then
            selfSay("If you find her, please tell me! She is sixteen years old, has brown hair and has my eyes.", cid)
            player:setStorageValue(config.searchForAurora, 1)
            states.look_for_aurora[talkUser] = 2
        end
    end

    if player:getStorageValue(config.searchForAurora) == 2 and msgcontains(msg, "found") then
        local msgs = {"Oh my God no...","*sob*", "What happened to her?"}
        for aux = 1, #msgs do
            doCreatureSayWithDelay(getNpcCid(), msgs[aux], TALKTYPE_PRIVATE_NP, ((aux-1) * (2000)) + 700, msgs, player)
        end
        
        --npcHandler:doNPCTalkALot({"Oh my God no...","*sob*", "What happened to her?"}, 6000, player)
    end


end

function thinkCallback()
    local talk = math.random(1,10000)
        if talk < 3 then
            doCreatureSay(getNpcCid(), "My girl.. Oh my poor girl...", TALKTYPE_SAY)
        end
    return true
end

npcHandler:setCallback(CALLBACK_ONTHINK, thinkCallback)
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:setCallback(CALLBACK_GREET, greetCallback)
npcHandler:addModule(FocusModule:new())
 
Solution
E
doNPCTalkALot is just like addEvent, want to know why it is unsafe? read this thread replies:
doNPCTalkALot is just like addEvent, want to know why it is unsafe? read this thread replies:
 
Solution
Looks like it should be:
Code:
local msgs = {"First msg","Second msg", "Third message"}
npcHandler:doNPCTalkALot(msgs, 1000, cid) -- cid, not player
It should send 3 messages with interval 1 second.

Executing another npcHandler:doNPCTalkALot on same player cancels previous doNPCTalkALot. First message should be send after 0.7 sec. If you call npcHandler:doNPCTalkALot again within that time, it will cancel previous messages and wait again 0.7 sec to send new messages.

Anyway, this function is a bit bugged. It will throw errors in console, if player logout while there are message waiting to be send to him.
It expects to get cid, not player and if you pass cid there is no way it will crash.
There are 2 IFs in npc.lua:
Code:
if Player(pcid):isPlayer() then
they will execute isPlayer on nil. They should be:
Code:
if Player(pcid) then


About crashing by passing player to addEvent:
 
Back
Top