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

NPC long story function

Ninkobi

Owner /Founder of Syphera
Joined
Apr 5, 2008
Messages
206
Reaction score
1
Location
England
Well, answering a thread at the Lua & XML help, I've just made a script to make a creature (mostly likely an npc) to say several phrases with a certain delay (like some npcs in real tibia who tells very long stories). I liked the script, and I think that it could be useful to other people too.

I hope that you will like it, it is my first contribution (five cents) at this forum.

Code:
function doCreatureSayWithDelay(cid,text,type,delay,e)
   if delay<=0 then
      doCreatureSay(cid,text,type)
   else
      local func=function(pars)
                    doCreatureSay(pars.cid,pars.text,pars.type)
                    pars.e.done=TRUE
                 end
      e.done=FALSE
      e.event=addEvent(func,delay,{cid=cid, text=text, type=type, e=e})
   end
end

--returns how many msgs he have said already
function cancelNPCTalk(events)
  local ret=1
  for aux=1,table.getn(events) do
     if events[aux].done==FALSE then
        stopEvent(events[aux].event)
     else
        ret=ret+1
     end
  end
  events=nil
  return(ret)
end

function doNPCTalkALot(msgs,interval)
  local e={}
  local ret={}
  if interval==nil then interval=3000 end --3 seconds is default time between messages
  for aux=1,table.getn(msgs) do
      e[aux]={}
      doCreatureSayWithDelay(getNpcCid(),msgs[aux],TALKTYPE_SAY,(aux-1)*interval,e[aux])
      table.insert(ret,e[aux])
  end
  return(ret)
end

As an example of how to use it:
Code:
local talk_var
function onCreatureSay(cid, type, msg)
   local msgs={"first message","second message","third message","4","5","6","7","8","9","10"}
   if msg=="hi" then
      talk_var=doNPCTalkALot(msgs,2750) --if the 2750 is ommited, it uses 3000 always
   else
      if (msg=="stop") and (talk_var~=nil) then
         local i=cancelNPCTalk(talk_var)
         if i<table.getn(msgs) then
            selfSay("Afff, but I was about to get into the best part! The part "..i)
         else
            selfSay("But I have already finished!")
         end
      end
   end
end

Well, I hope that you all enjoy it.

EDITED: At my home, I put all my functions in a lib (HTLib) and I wrote it here as if I was using this library. I've corrected it now. Also, a small typo has been corrected. I've also removed some debug print messages that I forgot to remove. I've also tested it AGAIN and it is working in clean SVN (I don't see any reason why it shouldn't work in TFS also).

Cheers,

Credits to Assassina Mutante
 
The bad thing about this script is that the npc wont talk in the Npc channel =/ And I'm not the man to solve it.


//Massen
 
A half year later I bump the thread as there's no working storytelling functions for npcs out there =(

//Massen
 
A half year later I bump the thread as there's no working storytelling functions for npcs out there =(

//Massen

Try like this:
Code:
selfSay("I r storyteller...", cid)
wait(1000)
selfSay("... and I is gogo say a story!", cid)
 
Try like this:
Code:
selfSay("I r storyteller...", cid)
wait(1000)
selfSay("... and I is gogo say a story!", cid)

Code:
[15/04/2009 20:09:56] Lua Script Error: [Npc interface] 
[15/04/2009 20:09:56] data/npc/scripts/talk.lua:onCreatureSay

[15/04/2009 20:09:56] attempt to yield across metamethod/C-call boundary
[15/04/2009 20:09:56] stack traceback:
[15/04/2009 20:09:56] 	[C]: in function 'wait'
[15/04/2009 20:09:56] 	data/npc/scripts/talk.lua:19: in function 'callback'
[15/04/2009 20:09:56] 	data/npc/lib/npcsystem/npchandler.lua:384: in function 'onCreatureSay'
[15/04/2009 20:09:56] 	data/npc/scripts/talk.lua:7: in function <data/npc/scripts/talk.lua:7>

:<
 
Last edited:
I customized the script some, Npcs will now talk in the npc channel

