Advertisement
alexmoretoni

Untitled

Dec 3rd, 2015
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.84 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. TAG_TIME = "|TIME|"
  63. TAG_BLESSCOST = "|BLESSCOST|"
  64. TAG_PVPBLESSCOST = "|PVPBLESSCOST|"
  65. TAG_TRAVELCOST = "|TRAVELCOST|"
  66.  
  67. NpcHandler = {
  68. keywordHandler = nil,
  69. focuses = nil,
  70. talkStart = nil,
  71. idleTime = 120,
  72. talkRadius = 3,
  73. talkDelayTime = 1, -- Seconds to delay outgoing messages.
  74. talkDelay = nil,
  75. callbackFunctions = nil,
  76. modules = nil,
  77. shopItems = nil, -- They must be here since ShopModule uses 'static' functions
  78. eventSay = nil,
  79. eventDelayedSay = nil,
  80. topic = nil,
  81. messages = {
  82. -- These are the default replies of all npcs. They can/should be changed individually for each npc.
  83. [MESSAGE_GREET] = "Greetings, |PLAYERNAME|.",
  84. [MESSAGE_FAREWELL] = "Good bye, |PLAYERNAME|.",
  85. [MESSAGE_BUY] = "Do you want to buy |ITEMCOUNT| |ITEMNAME| for |TOTALCOST| gold coins?",
  86. [MESSAGE_ONBUY] = "Here you are.",
  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] = "Here you are, |TOTALCOST| gold.",
  90. [MESSAGE_SOLD] = "Sold |ITEMCOUNT|x |ITEMNAME| for |TOTALCOST| gold.",
  91. [MESSAGE_MISSINGMONEY] = "You don't have enough money.",
  92. [MESSAGE_NEEDMONEY] = "You don't have enough money.",
  93. [MESSAGE_MISSINGITEM] = "You don't have so many.",
  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] = "Good bye.",
  98. [MESSAGE_WALKAWAY] = "Good bye.",
  99. [MESSAGE_DECLINE] = "Then not.",
  100. [MESSAGE_SENDTRADE] = "Of course, just browse through my wares.",
  101. [MESSAGE_NOSHOP] = "Sorry, I'm not offering anything.",
  102. [MESSAGE_ONCLOSESHOP] = "Thank you, come back whenever you're in need of something else.",
  103. [MESSAGE_ALREADYFOCUSED] = "|PLAYERNAME|, I am already talking to you.",
  104. [MESSAGE_WALKAWAY_MALE] = "Good bye.",
  105. [MESSAGE_WALKAWAY_FEMALE] = "Good bye."
  106. }
  107. }
  108.  
  109. -- Creates a new NpcHandler with an empty callbackFunction stack.
  110. function NpcHandler:new(keywordHandler)
  111. local obj = {}
  112. obj.callbackFunctions = {}
  113. obj.modules = {}
  114. obj.eventSay = {}
  115. obj.eventDelayedSay = {}
  116. obj.topic = {}
  117. obj.focuses = {}
  118. obj.talkStart = {}
  119. obj.talkDelay = {}
  120. obj.keywordHandler = keywordHandler
  121. obj.messages = {}
  122. obj.shopItems = {}
  123.  
  124. setmetatable(obj.messages, self.messages)
  125. self.messages.__index = self.messages
  126.  
  127. setmetatable(obj, self)
  128. self.__index = self
  129. return obj
  130. end
  131.  
  132. -- Re-defines the maximum idle time allowed for a player when talking to this npc.
  133. function NpcHandler:setMaxIdleTime(newTime)
  134. self.idleTime = newTime
  135. end
  136.  
  137. -- Attackes a new keyword handler to this npchandler
  138. function NpcHandler:setKeywordHandler(newHandler)
  139. self.keywordHandler = newHandler
  140. end
  141.  
  142. -- Function used to change the focus of this npc.
  143. function NpcHandler:addFocus(newFocus)
  144. if self:isFocused(newFocus) then
  145. return
  146. end
  147.  
  148. self.focuses[#self.focuses + 1] = newFocus
  149. self.topic[newFocus] = 0
  150. local callback = self:getCallback(CALLBACK_ONADDFOCUS)
  151. if callback == nil or callback(newFocus) then
  152. self:processModuleCallback(CALLBACK_ONADDFOCUS, newFocus)
  153. end
  154. self:updateFocus()
  155. end
  156.  
  157. -- Function used to verify if npc is focused to certain player
  158. function NpcHandler:isFocused(focus)
  159. for _, v in pairs(self.focuses) do
  160. if v == focus then
  161. return true
  162. end
  163. end
  164. return false
  165. end
  166.  
  167. -- This function should be called on each onThink and makes sure the npc faces the player it is talking to.
  168. -- Should also be called whenever a new player is focused.
  169. function NpcHandler:updateFocus()
  170. for _, focus in pairs(self.focuses) do
  171. if focus ~= nil then
  172. doNpcSetCreatureFocus(focus)
  173. return
  174. end
  175. end
  176. doNpcSetCreatureFocus(0)
  177. end
  178.  
  179. -- Used when the npc should un-focus the player.
  180. function NpcHandler:releaseFocus(focus)
  181. if shop_cost[focus] ~= nil then
  182. shop_amount[focus] = nil
  183. shop_cost[focus] = nil
  184. shop_rlname[focus] = nil
  185. shop_itemid[focus] = nil
  186. shop_container[focus] = nil
  187. shop_npcuid[focus] = nil
  188. shop_eventtype[focus] = nil
  189. shop_subtype[focus] = nil
  190. shop_destination[focus] = nil
  191. shop_premium[focus] = nil
  192. end
  193.  
  194. if self.eventDelayedSay[focus] then
  195. self:cancelNPCTalk(self.eventDelayedSay[focus])
  196. end
  197.  
  198. if not self:isFocused(focus) then
  199. return
  200. end
  201.  
  202. local pos = nil
  203. for k, v in pairs(self.focuses) do
  204. if v == focus then
  205. pos = k
  206. end
  207. end
  208.  
  209. self.focuses[pos] = nil
  210.  
  211. self.eventSay[focus] = nil
  212. self.eventDelayedSay[focus] = nil
  213. self.talkStart[focus] = nil
  214. self.topic[focus] = nil
  215.  
  216. local callback = self:getCallback(CALLBACK_ONRELEASEFOCUS)
  217. if callback == nil or callback(focus) then
  218. self:processModuleCallback(CALLBACK_ONRELEASEFOCUS, focus)
  219. end
  220.  
  221. if Player(focus) ~= nil then
  222. closeShopWindow(focus) --Even if it can not exist, we need to prevent it.
  223. self:updateFocus()
  224. end
  225. end
  226.  
  227. -- Returns the callback function with the specified id or nil if no such callback function exists.
  228. function NpcHandler:getCallback(id)
  229. local ret = nil
  230. if self.callbackFunctions ~= nil then
  231. ret = self.callbackFunctions[id]
  232. end
  233. return ret
  234. end
  235.  
  236. -- Changes the callback function for the given id to callback.
  237. function NpcHandler:setCallback(id, callback)
  238. if self.callbackFunctions ~= nil then
  239. self.callbackFunctions[id] = callback
  240. end
  241. end
  242.  
  243. -- Adds a module to this npchandler and inits it.
  244. function NpcHandler:addModule(module)
  245. if self.modules ~= nil then
  246. self.modules[#self.modules + 1] = module
  247. module:init(self)
  248. end
  249. end
  250.  
  251. -- Calls the callback function represented by id for all modules added to this npchandler with the given arguments.
  252. function NpcHandler:processModuleCallback(id, ...)
  253. local ret = true
  254. for _, module in pairs(self.modules) do
  255. local tmpRet = true
  256. if id == CALLBACK_CREATURE_APPEAR and module.callbackOnCreatureAppear ~= nil then
  257. tmpRet = module:callbackOnCreatureAppear(...)
  258. elseif id == CALLBACK_CREATURE_DISAPPEAR and module.callbackOnCreatureDisappear ~= nil then
  259. tmpRet = module:callbackOnCreatureDisappear(...)
  260. elseif id == CALLBACK_CREATURE_SAY and module.callbackOnCreatureSay ~= nil then
  261. tmpRet = module:callbackOnCreatureSay(...)
  262. elseif id == CALLBACK_PLAYER_ENDTRADE and module.callbackOnPlayerEndTrade ~= nil then
  263. tmpRet = module:callbackOnPlayerEndTrade(...)
  264. elseif id == CALLBACK_PLAYER_CLOSECHANNEL and module.callbackOnPlayerCloseChannel ~= nil then
  265. tmpRet = module:callbackOnPlayerCloseChannel(...)
  266. elseif id == CALLBACK_ONBUY and module.callbackOnBuy ~= nil then
  267. tmpRet = module:callbackOnBuy(...)
  268. elseif id == CALLBACK_ONSELL and module.callbackOnSell ~= nil then
  269. tmpRet = module:callbackOnSell(...)
  270. elseif id == CALLBACK_ONTRADEREQUEST and module.callbackOnTradeRequest ~= nil then
  271. tmpRet = module:callbackOnTradeRequest(...)
  272. elseif id == CALLBACK_ONADDFOCUS and module.callbackOnAddFocus ~= nil then
  273. tmpRet = module:callbackOnAddFocus(...)
  274. elseif id == CALLBACK_ONRELEASEFOCUS and module.callbackOnReleaseFocus ~= nil then
  275. tmpRet = module:callbackOnReleaseFocus(...)
  276. elseif id == CALLBACK_ONTHINK and module.callbackOnThink ~= nil then
  277. tmpRet = module:callbackOnThink(...)
  278. elseif id == CALLBACK_GREET and module.callbackOnGreet ~= nil then
  279. tmpRet = module:callbackOnGreet(...)
  280. elseif id == CALLBACK_FAREWELL and module.callbackOnFarewell ~= nil then
  281. tmpRet = module:callbackOnFarewell(...)
  282. elseif id == CALLBACK_MESSAGE_DEFAULT and module.callbackOnMessageDefault ~= nil then
  283. tmpRet = module:callbackOnMessageDefault(...)
  284. elseif id == CALLBACK_MODULE_RESET and module.callbackOnModuleReset ~= nil then
  285. tmpRet = module:callbackOnModuleReset(...)
  286. end
  287. if not tmpRet then
  288. ret = false
  289. break
  290. end
  291. end
  292. return ret
  293. end
  294.  
  295. -- Returns the message represented by id.
  296. function NpcHandler:getMessage(id)
  297. local ret = nil
  298. if self.messages ~= nil then
  299. ret = self.messages[id]
  300. end
  301. return ret
  302. end
  303.  
  304. -- Changes the default response message with the specified id to newMessage.
  305. function NpcHandler:setMessage(id, newMessage)
  306. if self.messages ~= nil then
  307. self.messages[id] = newMessage
  308. end
  309. end
  310.  
  311. -- Translates all message tags found in msg using parseInfo
  312. function NpcHandler:parseMessage(msg, parseInfo)
  313. local ret = msg
  314. if type(ret) == 'string' then
  315. for search, replace in pairs(parseInfo) do
  316. ret = string.gsub(ret, search, replace)
  317. end
  318. else
  319. for i = 1, #ret do
  320. for search, replace in pairs(parseInfo) do
  321. ret[i] = string.gsub(ret[i], search, replace)
  322. end
  323. end
  324. end
  325. return ret
  326. end
  327.  
  328. -- Makes sure the npc un-focuses the currently focused player
  329. function NpcHandler:unGreet(cid)
  330. if not self:isFocused(cid) then
  331. return
  332. end
  333.  
  334. local callback = self:getCallback(CALLBACK_FAREWELL)
  335. if callback == nil or callback() then
  336. if self:processModuleCallback(CALLBACK_FAREWELL) then
  337. local msg = self:getMessage(MESSAGE_FAREWELL)
  338. local player = Player(cid)
  339. local playerName = player and player:getName() or -1
  340. local parseInfo = { [TAG_PLAYERNAME] = playerName }
  341. self:resetNpc(cid)
  342. msg = self:parseMessage(msg, parseInfo)
  343. self:say(msg, cid, true)
  344. self:releaseFocus(cid)
  345. end
  346. end
  347. end
  348.  
  349. -- Greets a new player.
  350. function NpcHandler:greet(cid, message)
  351. if cid ~= 0 then
  352. local callback = self:getCallback(CALLBACK_GREET)
  353. if callback == nil or callback(cid, message) then
  354. if self:processModuleCallback(CALLBACK_GREET, cid) then
  355. local msg = self:getMessage(MESSAGE_GREET)
  356. local player = Player(cid)
  357. local playerName = player and player:getName() or -1
  358. local parseInfo = { [TAG_PLAYERNAME] = playerName }
  359. msg = self:parseMessage(msg, parseInfo)
  360. self:say(msg, cid, true)
  361. else
  362. return
  363. end
  364. else
  365. return
  366. end
  367. end
  368. self:addFocus(cid)
  369. end
  370.  
  371. -- Handles onCreatureAppear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_APPEAR callback.
  372. function NpcHandler:onCreatureAppear(creature)
  373. local cid = creature.uid
  374. if cid == getNpcCid() then
  375. local npc = Npc()
  376. if next(self.shopItems) then
  377. local speechBubble = npc:getSpeechBubble()
  378. if speechBubble == 3 then
  379. npc:setSpeechBubble(4)
  380. else
  381. npc:setSpeechBubble(2)
  382. end
  383. else
  384. if self:getMessage(MESSAGE_GREET) then
  385. npc:setSpeechBubble(1)
  386. end
  387. end
  388. end
  389.  
  390. local callback = self:getCallback(CALLBACK_CREATURE_APPEAR)
  391. if callback == nil or callback(cid) then
  392. if self:processModuleCallback(CALLBACK_CREATURE_APPEAR, cid) then
  393. --
  394. end
  395. end
  396. end
  397.  
  398. -- Handles onCreatureDisappear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_DISAPPEAR callback.
  399. function NpcHandler:onCreatureDisappear(creature)
  400. local cid = creature.uid
  401. if getNpcCid() == cid then
  402. return
  403. end
  404.  
  405. local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR)
  406. if callback == nil or callback(cid) then
  407. if self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid) then
  408. if self:isFocused(cid) then
  409. self:unGreet(cid)
  410. end
  411. end
  412. end
  413. end
  414.  
  415. -- Handles onCreatureSay events. If you with to handle this yourself, please use the CALLBACK_CREATURE_SAY callback.
  416. function NpcHandler:onCreatureSay(creature, msgtype, msg)
  417. local cid = creature.uid
  418. local callback = self:getCallback(CALLBACK_CREATURE_SAY)
  419. if callback == nil or callback(cid, msgtype, msg) then
  420. if self:processModuleCallback(CALLBACK_CREATURE_SAY, cid, msgtype, msg) then
  421. if not self:isInRange(cid) then
  422. return
  423. end
  424.  
  425. if self.keywordHandler ~= nil then
  426. if self:isFocused(cid) and msgtype == TALKTYPE_PRIVATE_PN or not self:isFocused(cid) then
  427. local ret = self.keywordHandler:processMessage(cid, msg)
  428. if not ret then
  429. local callback = self:getCallback(CALLBACK_MESSAGE_DEFAULT)
  430. if callback ~= nil and callback(cid, msgtype, msg) then
  431. self.talkStart[cid] = os.time()
  432. end
  433. else
  434. self.talkStart[cid] = os.time()
  435. end
  436. end
  437. end
  438. end
  439. end
  440. end
  441.  
  442. -- Handles onPlayerEndTrade events. If you wish to handle this yourself, use the CALLBACK_PLAYER_ENDTRADE callback.
  443. function NpcHandler:onPlayerEndTrade(creature)
  444. local cid = creature.uid
  445. local callback = self:getCallback(CALLBACK_PLAYER_ENDTRADE)
  446. if callback == nil or callback(cid) then
  447. if self:processModuleCallback(CALLBACK_PLAYER_ENDTRADE, cid, msgtype, msg) then
  448. if self:isFocused(cid) then
  449. local player = Player(cid)
  450. local playerName = player and player:getName() or -1
  451. local parseInfo = { [TAG_PLAYERNAME] = playerName }
  452. local msg = self:parseMessage(self:getMessage(MESSAGE_ONCLOSESHOP), parseInfo)
  453. self:say(msg, cid)
  454. end
  455. end
  456. end
  457. end
  458.  
  459. -- Handles onPlayerCloseChannel events. If you wish to handle this yourself, use the CALLBACK_PLAYER_CLOSECHANNEL callback.
  460. function NpcHandler:onPlayerCloseChannel(creature)
  461. local cid = creature.uid
  462. local callback = self:getCallback(CALLBACK_PLAYER_CLOSECHANNEL)
  463. if callback == nil or callback(cid) then
  464. if self:processModuleCallback(CALLBACK_PLAYER_CLOSECHANNEL, cid, msgtype, msg) then
  465. if self:isFocused(cid) then
  466. self:unGreet(cid)
  467. end
  468. end
  469. end
  470. end
  471.  
  472. -- Handles onBuy events. If you wish to handle this yourself, use the CALLBACK_ONBUY callback.
  473. function NpcHandler:onBuy(creature, itemid, subType, amount, ignoreCap, inBackpacks)
  474. local cid = creature.uid
  475. local callback = self:getCallback(CALLBACK_ONBUY)
  476. if callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks) then
  477. if self:processModuleCallback(CALLBACK_ONBUY, cid, itemid, subType, amount, ignoreCap, inBackpacks) then
  478. --
  479. end
  480. end
  481. end
  482.  
  483. -- Handles onSell events. If you wish to handle this yourself, use the CALLBACK_ONSELL callback.
  484. function NpcHandler:onSell(creature, itemid, subType, amount, ignoreCap, inBackpacks)
  485. local cid = creature.uid
  486. local callback = self:getCallback(CALLBACK_ONSELL)
  487. if callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks) then
  488. if self:processModuleCallback(CALLBACK_ONSELL, cid, itemid, subType, amount, ignoreCap, inBackpacks) then
  489. --
  490. end
  491. end
  492. end
  493.  
  494. -- Handles onTradeRequest events. If you wish to handle this yourself, use the CALLBACK_ONTRADEREQUEST callback.
  495. function NpcHandler:onTradeRequest(cid)
  496. local callback = self:getCallback(CALLBACK_ONTRADEREQUEST)
  497. if callback == nil or callback(cid) then
  498. if self:processModuleCallback(CALLBACK_ONTRADEREQUEST, cid) then
  499. return true
  500. end
  501. end
  502. return false
  503. end
  504.  
  505. -- Handles onThink events. If you wish to handle this yourself, please use the CALLBACK_ONTHINK callback.
  506. function NpcHandler:onThink()
  507. local callback = self:getCallback(CALLBACK_ONTHINK)
  508. if callback == nil or callback() then
  509. if NPCHANDLER_TALKDELAY == TALKDELAY_ONTHINK then
  510. for cid, talkDelay in pairs(self.talkDelay) do
  511. if talkDelay.time ~= nil and talkDelay.message ~= nil and os.time() >= talkDelay.time then
  512. selfSay(talkDelay.message, cid, talkDelay.publicize and true or false)
  513. self.talkDelay[cid] = nil
  514. end
  515. end
  516. end
  517.  
  518. if self:processModuleCallback(CALLBACK_ONTHINK) then
  519. for _, focus in pairs(self.focuses) do
  520. if focus ~= nil then
  521. if not self:isInRange(focus) then
  522. self:onWalkAway(focus)
  523. elseif self.talkStart[focus] ~= nil and (os.time() - self.talkStart[focus]) > self.idleTime then
  524. self:unGreet(focus)
  525. else
  526. self:updateFocus()
  527. end
  528. end
  529. end
  530. end
  531. end
  532. end
  533.  
  534. -- Tries to greet the player with the given cid.
  535. function NpcHandler:onGreet(cid, message)
  536. if self:isInRange(cid) then
  537. if not self:isFocused(cid) then
  538. self:greet(cid, message)
  539. return
  540. end
  541. end
  542. end
  543.  
  544. -- Simply calls the underlying unGreet function.
  545. function NpcHandler:onFarewell(cid)
  546. self:unGreet(cid)
  547. end
  548.  
  549. -- Should be called on this npc's focus if the distance to focus is greater then talkRadius.
  550. function NpcHandler:onWalkAway(cid)
  551. if self:isFocused(cid) then
  552. local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR)
  553. if callback == nil or callback() then
  554. if self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid) then
  555. local msg = self:getMessage(MESSAGE_WALKAWAY)
  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.  
  648. local player = Player(focusId)
  649. if player then
  650. local parseInfo = {[TAG_PLAYERNAME] = player:getName(), [TAG_TIME] = getTibianTime(), [TAG_BLESSCOST] = getBlessingsCost(player:getLevel()), [TAG_PVPBLESSCOST] = getPvpBlessingCost(player:getLevel())}
  651. npc:say(self:parseMessage(message, parseInfo), TALKTYPE_PRIVATE_NP, false, player, npc:getPosition())
  652. end
  653. end, self.talkDelayTime * 1000, Npc().uid, message, focus)
  654. end
  655. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement