Advertisement
Guest User

Untitled

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