Code:
	function doNPCTalkALot(msgs,interval)
  local e={}
  local ret={}
  if interval==nil then interval=3000 end --3 seconds is default time between messages
  for aux=1,table.getn(msgs) do
      e[aux]={}
      doCreatureSayWithDelay(getNpcCid(),msgs[aux],TALKTYPE_PRIVATE_NP,(aux-1)*interval,e[aux])
      table.insert(ret,e[aux])
  end
  return(ret)
end

Original credits too Ninkobi.

Not sure how this will work if 2 people talk with the npc at the same time tho...

//Massen
 
I tried to add this to Jido's npc system but I got error:
Code:
Lua Script Error: [Npc interface]
data/npc/scripts/sample.lua

luagetDistanceTo(). Thing not found

Lua Script Error: [Npc interface]
data/npc/scripts/sample.lua

@EDIT
Ok, I've fixed it but npc doesn't stop talking when I go away/say bye.
I added this to npchandler.lua
Lua:
	-- Handles onCreatureDisappear events. Only for long stories.
	function NpcHandler:onCreatureDisappearStories(cid)
		local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR)
		if(callback == nil or callback(cid)) then
			if(self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid)) then
				if(self:isFocused(cid)) then
					local i=cancelNPCTalk(talk_var)
					self:unGreet(cid)
				end
			end
		end
	end
 
Last edited:
I customized the script some, Npcs will now talk in the npc channel

Code:
	function doNPCTalkALot(msgs,interval)
  local e={}
  local ret={}
  if interval==nil then interval=3000 end --3 seconds is default time between messages
  for aux=1,table.getn(msgs) do
      e[aux]={}
      doCreatureSayWithDelay(getNpcCid(),msgs[aux],TALKTYPE_PRIVATE_NP,(aux-1)*interval,e[aux])
      table.insert(ret,e[aux])
  end
  return(ret)
end

Original credits too Ninkobi.

Not sure how this will work if 2 people talk with the npc at the same time tho...

//Massen

Well I don't really understand how to use this fuction...

in the script I must change it:
selfsay("blablabla")
to it:
doNPCTalkALot(blablabla,3000)
????

ps: where do I paste it:
Code:
	function doNPCTalkALot(msgs,interval)
  local e={}
  local ret={}
  if interval==nil then interval=3000 end --3 seconds is default time between messages
  for aux=1,table.getn(msgs) do
      e[aux]={}
      doCreatureSayWithDelay(getNpcCid(),msgs[aux],TALKTYPE_PRIVATE_NP,(aux-1)*interval,e[aux])
      table.insert(ret,e[aux])
  end
  return(ret)
end
???
 
Last edited:
@Up: Paste it under the functions that goes
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
 
function doNPCTalkALot(msgs,interval,pcid)
	local e={}
	local ret={}
	interval = interval or 10000
	for aux = 1, #msgs do
		e[aux]={}
		doCreatureSayWithDelay(getNpcCid(),msgs[aux],TALKTYPE_PRIVATE_NP,(aux-1)*interval,e[aux],pcid)
		table.insert(ret,e[aux])
	end
	return ret
end

function doCreatureSayWithDelay(cid,text,type,delay,e)
	if delay <= 0 then
		doCreatureSay(cid,text,type)
	else
		local func=function(pars)
			doCreatureSay(pars.cid,pars.text,pars.type)
			pars.e.done=true
		end
		e.done=false
		e.event=addEvent(func,delay,{cid=cid, text=text, type=type, e=e})
	end
end
 
function creatureSayCallback(cid, type, msg)
if (msgcontains(msg, 'beggan') or msgcontains(msg, 'quest') or msgcontains(msg, 'the beggan quest') or msgcontains(msg, 'the beggan')) and getPlayerStorageValue(cid, 45000) == -1 then
		doNPCTalkALot({"blablablablablablablablablablablablablablablablablablablablablablablabla ...", "blablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablabla ...", "blablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablabla.."}, 10000, cid)
10000 is delay!!
And Im pretty sure you must add withDelay function aswell.
 
Last edited:
Back
Top