Advertisement
Guest User

Untitled

a guest
May 20th, 2019
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.54 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. -- Attaches 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. shop_amount[focus] = nil
  179. shop_cost[focus] = nil
  180. shop_rlname[focus] = nil
  181. shop_itemid[focus] = nil
  182. shop_container[focus] = nil
  183. shop_npcuid[focus] = nil
  184. shop_eventtype[focus] = nil
  185. shop_subtype[focus] = nil
  186. shop_destination[focus] = nil
  187. shop_premium[focus] = nil
  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. self.focuses[pos] = nil
  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. if type(ret) == 'string' then
  310. for search, replace in pairs(parseInfo) do
  311. ret = string.gsub(ret, search, replace)
  312. end
  313. else
  314. for i = 1, #ret do
  315. for search, replace in pairs(parseInfo) do
  316. ret[i] = string.gsub(ret[i], search, replace)
  317. end
  318. end
  319. end
  320. return ret
  321. end
  322.  
  323.  
  324. -- Makes sure the npc un-focuses the currently focused player
  325. function NpcHandler:unGreet(cid)
  326. if not self:isFocused(cid) then
  327. return
  328. end
  329.  
  330. local callback = self:getCallback(CALLBACK_FAREWELL)
  331. if callback == nil or callback() then
  332. if self:processModuleCallback(CALLBACK_FAREWELL) then
  333. local msg = self:getMessage(MESSAGE_FAREWELL)
  334. local player = Player(cid)
  335. local playerName = player and player:getName() or -1
  336. local parseInfo = { [TAG_PLAYERNAME] = playerName }
  337. self:resetNpc(cid)
  338. msg = self:parseMessage(msg, parseInfo)
  339. self:say(msg, cid, true)
  340. self:releaseFocus(cid)
  341. end
  342. end
  343. end
  344.  
  345. -- Greets a new player.
  346. function NpcHandler:greet(cid)
  347. if cid ~= 0 then
  348. local callback = self:getCallback(CALLBACK_GREET)
  349. if callback == nil or callback(cid) then
  350. if self:processModuleCallback(CALLBACK_GREET, cid) then
  351. local msg = self:getMessage(MESSAGE_GREET)
  352. local player = Player(cid)
  353. local playerName = player and player:getName() or -1
  354. local parseInfo = { [TAG_PLAYERNAME] = playerName }
  355. msg = self:parseMessage(msg, parseInfo)
  356. self:say(msg, cid, true)
  357. else
  358. return
  359. end
  360. else
  361. return
  362. end
  363. end
  364. self:addFocus(cid)
  365. end
  366.  
  367. -- Handles onCreatureAppear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_APPEAR callback.
  368. function NpcHandler:onCreatureAppear(creature)
  369. local cid = creature:getId()
  370. if cid == getNpcCid() and next(self.shopItems) ~= nil then
  371. local npc = Npc()
  372. local speechBubble = npc:getSpeechBubble()
  373. if speechBubble == 3 then
  374. npc:setSpeechBubble(4)
  375. else
  376. npc:setSpeechBubble(2)
  377. end
  378. end
  379.  
  380. local callback = self:getCallback(CALLBACK_CREATURE_APPEAR)
  381. if callback == nil or callback(cid) then
  382. if self:processModuleCallback(CALLBACK_CREATURE_APPEAR, cid) then
  383. --
  384. end
  385. end
  386. end
  387.  
  388. -- Handles onCreatureDisappear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_DISAPPEAR callback.
  389. function NpcHandler:onCreatureDisappear(creature)
  390. local cid = creature:getId()
  391. if getNpcCid() == cid then
  392. return
  393. end
  394.  
  395. local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR)
  396. if callback == nil or callback(cid) then
  397. if self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid) then
  398. if self:isFocused(cid) then
  399. self:unGreet(cid)
  400. end
  401. end
  402. end
  403. end
  404.  
  405. -- Handles onCreatureSay events. If you with to handle this yourself, please use the CALLBACK_CREATURE_SAY callback.
  406. function NpcHandler:onCreatureSay(creature, msgtype, msg)
  407. local cid = creature:getId()
  408. local callback = self:getCallback(CALLBACK_CREATURE_SAY)
  409. if callback == nil or callback(cid, msgtype, msg) then
  410. if self:processModuleCallback(CALLBACK_CREATURE_SAY, cid, msgtype, msg) then
  411. if not self:isInRange(cid) then
  412. return
  413. end
  414.  
  415. if self.keywordHandler ~= nil then
  416. if self:isFocused(cid) and msgtype == TALKTYPE_PRIVATE_PN or not self:isFocused(cid) then
  417. local ret = self.keywordHandler:processMessage(cid, msg)
  418. if not ret then
  419. local callback = self:getCallback(CALLBACK_MESSAGE_DEFAULT)
  420. if callback ~= nil and callback(cid, msgtype, msg) then
  421. self.talkStart[cid] = os.time()
  422. end
  423. else
  424. self.talkStart[cid] = os.time()
  425. end
  426. end
  427. end
  428. end
  429. end
  430. end
  431.  
  432. -- Handles onPlayerEndTrade events. If you wish to handle this yourself, use the CALLBACK_PLAYER_ENDTRADE callback.
  433. function NpcHandler:onPlayerEndTrade(creature)
  434. local cid = creature:getId()
  435. local callback = self:getCallback(CALLBACK_PLAYER_ENDTRADE)
  436. if callback == nil or callback(cid) then
  437. if self:processModuleCallback(CALLBACK_PLAYER_ENDTRADE, cid, msgtype, msg) then
  438. if self:isFocused(cid) then
  439. local player = Player(cid)
  440. local playerName = player and player:getName() or -1
  441. local parseInfo = { [TAG_PLAYERNAME] = playerName }
  442. local msg = self:parseMessage(self:getMessage(MESSAGE_ONCLOSESHOP), parseInfo)
  443. self:say(msg, cid)
  444. end
  445. end
  446. end
  447. end
  448.  
  449. -- Handles onPlayerCloseChannel events. If you wish to handle this yourself, use the CALLBACK_PLAYER_CLOSECHANNEL callback.
  450. function NpcHandler:onPlayerCloseChannel(creature)
  451. local cid = creature:getId()
  452. local callback = self:getCallback(CALLBACK_PLAYER_CLOSECHANNEL)
  453. if callback == nil or callback(cid) then
  454. if self:processModuleCallback(CALLBACK_PLAYER_CLOSECHANNEL, cid, msgtype, msg) then
  455. if self:isFocused(cid) then
  456. self:unGreet(cid)
  457. end
  458. end
  459. end
  460. end
  461.  
  462. -- Handles onBuy events. If you wish to handle this yourself, use the CALLBACK_ONBUY callback.
  463. function NpcHandler:onBuy(creature, itemid, subType, amount, ignoreCap, inBackpacks)
  464. local cid = creature:getId()
  465.  
  466. local storage = 94447
  467.  
  468. if creature:getStorageValue(storage) > os.time() then
  469. return false
  470. end
  471.  
  472.  
  473. local callback = self:getCallback(CALLBACK_ONBUY)
  474. if callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks) then
  475. if self:processModuleCallback(CALLBACK_ONBUY, cid, itemid, subType, amount, ignoreCap, inBackpacks) then
  476. --
  477. end
  478. end
  479. creature:setStorageValue(storage, os.time() + 1)
  480. end
  481.  
  482. -- Handles onSell events. If you wish to handle this yourself, use the CALLBACK_ONSELL callback.
  483. function NpcHandler:onSell(creature, itemid, subType, amount, ignoreCap, inBackpacks)
  484. local cid = creature:getId()
  485. local callback = self:getCallback(CALLBACK_ONSELL)
  486. if callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks) then
  487. if self:processModuleCallback(CALLBACK_ONSELL, cid, itemid, subType, amount, ignoreCap, inBackpacks) then
  488. --
  489. end
  490. end
  491. end
  492.  
  493. -- Handles onTradeRequest events. If you wish to handle this yourself, use the CALLBACK_ONTRADEREQUEST callback.
  494. function NpcHandler:onTradeRequest(cid)
  495. local callback = self:getCallback(CALLBACK_ONTRADEREQUEST)
  496. if callback == nil or callback(cid) then
  497. if self:processModuleCallback(CALLBACK_ONTRADEREQUEST, cid) then
  498. return true
  499. end
  500. end
  501. return false
  502. end
  503.  
  504. -- Handles onThink events. If you wish to handle this yourself, please use the CALLBACK_ONTHINK callback.
  505. function NpcHandler:onThink()
  506. local callback = self:getCallback(CALLBACK_ONTHINK)
  507. if callback == nil or callback() then
  508. if NPCHANDLER_TALKDELAY == TALKDELAY_ONTHINK then
  509. for cid, talkDelay in pairs(self.talkDelay) do
  510. if talkDelay.time ~= nil and talkDelay.message ~= nil and os.time() >= talkDelay.time then
  511. selfSay(talkDelay.message, cid, talkDelay.publicize and true or false)
  512. self.talkDelay[cid] = nil
  513. end
  514. end
  515. end
  516.  
  517. if self:processModuleCallback(CALLBACK_ONTHINK) then
  518. for pos, focus in pairs(self.focuses) do
  519. if focus ~= nil then
  520. if not self:isInRange(focus) then
  521. self:onWalkAway(focus)
  522. elseif self.talkStart[focus] ~= nil and (os.time() - self.talkStart[focus]) > self.idleTime then
  523. self:unGreet(focus)
  524. else
  525. self:updateFocus()
  526. end
  527. end
  528. end
  529. end
  530. end
  531. end
  532.  
  533. -- Tries to greet the player with the given cid.
  534. function NpcHandler:onGreet(cid)
  535. if self:isInRange(cid) then
  536. if not self:isFocused(cid) then
  537. self:greet(cid)
  538. return
  539. end
  540. end
  541. end
  542.  
  543. -- Simply calls the underlying unGreet function.
  544. function NpcHandler:onFarewell(cid)
  545. self:unGreet(cid)
  546. end
  547.  
  548. -- Should be called on this npc's focus if the distance to focus is greater then talkRadius.
  549. function NpcHandler:onWalkAway(cid)
  550. if self:isFocused(cid) then
  551. local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR)
  552. if callback == nil or callback() then
  553. if self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid) then
  554. local msg = self:getMessage(MESSAGE_WALKAWAY)
  555.  
  556. local player = Player(cid)
  557. local playerName = player and player:getName() or -1
  558. local playerSex = player and player:getSex() or 0
  559.  
  560. local parseInfo = { [TAG_PLAYERNAME] = playerName }
  561. local message = self:parseMessage(msg, parseInfo)
  562.  
  563. local msg_male = self:getMessage(MESSAGE_WALKAWAY_MALE)
  564. local message_male = self:parseMessage(msg_male, parseInfo)
  565. local msg_female = self:getMessage(MESSAGE_WALKAWAY_FEMALE)
  566. local message_female = self:parseMessage(msg_female, parseInfo)
  567. if message_female ~= message_male then
  568. if playerSex == PLAYERSEX_FEMALE then
  569. selfSay(message_female)
  570. else
  571. selfSay(message_male)
  572. end
  573. elseif message ~= "" then
  574. selfSay(message)
  575. end
  576. self:resetNpc(cid)
  577. self:releaseFocus(cid)
  578. end
  579. end
  580. end
  581. end
  582.  
  583. -- Returns true if cid is within the talkRadius of this npc.
  584. function NpcHandler:isInRange(cid)
  585. local distance = Player(cid) ~= nil and getDistanceTo(cid) or -1
  586. if distance == -1 then
  587. return false
  588. end
  589.  
  590. return distance <= self.talkRadius
  591. end
  592.  
  593. -- Resets the npc into its initial state (in regard of the keywordhandler).
  594. -- All modules are also receiving a reset call through their callbackOnModuleReset function.
  595. function NpcHandler:resetNpc(cid)
  596. if self:processModuleCallback(CALLBACK_MODULE_RESET) then
  597. self.keywordHandler:reset(cid)
  598. end
  599. end
  600.  
  601. function NpcHandler:cancelNPCTalk(events)
  602. for aux = 1, #events do
  603. stopEvent(events[aux].event)
  604. end
  605. events = nil
  606. end
  607.  
  608. function NpcHandler:doNPCTalkALot(msgs, interval, pcid)
  609. if self.eventDelayedSay[pcid] then
  610. self:cancelNPCTalk(self.eventDelayedSay[pcid])
  611. end
  612.  
  613. self.eventDelayedSay[pcid] = {}
  614. local ret = {}
  615. for aux = 1, #msgs do
  616. self.eventDelayedSay[pcid][aux] = {}
  617. doCreatureSayWithDelay(getNpcCid(), msgs[aux], TALKTYPE_PRIVATE_NP, ((aux-1) * (interval or 4000)) + 700, self.eventDelayedSay[pcid][aux], pcid)
  618. ret[#ret + 1] = self.eventDelayedSay[pcid][aux]
  619. end
  620. return(ret)
  621. end
  622.  
  623. -- Makes the npc represented by this instance of NpcHandler say something.
  624. -- This implements the currently set type of talkdelay.
  625. -- shallDelay is a boolean value. If it is false, the message is not delayed. Default value is true.
  626. function NpcHandler:say(message, focus, publicize, shallDelay, delay)
  627. if type(message) == "table" then
  628. return self:doNPCTalkALot(message, delay or 6000, focus)
  629. end
  630.  
  631. if self.eventDelayedSay[focus] then
  632. self:cancelNPCTalk(self.eventDelayedSay[focus])
  633. end
  634.  
  635. local shallDelay = not shallDelay and true or shallDelay
  636. if NPCHANDLER_TALKDELAY == TALKDELAY_NONE or shallDelay == false then
  637. selfSay(message, focus, publicize and true or false)
  638. return
  639. end
  640.  
  641. stopEvent(self.eventSay[focus])
  642. self.eventSay[focus] = addEvent(function(npcId, message, focusId)
  643. local npc = Npc(npcId)
  644. if npc == nil then
  645. return
  646. end
  647. local player = Player(focusId)
  648. if player then
  649. npc:say(message, TALKTYPE_PRIVATE_NP, false, player, npc:getPosition())
  650. end
  651. end, self.talkDelayTime * 1000, Npc():getId(), message, focus)
  652. end
  653. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement