Guest User

Untitled

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