Guest User

modules

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