Advertisement
Berntan

Npchandler.lua

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