dervin13
Active Member
- Joined
- Apr 26, 2008
- Messages
- 459
- Solutions
- 1
- Reaction score
- 28
PHP:
[15:42:00.861] [Error - NpcScript Interface]
[15:42:00.861] data/npc/scripts/Zumtah.lua:onThink
[15:42:00.861] Description:
[15:42:00.861] (luaGetThingPosition) Thing not found
[15:42:00.861] [Error - NpcScript Interface]
[15:42:00.861] data/npc/scripts/Zumtah.lua:onThink
[15:42:00.861] Description:
[15:42:00.861] data/npc/lib/npc.lua:34: attempt to index local 'c' (a boolean va
lue)
[15:42:00.861] stack traceback:
[15:42:00.861] data/npc/lib/npc.lua:34: in function 'getDistanceTo'
[15:42:00.861] data/npc/lib/npcsystem/npchandler.lua:548: in function 'isInRang
e'
[15:42:00.861] data/npc/lib/npcsystem/npchandler.lua:474: in function 'onThink'
[15:42:00.861] data/npc/scripts/Zumtah.lua:9: in function <data/npc/scripts/Zum
tah.lua:9>
PHP:
-- Advanced NPC System (Created by Jiddo),
-- Modified by TheForgottenServer Team.
if(NpcHandler == nil) then
local eventSay, eventSayInDefault = {}, 0
-- Constant talkdelay behaviors.
TALKDELAY_NONE = 0 -- No talkdelay. Npc will reply immedeatly.
TALKDELAY_ONTHINK = 1 -- Talkdelay handled through the onThink callback function. (Default)
TALKDELAY_EVENT = 2 -- Not yet implemented
-- Currently applied talkdelay behavior. TALKDELAY_ONTHINK is default.
NPCHANDLER_TALKDELAY = TALKDELAY_ONTHINK
-- Constant conversation behaviors.
CONVERSATION_DEFAULT = 0 -- Conversation through default window, like it was before 8.2 update.
CONVERSATION_PRIVATE = 1 -- Conversation through NPCs chat window, as of 8.2 update. (Default)
--Small Note: Private conversations also means the NPC will use multi-focus system.
-- Currently applied conversation behavior. CONVERSATION_PRIVATE is default.
NPCHANDLER_CONVBEHAVIOR = CONVERSATION_PRIVATE
-- Constant indexes for defining default messages.
MESSAGE_GREET = 1 -- When the player greets the npc.
MESSAGE_FAREWELL = 2 -- When the player unGreets the npc.
MESSAGE_BUY = 3 -- When the npc asks the player if he wants to buy something.
MESSAGE_ONBUY = 4 -- When the player successfully buys something via talk.
MESSAGE_BOUGHT = 5 -- When the player bought something through the shop window.
MESSAGE_SELL = 6 -- When the npc asks the player if he wants to sell something.
MESSAGE_ONSELL = 7 -- When the player successfully sells something via talk.
MESSAGE_SOLD = 8 -- When the player sold something through the shop window.
MESSAGE_MISSINGMONEY = 9 -- When the player does not have enough money.
MESSAGE_NEEDMONEY = 10 -- Same as above, used for shop window.
MESSAGE_MISSINGITEM = 11 -- When the player is trying to sell an item he does not have.
MESSAGE_NEEDITEM = 12 -- Same as above, used for shop window.
MESSAGE_NEEDSPACE = 13 -- When the player don't have any space to buy an item
MESSAGE_NEEDMORESPACE = 14 -- When the player has some space to buy an item, but not enough space
MESSAGE_IDLETIMEOUT = 15 -- When the player has been idle for longer then idleTime allows.
MESSAGE_WALKAWAY = 16 -- When the player walks out of the talkRadius of the npc.
MESSAGE_DECLINE = 17 -- When the player says no to something.
MESSAGE_SENDTRADE = 18 -- When the npc sends the trade window to the player
MESSAGE_NOSHOP = 19 -- When the npc's shop is requested but he doesn't have any
MESSAGE_ONCLOSESHOP = 20 -- When the player closes the npc's shop window
MESSAGE_ALREADYFOCUSED = 21 -- When the player already has the focus of this npc.
MESSAGE_PLACEDINQUEUE = 22 -- When the player has been placed in the costumer queue.
-- Constant indexes for callback functions. These are also used for module callback ids.
CALLBACK_CREATURE_APPEAR = 1
CALLBACK_CREATURE_DISAPPEAR = 2
CALLBACK_CREATURE_SAY = 3
CALLBACK_ONTHINK = 4
CALLBACK_GREET = 5
CALLBACK_FAREWELL = 6
CALLBACK_MESSAGE_DEFAULT = 7
CALLBACK_PLAYER_ENDTRADE = 8
CALLBACK_PLAYER_CLOSECHANNEL = 9
CALLBACK_ONBUY = 10
CALLBACK_ONSELL = 11
-- Addidional module callback ids
CALLBACK_MODULE_INIT = 12
CALLBACK_MODULE_RESET = 13
-- Constant strings defining the keywords to replace in the default messages.
TAG_PLAYERNAME = '|PLAYERNAME|'
TAG_ITEMCOUNT = '|ITEMCOUNT|'
TAG_TOTALCOST = '|TOTALCOST|'
TAG_ITEMNAME = '|ITEMNAME|'
TAG_QUEUESIZE = '|QUEUESIZE|'
NpcHandler = {
keywordHandler = nil,
focuses = nil,
talkStart = nil,
idleTime = 90,
talkRadius = 3,
talkDelayTime = 1, -- Seconds to delay outgoing messages.
queue = nil,
talkDelay = nil,
callbackFunctions = nil,
modules = nil,
shopItems = nil, -- They must be here since ShopModule uses "static" functions
messages = {
-- These are the default replies of all npcs. They can/should be changed individually for each npc.
[MESSAGE_GREET] = 'Welcome, |PLAYERNAME|! I have been expecting you.',
[MESSAGE_FAREWELL] = 'Good bye, |PLAYERNAME|!',
[MESSAGE_BUY] = 'Do you want to buy |ITEMCOUNT| |ITEMNAME| for |TOTALCOST| gold coins?',
[MESSAGE_ONBUY] = 'It was a pleasure doing business with you.',
[MESSAGE_BOUGHT] = 'Bought |ITEMCOUNT|x |ITEMNAME| for |TOTALCOST| gold.',
[MESSAGE_SELL] = 'Do you want to sell |ITEMCOUNT| |ITEMNAME| for |TOTALCOST| gold coins?',
[MESSAGE_ONSELL] = 'Thank you for this |ITEMNAME|, |PLAYERNAME| gold.',
[MESSAGE_SOLD] = 'Sold |ITEMCOUNT|x |ITEMNAME| for |TOTALCOST| gold.',
[MESSAGE_MISSINGMONEY] = 'Sorry, you don\'t have enough money.',
[MESSAGE_NEEDMONEY] = 'You do not have enough money.',
[MESSAGE_MISSINGITEM] = 'You don\'t even have that item, |PLAYERNAME|!',
[MESSAGE_NEEDITEM] = 'You do not have this object.',
[MESSAGE_NEEDSPACE] = 'You do not have enough capacity.',
[MESSAGE_NEEDMORESPACE] = 'You do not have enough capacity for all items.',
[MESSAGE_IDLETIMEOUT] = 'Next, please!',
[MESSAGE_WALKAWAY] = 'How rude!',
[MESSAGE_DECLINE] = 'Not good enough, is it... ?',
[MESSAGE_SENDTRADE] = 'Here\'s my offer, |PLAYERNAME|. Don\'t you like it?',
[MESSAGE_NOSHOP] = 'Sorry, I\'m not offering anything.',
[MESSAGE_ONCLOSESHOP] = 'Thank you, come back when you want something more.',
[MESSAGE_ALREADYFOCUSED]= '|PLAYERNAME|! I am already talking to you...',
[MESSAGE_PLACEDINQUEUE] = '|PLAYERNAME|, please wait for your turn. There are |QUEUESIZE| customers before you.'
}
}
-- Creates a new NpcHandler with an empty callbackFunction stack.
function NpcHandler:new(keywordHandler)
local obj = {}
obj.callbackFunctions = {}
obj.modules = {}
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
obj.focuses = {}
obj.talkStart = {}
else
obj.queue = Queue:new(obj)
obj.focuses = 0
obj.talkStart = 0
end
obj.talkDelay = {}
obj.keywordHandler = keywordHandler
obj.messages = {}
obj.shopItems = {}
setmetatable(obj.messages, self.messages)
self.messages.__index = self.messages
setmetatable(obj, self)
self.__index = self
return obj
end
-- Re-defines the maximum idle time allowed for a player when talking to this npc.
function NpcHandler:setMaxIdleTime(newTime)
self.idleTime = newTime
end
-- Attackes a new keyword handler to this npchandler
function NpcHandler:setKeywordHandler(newHandler)
self.keywordHandler = newHandler
end
-- Function used to change the focus of this npc.
function NpcHandler:addFocus(newFocus)
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
if(self:isFocused(newFocus)) then
return
end
table.insert(self.focuses, newFocus)
else
self.focuses = newFocus
end
self:updateFocus()
end
NpcHandler.changeFocus = NpcHandler.addFocus --"changeFocus" looks better for CONVERSATION_DEFAULT
-- Function used to verify if npc is focused to certain player
function NpcHandler:isFocused(focus)
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
for k,v in pairs(self.focuses) do
if v == focus then
return true
end
end
return false
end
return (self.focuses == focus)
end
-- This function should be called on each onThink and makes sure the npc faces the player it is talking to.
-- Should also be called whenever a new player is focused.
function NpcHandler:updateFocus()
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
for pos, focus in pairs(self.focuses) do
if(focus ~= nil) then
doNpcSetCreatureFocus(focus)
return
end
end
doNpcSetCreatureFocus(0)
else
doNpcSetCreatureFocus(self.focuses)
end
end
-- Used when the npc should un-focus the player.
function NpcHandler:releaseFocus(focus)
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
if(not self:isFocused(focus)) then
return
end
local pos = nil
for k,v in pairs(self.focuses) do
if v == focus then
pos = k
end
end
table.remove(self.focuses, pos)
self.talkStart[focus] = nil
closeShopWindow(focus) --Even if it can not exist, we need to prevent it.
self:updateFocus()
else
closeShopWindow(focus)
self:changeFocus(0)
end
end
-- Returns the callback function with the specified id or nil if no such callback function exists.
function NpcHandler:getCallback(id)
local ret = nil
if(self.callbackFunctions ~= nil) then
ret = self.callbackFunctions[id]
end
return ret
end
-- Changes the callback function for the given id to callback.
function NpcHandler:setCallback(id, callback)
if(self.callbackFunctions ~= nil) then
self.callbackFunctions[id] = callback
end
end
-- Adds a module to this npchandler and inits it.
function NpcHandler:addModule(module)
if(self.modules == nil or module == nil) then
return false
end
module:init(self)
if(module.parseParameters ~= nil) then
module:parseParameters()
end
table.insert(self.modules, module)
return true
end
-- Calls the callback function represented by id for all modules added to this npchandler with the given arguments.
function NpcHandler:processModuleCallback(id, ...)
local ret = true
for i, module in pairs(self.modules) do
local tmpRet = true
if(id == CALLBACK_CREATURE_APPEAR and module.callbackOnCreatureAppear ~= nil) then
tmpRet = module:callbackOnCreatureAppear(unpack(arg))
elseif(id == CALLBACK_CREATURE_DISAPPEAR and module.callbackOnCreatureDisappear ~= nil) then
tmpRet = module:callbackOnCreatureDisappear(unpack(arg))
elseif(id == CALLBACK_CREATURE_SAY and module.callbackOnCreatureSay ~= nil) then
tmpRet = module:callbackOnCreatureSay(unpack(arg))
elseif(id == CALLBACK_PLAYER_ENDTRADE and module.callbackOnPlayerEndTrade ~= nil) then
tmpRet = module:callbackOnPlayerEndTrade(unpack(arg))
elseif(id == CALLBACK_PLAYER_CLOSECHANNEL and module.callbackOnPlayerCloseChannel ~= nil) then
tmpRet = module:callbackOnPlayerCloseChannel(unpack(arg))
elseif(id == CALLBACK_ONBUY and module.callbackOnBuy ~= nil) then
tmpRet = module:callbackOnBuy(unpack(arg))
elseif(id == CALLBACK_ONSELL and module.callbackOnSell ~= nil) then
tmpRet = module:callbackOnSell(unpack(arg))
elseif(id == CALLBACK_ONTHINK and module.callbackOnThink ~= nil) then
tmpRet = module:callbackOnThink(unpack(arg))
elseif(id == CALLBACK_GREET and module.callbackOnGreet ~= nil) then
tmpRet = module:callbackOnGreet(unpack(arg))
elseif(id == CALLBACK_FAREWELL and module.callbackOnFarewell ~= nil) then
tmpRet = module:callbackOnFarewell(unpack(arg))
elseif(id == CALLBACK_MESSAGE_DEFAULT and module.callbackOnMessageDefault ~= nil) then
tmpRet = module:callbackOnMessageDefault(unpack(arg))
elseif(id == CALLBACK_MODULE_RESET and module.callbackOnModuleReset ~= nil) then
tmpRet = module:callbackOnModuleReset(unpack(arg))
end
if(not tmpRet) then
ret = false
break
end
end
return ret
end
-- Returns the message represented by id.
function NpcHandler:getMessage(id)
local ret = nil
if(self.messages ~= nil) then
ret = self.messages[id]
end
return ret
end
-- Changes the default response message with the specified id to newMessage.
function NpcHandler:setMessage(id, newMessage)
if(self.messages ~= nil) then
self.messages[id] = newMessage
end
end
-- 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
-- Makes sure the npc un-focuses the currently focused player
function NpcHandler:unGreet(cid)
if(not self:isFocused(cid)) then
return
end
local callback = self:getCallback(CALLBACK_FAREWELL)
if(callback == nil or callback(cid)) then
if(self:processModuleCallback(CALLBACK_FAREWELL)) then
if(self.queue == nil or not self.queue:greetNext()) then
local msg = self:parseMessage(self:getMessage(MESSAGE_FAREWELL), { [TAG_PLAYERNAME] = getCreatureName(cid) })
self:say(msg, cid, true)
self:releaseFocus(cid)
self:say(msg, cid)
end
end
end
end
-- 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:parseMessage(self:getMessage(MESSAGE_GREET), { [TAG_PLAYERNAME] = getCreatureName(cid) })
self:say(msg, cid, true)
self:addFocus(cid)
self:say(msg, cid)
end
end
end
end
-- Handles onCreatureAppear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_APPEAR callback.
function NpcHandler:onCreatureAppear(cid)
local callback = self:getCallback(CALLBACK_CREATURE_APPEAR)
if(callback == nil or callback(cid)) then
if(self:processModuleCallback(CALLBACK_CREATURE_APPEAR, cid)) then
--
end
end
end
-- Handles onCreatureDisappear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_DISAPPEAR callback.
function NpcHandler:onCreatureDisappear(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
self:unGreet(cid)
end
end
end
end
-- Handles onCreatureSay events. If you with to handle this yourself, please use the CALLBACK_CREATURE_SAY callback.
function NpcHandler:onCreatureSay(cid, class, msg)
local callback = self:getCallback(CALLBACK_CREATURE_SAY)
if(callback == nil or callback(cid, class, msg)) then
if(self:processModuleCallback(CALLBACK_CREATURE_SAY, cid, class, msg)) then
if(not self:isInRange(cid)) then
return
end
if(self.keywordHandler ~= nil) then
if((self:isFocused(cid) and (class == TALKTYPE_PRIVATE_PN or NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT)) or not self:isFocused(cid)) then
local ret = self.keywordHandler:processMessage(cid, msg)
if(not ret) then
local callback = self:getCallback(CALLBACK_MESSAGE_DEFAULT)
if(callback ~= nil and callback(cid, class, msg)) then
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
self.talkStart[cid] = os.time()
else
self.talkStart = os.time()
end
end
else
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
self.talkStart[cid] = os.time()
else
self.talkStart = os.time()
end
end
end
end
end
end
end
-- Handles onPlayerEndTrade events. If you wish to handle this yourself, use the CALLBACK_PLAYER_ENDTRADE callback.
function NpcHandler:onPlayerEndTrade(cid)
local callback = self:getCallback(CALLBACK_PLAYER_ENDTRADE)
if(callback == nil or callback(cid)) then
if(self:processModuleCallback(CALLBACK_PLAYER_ENDTRADE, cid, class, msg)) then
if(self:isFocused(cid)) then
local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid) }
local msg = self:parseMessage(self:getMessage(MESSAGE_ONCLOSESHOP), parseInfo)
self:say(msg, cid)
end
end
end
end
-- Handles onPlayerCloseChannel events. If you wish to handle this yourself, use the CALLBACK_PLAYER_CLOSECHANNEL callback.
function NpcHandler:onPlayerCloseChannel(cid)
local callback = self:getCallback(CALLBACK_PLAYER_CLOSECHANNEL)
if(callback == nil or callback(cid)) then
if(self:processModuleCallback(CALLBACK_PLAYER_CLOSECHANNEL, cid, class, msg)) then
if(self:isFocused(cid)) then
self:unGreet(cid)
end
end
end
end
-- Handles onBuy events. If you wish to handle this yourself, use the CALLBACK_ONBUY callback.
function NpcHandler:onBuy(cid, itemid, subType, amount, ignoreCap, inBackpacks)
local callback = self:getCallback(CALLBACK_ONBUY)
if(callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
if(self:processModuleCallback(CALLBACK_ONBUY, cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
--
end
end
end
-- Handles onSell events. If you wish to handle this yourself, use the CALLBACK_ONSELL callback.
function NpcHandler:onSell(cid, itemid, subType, amount, ignoreCap, inBackpacks)
local callback = self:getCallback(CALLBACK_ONSELL)
if(callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
if(self:processModuleCallback(CALLBACK_ONSELL, cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
--
end
end
end
-- Handles onThink events. If you wish to handle this yourself, please use the CALLBACK_ONTHINK callback.
function NpcHandler:onThink()
local callback = self:getCallback(CALLBACK_ONTHINK)
if(callback == nil or callback()) then
if(NPCHANDLER_TALKDELAY == TALKDELAY_ONTHINK) then
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
for cid, talkDelay in pairs(self.talkDelay) do
if(talkDelay.time ~= nil and talkDelay.message ~= nil and os.time() >= talkDelay.time) then
selfSay(talkDelay.message, cid)
self.talkDelay[cid] = nil
end
end
elseif(self.talkDelay.time ~= nil and self.talkDelay.message ~= nil and os.time() >= self.talkDelay.time) then
selfSay(self.talkDelay.message)
self.talkDelay.time = nil
self.talkDelay.message = nil
end
end
if(self:processModuleCallback(CALLBACK_ONTHINK)) then
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
for pos, focus in pairs(self.focuses) do
if(focus ~= nil) then
if(not self:isInRange(focus)) then
self:onWalkAway(focus)
elseif((os.time() - self.talkStart[focus]) > self.idleTime) then
self:unGreet(focus)
else
self:updateFocus()
end
end
end
elseif(self.focuses ~= 0) then
if(not self:isInRange(self.focuses)) then
self:onWalkAway(self.focuses)
elseif(os.time()-self.talkStart > self.idleTime) then
self:unGreet(self.focuses)
else
self:updateFocus()
end
end
end
end
end
-- Tries to greet the player with the given cid.
function NpcHandler:onGreet(cid)
if(self:isInRange(cid)) then
if(NPCHANDLER_CONVBEHAVIOR == CONVERSATION_PRIVATE) then
if(not self:isFocused(cid)) then
self:greet(cid)
return
end
elseif(NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT) then
if(self.focuses == 0) then
self:greet(cid)
elseif(self.focuses == cid) then
local msg = self:getMessage(MESSAGE_ALREADYFOCUSED)
local parseInfo = { [TAG_PLAYERNAME] = getCreatureName(cid) }
msg = self:parseMessage(msg, parseInfo)
self:say(msg)
else
if(not self.queue:isInQueue(cid)) then
self.queue:push(cid)
end
local msg = self:getMessage(MESSAGE_PLACEDINQUEUE)
local parseInfo = { [TAG_PLAYERNAME] = getCreatureName(cid), [TAG_QUEUESIZE] = self.queue:getSize() }
msg = self:parseMessage(msg, parseInfo)
self:say(msg)
end
end
end
end
-- Simply calls the underlying unGreet function.
function NpcHandler:onFarewell(cid)
self:unGreet(cid)
end
-- Should be called on this npc's focus if the distance to focus is greater then talkRadius.
function NpcHandler:onWalkAway(cid)
if(self:isFocused(cid)) then
local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR)
if(callback == nil or callback(cid)) then
if(self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid)) then
if(self.queue == nil or not self.queue:greetNext()) then
self:releaseFocus(cid)
self:say(self:parseMessage(self:getMessage(MESSAGE_WALKAWAY), { [TAG_PLAYERNAME] = getPlayerName(cid) }))
end
end
end
end
end
-- Returns true if cid is within the talkRadius of this npc.
function NpcHandler:isInRange(cid)
local distance = getDistanceTo(cid) or -1
if(distance == -1) then
return false
end
return (distance <= self.talkRadius)
end
-- Resets the npc into it's initial state (in regard of the keyrodhandler).
-- All modules are also receiving a reset call through their callbackOnModuleReset function.
function NpcHandler:resetNpc()
if(self:processModuleCallback(CALLBACK_MODULE_RESET)) then
self.keywordHandler:reset()
end
end
-- Makes the npc represented by this instance of NpcHandler say something.
-- This implements the currently set type of talkdelay.
-- shallDelay is a boolean value. If it is false, the message is not delayed. Default value is false.
_say = function(message, focus, publicize, shallDelay, delay)
if not focus then
stopEvent(eventSayInDefault)
eventSayInDefault = addEvent(function(z) doCreatureSay(z[1], z[2], TALKTYPE_SAY) end, NpcHandler.talkDelayTime * 1000, {getNpcCid(), message})
return
elseif type(message) == "table" then
return doNPCTalkALot(message, delay or 10000, focus)
elseif eventDelayedSay[focus] then
cancelNPCTalk(eventDelayedSay[focus])
end
local shallDelay = not shallDelay and true or shallDelay
if(NPCHANDLER_TALKDELAY == TALKDELAY_NONE or not shallDelay) then
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
selfSay(message, focus, publicize and TRUE or FALSE)
return
else
selfSay(message)
return
end
end
if NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT then
stopEvent(eventSay[focus])
eventSay[focus] = addEvent(function(x) if isPlayer(x[3]) == TRUE then doCreatureSay(x[1], x[2], TALKTYPE_PRIVATE_NP, false, x[3], getCreaturePosition(x[1])) end end, NpcHandler.talkDelayTime * 1000, {getNpcCid(), message, focus})
if(publicize) then
addEvent(function(y) local spectators = getSpectators(getCreaturePosition(y[1]), 7, 5, false) for i = 1, #spectators do if spectators[i] == y[3] then table.remove(spectators, i) break end end if #spectators > 0 then for i, tid in ipairs(spectators) do if(isPlayer(tid) == TRUE) then doCreatureSay(y[1], y[2], TALKTYPE_SAY, false, tid, getCreaturePosition(getNpcCid())) end end end end, NpcHandler.talkDelayTime * 1000, {getNpcCid(), message, focus})
end
else
addEvent(function(x) doCreatureSay(x[1], x[2], TALKTYPE_SAY) end, NpcHandler.talkDelayTime * 1000, {getNpcCid(), message})
end
end
function NpcHandler:say(message, focus, publicize, shallDelay, delay)
_say(message, focus, publicize, shallDelay, delay)
end
_selfSay = selfSay
selfSay = _say
end
PHP:
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 greetCallback(cid)
talkState[cid] = 0
return true
end
npcHandler:setCallback(CALLBACK_GREET, greetCallback)
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 storage = 42337
local storage2 = 42325
local move = {x=33365, y=31204, z=8}
local locationcrate = {x=33356, y=31181, z=8, stackpos = 255}
local outfit = {lookType = getPlayerStorageValue(cid, 3431), lookHead = getPlayerStorageValue(cid, 3432), lookAddons = getPlayerStorageValue(cid, 3433), lookLegs = getPlayerStorageValue(cid, 3434), lookBody = getPlayerStorageValue(cid, 3435), lookFeet = getPlayerStorageValue(cid, 3436)}
if (getPlayerStorageValue(cid,storage2) == 0) then
if(msgcontains(msg, 'exit') and talkState[talkUser] < 1) then
npcHandler:say({'Oh of course, may I show you around a bit before? You want to go straight to the exit? Would you please follow me. Oh right, I am terribly sorry but THERE IS NONE. Will you finally give it up please?'}, cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'no') and talkState[talkUser] == 1) then
npcHandler:say({'You are starting to get on my nerves. Is this the only topic you know?'}, cid)
talkState[talkUser] = 2
elseif(msgcontains(msg, 'yes') and talkState[talkUser] == 2) then
npcHandler:say({'Pesky, persistent human.'}, cid)
talkState[talkUser] = 3
elseif(msgcontains(msg, 'exit') and talkState[talkUser] == 3) then
npcHandler:say({'Oh of course, may I show you around a bit before? You want to go straight to the exit? Would you please follow me. Oh right, I am terribly sorry but THERE IS NONE. Will you finally give it up please?'}, cid)
talkState[talkUser] = 4
elseif(msgcontains(msg, 'no') and talkState[talkUser] == 4) then
npcHandler:say({'You are starting to get on my nerves. Is this the only topic you know?'}, cid)
talkState[talkUser] = 5
elseif(msgcontains(msg, 'yes') and talkState[talkUser] == 5) then
npcHandler:say({'Pesky, persistent human.'}, cid)
talkState[talkUser] = 6
elseif(msgcontains(msg, 'exit') and talkState[talkUser] == 6) then
npcHandler:say({'Oh of course, may I show you around a bit before? You want to go straight to the exit? Would you please follow me. Oh right, I am terribly sorry but THERE IS NONE. Will you finally give it up please?'}, cid)
talkState[talkUser] = 7
elseif(msgcontains(msg, 'no') and talkState[talkUser] == 7) then
npcHandler:say({'You are starting to get on my nerves. Is this the only topic you know?'}, cid)
talkState[talkUser] = 8
elseif(msgcontains(msg, 'yes') and talkState[talkUser] == 8) then
npcHandler:say({'Muhahaha. Then I will give you a test. How many years do you think have I been here? {89}, {164} or {278?}'}, cid)
talkState[talkUser] = 9
elseif(msgcontains(msg, '278') and talkState[talkUser] == 9) then
npcHandler:say({'Correct human, and that is not nearly how high you would need to count to tell all the lost souls I\'ve seen dying here. I AM PERPETUAL. Muahahaha.'}, cid)
talkState[talkUser] = 10
elseif(msgcontains(msg, 'exit') and talkState[talkUser] == 10) then
npcHandler:say({'Oh, you mean - if I have ever been out of here in those 278 years? Well, I - I can\'t remember. No, I can\'t remember. Sorry'}, cid)
talkState[talkUser] = 11
elseif(msgcontains(msg, 'exit') and talkState[talkUser] == 11) then
npcHandler:say({'No, I really can\'t remember. I enjoyed my stay here so much that I forgot how it looks outside of this hole. Outside. The air, the sky, the light. Oh well... well.'}, cid)
talkState[talkUser] = 12
elseif(msgcontains(msg, 'exit') and talkState[talkUser] == 12) then
npcHandler:say({'Oh yes, yes. I... I never really thought about how you creatures feel in here I guess. I... just watched all these beings die here. ...'}, cid)
talkState[talkUser] = 13
elseif(msgcontains(msg, 'exit') and talkState[talkUser] == 13) then
npcHandler:say({'Oh, excuse me of course, you... wanted to go. Like all... the others. I am sorry, so sorry. You... you can leave. Yes. You can go. You are free. I shall stay here and help every poor soul which ever gets thrown in here from this day onward. ...'}, cid)
talkState[talkUser] = 14
elseif(msgcontains(msg, 'exit') and talkState[talkUser] == 14) then
npcHandler:say({'Alright, as I said you are free now. There will not be an outside for the next three centuries, but you - go. ...','Oh and I recovered the strange crate you where hiding in, it will wait for you at the exit since you can\'t carry it as... a beetle, muhaha. Yes, you shall now crawl through the passage as a beetle. There you go.'}, cid)
setPlayerStorageValue(cid, storage, 1)
setPlayerStorageValue(cid, storage2, 1)
setPlayerStorageValue(cid, 3431, getCreatureOutfit(cid).lookType)
setPlayerStorageValue(cid, 3432, getCreatureOutfit(cid).lookHead)
setPlayerStorageValue(cid, 3433, getCreatureOutfit(cid).lookAddons)
setPlayerStorageValue(cid, 3434, getCreatureOutfit(cid).lookLegs)
setPlayerStorageValue(cid, 3435, getCreatureOutfit(cid).lookBody)
setPlayerStorageValue(cid, 3436, getCreatureOutfit(cid).lookFeet)
doTeleportThing(cid, move, TRUE)
doSetMonsterOutfit(cid, "Lancer Beetle", -1)
talkState[talkUser] = 0
end
elseif (getPlayerStorageValue(cid,storage) == 1) then
if(msgcontains(msg, 'exit')) then
npcHandler:say({'It\'s you, why did they throw you in here again? Anyway, I will just transform you once more. I also recovered your crate which will wait for you at the exit. There, feel free to go.'}, cid)
doSetMonsterOutfit(cid, "Lancer Beetle", -1)
doTeleportThing(cid, move, TRUE)
end
end
return true
end
npcHandler:setMessage(MESSAGE_GREET, "Another visitor to this constricted, cosy, calm realm, perfect except for an {exit}. Muhaha.")
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())