Advertisement
Guest User

npchandler.lua

a guest
Apr 26th, 2014
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 26.42 KB | None | 0 0
  1. -- Advanced NPC System (Created by Jiddo),
  2. -- Modified by Talaturen.
  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 = 90,
  74.         talkRadius = 4,
  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 have been expecting you.',
  84.             [MESSAGE_FAREWELL]     = 'Good bye, |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) then
  235.             table.insert(self.modules, module)
  236.             module:init(self)
  237.         end
  238.     end
  239.  
  240.     -- Calls the callback function represented by id for all modules added to this npchandler with the given arguments.
  241.     function NpcHandler:processModuleCallback(id, ...)
  242.         local ret = true
  243.         for i, module in pairs(self.modules) do
  244.             local tmpRet = true
  245.             if(id == CALLBACK_CREATURE_APPEAR and module.callbackOnCreatureAppear ~= nil) then
  246.                 tmpRet = module:callbackOnCreatureAppear(unpack(arg))
  247.             elseif(id == CALLBACK_CREATURE_DISAPPEAR and module.callbackOnCreatureDisappear ~= nil) then
  248.                 tmpRet = module:callbackOnCreatureDisappear(unpack(arg))
  249.             elseif(id == CALLBACK_CREATURE_SAY and module.callbackOnCreatureSay ~= nil) then
  250.                 tmpRet = module:callbackOnCreatureSay(unpack(arg))
  251.             elseif(id == CALLBACK_PLAYER_ENDTRADE and module.callbackOnPlayerEndTrade ~= nil) then
  252.                 tmpRet = module:callbackOnPlayerEndTrade(unpack(arg))
  253.             elseif(id == CALLBACK_PLAYER_CLOSECHANNEL and module.callbackOnPlayerCloseChannel ~= nil) then
  254.                 tmpRet = module:callbackOnPlayerCloseChannel(unpack(arg))
  255.             elseif(id == CALLBACK_ONBUY and module.callbackOnBuy ~= nil) then
  256.                 tmpRet = module:callbackOnBuy(unpack(arg))
  257.             elseif(id == CALLBACK_ONSELL and module.callbackOnSell ~= nil) then
  258.                 tmpRet = module:callbackOnSell(unpack(arg))
  259.             elseif(id == CALLBACK_ONTHINK and module.callbackOnThink ~= nil) then
  260.                 tmpRet = module:callbackOnThink(unpack(arg))
  261.             elseif(id == CALLBACK_GREET and module.callbackOnGreet ~= nil) then
  262.                 tmpRet = module:callbackOnGreet(unpack(arg))
  263.             elseif(id == CALLBACK_FAREWELL and module.callbackOnFarewell ~= nil) then
  264.                 tmpRet = module:callbackOnFarewell(unpack(arg))
  265.             elseif(id == CALLBACK_MESSAGE_DEFAULT and module.callbackOnMessageDefault ~= nil) then
  266.                 tmpRet = module:callbackOnMessageDefault(unpack(arg))
  267.             elseif(id == CALLBACK_MODULE_RESET and module.callbackOnModuleReset ~= nil) then
  268.                 tmpRet = module:callbackOnModuleReset(unpack(arg))
  269.             end
  270.  
  271.             if(not tmpRet) then
  272.                 ret = false
  273.                 break
  274.             end
  275.         end
  276.  
  277.         return ret
  278.     end
  279.  
  280.     -- Returns the message represented by id.
  281.     function NpcHandler:getMessage(id)
  282.         local ret = nil
  283.         if(self.messages ~= nil) then
  284.             ret = self.messages[id]
  285.         end
  286.  
  287.         return ret
  288.     end
  289.  
  290.     -- Changes the default response message with the specified id to newMessage.
  291.     function NpcHandler:setMessage(id, newMessage)
  292.         if(self.messages ~= nil) then
  293.             self.messages[id] = newMessage
  294.         end
  295.     end
  296.  
  297.     -- Translates all message tags found in msg using parseInfo
  298.     function NpcHandler:parseMessage(msg, parseInfo)
  299.         local ret = msg
  300.         for search, replace in pairs(parseInfo) do
  301.             ret = string.gsub(ret, search, replace)
  302.         end
  303.  
  304.         return ret
  305.     end
  306.  
  307.     -- Makes sure the npc un-focuses the currently focused player
  308.     function NpcHandler:unGreet(cid)
  309.         if(not self:isFocused(cid)) then
  310.             return
  311.         end
  312.  
  313.         local callback = self:getCallback(CALLBACK_FAREWELL)
  314.         if(callback == nil or callback()) then
  315.             if(self:processModuleCallback(CALLBACK_FAREWELL)) then
  316.                 if(self.queue == nil or not self.queue:greetNext()) then
  317.                     local msg = self:getMessage(MESSAGE_FAREWELL)
  318.                     local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid) }
  319.                     msg = self:parseMessage(msg, parseInfo)
  320.  
  321.                     self:say(msg, cid)
  322.                     self:releaseFocus(cid)
  323.                     self:say(msg)
  324.                 end
  325.             end
  326.         end
  327.     end
  328.  
  329.     -- Greets a new player.
  330.     function NpcHandler:greet(cid)
  331.         if(cid ~= 0) then
  332.             local callback = self:getCallback(CALLBACK_GREET)
  333.             if(callback == nil or callback(cid)) then
  334.                 if(self:processModuleCallback(CALLBACK_GREET, cid)) then
  335.                     local msg = self:getMessage(MESSAGE_GREET)
  336.                     local parseInfo = { [TAG_PLAYERNAME] = getCreatureName(cid) }
  337.                     msg = self:parseMessage(msg, parseInfo)
  338.  
  339.                     self:say(msg)
  340.                     self:addFocus(cid)
  341.                     self:say(msg, cid)
  342.                 end
  343.             end
  344.         end
  345.     end
  346.  
  347.     -- Handles onCreatureAppear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_APPEAR callback.
  348.     function NpcHandler:onCreatureAppear(cid)
  349.         local callback = self:getCallback(CALLBACK_CREATURE_APPEAR)
  350.         if(callback == nil or callback(cid)) then
  351.             if(self:processModuleCallback(CALLBACK_CREATURE_APPEAR, cid)) then
  352.                 --
  353.             end
  354.         end
  355.     end
  356.  
  357.     -- Handles onCreatureDisappear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_DISAPPEAR callback.
  358.     function NpcHandler:onCreatureDisappear(cid)
  359.         local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR)
  360.         if(callback == nil or callback(cid)) then
  361.             if(self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid)) then
  362.                 if(self:isFocused(cid)) then
  363.                     self:unGreet(cid)
  364.                 end
  365.             end
  366.         end
  367.     end
  368.  
  369.     -- Handles onCreatureSay events. If you with to handle this yourself, please use the CALLBACK_CREATURE_SAY callback.
  370.     function NpcHandler:onCreatureSay(cid, class, msg)
  371.         local callback = self:getCallback(CALLBACK_CREATURE_SAY)
  372.         if(callback == nil or callback(cid, class, msg)) then
  373.             if(self:processModuleCallback(CALLBACK_CREATURE_SAY, cid, class, msg)) then
  374.                 if(not self:isInRange(cid)) then
  375.                     return
  376.                 end
  377.  
  378.                 if(self.keywordHandler ~= nil) then
  379.                     if((self:isFocused(cid) and (class == TALKTYPE_PRIVATE_PN or NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT)) or not self:isFocused(cid)) then
  380.                         local ret = self.keywordHandler:processMessage(cid, msg)
  381.                         if(not ret) then
  382.                             local callback = self:getCallback(CALLBACK_MESSAGE_DEFAULT)
  383.                             if(callback ~= nil and callback(cid, class, msg)) then
  384.                                 if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  385.                                     self.talkStart[cid] = os.time()
  386.                                 else
  387.                                     self.talkStart = os.time()
  388.                                 end
  389.                             end
  390.                         else
  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.                     end
  398.                 end
  399.             end
  400.         end
  401.     end
  402.  
  403.     -- Handles onPlayerEndTrade events. If you wish to handle this yourself, use the CALLBACK_PLAYER_ENDTRADE callback.
  404.     function NpcHandler:onPlayerEndTrade(cid)
  405.         local callback = self:getCallback(CALLBACK_PLAYER_ENDTRADE)
  406.         if(callback == nil or callback(cid)) then
  407.             if(self:processModuleCallback(CALLBACK_PLAYER_ENDTRADE, cid, class, msg)) then
  408.                 if(self:isFocused(cid)) then
  409.                     local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid) }
  410.                     local msg = self:parseMessage(self:getMessage(MESSAGE_ONCLOSESHOP), parseInfo)
  411.                     self:say(msg, cid)
  412.                 end
  413.             end
  414.         end
  415.     end
  416.  
  417.     -- Handles onPlayerCloseChannel events. If you wish to handle this yourself, use the CALLBACK_PLAYER_CLOSECHANNEL callback.
  418.     function NpcHandler:onPlayerCloseChannel(cid)
  419.         local callback = self:getCallback(CALLBACK_PLAYER_CLOSECHANNEL)
  420.         if(callback == nil or callback(cid)) then
  421.             if(self:processModuleCallback(CALLBACK_PLAYER_CLOSECHANNEL, cid, class, msg)) then
  422.                 if(self:isFocused(cid)) then
  423.                     self:unGreet(cid)
  424.                 end
  425.             end
  426.         end
  427.     end
  428.  
  429.     -- Handles onBuy events. If you wish to handle this yourself, use the CALLBACK_ONBUY callback.
  430.     function NpcHandler:onBuy(cid, itemid, subType, amount, ignoreCap, inBackpacks)
  431.         local callback = self:getCallback(CALLBACK_ONBUY)
  432.         if(callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
  433.             if(self:processModuleCallback(CALLBACK_ONBUY, cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
  434.                 --
  435.             end
  436.         end
  437.     end
  438.  
  439.     -- Handles onSell events. If you wish to handle this yourself, use the CALLBACK_ONSELL callback.
  440.     function NpcHandler:onSell(cid, itemid, subType, amount, ignoreCap, inBackpacks)
  441.         local callback = self:getCallback(CALLBACK_ONSELL)
  442.         if(callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
  443.             if(self:processModuleCallback(CALLBACK_ONSELL, cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
  444.                 --
  445.             end
  446.         end
  447.     end
  448.  
  449.     -- Handles onThink events. If you wish to handle this yourself, please use the CALLBACK_ONTHINK callback.
  450.     function NpcHandler:onThink()
  451.         local callback = self:getCallback(CALLBACK_ONTHINK)
  452.         if(callback == nil or callback()) then
  453.             if(NPCHANDLER_TALKDELAY == TALKDELAY_ONTHINK) then
  454.                 if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  455.                     for cid, talkDelay in pairs(self.talkDelay) do
  456.                         if(talkDelay.time ~= nil and talkDelay.message ~= nil and os.time() >= talkDelay.time) then
  457.                             selfSay(talkDelay.message, cid)
  458.                             self.talkDelay[cid] = nil
  459.                         end
  460.                     end
  461.                 elseif(self.talkDelay.time ~= nil and self.talkDelay.message ~= nil and os.time() >= self.talkDelay.time) then
  462.                     selfSay(self.talkDelay.message)
  463.                     self.talkDelay.time = nil
  464.                     self.talkDelay.message = nil
  465.                 end
  466.             end
  467.  
  468.             if(self:processModuleCallback(CALLBACK_ONTHINK)) then
  469.                 if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  470.                     for pos, focus in pairs(self.focuses) do
  471.                         if(focus ~= nil) then
  472.                             if(not self:isInRange(focus)) then
  473.                                 self:onWalkAway(focus)
  474.                             elseif((os.time() - self.talkStart[focus]) > self.idleTime) then
  475.                                 self:unGreet(focus)
  476.                             else
  477.                                 self:updateFocus()
  478.                             end
  479.                         end
  480.                     end
  481.                 elseif(self.focuses ~= 0) then
  482.                     if(not self:isInRange(self.focuses)) then
  483.                         self:onWalkAway(self.focuses)
  484.                     elseif(os.time()-self.talkStart > self.idleTime) then
  485.                         self:unGreet(self.focuses)
  486.                     else
  487.                         self:updateFocus()
  488.                     end
  489.                 end
  490.             end
  491.         end
  492.     end
  493.  
  494.     -- Tries to greet the player with the given cid.
  495.     function NpcHandler:onGreet(cid)
  496.         if(self:isInRange(cid)) then
  497.             if(NPCHANDLER_CONVBEHAVIOR == CONVERSATION_PRIVATE) then
  498.                 if(not self:isFocused(cid)) then
  499.                     self:greet(cid)
  500.                     return
  501.                 end
  502.             elseif(NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT) then
  503.                 if(self.focuses == 0) then
  504.                     self:greet(cid)
  505.                 elseif(self.focuses == cid) then
  506.                     local msg = self:getMessage(MESSAGE_ALREADYFOCUSED)
  507.                     local parseInfo = { [TAG_PLAYERNAME] = getCreatureName(cid) }
  508.                     msg = self:parseMessage(msg, parseInfo)
  509.                     self:say(msg)
  510.                 else
  511.                     if(not self.queue:isInQueue(cid)) then
  512.                         self.queue:push(cid)
  513.                     end
  514.  
  515.                     local msg = self:getMessage(MESSAGE_PLACEDINQUEUE)
  516.                     local parseInfo = { [TAG_PLAYERNAME] = getCreatureName(cid), [TAG_QUEUESIZE] = self.queue:getSize() }
  517.                     msg = self:parseMessage(msg, parseInfo)
  518.                     self:say(msg)
  519.                 end
  520.             end
  521.         end
  522.     end
  523.  
  524.     -- Simply calls the underlying unGreet function.
  525.     function NpcHandler:onFarewell(cid)
  526.         self:unGreet(cid)
  527.     end
  528.  
  529.     -- Should be called on this npc's focus if the distance to focus is greater then talkRadius.
  530.     function NpcHandler:onWalkAway(cid)
  531.         if(self:isFocused(cid)) then
  532.             local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR)
  533.             if(callback == nil or callback()) then
  534.                 if(self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid)) then
  535.                     if(self.queue == nil or not self.queue:greetNext()) then
  536.                         local msg = self:getMessage(MESSAGE_WALKAWAY)
  537.                         local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid) }
  538.                         msg = self:parseMessage(msg, parseInfo)
  539.  
  540.                         self:say(msg, cid)
  541.                         self:releaseFocus(cid)
  542.                         self:say(msg)
  543.                     end
  544.                 end
  545.             end
  546.         end
  547.     end
  548.  
  549.     -- Returns true if cid is within the talkRadius of this npc.
  550.     function NpcHandler:isInRange(cid)
  551.         local distance = getDistanceTo(cid) or -1
  552.         if(distance == -1) then
  553.             return false
  554.         end
  555.  
  556.         return (distance <= self.talkRadius)
  557.     end
  558.  
  559.     -- Resets the npc into it's initial state (in regard of the keyrodhandler).
  560.     --    All modules are also receiving a reset call through their callbackOnModuleReset function.
  561.     function NpcHandler:resetNpc()
  562.         if(self:processModuleCallback(CALLBACK_MODULE_RESET)) then
  563.             self.keywordHandler:reset()
  564.         end
  565.     end
  566.  
  567.     -- Makes the npc represented by this instance of NpcHandler say something.
  568.     --    This implements the currently set type of talkdelay.
  569.     --    shallDelay is a boolean value. If it is false, the message is not delayed. Default value is false.
  570.     function NpcHandler:say(message, focus, shallDelay)
  571.         local shallDelay = shallDelay or false
  572.         if(NPCHANDLER_TALKDELAY == TALKDELAY_NONE or not shallDelay) then
  573.             if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  574.                 selfSay(message, focus)
  575.                 return
  576.             else
  577.                 selfSay(message)
  578.                 return
  579.             end
  580.         end
  581.  
  582.         -- TODO: Add an event handling method for delayed messages
  583.         if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
  584.             self.talkDelay[focus] = {
  585.                 message = message,
  586.                 time = os.time() + self.talkDelayTime,
  587.             }
  588.         else
  589.             self.talkDelay = {
  590.                 message = message,
  591.                 time = os.time() + self.talkDelayTime
  592.             }
  593.         end
  594.     end
  595. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement