Guest User

Modules.lua

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