Guest User

Untitled

a guest
Mar 18th, 2017
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 43.58 KB | None | 0 0
  1. -- Advanced NPC System by Jiddo
  2.  
  3. if Modules == nil then
  4. -- default words for greeting and ungreeting the npc. Should be a table containing all such words.
  5. FOCUS_GREETWORDS = {"hi", "hello"}
  6. FOCUS_FAREWELLWORDS = {"bye", "farewell"}
  7.  
  8. -- The words for requesting trade window.
  9. SHOP_TRADEREQUEST = {"trade"}
  10.  
  11. -- The word for accepting/declining an offer. CAN ONLY CONTAIN ONE FIELD! Should be a table with a single string value.
  12. SHOP_YESWORD = {"yes"}
  13. SHOP_NOWORD = {"no"}
  14.  
  15. -- Pattern used to get the amount of an item a player wants to buy/sell.
  16. PATTERN_COUNT = "%d+"
  17.  
  18. -- Constants used to separate buying from selling.
  19. SHOPMODULE_SELL_ITEM = 1
  20. SHOPMODULE_BUY_ITEM = 2
  21. SHOPMODULE_BUY_ITEM_CONTAINER = 3
  22.  
  23. -- Constants used for shop mode. Notice: addBuyableItemContainer is working on all modes
  24. SHOPMODULE_MODE_TALK = 1 -- Old system used before client version 8.2: sell/buy item name
  25. SHOPMODULE_MODE_TRADE = 2 -- Trade window system introduced in client version 8.2
  26. SHOPMODULE_MODE_BOTH = 3 -- Both working at one time
  27.  
  28. -- Used shop mode
  29. SHOPMODULE_MODE = SHOPMODULE_MODE_BOTH
  30.  
  31. Modules = {
  32. parseableModules = {}
  33. }
  34.  
  35. StdModule = {}
  36.  
  37. -- These callback function must be called with parameters.npcHandler = npcHandler in the parameters table or they will not work correctly.
  38. -- Notice: The members of StdModule have not yet been tested. If you find any bugs, please report them to me.
  39. -- Usage:
  40. -- keywordHandler:addKeyword({"offer"}, StdModule.say, {npcHandler = npcHandler, text = "I sell many powerful melee weapons."})
  41. function StdModule.say(cid, message, keywords, parameters, node)
  42. local npcHandler = parameters.npcHandler
  43. if npcHandler == nil then
  44. error("StdModule.say called without any npcHandler instance.")
  45. end
  46.  
  47. if parameters.onlyFocus == true and parameters.onlyUnfocus == true then
  48. error("StdModule.say conflicting parameters 'onlyFocus' and 'onlyUnfocus' both true")
  49. end
  50.  
  51. local onlyFocus = (parameters.onlyFocus == nil and parameters.onlyUnfocus == nil or parameters.onlyFocus == true)
  52. if not npcHandler:isFocused(cid) and onlyFocus then
  53. return false
  54. end
  55.  
  56. if npcHandler:isFocused(cid) and parameters.onlyUnfocus == true then
  57. return false
  58. end
  59.  
  60. local player = Player(cid)
  61. local cost, costMessage = parameters.cost, '%d gold coins'
  62. if cost and cost > 0 then
  63. if parameters.discount then
  64. cost = cost - StdModule.travelDiscount(player, parameters.discount)
  65. end
  66.  
  67. costMessage = cost > 0 and string.format(costMessage, cost) or 'free'
  68. else
  69. costMessage = 'free'
  70. end
  71.  
  72. local parseInfo = {[TAG_PLAYERNAME] = player:getName(), [TAG_TIME] = getTibianTime(), [TAG_BLESSCOST] = getBlessingsCost(player:getLevel()), [TAG_PVPBLESSCOST] = getPvpBlessingCost(player:getLevel()), [TAG_TRAVELCOST] = costMessage}
  73. if parameters.text then
  74. npcHandler:say(npcHandler:parseMessage(parameters.text, parseInfo), cid, parameters.publicize and true)
  75. end
  76.  
  77. if parameters.ungreet then
  78. npcHandler:resetNpc(cid)
  79. npcHandler:releaseFocus(cid)
  80. elseif parameters.reset then
  81. npcHandler:resetNpc(cid)
  82. elseif parameters.moveup ~= nil then
  83. npcHandler.keywordHandler:moveUp(cid, parameters.moveup)
  84. end
  85.  
  86. return true
  87. end
  88.  
  89. --Usage:
  90. -- local node1 = keywordHandler:addKeyword({"promot"}, StdModule.say, {npcHandler = npcHandler, text = "I can promote you for 20000 gold coins. Do you want me to promote you?"})
  91. -- node1:addChildKeyword({"yes"}, StdModule.promotePlayer, {npcHandler = npcHandler, cost = 20000, level = 20}, text = "Congratulations! You are now promoted.")
  92. -- node1:addChildKeyword({"no"}, StdModule.say, {npcHandler = npcHandler, text = "Allright then. Come back when you are ready."}, reset = true)
  93. function StdModule.promotePlayer(cid, message, keywords, parameters, node)
  94. local npcHandler = parameters.npcHandler
  95. if npcHandler == nil then
  96. error("StdModule.promotePlayer called without any npcHandler instance.")
  97. end
  98. if not npcHandler:isFocused(cid) then
  99. return false
  100. end
  101.  
  102. local player = Player(cid)
  103. if player:isPremium() then
  104. if player:getStorageValue(Storage.Promotion) == 1 then
  105. npcHandler:say("You are already promoted!", cid)
  106. elseif player:getLevel() < parameters.level then
  107. npcHandler:say("I am sorry, but I can only promote you once you have reached level " .. parameters.level .. ".", cid)
  108. elseif not player:removeMoney(parameters.cost) then
  109. npcHandler:say("You do not have enough money!", cid)
  110. else
  111. player:setStorageValue(Storage.Promotion, 1)
  112. player:setVocation(player:getVocation():getPromotion())
  113. player:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
  114. npcHandler:say(parameters.text or "Congratulations! You are now promoted.", cid)
  115. end
  116. else
  117. npcHandler:say("You need a premium account in order to get promoted.", cid)
  118. end
  119. npcHandler:resetNpc(cid)
  120. return true
  121. end
  122.  
  123. function StdModule.learnSpell(cid, message, keywords, parameters, node)
  124. local npcHandler = parameters.npcHandler
  125. if npcHandler == nil then
  126. error("StdModule.learnSpell called without any npcHandler instance.")
  127. end
  128.  
  129. if not npcHandler:isFocused(cid) then
  130. return false
  131. end
  132.  
  133. local player = Player(cid)
  134. if player:hasLearnedSpell(parameters.spellName) then
  135. npcHandler:say("You already know how to cast this spell.", cid)
  136. elseif player:getLevel() < parameters.level then
  137. npcHandler:say("You have to be level " .. parameters.level .. " to learn this spell.", cid)
  138. elseif not player:removeMoney(parameters.price) then
  139. npcHandler:say("Return when you have enough gold.", cid)
  140. else
  141. npcHandler:say("Here you are. Look in your spellbook for the pronunciation of this spell.", cid)
  142. player:learnSpell(parameters.spellName)
  143. player:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
  144. end
  145.  
  146. npcHandler:resetNpc(cid)
  147. return true
  148. end
  149.  
  150. function StdModule.bless(cid, message, keywords, parameters, node)
  151. local npcHandler = parameters.npcHandler
  152. if npcHandler == nil then
  153. error("StdModule.bless called without any npcHandler instance.")
  154. end
  155.  
  156. if not npcHandler:isFocused(cid) then
  157. return false
  158. end
  159.  
  160. local player = Player(cid)
  161. local parseInfo = {[TAG_BLESSCOST] = getBlessingsCost(player:getLevel()), [TAG_PVPBLESSCOST] = getPvpBlessingCost(player:getLevel())}
  162. if player:hasBlessing(parameters.bless) then
  163. npcHandler:say("You already possess this blessing.", cid)
  164. elseif parameters.bless == 4 and player:getStorageValue(Storage.KawillBlessing) ~= 1 then
  165. npcHandler:say("You need the blessing of the great geomancer first.", cid)
  166. elseif parameters.bless == 6 and player:getBlessings() == 0 and not player:getItemById(2173, true) then
  167. npcHandler:say("You don't have any of the other blessings nor an amulet of loss, so it wouldn't make sense to bestow this protection on you now. Remember that it can only protect you from the loss of those!", cid)
  168. elseif not player:removeMoney(type(parameters.cost) == "string" and npcHandler:parseMessage(parameters.cost, parseInfo) or parameters.cost) then
  169. npcHandler:say("Oh. You do not have enough money.", cid)
  170. else
  171. npcHandler:say(parameters.text or "You have been blessed by one of the five gods!", cid)
  172. if parameters.bless == 4 then
  173. player:setStorageValue(Storage.KawillBlessing, 0)
  174. end
  175. player:addBlessing(parameters.bless)
  176. player:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
  177. end
  178.  
  179. npcHandler:resetNpc(cid)
  180. return true
  181. end
  182.  
  183. function StdModule.travel(cid, message, keywords, parameters, node)
  184. local npcHandler = parameters.npcHandler
  185. if npcHandler == nil then
  186. error("StdModule.travel called without any npcHandler instance.")
  187. end
  188.  
  189. if not npcHandler:isFocused(cid) then
  190. return false
  191. end
  192.  
  193. local player = Player(cid)
  194. local cost = parameters.cost
  195. if cost and cost > 0 then
  196. if parameters.discount then
  197. cost = cost - StdModule.travelDiscount(player, parameters.discount)
  198.  
  199. if cost < 0 then
  200. cost = 0
  201. end
  202. end
  203. else
  204. cost = 0
  205. end
  206.  
  207. local exhausts
  208.  
  209. if parameters.premium and not player:isPremium() then
  210. npcHandler:say("I'm sorry, but you need a premium account in order to travel onboard our ships.", cid)
  211. elseif parameters.level and player:getLevel() < parameters.level then
  212. npcHandler:say("You must reach level " .. parameters.level .. " before I can let you go there.", cid)
  213. elseif player:isPzLocked() then
  214. npcHandler:say("First get rid of those blood stains! You are not going to ruin my vehicle!", cid)
  215. elseif not player:removeMoney(cost) then
  216. npcHandler:say("You don't have enough money.", cid)
  217.  
  218. -- EU ADD AQUI
  219. elseif os.time() < getPlayerStorageValue(cid, exhausts) then
  220. npcHandler:say('Sorry, but you need to wait three seconds before travel again.', cid)
  221. player:getPosition():sendMagicEffect(CONST_ME_POFF)
  222. -- EU ADD FIM AQUI
  223. else
  224. npcHandler:releaseFocus(cid)
  225. npcHandler:say(parameters.text or "Set the sails!", cid)
  226. player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
  227.  
  228. local destination = parameters.destination
  229. if type(destination) == 'function' then
  230. destination = destination(player)
  231. end
  232.  
  233. --[[ ANTI NUKER TRAVEL
  234.  
  235. local exhausts = 2
  236. if os.time() > getPlayerStorageValue(cid, exhausts) then
  237. player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
  238. player:teleportTo(destination)
  239. Position(destination):sendMagicEffect(CONST_ME_TELEPORT)
  240. setPlayerStorageValue(cid, exhausts, 2 + os.time())
  241. else
  242. npcHandler:say('Sorry, but you need to wait two seconds before travel again.', cid)
  243. end
  244.  
  245.  
  246. ]]-- ANTI NUKER TRAVEL
  247. setPlayerStorageValue(cid, exhausts, 3 + os.time())
  248. player:teleportTo(destination)
  249. destination:sendMagicEffect(CONST_ME_TELEPORT)
  250.  
  251. -- What a foolish Quest - Mission 3
  252. if player:getStorageValue(Storage.WhatAFoolishQuest.PieBoxTimer) > os.time() then
  253. if destination ~= Position(32660, 31957, 15) then -- kazordoon steamboat
  254. player:setStorageValue(Storage.WhatAFoolishQuest.PieBoxTimer, 1)
  255. end
  256. end
  257. end
  258.  
  259. npcHandler:resetNpc(cid)
  260. return true
  261. end
  262.  
  263. FocusModule = {
  264. npcHandler = nil,
  265. greetWords = nil,
  266. farewellWords = nil,
  267. greetCallback = nil,
  268. farewellCallback = nil
  269. }
  270.  
  271. -- Creates a new instance of FocusModule without an associated NpcHandler.
  272. function FocusModule:new()
  273. local obj = {}
  274. setmetatable(obj, self)
  275. self.__index = self
  276. return obj
  277. end
  278.  
  279. -- Inits the module and associates handler to it.
  280. function FocusModule:init(handler)
  281. self.npcHandler = handler
  282.  
  283. local greetWords = self.greetWords or FOCUS_GREETWORDS
  284. for _, word in pairs(greetWords) do
  285. local obj = {}
  286. obj[#obj + 1] = word
  287. obj.callback = self.greetCallback or FocusModule.messageMatcherDefault
  288. handler.keywordHandler:addKeyword(obj, FocusModule.onGreet, {module = self})
  289. end
  290.  
  291. local farewellWords = self.farewellWords or FOCUS_FAREWELLWORDS
  292. for _, word in pairs(farewellWords) do
  293. local obj = {}
  294. obj[#obj + 1] = word
  295. obj.callback = self.farewellCallback or FocusModule.messageMatcherDefault
  296. handler.keywordHandler:addKeyword(obj, FocusModule.onFarewell, {module = self})
  297. end
  298.  
  299. return true
  300. end
  301.  
  302. -- Set custom greeting messages
  303. function FocusModule:addGreetMessage(message)
  304. if not self.greetWords then
  305. self.greetWords = {}
  306. end
  307.  
  308.  
  309. if type(message) == 'string' then
  310. table.insert(self.greetWords, message)
  311. else
  312. for i = 1, #message do
  313. table.insert(self.greetWords, message[i])
  314. end
  315. end
  316. end
  317.  
  318. -- Set custom farewell messages
  319. function FocusModule:addFarewellMessage(message)
  320. if not self.farewellWords then
  321. self.farewellWords = {}
  322. end
  323.  
  324. if type(message) == 'string' then
  325. table.insert(self.farewellWords, message)
  326. else
  327. for i = 1, #message do
  328. table.insert(self.farewellWords, message[i])
  329. end
  330. end
  331. end
  332.  
  333. -- Set custom greeting callback
  334. function FocusModule:setGreetCallback(callback)
  335. self.greetCallback = callback
  336. end
  337.  
  338. -- Set custom farewell callback
  339. function FocusModule:setFarewellCallback(callback)
  340. self.farewellCallback = callback
  341. end
  342.  
  343. -- Greeting callback function.
  344. function FocusModule.onGreet(cid, message, keywords, parameters)
  345. parameters.module.npcHandler:onGreet(cid, message)
  346. return true
  347. end
  348.  
  349. -- UnGreeting callback function.
  350. function FocusModule.onFarewell(cid, message, keywords, parameters)
  351. if parameters.module.npcHandler:isFocused(cid) then
  352. parameters.module.npcHandler:onFarewell(cid)
  353. return true
  354. else
  355. return false
  356. end
  357. end
  358.  
  359. -- Custom message matching callback function for greeting messages.
  360. function FocusModule.messageMatcherDefault(keywords, message)
  361. for _, word in pairs(keywords) do
  362. if type(word) == "string" then
  363. if string.find(message, word) and not string.find(message, "[%w+]" .. word) and not string.find(message, word .. "[%w+]") then
  364. return true
  365. end
  366. end
  367. end
  368. return false
  369. end
  370.  
  371. function FocusModule.messageMatcherStart(keywords, message)
  372. for _, word in pairs(keywords) do
  373. if type(word) == "string" then
  374. if string.starts(message, word) then
  375. return true
  376. end
  377. end
  378. end
  379. return false
  380. end
  381.  
  382. KeywordModule = {
  383. npcHandler = nil
  384. }
  385. -- Add it to the parseable module list.
  386. Modules.parseableModules["module_keywords"] = KeywordModule
  387.  
  388. function KeywordModule:new()
  389. local obj = {}
  390. setmetatable(obj, self)
  391. self.__index = self
  392. return obj
  393. end
  394.  
  395. function KeywordModule:init(handler)
  396. self.npcHandler = handler
  397. return true
  398. end
  399.  
  400. -- Parses all known parameters.
  401. function KeywordModule:parseParameters()
  402. local ret = NpcSystem.getParameter("keywords")
  403. if ret ~= nil then
  404. self:parseKeywords(ret)
  405. end
  406. end
  407.  
  408. function KeywordModule:parseKeywords(data)
  409. local n = 1
  410. for keys in string.gmatch(data, "[^;]+") do
  411. local i = 1
  412.  
  413. local keywords = {}
  414. for temp in string.gmatch(keys, "[^,]+") do
  415. keywords[#keywords + 1] = temp
  416. i = i + 1
  417. end
  418.  
  419. if i ~= 1 then
  420. local reply = NpcSystem.getParameter("keyword_reply" .. n)
  421. if reply ~= nil then
  422. self:addKeyword(keywords, reply)
  423. else
  424. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter '" .. "keyword_reply" .. n .. "' missing. Skipping...")
  425. end
  426. else
  427. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "No keywords found for keyword set #" .. n .. ". Skipping...")
  428. end
  429.  
  430. n = n + 1
  431. end
  432. end
  433.  
  434. function KeywordModule:addKeyword(keywords, reply)
  435. self.npcHandler.keywordHandler:addKeyword(keywords, StdModule.say, {npcHandler = self.npcHandler, text = reply, reset = true})
  436. end
  437.  
  438. TravelModule = {
  439. npcHandler = nil,
  440. destinations = nil,
  441. yesNode = nil,
  442. noNode = nil,
  443. }
  444.  
  445. -- Add it to the parseable module list.
  446. Modules.parseableModules["module_travel"] = TravelModule
  447.  
  448. function TravelModule:new()
  449. local obj = {}
  450. setmetatable(obj, self)
  451. self.__index = self
  452. return obj
  453. end
  454.  
  455. function TravelModule:init(handler)
  456. self.npcHandler = handler
  457. self.yesNode = KeywordNode:new(SHOP_YESWORD, TravelModule.onConfirm, {module = self})
  458. self.noNode = KeywordNode:new(SHOP_NOWORD, TravelModule.onDecline, {module = self})
  459. self.destinations = {}
  460. return true
  461. end
  462.  
  463. -- Parses all known parameters.
  464. function TravelModule:parseParameters()
  465. local ret = NpcSystem.getParameter("travel_destinations")
  466. if ret ~= nil then
  467. self:parseDestinations(ret)
  468.  
  469. self.npcHandler.keywordHandler:addKeyword({"destination"}, TravelModule.listDestinations, {module = self})
  470. self.npcHandler.keywordHandler:addKeyword({"where"}, TravelModule.listDestinations, {module = self})
  471. self.npcHandler.keywordHandler:addKeyword({"travel"}, TravelModule.listDestinations, {module = self})
  472.  
  473. end
  474. end
  475.  
  476. function TravelModule:parseDestinations(data)
  477. for destination in string.gmatch(data, "[^;]+") do
  478. local i = 1
  479.  
  480. local name = nil
  481. local x = nil
  482. local y = nil
  483. local z = nil
  484. local cost = nil
  485. local premium = false
  486.  
  487. for temp in string.gmatch(destination, "[^,]+") do
  488. if i == 1 then
  489. name = temp
  490. elseif i == 2 then
  491. x = tonumber(temp)
  492. elseif i == 3 then
  493. y = tonumber(temp)
  494. elseif i == 4 then
  495. z = tonumber(temp)
  496. elseif i == 5 then
  497. cost = tonumber(temp)
  498. elseif i == 6 then
  499. premium = temp == "true"
  500. else
  501. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Unknown parameter found in travel destination parameter.", temp, destination)
  502. end
  503. i = i + 1
  504. end
  505.  
  506. if name ~= nil and x ~= nil and y ~= nil and z ~= nil and cost ~= nil then
  507. self:addDestination(name, {x=x, y=y, z=z}, cost, premium)
  508. else
  509. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for travel destination:", name, x, y, z, cost, premium)
  510. end
  511. end
  512. end
  513.  
  514. function TravelModule:addDestination(name, position, price, premium)
  515. self.destinations[#self.destinations + 1] = name
  516.  
  517. local parameters = {
  518. cost = price,
  519. destination = position,
  520. premium = premium,
  521. module = self
  522. }
  523. local keywords = {}
  524. keywords[#keywords + 1] = name
  525.  
  526. local keywords2 = {}
  527. keywords2[#keywords2 + 1] = "bring me to " .. name
  528. local node = self.npcHandler.keywordHandler:addKeyword(keywords, TravelModule.travel, parameters)
  529. self.npcHandler.keywordHandler:addKeyword(keywords2, TravelModule.bringMeTo, parameters)
  530. node:addChildKeywordNode(self.yesNode)
  531. node:addChildKeywordNode(self.noNode)
  532.  
  533. if npcs_loaded_travel[getNpcCid()] == nil then
  534. npcs_loaded_travel[getNpcCid()] = getNpcCid()
  535. self.npcHandler.keywordHandler:addKeyword({'yes'}, TravelModule.onConfirm, {module = self})
  536. self.npcHandler.keywordHandler:addKeyword({'no'}, TravelModule.onDecline, {module = self})
  537. end
  538. end
  539.  
  540. function TravelModule.travel(cid, message, keywords, parameters, node)
  541. local module = parameters.module
  542. if not module.npcHandler:isFocused(cid) then
  543. return false
  544. end
  545.  
  546. local npcHandler = module.npcHandler
  547.  
  548. shop_destination[cid] = parameters.destination
  549. shop_cost[cid] = parameters.cost
  550. shop_premium[cid] = parameters.premium
  551. shop_npcuid[cid] = getNpcCid()
  552.  
  553. local cost = parameters.cost
  554. local destination = parameters.destination
  555. local premium = parameters.premium
  556.  
  557. module.npcHandler:say("Do you want to travel to " .. keywords[1] .. " for " .. cost .. " gold coins?", cid)
  558. return true
  559. end
  560.  
  561. function TravelModule.onConfirm(cid, message, keywords, parameters, node)
  562. local module = parameters.module
  563. if not module.npcHandler:isFocused(cid) then
  564. return false
  565. end
  566.  
  567. if shop_npcuid[cid] ~= getNpcCid() then
  568. return false
  569. end
  570.  
  571. local npcHandler = module.npcHandler
  572.  
  573. local parentParameters = node:getParent():getParameters()
  574. local cost = shop_cost[cid]
  575. local destination = shop_destination[cid]
  576. local premium = shop_premium[cid]
  577.  
  578. local player = Player(cid)
  579. if not isPlayerPremiumCallback or isPlayerPremiumCallback(player) or shop_premium[cid] ~= true then
  580. if not player:removeMoney(cost) then
  581. npcHandler:say("You do not have enough money!", cid)
  582. elseif player:isPzLocked() then
  583. npcHandler:say("Get out of there with this blood.", cid)
  584. else
  585. npcHandler:say("It was a pleasure doing business with you.", cid)
  586. npcHandler:releaseFocus(cid)
  587. -- Todo convert all destionation parameters to Position(x, y, z) instead of lua tables
  588. player:teleportTo(destination)
  589. Position(destination):sendMagicEffect(CONST_ME_TELEPORT)
  590. end
  591. else
  592. npcHandler:say("I can only allow premium players to travel there.", cid)
  593. end
  594.  
  595. npcHandler:resetNpc(cid)
  596. return true
  597. end
  598.  
  599. -- onDecline keyword callback function. Generally called when the player sais "no" after wanting to buy an item.
  600. function TravelModule.onDecline(cid, message, keywords, parameters, node)
  601. local module = parameters.module
  602. if not module.npcHandler:isFocused(cid) or shop_npcuid[cid] ~= getNpcCid() then
  603. return false
  604. end
  605. local parentParameters = node:getParent():getParameters()
  606. local parseInfo = { [TAG_PLAYERNAME] = Player(cid):getName() }
  607. local msg = module.npcHandler:parseMessage(module.npcHandler:getMessage(MESSAGE_DECLINE), parseInfo)
  608. module.npcHandler:say(msg, cid)
  609. module.npcHandler:resetNpc(cid)
  610. return true
  611. end
  612.  
  613. function TravelModule.bringMeTo(cid, message, keywords, parameters, node)
  614. local module = parameters.module
  615. if not module.npcHandler:isFocused(cid) then
  616. return false
  617. end
  618.  
  619. local cost = parameters.cost
  620. local destination = parameters.destination
  621. local premium = parameters.premium
  622.  
  623. if(not isPlayerPremiumCallback or isPlayerPremiumCallback(cid) or parameters.premium ~= true) then
  624. local player = Player(cid)
  625. if player:removeMoney(cost) then
  626. player:teleportTo(destination)
  627. Position(destination):sendMagicEffect(CONST_ME_TELEPORT)
  628. end
  629. end
  630. return true
  631. end
  632.  
  633. function TravelModule.listDestinations(cid, message, keywords, parameters, node)
  634. local module = parameters.module
  635. if not module.npcHandler:isFocused(cid) then
  636. return false
  637. end
  638.  
  639. local msg = "I can bring you to "
  640. --local i = 1
  641. local maxn = #module.destinations
  642. for i, destination in pairs(module.destinations) do
  643. msg = msg .. destination
  644. if i == maxn - 1 then
  645. msg = msg .. " and "
  646. elseif i == maxn then
  647. msg = msg .. "."
  648. else
  649. msg = msg .. ", "
  650. end
  651. i = i + 1
  652. end
  653.  
  654. module.npcHandler:say(msg, cid)
  655. module.npcHandler:resetNpc(cid)
  656. return true
  657. end
  658.  
  659. ShopModule = {
  660. npcHandler = nil,
  661. yesNode = nil,
  662. noNode = nil,
  663. noText = "",
  664. maxCount = 100,
  665. amount = 0
  666. }
  667.  
  668. -- Add it to the parseable module list.
  669. Modules.parseableModules["module_shop"] = ShopModule
  670.  
  671. -- Creates a new instance of ShopModule
  672. function ShopModule:new()
  673. local obj = {}
  674. setmetatable(obj, self)
  675. self.__index = self
  676. return obj
  677. end
  678.  
  679. -- Parses all known parameters.
  680. function ShopModule:parseParameters()
  681. local ret = NpcSystem.getParameter("shop_buyable")
  682. if ret ~= nil then
  683. self:parseBuyable(ret)
  684. end
  685.  
  686. local ret = NpcSystem.getParameter("shop_sellable")
  687. if ret ~= nil then
  688. self:parseSellable(ret)
  689. end
  690.  
  691. local ret = NpcSystem.getParameter("shop_buyable_containers")
  692. if ret ~= nil then
  693. self:parseBuyableContainers(ret)
  694. end
  695. end
  696.  
  697. -- Parse a string contaning a set of buyable items.
  698. function ShopModule:parseBuyable(data)
  699. for item in string.gmatch(data, "[^;]+") do
  700. local i = 1
  701.  
  702. local name = nil
  703. local itemid = nil
  704. local cost = nil
  705. local subType = nil
  706. local realName = nil
  707.  
  708. for temp in string.gmatch(item, "[^,]+") do
  709. if i == 1 then
  710. name = temp
  711. elseif i == 2 then
  712. itemid = tonumber(temp)
  713. elseif i == 3 then
  714. cost = tonumber(temp)
  715. elseif i == 4 then
  716. subType = tonumber(temp)
  717. elseif i == 5 then
  718. realName = temp
  719. else
  720. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Unknown parameter found in buyable items parameter.", temp, item)
  721. end
  722. i = i + 1
  723. end
  724.  
  725. if SHOPMODULE_MODE == SHOPMODULE_MODE_TRADE then
  726. if itemid ~= nil and cost ~= nil then
  727. if subType == nil and ItemType(itemid):isFluidContainer() then
  728. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "SubType missing for parameter item:", item)
  729. else
  730. self:addBuyableItem(nil, itemid, cost, subType, realName)
  731. end
  732. else
  733. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", itemid, cost)
  734. end
  735. else
  736. if name ~= nil and itemid ~= nil and cost ~= nil then
  737. if subType == nil and ItemType(itemid):isFluidContainer() then
  738. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "SubType missing for parameter item:", item)
  739. else
  740. local names = {}
  741. names[#names + 1] = name
  742. self:addBuyableItem(names, itemid, cost, subType, realName)
  743. end
  744. else
  745. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", name, itemid, cost)
  746. end
  747. end
  748. end
  749. end
  750.  
  751. -- Parse a string contaning a set of sellable items.
  752. function ShopModule:parseSellable(data)
  753. for item in string.gmatch(data, "[^;]+") do
  754. local i = 1
  755.  
  756. local name = nil
  757. local itemid = nil
  758. local cost = nil
  759. local realName = nil
  760. local subType = nil
  761.  
  762. for temp in string.gmatch(item, "[^,]+") do
  763. if i == 1 then
  764. name = temp
  765. elseif i == 2 then
  766. itemid = tonumber(temp)
  767. elseif i == 3 then
  768. cost = tonumber(temp)
  769. elseif i == 4 then
  770. realName = temp
  771. elseif i == 5 then
  772. subType = tonumber(temp)
  773. else
  774. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Unknown parameter found in sellable items parameter.", temp, item)
  775. end
  776. i = i + 1
  777. end
  778.  
  779. if SHOPMODULE_MODE == SHOPMODULE_MODE_TRADE then
  780. if itemid ~= nil and cost ~= nil then
  781. self:addSellableItem(nil, itemid, cost, realName, subType)
  782. else
  783. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", itemid, cost)
  784. end
  785. else
  786. if name ~= nil and itemid ~= nil and cost ~= nil then
  787. local names = {}
  788. names[#names + 1] = name
  789. self:addSellableItem(names, itemid, cost, realName, subType)
  790. else
  791. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", name, itemid, cost)
  792. end
  793. end
  794. end
  795. end
  796.  
  797. -- Parse a string contaning a set of buyable items.
  798. function ShopModule:parseBuyableContainers(data)
  799. for item in string.gmatch(data, "[^;]+") do
  800. local i = 1
  801.  
  802. local name = nil
  803. local container = nil
  804. local itemid = nil
  805. local cost = nil
  806. local subType = nil
  807. local realName = nil
  808.  
  809. for temp in string.gmatch(item, "[^,]+") do
  810. if i == 1 then
  811. name = temp
  812. elseif i == 2 then
  813. itemid = tonumber(temp)
  814. elseif i == 3 then
  815. itemid = tonumber(temp)
  816. elseif i == 4 then
  817. cost = tonumber(temp)
  818. elseif i == 5 then
  819. subType = tonumber(temp)
  820. elseif i == 6 then
  821. realName = temp
  822. else
  823. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Unknown parameter found in buyable items parameter.", temp, item)
  824. end
  825. i = i + 1
  826. end
  827.  
  828. if name ~= nil and container ~= nil and itemid ~= nil and cost ~= nil then
  829. if subType == nil and ItemType(itemid):isFluidContainer() then
  830. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "SubType missing for parameter item:", item)
  831. else
  832. local names = {}
  833. names[#names + 1] = name
  834. self:addBuyableItemContainer(names, container, itemid, cost, subType, realName)
  835. end
  836. else
  837. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", name, container, itemid, cost)
  838. end
  839. end
  840. end
  841.  
  842. -- Initializes the module and associates handler to it.
  843. function ShopModule:init(handler)
  844. self.npcHandler = handler
  845. self.yesNode = KeywordNode:new(SHOP_YESWORD, ShopModule.onConfirm, {module = self})
  846. self.noNode = KeywordNode:new(SHOP_NOWORD, ShopModule.onDecline, {module = self})
  847. self.noText = handler:getMessage(MESSAGE_DECLINE)
  848.  
  849. if SHOPMODULE_MODE ~= SHOPMODULE_MODE_TALK then
  850. for _, word in pairs(SHOP_TRADEREQUEST) do
  851. local obj = {}
  852. obj[#obj + 1] = word
  853. obj.callback = SHOP_TRADEREQUEST.callback or ShopModule.messageMatcher
  854. handler.keywordHandler:addKeyword(obj, ShopModule.requestTrade, {module = self})
  855. end
  856. end
  857.  
  858. return true
  859. end
  860.  
  861. -- Custom message matching callback function for requesting trade messages.
  862. function ShopModule.messageMatcher(keywords, message)
  863. for _, word in pairs(keywords) do
  864. if type(word) == "string" then
  865. if string.find(message, word) and not string.find(message, "[%w+]" .. word) and not string.find(message, word .. "[%w+]") then
  866. return true
  867. end
  868. end
  869. end
  870.  
  871. return false
  872. end
  873.  
  874. -- Resets the module-specific variables.
  875. function ShopModule:reset()
  876. self.amount = 0
  877. end
  878.  
  879. -- Function used to match a number value from a string.
  880. function ShopModule:getCount(message)
  881. local ret = 1
  882. local b, e = string.find(message, PATTERN_COUNT)
  883. if b ~= nil and e ~= nil then
  884. ret = tonumber(string.sub(message, b, e))
  885. end
  886.  
  887. if ret <= 0 then
  888. ret = 1
  889. elseif ret > self.maxCount then
  890. ret = self.maxCount
  891. end
  892.  
  893. return ret
  894. end
  895.  
  896. -- Adds a new buyable item.
  897. -- names = A table containing one or more strings of alternative names to this item. Used only for old buy/sell system.
  898. -- itemid = The itemid of the buyable item
  899. -- cost = The price of one single item
  900. -- subType - The subType of each rune or fluidcontainer item. Can be left out if it is not a rune/fluidcontainer. Default value is 1.
  901. -- realName - The real, full name for the item. Will be used as ITEMNAME in MESSAGE_ONBUY and MESSAGE_ONSELL if defined. Default value is nil (getName will be used)
  902. function ShopModule:addBuyableItem(names, itemid, cost, itemSubType, realName)
  903. if SHOPMODULE_MODE ~= SHOPMODULE_MODE_TALK then
  904. if itemSubType == nil then
  905. itemSubType = 1
  906. end
  907.  
  908. local shopItem = self:getShopItem(itemid, itemSubType)
  909. if shopItem == nil then
  910. self.npcHandler.shopItems[#self.npcHandler.shopItems + 1] = {id = itemid, buy = cost, sell = -1, subType = itemSubType, name = realName or ItemType(itemid):getName()}
  911. else
  912. shopItem.buy = cost
  913. end
  914. end
  915.  
  916. if names ~= nil and SHOPMODULE_MODE ~= SHOPMODULE_MODE_TRADE then
  917. for _, name in pairs(names) do
  918. local parameters = {
  919. itemid = itemid,
  920. cost = cost,
  921. eventType = SHOPMODULE_BUY_ITEM,
  922. module = self,
  923. realName = realName or ItemType(itemid):getName(),
  924. subType = itemSubType or 1
  925. }
  926.  
  927. keywords = {}
  928. keywords[#keywords + 1] = "buy"
  929. keywords[#keywords + 1] = name
  930. local node = self.npcHandler.keywordHandler:addKeyword(keywords, ShopModule.tradeItem, parameters)
  931. node:addChildKeywordNode(self.yesNode)
  932. node:addChildKeywordNode(self.noNode)
  933. end
  934. end
  935.  
  936. if npcs_loaded_shop[getNpcCid()] == nil then
  937. npcs_loaded_shop[getNpcCid()] = getNpcCid()
  938. self.npcHandler.keywordHandler:addKeyword({'yes'}, ShopModule.onConfirm, {module = self})
  939. self.npcHandler.keywordHandler:addKeyword({'no'}, ShopModule.onDecline, {module = self})
  940. end
  941. end
  942.  
  943. function ShopModule:getShopItem(itemId, itemSubType)
  944. if ItemType(itemId):isFluidContainer() then
  945. for i = 1, #self.npcHandler.shopItems do
  946. local shopItem = self.npcHandler.shopItems[i]
  947. if shopItem.id == itemId and shopItem.subType == itemSubType then
  948. return shopItem
  949. end
  950. end
  951. else
  952. for i = 1, #self.npcHandler.shopItems do
  953. local shopItem = self.npcHandler.shopItems[i]
  954. if shopItem.id == itemId then
  955. return shopItem
  956. end
  957. end
  958. end
  959. return nil
  960. end
  961.  
  962. -- Adds a new buyable container of items.
  963. -- names = A table containing one or more strings of alternative names to this item.
  964. -- container = Backpack, bag or any other itemid of container where bought items will be stored
  965. -- itemid = The itemid of the buyable item
  966. -- cost = The price of one single item
  967. -- subType - The subType of each rune or fluidcontainer item. Can be left out if it is not a rune/fluidcontainer. Default value is 1.
  968. -- realName - The real, full name for the item. Will be used as ITEMNAME in MESSAGE_ONBUY and MESSAGE_ONSELL if defined. Default value is nil (getName will be used)
  969. function ShopModule:addBuyableItemContainer(names, container, itemid, cost, subType, realName)
  970. if names ~= nil then
  971. for _, name in pairs(names) do
  972. local parameters = {
  973. container = container,
  974. itemid = itemid,
  975. cost = cost,
  976. eventType = SHOPMODULE_BUY_ITEM_CONTAINER,
  977. module = self,
  978. realName = realName or ItemType(itemid):getName(),
  979. subType = subType or 1
  980. }
  981.  
  982. keywords = {}
  983. keywords[#keywords + 1] = "buy"
  984. keywords[#keywords + 1] = name
  985. local node = self.npcHandler.keywordHandler:addKeyword(keywords, ShopModule.tradeItem, parameters)
  986. node:addChildKeywordNode(self.yesNode)
  987. node:addChildKeywordNode(self.noNode)
  988. end
  989. end
  990. end
  991.  
  992. -- Adds a new sellable item.
  993. -- names = A table containing one or more strings of alternative names to this item. Used only by old buy/sell system.
  994. -- itemid = The itemid of the sellable item
  995. -- cost = The price of one single item
  996. -- realName - The real, full name for the item. Will be used as ITEMNAME in MESSAGE_ONBUY and MESSAGE_ONSELL if defined. Default value is nil (getName will be used)
  997. function ShopModule:addSellableItem(names, itemid, cost, realName, itemSubType)
  998. if SHOPMODULE_MODE ~= SHOPMODULE_MODE_TALK then
  999. if itemSubType == nil then
  1000. itemSubType = 0
  1001. end
  1002.  
  1003. local shopItem = self:getShopItem(itemid, itemSubType)
  1004. if shopItem == nil then
  1005. table.insert(self.npcHandler.shopItems, {id = itemid, buy = -1, sell = cost, subType = itemSubType, name = realName or ItemType(itemid):getName()})
  1006. else
  1007. shopItem.sell = cost
  1008. end
  1009. end
  1010.  
  1011. if (names ~= nil and SHOPMODULE_MODE ~= SHOPMODULE_MODE_TRADE) then
  1012. for i = 1, #names do
  1013. local parameters = {
  1014. itemid = itemid,
  1015. cost = cost,
  1016. eventType = SHOPMODULE_SELL_ITEM,
  1017. module = self,
  1018. realName = realName or ItemType(itemid):getName()
  1019. }
  1020.  
  1021. keywords = {}
  1022. table.insert(keywords, "sell")
  1023. table.insert(keywords, name)
  1024. local node = self.npcHandler.keywordHandler:addKeyword(keywords, ShopModule.tradeItem, parameters)
  1025. node:addChildKeywordNode(self.yesNode)
  1026. node:addChildKeywordNode(self.noNode)
  1027. end
  1028. end
  1029. end
  1030.  
  1031. -- onModuleReset callback function. Calls ShopModule:reset()
  1032. function ShopModule:callbackOnModuleReset()
  1033. self:reset()
  1034. return true
  1035. end
  1036.  
  1037. -- Callback onBuy() function. If you wish, you can change certain Npc to use your onBuy().
  1038. function ShopModule:callbackOnBuy(cid, itemid, subType, amount, ignoreCap, inBackpacks)
  1039. local shopItem = self:getShopItem(itemid, subType)
  1040. if shopItem == nil then
  1041. error("[ShopModule.onBuy] shopItem == nil")
  1042. return false
  1043. end
  1044.  
  1045. if shopItem.buy == -1 then
  1046. error("[ShopModule.onSell] attempt to buy a non-buyable item")
  1047. return false
  1048. end
  1049.  
  1050. local backpack = 23782
  1051. local totalCost = amount * shopItem.buy
  1052. if inBackpacks then
  1053. totalCost = ItemType(itemid):isStackable() and totalCost + 20 or totalCost + (math.max(1, math.floor(amount / ItemType(backpack):getCapacity())) * 20)
  1054. end
  1055.  
  1056. local player = Player(cid)
  1057. local parseInfo = {
  1058. [TAG_PLAYERNAME] = player:getName(),
  1059. [TAG_ITEMCOUNT] = amount,
  1060. [TAG_TOTALCOST] = totalCost,
  1061. [TAG_ITEMNAME] = shopItem.name
  1062. }
  1063.  
  1064. if player:getMoney() + player:getBankBalance() < totalCost then
  1065. local msg = self.npcHandler:getMessage(MESSAGE_NEEDMONEY)
  1066. msg = self.npcHandler:parseMessage(msg, parseInfo)
  1067. player:sendCancelMessage(msg)
  1068. return false
  1069. end
  1070.  
  1071. local subType = shopItem.subType or 1
  1072. local a, b = doNpcSellItem(cid, itemid, amount, subType, ignoreCap, inBackpacks, backpack)
  1073. if a < amount then
  1074. local msgId = MESSAGE_NEEDMORESPACE
  1075. if a == 0 then
  1076. msgId = MESSAGE_NEEDSPACE
  1077. end
  1078.  
  1079. local msg = self.npcHandler:getMessage(msgId)
  1080. parseInfo[TAG_ITEMCOUNT] = a
  1081. msg = self.npcHandler:parseMessage(msg, parseInfo)
  1082. player:sendCancelMessage(msg)
  1083. self.npcHandler.talkStart[cid] = os.time()
  1084.  
  1085. if a > 0 then
  1086. player:removeMoney((a * shopItem.buy) + (b * 20))
  1087. return true
  1088. end
  1089.  
  1090. return false
  1091. else
  1092. local msg = self.npcHandler:getMessage(MESSAGE_BOUGHT)
  1093. msg = self.npcHandler:parseMessage(msg, parseInfo)
  1094. player:sendTextMessage(MESSAGE_INFO_DESCR, msg)
  1095. player:removeMoney(totalCost)
  1096. self.npcHandler.talkStart[cid] = os.time()
  1097. return true
  1098. end
  1099. end
  1100.  
  1101. -- Callback onSell() function. If you wish, you can change certain Npc to use your onSell().
  1102. function ShopModule:callbackOnSell(cid, itemid, subType, amount, ignoreEquipped, _)
  1103. local shopItem = self:getShopItem(itemid, subType)
  1104. if shopItem == nil then
  1105. error("[ShopModule.onSell] items[itemid] == nil")
  1106. return false
  1107. end
  1108.  
  1109. if shopItem.sell == -1 then
  1110. error("[ShopModule.onSell] attempt to sell a non-sellable item")
  1111. return false
  1112. end
  1113.  
  1114. local player = Player(cid)
  1115. local parseInfo = {
  1116. [TAG_PLAYERNAME] = player:getName(),
  1117. [TAG_ITEMCOUNT] = amount,
  1118. [TAG_TOTALCOST] = amount * shopItem.sell,
  1119. [TAG_ITEMNAME] = shopItem.name
  1120. }
  1121.  
  1122. if not ItemType(itemid):isFluidContainer() then
  1123. subType = -1
  1124. end
  1125.  
  1126. if player:removeItem(itemid, amount, subType, ignoreEquipped) then
  1127. local msg = self.npcHandler:getMessage(MESSAGE_SOLD)
  1128. msg = self.npcHandler:parseMessage(msg, parseInfo)
  1129. player:sendTextMessage(MESSAGE_INFO_DESCR, msg)
  1130. player:addMoney(amount * shopItem.sell)
  1131. self.npcHandler.talkStart[cid] = os.time()
  1132. return true
  1133. else
  1134. local msg = self.npcHandler:getMessage(MESSAGE_NEEDITEM)
  1135. msg = self.npcHandler:parseMessage(msg, parseInfo)
  1136. player:sendCancelMessage(msg)
  1137. self.npcHandler.talkStart[cid] = os.time()
  1138. return false
  1139. end
  1140. end
  1141.  
  1142. -- Callback for requesting a trade window with the NPC.
  1143. function ShopModule.requestTrade(cid, message, keywords, parameters, node)
  1144. local module = parameters.module
  1145. if not module.npcHandler:isFocused(cid) then
  1146. return false
  1147. end
  1148.  
  1149. if not module.npcHandler:onTradeRequest(cid) then
  1150. return false
  1151. end
  1152.  
  1153. local itemWindow = {}
  1154. for i = 1, #module.npcHandler.shopItems do
  1155. itemWindow[#itemWindow + 1] = module.npcHandler.shopItems[i]
  1156. end
  1157.  
  1158. if itemWindow[1] == nil then
  1159. local parseInfo = { [TAG_PLAYERNAME] = Player(cid):getName() }
  1160. local msg = module.npcHandler:parseMessage(module.npcHandler:getMessage(MESSAGE_NOSHOP), parseInfo)
  1161. module.npcHandler:say(msg, cid)
  1162. return true
  1163. end
  1164.  
  1165. local parseInfo = { [TAG_PLAYERNAME] = Player(cid):getName() }
  1166. local msg = module.npcHandler:parseMessage(module.npcHandler:getMessage(MESSAGE_SENDTRADE), parseInfo)
  1167. openShopWindow(cid, itemWindow,
  1168. function(cid, itemid, subType, amount, ignoreCap, inBackpacks) module.npcHandler:onBuy(cid, itemid, subType, amount, ignoreCap, inBackpacks) end,
  1169. function(cid, itemid, subType, amount, ignoreCap, inBackpacks) module.npcHandler:onSell(cid, itemid, subType, amount, ignoreCap, inBackpacks) end)
  1170. module.npcHandler:say(msg, cid)
  1171. return true
  1172. end
  1173.  
  1174. -- onConfirm keyword callback function. Sells/buys the actual item.
  1175. function ShopModule.onConfirm(cid, message, keywords, parameters, node)
  1176. local module = parameters.module
  1177. if not module.npcHandler:isFocused(cid) or shop_npcuid[cid] ~= getNpcCid() then
  1178. return false
  1179. end
  1180. shop_npcuid[cid] = 0
  1181.  
  1182. local parentParameters = node:getParent():getParameters()
  1183. local parseInfo = {
  1184. [TAG_PLAYERNAME] = Player(cid):getName(),
  1185. [TAG_ITEMCOUNT] = shop_amount[cid],
  1186. [TAG_TOTALCOST] = shop_cost[cid] * shop_amount[cid],
  1187. [TAG_ITEMNAME] = shop_rlname[cid]
  1188. }
  1189.  
  1190. if shop_eventtype[cid] == SHOPMODULE_SELL_ITEM then
  1191. local ret = doPlayerSellItem(cid, shop_itemid[cid], shop_amount[cid], shop_cost[cid] * shop_amount[cid])
  1192. if ret then
  1193. local msg = module.npcHandler:getMessage(MESSAGE_ONSELL)
  1194. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1195. module.npcHandler:say(msg, cid)
  1196. else
  1197. local msg = module.npcHandler:getMessage(MESSAGE_MISSINGITEM)
  1198. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1199. module.npcHandler:say(msg, cid)
  1200. end
  1201. elseif shop_eventtype[cid] == SHOPMODULE_BUY_ITEM then
  1202. local cost = shop_cost[cid] * shop_amount[cid]
  1203. if Player(cid):getMoney() + player:getBankBalance() < cost then
  1204. local msg = module.npcHandler:getMessage(MESSAGE_MISSINGMONEY)
  1205. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1206. module.npcHandler:say(msg, cid)
  1207. return false
  1208. end
  1209.  
  1210. local a, b = doNpcSellItem(cid, shop_itemid[cid], shop_amount[cid], shop_subtype[cid], false, false, 1988)
  1211. if a < shop_amount[cid] then
  1212. local msgId = MESSAGE_NEEDMORESPACE
  1213. if a == 0 then
  1214. msgId = MESSAGE_NEEDSPACE
  1215. end
  1216.  
  1217. local msg = module.npcHandler:getMessage(msgId)
  1218. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1219. module.npcHandler:say(msg, cid)
  1220. if a > 0 then
  1221. Player(cid):removeMoney(a * shop_cost[cid])
  1222. if shop_itemid[cid] == ITEM_PARCEL then
  1223. doNpcSellItem(cid, ITEM_LABEL, shop_amount[cid], shop_subtype[cid], true, false, 1988)
  1224. end
  1225. return true
  1226. end
  1227. return false
  1228. else
  1229. local msg = module.npcHandler:getMessage(MESSAGE_ONBUY)
  1230. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1231. module.npcHandler:say(msg, cid)
  1232. Player(cid):removeMoney(cost)
  1233. if shop_itemid[cid] == ITEM_PARCEL then
  1234. doNpcSellItem(cid, ITEM_LABEL, shop_amount[cid], shop_subtype[cid], true, false, 1988)
  1235. end
  1236. return true
  1237. end
  1238. elseif shop_eventtype[cid] == SHOPMODULE_BUY_ITEM_CONTAINER then
  1239. local ret = doPlayerBuyItemContainer(cid, shop_container[cid], shop_itemid[cid], shop_amount[cid], shop_cost[cid] * shop_amount[cid], shop_subtype[cid])
  1240. if ret then
  1241. local msg = module.npcHandler:getMessage(MESSAGE_ONBUY)
  1242. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1243. module.npcHandler:say(msg, cid)
  1244. else
  1245. local msg = module.npcHandler:getMessage(MESSAGE_MISSINGMONEY)
  1246. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1247. module.npcHandler:say(msg, cid)
  1248. end
  1249. end
  1250.  
  1251. module.npcHandler:resetNpc(cid)
  1252. return true
  1253. end
  1254.  
  1255. -- onDecline keyword callback function. Generally called when the player sais "no" after wanting to buy an item.
  1256. function ShopModule.onDecline(cid, message, keywords, parameters, node)
  1257. local module = parameters.module
  1258. if not module.npcHandler:isFocused(cid) or shop_npcuid[cid] ~= getNpcCid() then
  1259. return false
  1260. end
  1261. shop_npcuid[cid] = 0
  1262.  
  1263. local parentParameters = node:getParent():getParameters()
  1264. local parseInfo = {
  1265. [TAG_PLAYERNAME] = Player(cid):getName(),
  1266. [TAG_ITEMCOUNT] = shop_amount[cid],
  1267. [TAG_TOTALCOST] = shop_cost[cid] * shop_amount[cid],
  1268. [TAG_ITEMNAME] = shop_rlname[cid]
  1269. }
  1270.  
  1271. local msg = module.npcHandler:parseMessage(module.noText, parseInfo)
  1272. module.npcHandler:say(msg, cid)
  1273. module.npcHandler:resetNpc(cid)
  1274. return true
  1275. end
  1276.  
  1277. -- tradeItem callback function. Makes the npc say the message defined by MESSAGE_BUY or MESSAGE_SELL
  1278. function ShopModule.tradeItem(cid, message, keywords, parameters, node)
  1279. local module = parameters.module
  1280. if not module.npcHandler:isFocused(cid) then
  1281. return false
  1282. end
  1283.  
  1284. if not module.npcHandler:onTradeRequest(cid) then
  1285. return true
  1286. end
  1287.  
  1288. local count = module:getCount(message)
  1289. module.amount = count
  1290.  
  1291. shop_amount[cid] = module.amount
  1292. shop_cost[cid] = parameters.cost
  1293. shop_rlname[cid] = parameters.realName
  1294. shop_itemid[cid] = parameters.itemid
  1295. shop_container[cid] = parameters.container
  1296. shop_npcuid[cid] = getNpcCid()
  1297. shop_eventtype[cid] = parameters.eventType
  1298. shop_subtype[cid] = parameters.subType
  1299.  
  1300. local parseInfo = {
  1301. [TAG_PLAYERNAME] = Player(cid):getName(),
  1302. [TAG_ITEMCOUNT] = shop_amount[cid],
  1303. [TAG_TOTALCOST] = shop_cost[cid] * shop_amount[cid],
  1304. [TAG_ITEMNAME] = shop_rlname[cid]
  1305. }
  1306.  
  1307. if shop_eventtype[cid] == SHOPMODULE_SELL_ITEM then
  1308. local msg = module.npcHandler:getMessage(MESSAGE_SELL)
  1309. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1310. module.npcHandler:say(msg, cid)
  1311. elseif shop_eventtype[cid] == SHOPMODULE_BUY_ITEM then
  1312. local msg = module.npcHandler:getMessage(MESSAGE_BUY)
  1313. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1314. module.npcHandler:say(msg, cid)
  1315. elseif shop_eventtype[cid] == SHOPMODULE_BUY_ITEM_CONTAINER then
  1316. local msg = module.npcHandler:getMessage(MESSAGE_BUY)
  1317. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1318. module.npcHandler:say(msg, cid)
  1319. end
  1320. return true
  1321. end
  1322. end
Add Comment
Please, Sign In to add comment