Guest User

Untitled

a guest
Oct 23rd, 2013
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 21.39 KB | None | 0 0
  1. -- Advanced NPC System (Created by Jiddo),
  2. -- Modified by TheForgottenServer Team.
  3.  
  4. if(NpcHandler == nil) then
  5.     -- Constant talkdelay behaviors.
  6.     TALKDELAY_NONE = 0 -- No talkdelay. Npc will reply immedeatly.
  7.     TALKDELAY_ONTHINK = 1 -- Talkdelay handled through the onThink callback function. (Default)
  8.     TALKDELAY_EVENT = 2 -- Not yet implemented
  9.  
  10.     -- Currently applied talkdelay behavior. TALKDELAY_ONTHINK is default.
  11.     NPCHANDLER_TALKDELAY = TALKDELAY_ONTHINK
  12.  
  13.     -- Constant conversation behaviors.
  14.     CONVERSATION_DEFAULT = 0 -- Conversation through default window, like it was before 8.2 update.
  15.     CONVERSATION_PRIVATE = 1 -- Conversation through NPCs chat window, as of 8.2 update. (Default)
  16.         --Small Note: Private conversations also means the NPC will use multi-focus system.
  17.  
  18.     -- Currently applied conversation behavior. CONVERSATION_PRIVATE is default.
  19.     NPCHANDLER_CONVBEHAVIOR = CONVERSATION_PRIVATE
  20.  
  21.     -- Constant indexes for defining default messages.
  22.     MESSAGE_GREET           = 1 -- When the player greets the npc.
  23.     MESSAGE_FAREWELL        = 2 -- When the player unGreets the npc.
  24.     MESSAGE_BUY             = 3 -- When the npc asks the player if he wants to buy something.
  25.     MESSAGE_ONBUY           = 4 -- When the player successfully buys something via talk.
  26.     MESSAGE_BOUGHT          = 5 -- When the player bought something through the shop window.
  27.     MESSAGE_SELL            = 6 -- When the npc asks the player if he wants to sell something.
  28.     MESSAGE_ONSELL          = 7 -- When the player successfully sells something via talk.
  29.     MESSAGE_SOLD            = 8 -- When the player sold something through the shop window.
  30.     MESSAGE_MISSINGMONEY        = 9 -- When the player does not have enough money.
  31.     MESSAGE_NEEDMONEY       = 10 -- Same as above, used for shop window.
  32.     MESSAGE_MISSINGITEM     = 11 -- When the player is trying to sell an item he does not have.
  33.     MESSAGE_NEEDITEM        = 12 -- Same as above, used for shop window.
  34.     MESSAGE_NEEDSPACE       = 13 -- When the player don't have any space to buy an item
  35.     MESSAGE_NEEDMORESPACE       = 14 -- When the player has some space to buy an item, but not enough space
  36.     MESSAGE_IDLETIMEOUT     = 15 -- When the player has been idle for longer then idleTime allows.
  37.     MESSAGE_WALKAWAY        = 16 -- When the player walks out of the talkRadius of the npc.
  38.     MESSAGE_DECLINE         = 17 -- When the player says no to something.
  39.     MESSAGE_SENDTRADE       = 18 -- When the npc sends the trade window to the player
  40.     MESSAGE_NOSHOP          = 19 -- When the npc's shop is requested but he doesn't have any
  41.     MESSAGE_ONCLOSESHOP     = 20 -- When the player closes the npc's shop window
  42.     MESSAGE_ALREADYFOCUSED      = 21 -- When the player already has the focus of this npc.
  43.     MESSAGE_PLACEDINQUEUE       = 22 -- When the player has been placed in the costumer queue.
  44.  
  45.     -- Constant indexes for callback functions. These are also used for module callback ids.
  46.     CALLBACK_CREATURE_APPEAR    = 1
  47.     CALLBACK_CREATURE_DISAPPEAR = 2
  48.     CALLBACK_CREATURE_SAY       = 3
  49.     CALLBACK_ONTHINK        = 4
  50.     CALLBACK_GREET          = 5
  51.     CALLBACK_FAREWELL       = 6
  52.     CALLBACK_MESSAGE_DEFAULT    = 7
  53.     CALLBACK_PLAYER_ENDTRADE    = 8
  54.     CALLBACK_PLAYER_CLOSECHANNEL    = 9
  55.     CALLBACK_ONBUY          = 10
  56.     CALLBACK_ONSELL         = 11
  57.  
  58.     -- Addidional module callback ids
  59.     CALLBACK_MODULE_INIT        = 12
  60.     CALLBACK_MODULE_RESET       = 13
  61.  
  62.     -- Constant strings defining the keywords to replace in the default messages.
  63.     TAG_PLAYERNAME = '|PLAYERNAME|'
  64.     TAG_ITEMCOUNT = '|ITEMCOUNT|'
  65.     TAG_TOTALCOST = '|TOTALCOST|'
  66.     TAG_ITEMNAME = '|ITEMNAME|'
  67.     TAG_QUEUESIZE = '|QUEUESIZE|'
  68.  
  69.     NpcHandler = {
  70.         keywordHandler = nil,
  71.         focuses = nil,
  72.         talkStart = nil,
  73.         idleTime = 300,
  74.         talkRadius = 3,
  75.         talkDelayTime = 1, -- Seconds to delay outgoing messages.
  76.         queue = nil,
  77.         talkDelay = nil,
  78.         callbackFunctions = nil,
  79.         modules = nil,
  80.         shopItems = nil, -- They must be here since ShopModule uses "static" functions
  81.         messages = {
  82.             -- These are the default replies of all npcs. They can/should be changed individually for each npc.
  83.             [MESSAGE_GREET]     = 'Welcome, |PLAYERNAME|! I\'ve been waiting for you.',
  84.             [MESSAGE_FAREWELL]  = 'Goodbye, |PLAYERNAME|!',
  85.             [MESSAGE_BUY]       = 'Do you want to buy |ITEMCOUNT| |ITEMNAME| for |TOTALCOST| gold coins?',
  86.             [MESSAGE_ONBUY]     = 'It was a pleasure doing business with you.',
  87.             [MESSAGE_BOUGHT]    = 'Bought |ITEMCOUNT|x |ITEMNAME| for |TOTALCOST| gold.',
  88.             [MESSAGE_SELL]      = 'Do you want to sell |ITEMCOUNT| |ITEMNAME| for |TOTALCOST| gold coins?',
  89.             [MESSAGE_ONSELL]    = 'Thank you for this |ITEMNAME|, |PLAYERNAME| gold.',
  90.             [MESSAGE_SOLD]      = 'Sold |ITEMCOUNT|x |ITEMNAME| for |TOTALCOST| gold.',
  91.             [MESSAGE_MISSINGMONEY]  = 'Sorry, you don\'t have enough money.',
  92.             [MESSAGE_NEEDMONEY]     = 'You do not have enough money.',
  93.             [MESSAGE_MISSINGITEM]   = 'You don\'t even have that item, |PLAYERNAME|!',
  94.             [MESSAGE_NEEDITEM]  = 'You do not have this object.',
  95.             [MESSAGE_NEEDSPACE] = 'You do not have enough capacity.',
  96.             [MESSAGE_NEEDMORESPACE] = 'You do not have enough capacity for all items.',
  97.             [MESSAGE_IDLETIMEOUT]   = 'Next, please!',
  98.             [MESSAGE_WALKAWAY]  = 'How rude!',
  99.             [MESSAGE_DECLINE]   = 'Not good enough, is it... ?',
  100.             [MESSAGE_SENDTRADE] = 'Here\'s my offer, |PLAYERNAME|. Don\'t you like it?',
  101.             [MESSAGE_NOSHOP]    = 'Sorry, I\'m not offering anything.',
  102.             [MESSAGE_ONCLOSESHOP]   = 'Thank you, come back when you want something more.',
  103.             [MESSAGE_ALREADYFOCUSED]= '|PLAYERNAME|! I am already talking to you...',
  104.             [MESSAGE_PLACEDINQUEUE] = '|PLAYERNAME|, please wait for your turn. There are |QUEUESIZE| customers before you.'
  105.         }
  106.     }
  107.  
  108.     -- Creates a new NpcHandler with an empty callbackFunction stack.
  109.     function NpcHandler:new(keywordHandler)
  110.         local obj = {}
  111.         obj.callbackFunctions = {}
  112.         obj.modules = {}
  113.         if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  114.             obj.focuses = {}
  115.             obj.talkStart = {}
  116.         else
  117.             obj.queue = Queue:new(obj)
  118.             obj.focuses = 0
  119.             obj.talkStart = 0
  120.         end
  121.         obj.talkDelay = {}
  122.         obj.keywordHandler = keywordHandler
  123.         obj.messages = {}
  124.         obj.shopItems = {}
  125.  
  126.         setmetatable(obj.messages, self.messages)
  127.         self.messages.__index = self.messages
  128.  
  129.         setmetatable(obj, self)
  130.         self.__index = self
  131.         return obj
  132.     end
  133.  
  134.     -- Re-defines the maximum idle time allowed for a player when talking to this npc.
  135.     function NpcHandler:setMaxIdleTime(newTime)
  136.         self.idleTime = newTime
  137.     end
  138.  
  139.     -- Attackes a new keyword handler to this npchandler
  140.     function NpcHandler:setKeywordHandler(newHandler)
  141.         self.keywordHandler = newHandler
  142.     end
  143.  
  144.     -- Function used to change the focus of this npc.
  145.     function NpcHandler:addFocus(newFocus)
  146.         if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  147.             if(self:isFocused(newFocus)) then
  148.                 return
  149.             end
  150.  
  151.             table.insert(self.focuses, newFocus)
  152.         else
  153.             self.focuses = newFocus
  154.         end
  155.  
  156.         self:updateFocus()
  157.     end
  158.     NpcHandler.changeFocus = NpcHandler.addFocus --"changeFocus" looks better for CONVERSATION_DEFAULT
  159.  
  160.     -- Function used to verify if npc is focused to certain player
  161.     function NpcHandler:isFocused(focus)
  162.         if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  163.             for k,v in pairs(self.focuses) do
  164.                 if v == focus then
  165.                     return true
  166.                 end
  167.             end
  168.  
  169.             return false
  170.         end
  171.  
  172.         return (self.focuses == focus)
  173.     end
  174.  
  175.     -- This function should be called on each onThink and makes sure the npc faces the player it is talking to.
  176.     --  Should also be called whenever a new player is focused.
  177.     function NpcHandler:updateFocus()
  178.         if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  179.             for pos, focus in pairs(self.focuses) do
  180.                 if(focus ~= nil) then
  181.                     doNpcSetCreatureFocus(focus)
  182.                     return
  183.                 end
  184.             end
  185.  
  186.             doNpcSetCreatureFocus(0)
  187.         else
  188.             doNpcSetCreatureFocus(self.focuses)
  189.         end
  190.     end
  191.  
  192.     -- Used when the npc should un-focus the player.
  193.     function NpcHandler:releaseFocus(focus)
  194.         if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  195.             if(not self:isFocused(focus)) then
  196.                 return
  197.             end
  198.  
  199.             local pos = nil
  200.             for k,v in pairs(self.focuses) do
  201.                 if v == focus then
  202.                     pos = k
  203.                 end
  204.             end
  205.             table.remove(self.focuses, pos)
  206.             self.talkStart[focus] = nil
  207.             closeShopWindow(focus) --Even if it can not exist, we need to prevent it.
  208.             self:updateFocus()
  209.         else
  210.             closeShopWindow(focus)
  211.             self:changeFocus(0)
  212.         end
  213.     end
  214.  
  215.     -- Returns the callback function with the specified id or nil if no such callback function exists.
  216.     function NpcHandler:getCallback(id)
  217.         local ret = nil
  218.         if(self.callbackFunctions ~= nil) then
  219.             ret = self.callbackFunctions[id]
  220.         end
  221.  
  222.         return ret
  223.     end
  224.  
  225.     -- Changes the callback function for the given id to callback.
  226.     function NpcHandler:setCallback(id, callback)
  227.         if(self.callbackFunctions ~= nil) then
  228.             self.callbackFunctions[id] = callback
  229.         end
  230.     end
  231.  
  232.     -- Adds a module to this npchandler and inits it.
  233.     function NpcHandler:addModule(module)
  234.         if(self.modules == nil or module == nil) then
  235.             return false
  236.         end
  237.  
  238.         module:init(self)
  239.         if(module.parseParameters ~= nil) then
  240.             module:parseParameters()
  241.         end
  242.  
  243.         table.insert(self.modules, module)
  244.         return true
  245.     end
  246.  
  247.     -- Calls the callback function represented by id for all modules added to this npchandler with the given arguments.
  248.     function NpcHandler:processModuleCallback(id, ...)
  249.         local ret = true
  250.         for i, module in pairs(self.modules) do
  251.             local tmpRet = true
  252.             if(id == CALLBACK_CREATURE_APPEAR and module.callbackOnCreatureAppear ~= nil) then
  253.                 tmpRet = module:callbackOnCreatureAppear(unpack(arg))
  254.             elseif(id == CALLBACK_CREATURE_DISAPPEAR and module.callbackOnCreatureDisappear ~= nil) then
  255.                 tmpRet = module:callbackOnCreatureDisappear(unpack(arg))
  256.             elseif(id == CALLBACK_CREATURE_SAY and module.callbackOnCreatureSay ~= nil) then
  257.                 tmpRet = module:callbackOnCreatureSay(unpack(arg))
  258.             elseif(id == CALLBACK_PLAYER_ENDTRADE and module.callbackOnPlayerEndTrade ~= nil) then
  259.                 tmpRet = module:callbackOnPlayerEndTrade(unpack(arg))
  260.             elseif(id == CALLBACK_PLAYER_CLOSECHANNEL and module.callbackOnPlayerCloseChannel ~= nil) then
  261.                 tmpRet = module:callbackOnPlayerCloseChannel(unpack(arg))
  262.             elseif(id == CALLBACK_ONBUY and module.callbackOnBuy ~= nil) then
  263.                 tmpRet = module:callbackOnBuy(unpack(arg))
  264.             elseif(id == CALLBACK_ONSELL and module.callbackOnSell ~= nil) then
  265.                 tmpRet = module:callbackOnSell(unpack(arg))
  266.             elseif(id == CALLBACK_ONTHINK and module.callbackOnThink ~= nil) then
  267.                 tmpRet = module:callbackOnThink(unpack(arg))
  268.             elseif(id == CALLBACK_GREET and module.callbackOnGreet ~= nil) then
  269.                 tmpRet = module:callbackOnGreet(unpack(arg))
  270.             elseif(id == CALLBACK_FAREWELL and module.callbackOnFarewell ~= nil) then
  271.                 tmpRet = module:callbackOnFarewell(unpack(arg))
  272.             elseif(id == CALLBACK_MESSAGE_DEFAULT and module.callbackOnMessageDefault ~= nil) then
  273.                 tmpRet = module:callbackOnMessageDefault(unpack(arg))
  274.             elseif(id == CALLBACK_MODULE_RESET and module.callbackOnModuleReset ~= nil) then
  275.                 tmpRet = module:callbackOnModuleReset(unpack(arg))
  276.             end
  277.  
  278.             if(not tmpRet) then
  279.                 ret = false
  280.                 break
  281.             end
  282.         end
  283.  
  284.         return ret
  285.     end
  286.  
  287.     -- Returns the message represented by id.
  288.     function NpcHandler:getMessage(id)
  289.         local ret = nil
  290.         if(self.messages ~= nil) then
  291.             ret = self.messages[id]
  292.         end
  293.  
  294.         return ret
  295.     end
  296.  
  297.     -- Changes the default response message with the specified id to newMessage.
  298.     function NpcHandler:setMessage(id, newMessage)
  299.         if(self.messages ~= nil) then
  300.             self.messages[id] = newMessage
  301.         end
  302.     end
  303.  
  304.     -- Translates all message tags found in msg using parseInfo
  305.     function NpcHandler:parseMessage(msg, parseInfo)
  306.         local ret = msg
  307.         for search, replace in pairs(parseInfo) do
  308.             ret = string.gsub(ret, search, replace)
  309.         end
  310.  
  311.         return ret
  312.     end
  313.  
  314.     -- Makes sure the npc un-focuses the currently focused player
  315.     function NpcHandler:unGreet(cid)
  316.         if(not self:isFocused(cid)) then
  317.             return
  318.         end
  319.  
  320.         local callback = self:getCallback(CALLBACK_FAREWELL)
  321.         if(callback == nil or callback(cid)) then
  322.             if(self:processModuleCallback(CALLBACK_FAREWELL)) then
  323.                 if(self.queue == nil or not self.queue:greetNext()) then
  324.                     local msg = self:getMessage(MESSAGE_FAREWELL)
  325.                     local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid) }
  326.                     msg = self:parseMessage(msg, parseInfo)
  327.  
  328.                     self:say(msg, cid)
  329.                     self:releaseFocus(cid)
  330.                     self:say(msg)
  331.                 end
  332.             end
  333.         end
  334.     end
  335.  
  336.     -- Greets a new player.
  337.     function NpcHandler:greet(cid)
  338.         if(cid ~= 0) then
  339.             local callback = self:getCallback(CALLBACK_GREET)
  340.             if(callback == nil or callback(cid)) then
  341.                 if(self:processModuleCallback(CALLBACK_GREET, cid)) then
  342.                     local msg = self:getMessage(MESSAGE_GREET)
  343.                     local parseInfo = { [TAG_PLAYERNAME] = getCreatureName(cid) }
  344.                     msg = self:parseMessage(msg, parseInfo)
  345.  
  346.                     self:say(msg)
  347.                     self:addFocus(cid)
  348.                     self:say(msg, cid)
  349.                 end
  350.             end
  351.         end
  352.     end
  353.  
  354.     -- Handles onCreatureAppear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_APPEAR callback.
  355.     function NpcHandler:onCreatureAppear(cid)
  356.         local callback = self:getCallback(CALLBACK_CREATURE_APPEAR)
  357.         if(callback == nil or callback(cid)) then
  358.             if(self:processModuleCallback(CALLBACK_CREATURE_APPEAR, cid)) then
  359.                 --
  360.             end
  361.         end
  362.     end
  363.  
  364.     -- Handles onCreatureDisappear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_DISAPPEAR callback.
  365.     function NpcHandler:onCreatureDisappear(cid)
  366.         local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR)
  367.         if(callback == nil or callback(cid)) then
  368.             if(self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid)) then
  369.                 if(self:isFocused(cid)) then
  370.                     self:unGreet(cid)
  371.                 end
  372.             end
  373.         end
  374.     end
  375.  
  376.     -- Handles onCreatureSay events. If you with to handle this yourself, please use the CALLBACK_CREATURE_SAY callback.
  377.     function NpcHandler:onCreatureSay(cid, class, msg)
  378.         local callback = self:getCallback(CALLBACK_CREATURE_SAY)
  379.         if(callback == nil or callback(cid, class, msg)) then
  380.             if(self:processModuleCallback(CALLBACK_CREATURE_SAY, cid, class, msg)) then
  381.                 if(not self:isInRange(cid)) then
  382.                     return
  383.                 end
  384.  
  385.                 if(self.keywordHandler ~= nil) then
  386.                     if((self:isFocused(cid) and (class == TALKTYPE_PRIVATE_PN or NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT)) or not self:isFocused(cid)) then
  387.                         local ret = self.keywordHandler:processMessage(cid, msg)
  388.                         if(not ret) then
  389.                             local callback = self:getCallback(CALLBACK_MESSAGE_DEFAULT)
  390.                             if(callback ~= nil and callback(cid, class, msg)) then
  391.                                 if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  392.                                     self.talkStart[cid] = os.time()
  393.                                 else
  394.                                     self.talkStart = os.time()
  395.                                 end
  396.                             end
  397.                         else
  398.                             if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  399.                                 self.talkStart[cid] = os.time()
  400.                             else
  401.                                 self.talkStart = os.time()
  402.                             end
  403.                         end
  404.                     end
  405.                 end
  406.             end
  407.         end
  408.     end
  409.  
  410.     -- Handles onPlayerEndTrade events. If you wish to handle this yourself, use the CALLBACK_PLAYER_ENDTRADE callback.
  411.     function NpcHandler:onPlayerEndTrade(cid)
  412.         local callback = self:getCallback(CALLBACK_PLAYER_ENDTRADE)
  413.         if(callback == nil or callback(cid)) then
  414.             if(self:processModuleCallback(CALLBACK_PLAYER_ENDTRADE, cid, class, msg)) then
  415.                 if(self:isFocused(cid)) then
  416.                     local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid) }
  417.                     local msg = self:parseMessage(self:getMessage(MESSAGE_ONCLOSESHOP), parseInfo)
  418.                     self:say(msg, cid)
  419.                 end
  420.             end
  421.         end
  422.     end
  423.  
  424.     -- Handles onPlayerCloseChannel events. If you wish to handle this yourself, use the CALLBACK_PLAYER_CLOSECHANNEL callback.
  425.     function NpcHandler:onPlayerCloseChannel(cid)
  426.         local callback = self:getCallback(CALLBACK_PLAYER_CLOSECHANNEL)
  427.         if(callback == nil or callback(cid)) then
  428.             if(self:processModuleCallback(CALLBACK_PLAYER_CLOSECHANNEL, cid, class, msg)) then
  429.                 if(self:isFocused(cid)) then
  430.                     self:unGreet(cid)
  431.                 end
  432.             end
  433.         end
  434.     end
  435.  
  436.     -- Handles onBuy events. If you wish to handle this yourself, use the CALLBACK_ONBUY callback.
  437.     function NpcHandler:onBuy(cid, itemid, subType, amount, ignoreCap, inBackpacks)
  438.         local callback = self:getCallback(CALLBACK_ONBUY)
  439.         if(callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
  440.             if(self:processModuleCallback(CALLBACK_ONBUY, cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
  441.                 --
  442.             end
  443.         end
  444.     end
  445.  
  446.     -- Handles onSell events. If you wish to handle this yourself, use the CALLBACK_ONSELL callback.
  447.     function NpcHandler:onSell(cid, itemid, subType, amount, ignoreCap, inBackpacks)
  448.         local callback = self:getCallback(CALLBACK_ONSELL)
  449.         if(callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
  450.             if(self:processModuleCallback(CALLBACK_ONSELL, cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
  451.                 --
  452.             end
  453.         end
  454.     end
  455.  
  456.     -- Handles onThink events. If you wish to handle this yourself, please use the CALLBACK_ONTHINK callback.
  457.     function NpcHandler:onThink()
  458.         local callback = self:getCallback(CALLBACK_ONTHINK)
  459.         if(callback == nil or callback()) then
  460.             if(NPCHANDLER_TALKDELAY == TALKDELAY_ONTHINK) then
  461.                 if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  462.                     for cid, talkDelay in pairs(self.talkDelay) do
  463.                         if(talkDelay.time ~= nil and talkDelay.message ~= nil and os.time() >= talkDelay.time) then
  464.                             selfSay(talkDelay.message, cid)
  465.                             self.talkDelay[cid] = nil
  466.                         end
  467.                     end
  468.                 elseif(self.talkDelay.time ~= nil and self.talkDelay.message ~= nil and os.time() >= self.talkDelay.time) then
  469.                     selfSay(self.talkDelay.message)
  470.                     self.talkDelay.time = nil
  471.                     self.talkDelay.message = nil
  472.                 end
  473.             end
  474.  
  475.             if(self:processModuleCallback(CALLBACK_ONTHINK)) then
  476.                 if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  477.                     for pos, focus in pairs(self.focuses) do
  478.                         if(focus ~= nil) then
  479.                             if(not self:isInRange(focus)) then
  480.                                 self:onWalkAway(focus)
  481.                             elseif((os.time() - self.talkStart[focus]) > self.idleTime) then
  482.                                 self:unGreet(focus)
  483.                             else
  484.                                 self:updateFocus()
  485.                             end
  486.                         end
  487.                     end
  488.                 elseif(self.focuses ~= 0) then
  489.                     if(not self:isInRange(self.focuses)) then
  490.                         self:onWalkAway(self.focuses)
  491.                     elseif(os.time()-self.talkStart > self.idleTime) then
  492.                         self:unGreet(self.focuses)
  493.                     else
  494.                         self:updateFocus()
  495.                     end
  496.                 end
  497.             end
  498.         end
  499.     end
  500.  
  501.     -- Tries to greet the player with the given cid.
  502.     function NpcHandler:onGreet(cid)
  503.         if(self:isInRange(cid)) then
  504.             if(NPCHANDLER_CONVBEHAVIOR == CONVERSATION_PRIVATE) then
  505.                 if(not self:isFocused(cid)) then
  506.                     self:greet(cid)
  507.                     return
  508.                 end
  509.             elseif(NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT) then
  510.                 if(self.focuses == 0) then
  511.                     self:greet(cid)
  512.                 elseif(self.focuses == cid) then
  513.                     local msg = self:getMessage(MESSAGE_ALREADYFOCUSED)
  514.                     local parseInfo = { [TAG_PLAYERNAME] = getCreatureName(cid) }
  515.                     msg = self:parseMessage(msg, parseInfo)
  516.                     self:say(msg)
  517.                 else
  518.                     if(not self.queue:isInQueue(cid)) then
  519.                         self.queue:push(cid)
  520.                     end
  521.  
  522.                     local msg = self:getMessage(MESSAGE_PLACEDINQUEUE)
  523.                     local parseInfo = { [TAG_PLAYERNAME] = getCreatureName(cid), [TAG_QUEUESIZE] = self.queue:getSize() }
  524.                     msg = self:parseMessage(msg, parseInfo)
  525.                     self:say(msg)
  526.                 end
  527.             end
  528.         end
  529.     end
  530.  
  531.     -- Simply calls the underlying unGreet function.
  532.     function NpcHandler:onFarewell(cid)
  533.         self:unGreet(cid)
  534.     end
  535.  
  536.     -- Should be called on this npc's focus if the distance to focus is greater then talkRadius.
  537.     function NpcHandler:onWalkAway(cid)
  538.         if(self:isFocused(cid)) then
  539.             local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR)
  540.             if(callback == nil or callback(cid)) then
  541.                 if(self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid)) then
  542.                     if(self.queue == nil or not self.queue:greetNext()) then
  543.                         local msg = self:getMessage(MESSAGE_WALKAWAY)
  544.                         local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid) }
  545.                         msg = self:parseMessage(msg, parseInfo)
  546.  
  547.                         self:say(msg, cid)
  548.                         self:releaseFocus(cid)
  549.                         self:say(msg)
  550.                     end
  551.                 end
  552.             end
  553.         end
  554.     end
  555.  
  556.     -- Returns true if cid is within the talkRadius of this npc.
  557.     function NpcHandler:isInRange(cid)
  558.         local distance = getDistanceTo(cid) or -1
  559.         if(distance == -1) then
  560.             return false
  561.         end
  562.  
  563.         return (distance <= self.talkRadius)
  564.     end
  565.  
  566.     -- Resets the npc into it's initial state (in regard of the keyrodhandler).
  567.     --  All modules are also receiving a reset call through their callbackOnModuleReset function.
  568.     function NpcHandler:resetNpc()
  569.         if(self:processModuleCallback(CALLBACK_MODULE_RESET)) then
  570.             self.keywordHandler:reset()
  571.         end
  572.     end
  573.  
  574.     -- Makes the npc represented by this instance of NpcHandler say something.
  575.     --  This implements the currently set type of talkdelay.
  576.     --  shallDelay is a boolean value. If it is false, the message is not delayed. Default value is false.
  577.     function NpcHandler:say(message, focus, shallDelay)
  578.         local shallDelay = shallDelay or false
  579.         if(NPCHANDLER_TALKDELAY == TALKDELAY_NONE or not shallDelay) then
  580.             if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  581.                 selfSay(message, focus)
  582.                 return
  583.             else
  584.                 selfSay(message)
  585.                 return
  586.             end
  587.         end
  588.  
  589.         -- TODO: Add an event handling method for delayed messages
  590.         if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  591.             self.talkDelay[focus] = {
  592.                 message = message,
  593.                 time = os.time() + self.talkDelayTime,
  594.             }
  595.         else
  596.             self.talkDelay = {
  597.                 message = message,
  598.                 time = os.time() + self.talkDelayTime
  599.             }
  600.         end
  601.     end
  602. end
Advertisement
Add Comment
Please, Sign In to add comment