Guest User

Untitled

a guest
Apr 26th, 2020
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 44.99 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 and player:getLevel() >= 50 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] = getFormattedWorldTime(), [TAG_BLESSCOST] = getBlessingsCost(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. function StdModule.say(cid, message, keywords, parameters, node)
  90. local npcHandler = parameters.npcHandler
  91. if npcHandler == nil then
  92. error("StdModule.say called without any npcHandler instance.")
  93. end
  94. local onlyFocus = (parameters.onlyFocus == nil or parameters.onlyFocus == true)
  95. if not npcHandler:isFocused(cid) and onlyFocus then
  96. return false
  97. end
  98.  
  99. local parseInfo = {
  100. [TAG_PLAYERNAME] = Player(cid):getName(),
  101. [TAG_TIME] = getFormattedWorldTime()
  102. }
  103.  
  104. npcHandler:say(npcHandler:parseMessage(parameters.text or parameters.message, parseInfo), cid, parameters.publicize and true)
  105. if parameters.reset then
  106. npcHandler:resetNpc(cid)
  107. elseif parameters.moveup ~= nil then
  108. npcHandler.keywordHandler:moveUp(cid, parameters.moveup)
  109. end
  110.  
  111. return true
  112. end
  113.  
  114. --Usage:
  115. -- 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?"})
  116. -- node1:addChildKeyword({"yes"}, StdModule.promotePlayer, {npcHandler = npcHandler, cost = 20000, level = 20}, text = "Congratulations! You are now promoted.")
  117. -- node1:addChildKeyword({"no"}, StdModule.say, {npcHandler = npcHandler, text = "Allright then. Come back when you are ready."}, reset = true)
  118. function StdModule.promotePlayer(cid, message, keywords, parameters, node)
  119. local npcHandler = parameters.npcHandler
  120. if npcHandler == nil then
  121. error("StdModule.promotePlayer called without any npcHandler instance.")
  122. end
  123.  
  124. if not npcHandler:isFocused(cid) then
  125. return false
  126. end
  127.  
  128. local player = Player(cid)
  129. if player:isPremium() or not parameters.premium then
  130. local promotion = player:getVocation():getPromotion()
  131. if player:getStorageValue(STORAGEVALUE_PROMOTION) == 1 then
  132. npcHandler:say("You are already promoted!", cid)
  133. elseif player:getLevel() < parameters.level then
  134. npcHandler:say("I am sorry, but I can only promote you once you have reached level " .. parameters.level .. ".", cid)
  135. elseif not player:removeMoney(parameters.cost) then
  136. npcHandler:say("You do not have enough money!", cid)
  137. else
  138. player:setStorageValue(STORAGEVALUE_PROMOTION, 1)
  139. player:setVocation(promotion)
  140. player:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
  141. npcHandler:say(parameters.text or "Congratulations! You are now promoted.", cid)
  142. end
  143. else
  144. npcHandler:say("You need a premium account in order to get promoted.", cid)
  145. end
  146. npcHandler:resetNpc(cid)
  147. return true
  148. end
  149.  
  150. function StdModule.learnSpell(cid, message, keywords, parameters, node)
  151. local npcHandler = parameters.npcHandler
  152. if npcHandler == nil then
  153. error("StdModule.learnSpell 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. if player:isPremium() or not parameters.premium then
  162. if player:hasLearnedSpell(parameters.spellName) then
  163. npcHandler:say("You already know this spell.", cid)
  164. elseif not player:canLearnSpell(parameters.spellName) then
  165. npcHandler:say("You cannot learn this spell.", cid)
  166. elseif not player:removeMoney(parameters.price) then
  167. npcHandler:say("You do not have enough money, this spell costs " .. parameters.price .. " gold.", cid)
  168. else
  169. npcHandler:say("You have learned " .. parameters.spellName .. ".", cid)
  170. player:learnSpell(parameters.spellName)
  171. end
  172. else
  173. npcHandler:say("You need a premium account in order to buy " .. parameters.spellName .. ".", cid)
  174. end
  175. npcHandler:resetNpc(cid)
  176. return true
  177. end
  178.  
  179. function StdModule.bless(cid, message, keywords, parameters, node)
  180. local npcHandler = parameters.npcHandler
  181. if npcHandler == nil then
  182. error("StdModule.bless called without any npcHandler instance.")
  183. end
  184.  
  185. if not npcHandler:isFocused(cid) then
  186. return false
  187. end
  188.  
  189. local player = Player(cid)
  190. local parseInfo = {[TAG_PLAYERNAME] = player:getName(), [TAG_TIME] = getFormattedWorldTime(), [TAG_BLESSCOST] = getBlessingsCost(player:getLevel()), [TAG_TRAVELCOST] = costMessage}
  191. if player:hasBlessing(parameters.bless) then
  192. npcHandler:say("You already possess this blessing.", cid)
  193. elseif parameters.bless == 4 and player:getStorageValue(Storage.KawillBlessing) ~= 1 then
  194. npcHandler:say("You need the blessing of the great geomancer first.", cid)
  195. elseif parameters.bless == 6 and player:getBlessings() == 0 and not player:getItemById(2173, true) then
  196. 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)
  197. elseif not player:removeMoney(type(parameters.cost) == "string" and npcHandler:parseMessage(parameters.cost, parseInfo) or parameters.cost) then
  198. npcHandler:say("Oh. You do not have enough money.", cid)
  199. else
  200. npcHandler:say(parameters.text or "You have been blessed by one of the five gods!", cid)
  201. player:addBlessing(parameters.bless)
  202. player:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)
  203. end
  204.  
  205. npcHandler:resetNpc(cid)
  206. return true
  207. end
  208.  
  209. function StdModule.travel(cid, message, keywords, parameters, node)
  210. local npcHandler = parameters.npcHandler
  211. if npcHandler == nil then
  212. error("StdModule.travel called without any npcHandler instance.")
  213. end
  214.  
  215. if not npcHandler:isFocused(cid) then
  216. return false
  217. end
  218.  
  219. local player = Player(cid)
  220. if player:isPremium() or not parameters.premium then
  221. if player:isPzLocked() then
  222. npcHandler:say("First get rid of those blood stains! You are not going to ruin my vehicle!", cid)
  223. elseif parameters.level and player:getLevel() < parameters.level then
  224. npcHandler:say("You must reach level " .. parameters.level .. " before I can let you go there.", cid)
  225. elseif not player:removeMoney(parameters.cost) then
  226. npcHandler:say("You don't have enough money.", cid)
  227. else
  228. npcHandler:say(parameters.msg or "Set the sails!", cid)
  229. npcHandler:releaseFocus(cid)
  230.  
  231. local destination = Position(parameters.destination)
  232. local position = player:getPosition()
  233. player:teleportTo(destination)
  234.  
  235. position:sendMagicEffect(CONST_ME_TELEPORT)
  236. destination:sendMagicEffect(CONST_ME_TELEPORT)
  237. end
  238. else
  239. npcHandler:say("I'm sorry, but you need a premium account in order to travel onboard our ships.", cid)
  240. end
  241. npcHandler:resetNpc(cid)
  242. return true
  243. end
  244.  
  245. FocusModule = {
  246. npcHandler = nil,
  247. greetWords = nil,
  248. farewellWords = nil,
  249. greetCallback = nil,
  250. farewellCallback = nil
  251. }
  252.  
  253. -- Creates a new instance of FocusModule without an associated NpcHandler.
  254. function FocusModule:new()
  255. local obj = {}
  256. setmetatable(obj, self)
  257. self.__index = self
  258. return obj
  259. end
  260.  
  261. -- Inits the module and associates handler to it.
  262. function FocusModule:init(handler)
  263. self.npcHandler = handler
  264.  
  265. local greetWords = self.greetWords or FOCUS_GREETWORDS
  266. for i = 1, #greetWords do
  267. local obj = {}
  268. obj[#obj + 1] = greetWords[i]
  269. obj.callback = self.greetCallback or FocusModule.messageMatcherDefault
  270. handler.keywordHandler:addKeyword(obj, FocusModule.onGreet, {module = self})
  271. end
  272.  
  273. local farewellWords = self.farewellWords or FOCUS_FAREWELLWORDS
  274. for i = 1, #farewellWords do
  275. local obj = {}
  276. obj[#obj + 1] = farewellWords[i]
  277. obj.callback = self.farewellCallback or FocusModule.messageMatcherDefault
  278. handler.keywordHandler:addKeyword(obj, FocusModule.onFarewell, {module = self})
  279. end
  280.  
  281. return true
  282. end
  283.  
  284. -- Set custom greeting messages
  285. function FocusModule:addGreetMessage(message)
  286. if not self.greetWords then
  287. self.greetWords = {}
  288. end
  289.  
  290. if type(message) == 'string' then
  291. self.greetWords[#self.greetWords + 1] = message
  292. else
  293. for i = 1, #message do
  294. self.greetWords[#self.greetWords + 1] = message[i]
  295. end
  296. end
  297. end
  298.  
  299. -- Set custom farewell messages
  300. function FocusModule:addFarewellMessage(message)
  301. if not self.farewellWords then
  302. self.farewellWords = {}
  303. end
  304.  
  305. if type(message) == 'string' then
  306. self.farewellWords[#self.farewellWords + 1] = message
  307. else
  308. for i = 1, #message do
  309. self.farewellWords[#self.farewellWords + 1] = message
  310. end
  311. end
  312. end
  313.  
  314. -- Set custom greeting callback
  315. function FocusModule:setGreetCallback(callback)
  316. self.greetCallback = callback
  317. end
  318.  
  319. -- Set custom farewell callback
  320. function FocusModule:setFarewellCallback(callback)
  321. self.farewellCallback = callback
  322. end
  323.  
  324. -- Greeting callback function.
  325. function FocusModule.onGreet(cid, message, keywords, parameters)
  326. parameters.module.npcHandler:onGreet(cid, message)
  327. return true
  328. end
  329.  
  330. -- UnGreeting callback function.
  331. function FocusModule.onFarewell(cid, message, keywords, parameters)
  332. if parameters.module.npcHandler:isFocused(cid) then
  333. parameters.module.npcHandler:onFarewell(cid)
  334. return true
  335. else
  336. return false
  337. end
  338. end
  339.  
  340. -- Custom message matching callback function for greeting messages.
  341. function FocusModule.messageMatcherDefault(keywords, message)
  342. for i = 1, #keywords do
  343. local word = keywords[i]
  344. if type(word) == "string" then
  345. if string.find(message, word) and not string.find(message, "[%w+]" .. word) and not string.find(message, word .. "[%w+]") then
  346. return true
  347. end
  348. end
  349. end
  350. return false
  351. end
  352.  
  353. function FocusModule.messageMatcherStart(keywords, message)
  354. for i = 1, #keywords do
  355. local word = keywords[i]
  356. if type(word) == "string" then
  357. if string.starts(message, word) then
  358. return true
  359. end
  360. end
  361. end
  362. return false
  363. end
  364.  
  365. KeywordModule = {
  366. npcHandler = nil
  367. }
  368. -- Add it to the parseable module list.
  369. Modules.parseableModules["module_keywords"] = KeywordModule
  370.  
  371. function KeywordModule:new()
  372. local obj = {}
  373. setmetatable(obj, self)
  374. self.__index = self
  375. return obj
  376. end
  377.  
  378. function KeywordModule:init(handler)
  379. self.npcHandler = handler
  380. return true
  381. end
  382.  
  383. -- Parses all known parameters.
  384. function KeywordModule:parseParameters()
  385. local ret = NpcSystem.getParameter("keywords")
  386. if ret ~= nil then
  387. self:parseKeywords(ret)
  388. end
  389. end
  390.  
  391. function KeywordModule:parseKeywords(data)
  392. local n = 1
  393. for keys in string.gmatch(data, "[^;]+") do
  394. local i = 1
  395.  
  396. local keywords = {}
  397. for temp in string.gmatch(keys, "[^,]+") do
  398. keywords[#keywords + 1] = temp
  399. i = i + 1
  400. end
  401.  
  402. if i ~= 1 then
  403. local reply = NpcSystem.getParameter("keyword_reply" .. n)
  404. if reply ~= nil then
  405. self:addKeyword(keywords, reply)
  406. else
  407. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter '" .. "keyword_reply" .. n .. "' missing. Skipping...")
  408. end
  409. else
  410. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "No keywords found for keyword set #" .. n .. ". Skipping...")
  411. end
  412.  
  413. n = n+1
  414. end
  415. end
  416.  
  417. function KeywordModule:addKeyword(keywords, reply)
  418. self.npcHandler.keywordHandler:addKeyword(keywords, StdModule.say, {npcHandler = self.npcHandler, text = reply, reset = true})
  419. end
  420.  
  421. TravelModule = {
  422. npcHandler = nil,
  423. destinations = nil,
  424. yesNode = nil,
  425. noNode = nil,
  426. }
  427. -- Add it to the parseable module list.
  428. Modules.parseableModules["module_travel"] = TravelModule
  429.  
  430. function TravelModule:new()
  431. local obj = {}
  432. setmetatable(obj, self)
  433. self.__index = self
  434. return obj
  435. end
  436.  
  437. function TravelModule:init(handler)
  438. self.npcHandler = handler
  439. self.yesNode = KeywordNode:new(SHOP_YESWORD, TravelModule.onConfirm, {module = self})
  440. self.noNode = KeywordNode:new(SHOP_NOWORD, TravelModule.onDecline, {module = self})
  441. self.destinations = {}
  442. return true
  443. end
  444.  
  445. -- Parses all known parameters.
  446. function TravelModule:parseParameters()
  447. local ret = NpcSystem.getParameter("travel_destinations")
  448. if ret ~= nil then
  449. self:parseDestinations(ret)
  450.  
  451. self.npcHandler.keywordHandler:addKeyword({"destination"}, TravelModule.listDestinations, {module = self})
  452. self.npcHandler.keywordHandler:addKeyword({"where"}, TravelModule.listDestinations, {module = self})
  453. self.npcHandler.keywordHandler:addKeyword({"travel"}, TravelModule.listDestinations, {module = self})
  454.  
  455. end
  456. end
  457.  
  458. function TravelModule:parseDestinations(data)
  459. for destination in string.gmatch(data, "[^;]+") do
  460. local i = 1
  461.  
  462. local name = nil
  463. local x = nil
  464. local y = nil
  465. local z = nil
  466. local cost = nil
  467. local premium = false
  468.  
  469. for temp in string.gmatch(destination, "[^,]+") do
  470. if i == 1 then
  471. name = temp
  472. elseif i == 2 then
  473. x = tonumber(temp)
  474. elseif i == 3 then
  475. y = tonumber(temp)
  476. elseif i == 4 then
  477. z = tonumber(temp)
  478. elseif i == 5 then
  479. cost = tonumber(temp)
  480. elseif i == 6 then
  481. premium = temp == "true"
  482. else
  483. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Unknown parameter found in travel destination parameter.", temp, destination)
  484. end
  485. i = i + 1
  486. end
  487.  
  488. if(name ~= nil and x ~= nil and y ~= nil and z ~= nil and cost ~= nil) then
  489. self:addDestination(name, {x=x, y=y, z=z}, cost, premium)
  490. else
  491. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for travel destination:", name, x, y, z, cost, premium)
  492. end
  493. end
  494. end
  495.  
  496. function TravelModule:addDestination(name, position, price, premium)
  497. self.destinations[#self.destinations + 1] = name
  498.  
  499. local parameters = {
  500. cost = price,
  501. destination = position,
  502. premium = premium,
  503. module = self
  504. }
  505. local keywords = {}
  506. keywords[#keywords + 1] = name
  507.  
  508. local keywords2 = {}
  509. keywords2[#keywords2 + 1] = "bring me to " .. name
  510. local node = self.npcHandler.keywordHandler:addKeyword(keywords, TravelModule.travel, parameters)
  511. self.npcHandler.keywordHandler:addKeyword(keywords2, TravelModule.bringMeTo, parameters)
  512. node:addChildKeywordNode(self.yesNode)
  513. node:addChildKeywordNode(self.noNode)
  514.  
  515. if npcs_loaded_travel[getNpcCid()] == nil then
  516. npcs_loaded_travel[getNpcCid()] = getNpcCid()
  517. self.npcHandler.keywordHandler:addKeyword({'yes'}, TravelModule.onConfirm, {module = self})
  518. self.npcHandler.keywordHandler:addKeyword({'no'}, TravelModule.onDecline, {module = self})
  519. end
  520. end
  521.  
  522. function TravelModule.travel(cid, message, keywords, parameters, node)
  523. local module = parameters.module
  524. if(not module.npcHandler:isFocused(cid)) then
  525. return false
  526. end
  527.  
  528. local npcHandler = module.npcHandler
  529.  
  530. shop_destination[cid] = parameters.destination
  531. shop_cost[cid] = parameters.cost
  532. shop_premium[cid] = parameters.premium
  533. shop_npcuid[cid] = getNpcCid()
  534.  
  535. local cost = parameters.cost
  536. local destination = parameters.destination
  537. local premium = parameters.premium
  538.  
  539. module.npcHandler:say("Do you want to travel to " .. keywords[1] .. " for " .. cost .. " gold coins?", cid)
  540. return true
  541. end
  542.  
  543. function TravelModule.onConfirm(cid, message, keywords, parameters, node)
  544. local module = parameters.module
  545. if not module.npcHandler:isFocused(cid) then
  546. return false
  547. end
  548.  
  549. if shop_npcuid[cid] ~= Npc():getId() then
  550. return false
  551. end
  552.  
  553. local npcHandler = module.npcHandler
  554.  
  555. local cost = shop_cost[cid]
  556. local destination = shop_destination[cid]
  557.  
  558. local player = Player(cid)
  559. if player:isPremium() or not shop_premium[cid] then
  560. if not player:removeMoney(cost) then
  561. npcHandler:say("You do not have enough money!", cid)
  562. elseif player:isPzLocked(cid) then
  563. npcHandler:say("Get out of there with this blood.", cid)
  564. else
  565. npcHandler:say("It was a pleasure doing business with you.", cid)
  566. npcHandler:releaseFocus(cid)
  567.  
  568. player:teleportTo(destination)
  569.  
  570. player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
  571. destination:sendMagicEffect(CONST_ME_TELEPORT)
  572. end
  573. else
  574. npcHandler:say("I can only allow premium players to travel there.", cid)
  575. end
  576.  
  577. npcHandler:resetNpc(cid)
  578. return true
  579. end
  580.  
  581. -- onDecline keyword callback function. Generally called when the player sais "no" after wanting to buy an item.
  582. function TravelModule.onDecline(cid, message, keywords, parameters, node)
  583. local module = parameters.module
  584. if not module.npcHandler:isFocused(cid) or shop_npcuid[cid] ~= getNpcCid() then
  585. return false
  586. end
  587. local parentParameters = node:getParent():getParameters()
  588. local parseInfo = { [TAG_PLAYERNAME] = Player(cid):getName() }
  589. local msg = module.npcHandler:parseMessage(module.npcHandler:getMessage(MESSAGE_DECLINE), parseInfo)
  590. module.npcHandler:say(msg, cid)
  591. module.npcHandler:resetNpc(cid)
  592. return true
  593. end
  594.  
  595. function TravelModule.bringMeTo(cid, message, keywords, parameters, node)
  596. local module = parameters.module
  597. if not module.npcHandler:isFocused(cid) then
  598. return false
  599. end
  600.  
  601. local cost = parameters.cost
  602. local destination = Position(parameters.destination)
  603.  
  604. local player = Player(cid)
  605. if player:isPremium() or not parameters.premium then
  606. if player:removeMoney(cost) then
  607. local position = player:getPosition()
  608. player:teleportTo(destination)
  609.  
  610. position:sendMagicEffect(CONST_ME_TELEPORT)
  611. destination:sendMagicEffect(CONST_ME_TELEPORT)
  612. end
  613. end
  614. return true
  615. end
  616.  
  617. function TravelModule.listDestinations(cid, message, keywords, parameters, node)
  618. local module = parameters.module
  619. if not module.npcHandler:isFocused(cid) then
  620. return false
  621. end
  622.  
  623. local msg = "I can bring you to "
  624. --local i = 1
  625. local maxn = #module.destinations
  626. for i, destination in pairs(module.destinations) do
  627. msg = msg .. destination
  628. if i == maxn - 1 then
  629. msg = msg .. " and "
  630. elseif i == maxn then
  631. msg = msg .. "."
  632. else
  633. msg = msg .. ", "
  634. end
  635. i = i + 1
  636. end
  637.  
  638. module.npcHandler:say(msg, cid)
  639. module.npcHandler:resetNpc(cid)
  640. return true
  641. end
  642.  
  643. ShopModule = {
  644. npcHandler = nil,
  645. yesNode = nil,
  646. noNode = nil,
  647. noText = "",
  648. maxCount = 100,
  649. amount = 0
  650. }
  651.  
  652. -- Add it to the parseable module list.
  653. Modules.parseableModules["module_shop"] = ShopModule
  654.  
  655. -- Creates a new instance of ShopModule
  656. function ShopModule:new()
  657. local obj = {}
  658. setmetatable(obj, self)
  659. self.__index = self
  660. return obj
  661. end
  662.  
  663. -- Parses all known parameters.
  664. function ShopModule:parseParameters()
  665. local ret = NpcSystem.getParameter("shop_buyable")
  666. if ret ~= nil then
  667. self:parseBuyable(ret)
  668. end
  669.  
  670. local ret = NpcSystem.getParameter("shop_sellable")
  671. if ret ~= nil then
  672. self:parseSellable(ret)
  673. end
  674.  
  675. local ret = NpcSystem.getParameter("shop_buyable_containers")
  676. if ret ~= nil then
  677. self:parseBuyableContainers(ret)
  678. end
  679. end
  680.  
  681. -- Parse a string contaning a set of buyable items.
  682. function ShopModule:parseBuyable(data)
  683. for item in string.gmatch(data, "[^;]+") do
  684. local i = 1
  685.  
  686. local name = nil
  687. local itemid = nil
  688. local cost = nil
  689. local subType = nil
  690. local realName = nil
  691.  
  692. for temp in string.gmatch(item, "[^,]+") do
  693. if i == 1 then
  694. name = temp
  695. elseif i == 2 then
  696. itemid = tonumber(temp)
  697. elseif i == 3 then
  698. cost = tonumber(temp)
  699. elseif i == 4 then
  700. subType = tonumber(temp)
  701. elseif i == 5 then
  702. realName = temp
  703. else
  704. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Unknown parameter found in buyable items parameter.", temp, item)
  705. end
  706. i = i + 1
  707. end
  708.  
  709. local it = ItemType(itemid)
  710. if subType == nil and it:getCharges() ~= 0 then
  711. subType = it:getCharges()
  712. end
  713.  
  714. if SHOPMODULE_MODE == SHOPMODULE_MODE_TRADE then
  715. if itemid ~= nil and cost ~= nil then
  716. if subType == nil and it:isFluidContainer() then
  717. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "SubType missing for parameter item:", item)
  718. else
  719. self:addBuyableItem(nil, itemid, cost, subType, realName)
  720. end
  721. else
  722. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", itemid, cost)
  723. end
  724. else
  725. if name ~= nil and itemid ~= nil and cost ~= nil then
  726. if subType == nil and it:isFluidContainer() then
  727. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "SubType missing for parameter item:", item)
  728. else
  729. local names = {}
  730. names[#names + 1] = name
  731. self:addBuyableItem(names, itemid, cost, subType, realName)
  732. end
  733. else
  734. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", name, itemid, cost)
  735. end
  736. end
  737. end
  738. end
  739.  
  740. -- Parse a string contaning a set of sellable items.
  741. function ShopModule:parseSellable(data)
  742. for item in string.gmatch(data, "[^;]+") do
  743. local i = 1
  744.  
  745. local name = nil
  746. local itemid = nil
  747. local cost = nil
  748. local realName = nil
  749. local subType = nil
  750.  
  751. for temp in string.gmatch(item, "[^,]+") do
  752. if i == 1 then
  753. name = temp
  754. elseif i == 2 then
  755. itemid = tonumber(temp)
  756. elseif i == 3 then
  757. cost = tonumber(temp)
  758. elseif i == 4 then
  759. realName = temp
  760. elseif i == 5 then
  761. subType = tonumber(temp)
  762. else
  763. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Unknown parameter found in sellable items parameter.", temp, item)
  764. end
  765. i = i + 1
  766. end
  767.  
  768. if SHOPMODULE_MODE == SHOPMODULE_MODE_TRADE then
  769. if itemid ~= nil and cost ~= nil then
  770. self:addSellableItem(nil, itemid, cost, realName, subType)
  771. else
  772. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", itemid, cost)
  773. end
  774. else
  775. if name ~= nil and itemid ~= nil and cost ~= nil then
  776. local names = {}
  777. names[#names + 1] = name
  778. self:addSellableItem(names, itemid, cost, realName, subType)
  779. else
  780. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", name, itemid, cost)
  781. end
  782. end
  783. end
  784. end
  785.  
  786. -- Parse a string contaning a set of buyable items.
  787. function ShopModule:parseBuyableContainers(data)
  788. for item in string.gmatch(data, "[^;]+") do
  789. local i = 1
  790.  
  791. local name = nil
  792. local container = nil
  793. local itemid = nil
  794. local cost = nil
  795. local subType = nil
  796. local realName = nil
  797.  
  798. for temp in string.gmatch(item, "[^,]+") do
  799. if i == 1 then
  800. name = temp
  801. elseif i == 2 then
  802. itemid = tonumber(temp)
  803. elseif i == 3 then
  804. itemid = tonumber(temp)
  805. elseif i == 4 then
  806. cost = tonumber(temp)
  807. elseif i == 5 then
  808. subType = tonumber(temp)
  809. elseif i == 6 then
  810. realName = temp
  811. else
  812. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Unknown parameter found in buyable items parameter.", temp, item)
  813. end
  814. i = i + 1
  815. end
  816.  
  817. if name ~= nil and container ~= nil and itemid ~= nil and cost ~= nil then
  818. if subType == nil and ItemType(itemid):isFluidContainer() then
  819. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "SubType missing for parameter item:", item)
  820. else
  821. local names = {}
  822. names[#names + 1] = name
  823. self:addBuyableItemContainer(names, container, itemid, cost, subType, realName)
  824. end
  825. else
  826. print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", name, container, itemid, cost)
  827. end
  828. end
  829. end
  830.  
  831. -- Initializes the module and associates handler to it.
  832. function ShopModule:init(handler)
  833. self.npcHandler = handler
  834. self.yesNode = KeywordNode:new(SHOP_YESWORD, ShopModule.onConfirm, {module = self})
  835. self.noNode = KeywordNode:new(SHOP_NOWORD, ShopModule.onDecline, {module = self})
  836. self.noText = handler:getMessage(MESSAGE_DECLINE)
  837.  
  838. if SHOPMODULE_MODE ~= SHOPMODULE_MODE_TALK then
  839. for i = 1, #SHOP_TRADEREQUEST do
  840. local obj = {}
  841. obj[#obj + 1] = SHOP_TRADEREQUEST[i]
  842. obj.callback = SHOP_TRADEREQUEST.callback or ShopModule.messageMatcher
  843. handler.keywordHandler:addKeyword(obj, ShopModule.requestTrade, {module = self})
  844. end
  845. end
  846.  
  847. return true
  848. end
  849.  
  850. -- Custom message matching callback function for requesting trade messages.
  851. function ShopModule.messageMatcher(keywords, message)
  852. for i = 1, #keywords do
  853. local word = keywords[i]
  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 i = 1, #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] = names[i]
  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 i = 1, #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] = names[i]
  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. self.npcHandler.shopItems[#self.npcHandler.shopItems + 1] = {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. keywords[#keywords + 1] = "sell"
  1013. keywords[#keywords + 1] = names[i]
  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() < 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:removeMoney((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:removeMoney(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. if SHOPMODULE_MODE == SHOPMODULE_MODE_BOTH then
  1156. local sellableItems, buyableItems = {}, {}
  1157. for i, shopItem in ipairs(module.npcHandler.shopItems) do
  1158. if shopItem.sell >= 0 then
  1159. sellableItems[#sellableItems + 1] = shopItem.name
  1160. end
  1161. if shopItem.buy >= 0 then
  1162. buyableItems[#buyableItems + 1] = shopItem.name
  1163. end
  1164. end
  1165.  
  1166. local npc = Npc()
  1167. if table.maxn(buyableItems) > 0 then
  1168. local message = "I'm selling "
  1169. for i = 1, table.maxn(buyableItems) do
  1170. message = message .. buyableItems[i] .. ", "
  1171. if message:len() > 500 then
  1172. npc:say(message:sub(0, -3) .. ".", TALKTYPE_SAY)
  1173. message = "I'm selling "
  1174. end
  1175. end
  1176. if message:len() > 12 then
  1177. npc:say(message:sub(0, -3) .. ".", TALKTYPE_SAY)
  1178. end
  1179. end
  1180. if table.maxn(sellableItems) > 0 then
  1181. local message = "I'm buying "
  1182. for i = 1, table.maxn(sellableItems) do
  1183. message = message .. sellableItems[i] .. ", "
  1184. if message:len() > 500 then
  1185. addEvent(function(cid)
  1186. local npcId = Npc(cid)
  1187. if not npcId then
  1188. return
  1189. end
  1190. npcId:say(message:sub(0, -3) .. ".", TALKTYPE_SAY)
  1191. end, 2000, npc.uid)
  1192. message = "I'm buying "
  1193. end
  1194. end
  1195. if message:len() > 12 then
  1196. addEvent(function(cid)
  1197. local npcId = Npc(cid)
  1198. if not npcId then
  1199. return
  1200. end
  1201. npcId:say(message:sub(0, -3) .. ".", TALKTYPE_SAY)
  1202. end, 2000, npc.uid)
  1203. end
  1204. end
  1205. return true
  1206. end
  1207. return true
  1208. end
  1209.  
  1210. -- onConfirm keyword callback function. Sells/buys the actual item.
  1211. function ShopModule.onConfirm(cid, message, keywords, parameters, node)
  1212. local module = parameters.module
  1213. if(not module.npcHandler:isFocused(cid)) or shop_npcuid[cid] ~= getNpcCid() then
  1214. return false
  1215. end
  1216. shop_npcuid[cid] = 0
  1217.  
  1218. local parentParameters = node:getParent():getParameters()
  1219. local parseInfo = {
  1220. [TAG_PLAYERNAME] = Player(cid):getName(),
  1221. [TAG_ITEMCOUNT] = shop_amount[cid],
  1222. [TAG_TOTALCOST] = shop_cost[cid] * shop_amount[cid],
  1223. [TAG_ITEMNAME] = shop_rlname[cid]
  1224. }
  1225.  
  1226. if(shop_eventtype[cid] == SHOPMODULE_SELL_ITEM) then
  1227. local ret = doPlayerSellItem(cid, shop_itemid[cid], shop_amount[cid], shop_cost[cid] * shop_amount[cid])
  1228. if(ret == LUA_NO_ERROR) then
  1229. local msg = module.npcHandler:getMessage(MESSAGE_ONSELL)
  1230. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1231. module.npcHandler:say(msg, cid)
  1232. else
  1233. local msg = module.npcHandler:getMessage(MESSAGE_MISSINGITEM)
  1234. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1235. module.npcHandler:say(msg, cid)
  1236. end
  1237. elseif(shop_eventtype[cid] == SHOPMODULE_BUY_ITEM) then
  1238. local cost = shop_cost[cid] * shop_amount[cid]
  1239. if Player(cid):getMoney() < cost then
  1240. local msg = module.npcHandler:getMessage(MESSAGE_MISSINGMONEY)
  1241. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1242. module.npcHandler:say(msg, cid)
  1243. return false
  1244. end
  1245.  
  1246. local a, b = doNpcSellItem(cid, shop_itemid[cid], shop_amount[cid], shop_subtype[cid], false, false, 1988)
  1247. if(a < shop_amount[cid]) then
  1248. local msgId = MESSAGE_NEEDMORESPACE
  1249. if(a == 0) then
  1250. msgId = MESSAGE_NEEDSPACE
  1251. end
  1252.  
  1253. local msg = module.npcHandler:getMessage(msgId)
  1254. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1255. module.npcHandler:say(msg, cid)
  1256. if(a > 0) then
  1257. Player(cid):removeMoney(a * shop_cost[cid])
  1258. if shop_itemid[cid] == ITEM_PARCEL then
  1259. doNpcSellItem(cid, ITEM_LABEL, shop_amount[cid], shop_subtype[cid], true, false, 1988)
  1260. end
  1261. return true
  1262. end
  1263. return false
  1264. else
  1265. local msg = module.npcHandler:getMessage(MESSAGE_ONBUY)
  1266. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1267. module.npcHandler:say(msg, cid)
  1268. Player(cid):removeMoney(cost)
  1269. if shop_itemid[cid] == ITEM_PARCEL then
  1270. doNpcSellItem(cid, ITEM_LABEL, shop_amount[cid], shop_subtype[cid], true, false, 1988)
  1271. end
  1272. return true
  1273. end
  1274. elseif(shop_eventtype[cid] == SHOPMODULE_BUY_ITEM_CONTAINER) then
  1275. local ret = doPlayerBuyItemContainer(cid, shop_container[cid], shop_itemid[cid], shop_amount[cid], shop_cost[cid] * shop_amount[cid], shop_subtype[cid])
  1276. if(ret == LUA_NO_ERROR) then
  1277. local msg = module.npcHandler:getMessage(MESSAGE_ONBUY)
  1278. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1279. module.npcHandler:say(msg, cid)
  1280. else
  1281. local msg = module.npcHandler:getMessage(MESSAGE_MISSINGMONEY)
  1282. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1283. module.npcHandler:say(msg, cid)
  1284. end
  1285. end
  1286.  
  1287. module.npcHandler:resetNpc(cid)
  1288. return true
  1289. end
  1290.  
  1291. -- onDecline keyword callback function. Generally called when the player sais "no" after wanting to buy an item.
  1292. function ShopModule.onDecline(cid, message, keywords, parameters, node)
  1293. local module = parameters.module
  1294. if(not module.npcHandler:isFocused(cid)) or shop_npcuid[cid] ~= getNpcCid() then
  1295. return false
  1296. end
  1297. shop_npcuid[cid] = 0
  1298.  
  1299. local parentParameters = node:getParent():getParameters()
  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. local msg = module.npcHandler:parseMessage(module.noText, parseInfo)
  1308. module.npcHandler:say(msg, cid)
  1309. module.npcHandler:resetNpc(cid)
  1310. return true
  1311. end
  1312.  
  1313. -- tradeItem callback function. Makes the npc say the message defined by MESSAGE_BUY or MESSAGE_SELL
  1314. function ShopModule.tradeItem(cid, message, keywords, parameters, node)
  1315. local module = parameters.module
  1316. if(not module.npcHandler:isFocused(cid)) then
  1317. return false
  1318. end
  1319.  
  1320. if(not module.npcHandler:onTradeRequest(cid)) then
  1321. return true
  1322. end
  1323.  
  1324. local count = module:getCount(message)
  1325. module.amount = count
  1326.  
  1327. shop_amount[cid] = module.amount
  1328. shop_cost[cid] = parameters.cost
  1329. shop_rlname[cid] = parameters.realName
  1330. shop_itemid[cid] = parameters.itemid
  1331. shop_container[cid] = parameters.container
  1332. shop_npcuid[cid] = getNpcCid()
  1333. shop_eventtype[cid] = parameters.eventType
  1334. shop_subtype[cid] = parameters.subType
  1335.  
  1336. local parseInfo = {
  1337. [TAG_PLAYERNAME] = Player(cid):getName(),
  1338. [TAG_ITEMCOUNT] = shop_amount[cid],
  1339. [TAG_TOTALCOST] = shop_cost[cid] * shop_amount[cid],
  1340. [TAG_ITEMNAME] = shop_rlname[cid]
  1341. }
  1342.  
  1343. if(shop_eventtype[cid] == SHOPMODULE_SELL_ITEM) then
  1344. local msg = module.npcHandler:getMessage(MESSAGE_SELL)
  1345. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1346. module.npcHandler:say(msg, cid)
  1347. elseif(shop_eventtype[cid] == SHOPMODULE_BUY_ITEM) then
  1348. local msg = module.npcHandler:getMessage(MESSAGE_BUY)
  1349. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1350. module.npcHandler:say(msg, cid)
  1351. elseif(shop_eventtype[cid] == SHOPMODULE_BUY_ITEM_CONTAINER) then
  1352. local msg = module.npcHandler:getMessage(MESSAGE_BUY)
  1353. msg = module.npcHandler:parseMessage(msg, parseInfo)
  1354. module.npcHandler:say(msg, cid)
  1355. end
  1356. return true
  1357. end
  1358. end
Add Comment
Please, Sign In to add comment