Advertisement
alexmoretoni

NPCCHANDLER

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