Este é um NPC system do Jiddo da Equipe SVN criadora do Open Tibia
Características da versão 2.00:
- Classbased object structure*
- Sistema da fila do npc com suporte para uma quantidade infinita de jogadores em espera. - Sistema de manipulação avançado de keyword. Agora também com sustentação prolongada para quase tudo.
- Classe simples de NpcHandler para a maioria das características básicas do npc. - Distance checking system
- Comprar muitos items stackable non-stackable de uma só vez por exemplo 150 hams e 320 meats.
Tudo isto faz possível fazer enormes os npcs avançados da loja (e outros)
que usam somente aproximadamente 50-100 linhas no lua dos arquivos dos npcs.
Está aqui o código:
Colocar isto nos dados/global.lua:
ITEM_GOLD_COIN = 2148 ITEM_PLATINUM_COIN = 2152 ITEM_CRYSTAL_COIN = 2160 function doPlayerGiveItem(cid, itemid, stackable, count) while count > 0 do local tempcount = 0 if(stackable == true) then tempcount = math.min (100, count) else tempcount = 1 end local ret = doPlayerAddItem(cid, itemid, tempcount) if(ret == LUA_ERROR) then ret = doCreateItem(itemid, tempcount, getPlayerPosition(cid)) end if(ret ~= LUA_ERROR) then count = count-tempcount else return LUA_ERROR end end return LUA_NO_ERROR end function doPlayerTakeItem(cid, itemid, stackable, count) if(getPlayerItemCount(cid,itemid) >= count) then while count > 0 do local tempcount = 0 if(stackable == true) then tempcount = math.min (100, count) else tempcount = 1 end local ret = doPlayerRemoveItem(cid, itemid, tempcount) if(ret ~= LUA_ERROR) then count = count-tempcount else return LUA_ERROR end end if(count == 0) then return LUA_NO_ERROR end else return LUA_ERROR end end function doPlayerAddMoney(cid, amount) local crystals = math.floor(amount/10000) amount = amount - crystals*10000 local platinum = math.floor(amount/100) amount = amount - platinum*100 local gold = amount local ret = 0 if(crystals > 0) then ret = doPlayerGiveItem(cid, ITEM_CRYSTAL_COIN, true, crystals) if(ret ~= LUA_NO_ERROR) then return LUA_ERROR end end if(platinum > 0) then ret = doPlayerGiveItem(cid, ITEM_PLATINUM_COIN, true, platinum) if(ret ~= LUA_NO_ERROR) then return LUA_ERROR end end if(gold > 0) then ret = doPlayerGiveItem(cid, ITEM_GOLD_COIN, true, gold) if(ret ~= LUA_NO_ERROR) then return LUA_ERROR end end return LUA_NO_ERROR end function doPlayerBuyItem(cid, itemid, stackable, count, price) if(doPlayerRemoveMoney(cid, price) == TRUE) then return doPlayerGiveItem(cid, itemid, stackable, count) else return LUA_ERROR end end function doPlayerBuyRune(cid, itemid, count, charges, price) if(doPlayerRemoveMoney(cid, price) == TRUE) then local ret = 0 for i = 1, count do ret = doPlayerGiveItem(cid, itemid, true, charges) end return ret --return doPlayerGiveItem(cid, itemid, true, charges) else return LUA_ERROR end end function doPlayerSellItem(cid, itemid, stackable, count, price) if(doPlayerTakeItem(cid, itemid, stackable, count) == LUA_NO_ERROR) then doPlayerAddMoney(cid, price) return LUA_NO_ERROR else return LUA_ERROR end end
Colocar isto em seus dados/npc/certificados/lib/npc.lua:
(Se você tiver já uma ou mais destas funções, remover as antigas!)
TALKSTATE_NONE = 0 TALKSTATE_SELL_ITEM = 1 TALKSTATE_BUY_ITEM = 2 -- get the distance to a creature function getDistanceToCreature(id) if id == 0 or id == nil then -- return 0 end local cx, cy, cz = creatureGetPosition(id) if cx == nil then return 100 end local sx, sy, sz = selfGetPosition() if(cz ~= sz) then return 100 end return math.max(math.abs(sx-cx), math.abs(sy-cy)) end -- do one step to reach position function moveToPosition(x,y,z) selfMoveTo(x, y, z) end -- do one step to reach creature function moveToCreature(id) if id == 0 or id == nil then selfGotoIdle() end local tx,ty,tz=creatureGetPosition(id) if tx == nil then -- else moveToPosition(tx, ty, tz) end end CustomerQueue = { customers = nil, handler = nil } function CustomerQueue:new(o) o = o or {} -- create object if user does not provide one setmetatable(o, self) self.__index = self return o end function CustomerQueue:removeFirst() table.remove(self.customers, 1) end function CustomerQueue:pushBack(cid) table.insert(self.customers, cid) end function CustomerQueue:getFirst() return self.customers[1] end function CustomerQueue:isInQueue(id) local pos = 1 while true do local value = self.customers[pos] if value == nil then return false else if value == id then return true end end pos = pos+1 end return false end function CustomerQueue:isEmpty() return (self:getFirst() == nil) end function CustomerQueue:greet(cid) selfSay('Hello, ' .. creatureGetName(cid) .. '! What a pleasent surprise.') self.handler:resetNpc() self.handler.focus = cid self.handler.talkStart = os.clock() end function CustomerQueue:canGreet(cid) local cx, cy, cz = creatureGetPosition(cid) if cx == nil then return false end local sx, sy, sz = selfGetPosition() local dist = math.max(math.abs(sx-cx), math.abs(sy-cy)) return (dist <= 4 and sz == cz) end function CustomerQueue:greetNext() while true do local first = self:getFirst() if(first == nil) then return false end if(not self:canGreet(first)) then self:removeFirst() else self:greet(first) self:removeFirst() return true end return true end return false end function getCount(msg) local ret = 1 local b, e = string.find(msg, "%d+") if b ~= nil and e ~= nil then ret = tonumber(string.sub(msg, b, e)) end return ret end function msgContains(message, keyword) return string.find(message, '(%a*)' .. keyword .. '(%a*)') end function walk(lastmove, spawn, dist) if(dist <= 0) then return 0 end if(os.time() - lastmove > 1) then local dir = math.random (0,3) sx, sy, sz = selfGetPosition() if(dir == DIRECTION_NORTH and (spawn.y-sy) >= dist) then return lastmove end if(dir == DIRECTION_SOUTH and (sy-spawn.y) >= dist) then return lastmove end if(dir == DIRECTION_EAST and (sx-spawn.x) >= dist) then return lastmove end if(dir == DIRECTION_WEST and (spawn.x-sx) >= dist) then return lastmove end selfMove(dir) lastmove = os.time() end return lastmove end function turnToCreature(cid, lastPos) local pos = getPlayerPosition(cid) local sx, sy, sz = selfGetPosition() if(pos == nil or sx == nil) then return else local dx = sx - pos.x local dy = sy - pos.y local direction = 0; local tan = 0; if(dx ~= 0) then tan = dy/dx; else tan = 10; end if(math.abs(tan) < 1) then if(dx > 0) then direction = 3; else direction = 1; end else if(dy > 0) then direction = 0; else direction = 2; end end selfTurn(direction) end end KeywordLevel = { keywords = {}, --children = {}, func = nil, parameters = {} } function KeywordLevel:new(o) o = o or {} -- create object if user does not provide one setmetatable(o, self) self.__index = self return o end function KeywordLevel:processMessage(cid, message) local i = 1 while true do local key = self.keywords[i] if(key == nil) then break end if(not self:checkKeyword(message, key)) then return false end i = i+1 end if(self.func == nil) then return true end return self.func(cid, message, self.keywords, self.parameters) end function KeywordLevel:checkKeyword(message, key) return msgContains(message, key) end KeywordHandler = { root = {} } function KeywordHandler:new(o) o = o or {} -- create object if user does not provide one setmetatable(o, self) self.__index = self return o end function KeywordHandler:processMessage(cid, message) local ret = false local i = 1 while true do local key = self.root[i] if(key == nil) then return false end ret = key:processMessage(cid, message) if(ret) then return ret end i = i+1 end return false end function KeywordHandler:addKeyword(keys, f, params) local new = KeywordLevel:new(nil) new.keywords = keys new.func = f new.parameters = params table.insert(self.root, new) end -- NpcHandler class start NpcHandler = { started = false, focus = 0, talkState = 0, talkStart = 0, lastPos = nil, lastMove = 0, queue = nil, keywordHandler = nil } function NpcHandler:new(o) o = o or {} -- create object if user does not provide one setmetatable(o, self) self.__index = self return o end function NpcHandler:resetNpc() self.focus = 0 self.talkState = 0 self.talkStart = 0 end function NpcHandler:onThingMove(creature, thing, oldpos, oldstackpos) end function NpcHandler:onCreatureAppear(creature) end function NpcHandler:onCreatureDisappear(cid) end function NpcHandler:onCreatureSay(cid, type, msg) end function NpcHandler:onThink() end function NpcHandler:init(costumerQueue, newKeywordHandler) if(self.started) then return end self.queue = costumerQueue self.keywordHandler = newKeywordHandler self:resetNpc() self.started = true end -- NpcHandler class end -- ShopHandler class start ShopNpcHandler = { itemid = 0, count = 0, charges = 0, cost = 0, stackable = false, walkDistance = 5, spawnPos = nil } ShopNpcHandler = NpcHandler:new(ShopNpcHandler) function ShopNpcHandler:setActiveItem(itemid, count, charges, cost, stackable) self.itemid = itemid self.count = count self.charges = charges self.cost = cost self.stackable = stackable end function ShopNpcHandler:resetNpc() self.focus = 0 self.talkState = 0 self.talkStart = 0 self.itemid = 0 self.count = 0 self.charges = 0 self.cost = 0 self.stackable = false end function ShopNpcHandler:onCreatureDisappear(cid) if(cid == self.focus) then self:resetNpc() self.queue:greetNext() end end function ShopNpcHandler:onCreatureSay(cid, type, msg) --Only allow players... if(isPlayer(cid) == 0) then return end local dist = getDistanceToCreature(cid) if dist > 4 then return end msg = string.lower(msg) if cid == self.focus then self.talkStart = os.clock() end local ret = self.keywordHandler:processMessage(cid, msg) if(ret == true) then return end if(cid == self.focus and self.talkState ~= TALKSTATE_NONE) then selfSay('I guess not then.') self.talkState = TALKSTATE_NONE return end end function ShopNpcHandler:onThink() if (os.clock() - self.talkStart) > 25 then if self.focus > 0 then selfSay('Next please!') end self:resetNpc() self.queue:greetNext() end local dist = getDistanceToCreature(self.focus) if dist > 4 then selfSay('Next please!') self:resetNpc() self.queue:greetNext() end if self.focus == 0 then if(self.spawnPos == nil) then local sx, sy, sz = selfGetPosition() self.spawnPos = {x = sx, y = sy, z = sz} end self.lastMove = walk(self.lastMove, self.spawnPos, self.walkDistance) else self.lastPos = turnToCreature(self.focus, self.lastPos) end end -- ShopHandler class end -- Default shop keyword handling functions... function ShopNpcHandler:defaultTradeHandler(cid, message, keywords, parameters) if self.focus ~= cid then return false end local tempcount = getCount(message) if(tempcount > 500) then tempcount = 500 end local itemname = keywords[1] if(keywords[1] == 'sell') then itemname = keywords[2] end if(parameters.realname ~= nil) then itemname = parameters.realname end local tradeKeyword = 'buy' if(keywords[1] == 'sell') then tradeKeyword = 'sell' end selfSay('Do you want to ' .. tradeKeyword .. ' ' .. tempcount .. ' ' .. itemname .. ' for ' .. parameters.cost*tempcount .. ' gold coins?') if(keywords[1] == 'sell') then self.talkState = TALKSTATE_SELL_ITEM else self.talkState = TALKSTATE_BUY_ITEM end self:setActiveItem(parameters.itemid, tempcount, parameters.charges, tempcount*parameters.cost, (parameters.stackable ~= nil and parameters.stackable == true)) return true end function ShopNpcHandler:defaultConfirmHandler(cid, message, keywords, parameters) if self.focus ~= cid then return false end if(keywords[1] == 'yes') then if(self.talkState == TALKSTATE_SELL_ITEM) then self.talkState = TALKSTATE_NONE local ret = doPlayerSellItem(self.focus, self.itemid, self.stackable, self.count, self.cost) if(ret == LUA_NO_ERROR) then selfSay('Thank you.') else selfSay('You do not have that item.') end elseif(self.talkState == TALKSTATE_BUY_ITEM) then self.talkState = TALKSTATE_NONE local ret = 0 if(self.charges == nil or self.charges <= 1) then ret = doPlayerBuyItem(self.focus, self.itemid, self.stackable, self.count, self.cost) else ret = doPlayerBuyRune(self.focus, self.itemid, self.count, self.charges, self.cost) end if(ret == LUA_NO_ERROR) then selfSay('Here you go.') else selfSay('You do not have enough money.') end end elseif(keywords[1] == 'no') then if(self.talkState == TALKSTATE_SELL_ITEM) then selfSay('I wouldnt sell that either.') self.talkState = TALKSTATE_NONE elseif(self.talkState == TALKSTATE_BUY_ITEM) then selfSay('Too expensive you think?') self.talkState = TALKSTATE_NONE end end return true end function NpcHandler:defaultMessageHandler(cid, message, keywords, parameters) if(not parameters.onlyfocus or (parameters.onlyfocus and cid == self.focus)) then selfSay(parameters.text) self.talkState = TALKSTATE_NONE return true end return false end function NpcHandler:defaultGreetHandler(cid, message, keywords, parameters) if self.focus == cid then selfSay('I am already talking to you.') self.talkStart = os.clock() elseif self.focus > 0 or not(self.queue:isEmpty()) then selfSay('Please, ' .. creatureGetName(cid) .. '. Wait for your turn!.') if(not self.queue:isInQueue(cid)) then self.queue:pushBack(cid) end elseif(self.focus == 0) and (self.queue:isEmpty()) then selfSay('Hello, ' .. creatureGetName(cid) .. '. Welcome to my shop!') self.focus = cid self.talkStart = os.clock() end return true end function NpcHandler:defaultFarewellHandler(cid, message, keywords, parameters) if(cid == self.focus) then selfSay('Farewell, ' .. creatureGetName(cid) .. '!') self:resetNpc() self.queue:greetNext() return true end return false end -- End
Então este são alguns exemplos de npcs que você pode-se usar:
local internalCustomerQueue = {} local keywordHandler = KeywordHandler:new({root = {}}) local npcHandler = ShopNpcHandler:new({}) local customerQueue = CustomerQueue:new({customers = internalCustomerQueue, handler = npcHandler}) npcHandler:init(customerQueue, keywordHandler) -- OTServ event handling functions start function onThingMove(creature, thing, oldpos, oldstackpos) npcHandler:onThingMove(creature, thing, oldpos, oldstackpos) end function onCreatureAppear(creature) npcHandler:onCreatureAppear(creature) end function onCreatureDisappear(id) npcHandler:onCreatureDisappear(id) end function onCreatureTurn(creature) npcHandler:onCreatureTurn(creature) end function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end function onCreatureChangeOutfit(creature) npcHandler:onCreatureChangeOutfit(creature) end function onThink() npcHandler:onThink() end -- OTServ event handling functions end -- Keyword handling functions start function tradeItem(cid, message, keywords, parameters) return npcHandler:defaultTradeHandler(cid, message, keywords, parameters) end function confirmAction(cid, message, keywords, parameters) return npcHandler:defaultConfirmHandler(cid, message, keywords, parameters) end function sayMessage(cid, message, keywords, parameters) return npcHandler:defaultMessageHandler(cid, message, keywords, parameters) end function greet(cid, message, keywords, parameters) return npcHandler:defaultGreetHandler(cid, message, keywords, parameters) end function farewell(cid, message, keywords, parameters) return npcHandler:defaultFarewellHandler(cid, message, keywords, parameters) end -- Keyword handling functions end -- Keyword structure generation start keywordHandler:addKeyword({'rope'}, tradeItem, {itemid = 2120, cost = 50}) keywordHandler:addKeyword({'shovel'}, tradeItem, {itemid = 2554, cost = 10}) keywordHandler:addKeyword({'torch'}, tradeItem, {itemid = 2050, cost = 2}) keywordHandler:addKeyword({'pick'}, tradeItem, {itemid = 2553, cost = 40}) keywordHandler:addKeyword({'machete'}, tradeItem, {itemid = 2420, cost = 30}) keywordHandler:addKeyword({'scythe'}, tradeItem, {itemid = 2550, cost = 30}) keywordHandler:addKeyword({'yes'}, confirmAction, nil) keywordHandler:addKeyword({'no'}, confirmAction, nil) keywordHandler:addKeyword({'offer'}, sayMessage, {text = 'I sell ropes, shovels, torches, picks, machetes and scythes.', onlyfocus = true}) keywordHandler:addKeyword({'sell'}, sayMessage, {text = 'Why would I need that rubbish?', onlyfocus = true}) keywordHandler:addKeyword({'job'}, sayMessage, {text = 'I seel all kinds of tools.', onlyfocus = true}) keywordHandler:addKeyword({'quest'}, sayMessage, {text = 'A quest is nothing I want to be involved in.', onlyfocus = true}) keywordHandler:addKeyword({'mission'},sayMessage, {text = 'I cannot help you in that area, son.', onlyfocus = true}) keywordHandler:addKeyword({'buy'}, sayMessage, {text = 'Sorry but I do not sell those.', onlyfocus = true}) keywordHandler:addKeyword({'hi'}, greet, nil) keywordHandler:addKeyword({'hello'}, greet, nil) keywordHandler:addKeyword({'hey'}, greet, nil) keywordHandler:addKeyword({'bye'}, farewell, nil) keywordHandler:addKeyword({'farewell'}, farewell, nil) -- Keyword structure generation end
Runeseller npc:
local internalCustomerQueue = {} local keywordHandler = KeywordHandler:new({root = {}}) local npcHandler = ShopNpcHandler:new({}) local customerQueue = CustomerQueue:new({customers = internalCustomerQueue, handler = npcHandler}) npcHandler:init(customerQueue, keywordHandler) -- OTServ event handling functions start function onThingMove(creature, thing, oldpos, oldstackpos) npcHandler:onThingMove(creature, thing, oldpos, oldstackpos) end function onCreatureAppear(creature) npcHandler:onCreatureAppear(creature) end function onCreatureDisappear(id) npcHandler:onCreatureDisappear(id) end function onCreatureTurn(creature) npcHandler:onCreatureTurn(creature) end function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end function onCreatureChangeOutfit(creature) npcHandler:onCreatureChangeOutfit(creature) end function onThink() npcHandler:onThink() end -- OTServ event handling functions end -- Keyword handling functions start function tradeItem(cid, message, keywords, parameters) return npcHandler:defaultTradeHandler(cid, message, keywords, parameters) end function confirmAction(cid, message, keywords, parameters) return npcHandler:defaultConfirmHandler(cid, message, keywords, parameters) end function sayMessage(cid, message, keywords, parameters) return npcHandler:defaultMessageHandler(cid, message, keywords, parameters) end function greet(cid, message, keywords, parameters) return npcHandler:defaultGreetHandler(cid, message, keywords, parameters) end function farewell(cid, message, keywords, parameters) return npcHandler:defaultFarewellHandler(cid, message, keywords, parameters) end -- Keyword handling functions end -- Buy item keywords keywordHandler:addKeyword({'heavy magic missile'}, tradeItem, {itemid = 2311, cost = 125, charges = 10, realname = "heavy magic missile rune"}) keywordHandler:addKeyword({'ultimate healing'}, tradeItem, {itemid = 2273, cost = 175, charges = 2, realname = "ultimate healing rune"}) keywordHandler:addKeyword({'sudden death'}, tradeItem, {itemid = 2268, cost = 325, charges = 2, realname = "sudden death rune"}) keywordHandler:addKeyword({'great fireball'}, tradeItem, {itemid = 2304, cost = 180, charges = 4, realname = "great fireball rune"}) keywordHandler:addKeyword({'explosion'}, tradeItem, {itemid = 2313, cost = 250, charges = 6, realname = "explosion rune"}) keywordHandler:addKeyword({'light wand'}, tradeItem, {itemid = 2163, cost = 500, realname = "magic light wand"}) keywordHandler:addKeyword({'lightwand'}, tradeItem, {itemid = 2163, cost = 500, realname = "magic light wand"}) keywordHandler:addKeyword({'mana fluid'}, tradeItem, {itemid = 2006, cost = 100, charges = 7}) keywordHandler:addKeyword({'manafluid'}, tradeItem, {itemid = 2006, cost = 100, charges = 7}) keywordHandler:addKeyword({'life fluid'}, tradeItem, {itemid = 2006, cost = 80, charges = 10}) keywordHandler:addKeyword({'lifefluid'}, tradeItem, {itemid = 2006, cost = 80, charges = 10}) keywordHandler:addKeyword({'life fluid'}, tradeItem, {itemid = 2006, cost = 80, charges = 10}) keywordHandler:addKeyword({'lifefluid'}, tradeItem, {itemid = 2006, cost = 80, charges = 10}) keywordHandler:addKeyword({'blank'}, tradeItem, {itemid = 2260, cost = 10, realname = "blank rune"}) keywordHandler:addKeyword({'xpl'}, tradeItem, {itemid = 2313, cost = 250, charges = 6, realname = "explosion rune"}) keywordHandler:addKeyword({'explo'}, tradeItem, {itemid = 2313, cost = 250, charges = 6, realname = "explosion rune"}) keywordHandler:addKeyword({'gfb'}, tradeItem, {itemid = 2304, cost = 180, charges = 4, realname = "great fireball rune"}) keywordHandler:addKeyword({'sd'}, tradeItem, {itemid = 2268, cost = 325, charges = 2, realname = "sudden death rune"}) keywordHandler:addKeyword({'uh'}, tradeItem, {itemid = 2273, cost = 175, charges = 2, realname = "ultimate healing rune"}) keywordHandler:addKeyword({'hmm'}, tradeItem, {itemid = 2311, cost = 125, charges = 10, realname = "heavy magic missile rune"}) keywordHandler:addKeyword({'rune'}, tradeItem, {itemid = 2260, cost = 20, realname = "blank rune"}) -- Confirm sell/buy keywords keywordHandler:addKeyword({'yes'}, confirmAction) keywordHandler:addKeyword({'no'}, confirmAction) -- General message keywords keywordHandler:addKeyword({'offer'}, sayMessage, {text = 'I offer several kinds of magical runes and other magical items.'}) keywordHandler:addKeyword({'sell'}, sayMessage, {text = 'Why would I need that rubbish?'}) keywordHandler:addKeyword({'job'}, sayMessage, {text = 'I am the shopkeeper of this magic shop.'}) keywordHandler:addKeyword({'quest'}, sayMessage, {text = 'A quest is nothing I want to be involved in.'}) keywordHandler:addKeyword({'mission'},sayMessage, {text = 'I cannot help you in that area, son.'}) keywordHandler:addKeyword({'buy'}, sayMessage, {text = 'I cannot sell that.'}) keywordHandler:addKeyword({'hi'}, greet, nil) keywordHandler:addKeyword({'hello'}, greet, nil) keywordHandler:addKeyword({'hey'}, greet, nil) keywordHandler:addKeyword({'bye'}, farewell, nil) keywordHandler:addKeyword({'farewell'}, farewell, nil)
Oracle npc:
local internalCustomerQueue = {} local keywordHandler = KeywordHandler:new({root = {}}) local npcHandler = ShopNpcHandler:new({}) local customerQueue = CustomerQueue:new({customers = internalCustomerQueue, handler = npcHandler}) npcHandler:init(customerQueue, keywordHandler) npcHandler.walkDistance = 0 local voc = 0 -- OTServ event handling functions start function onThingMove(creature, thing, oldpos, oldstackpos) npcHandler:onThingMove(creature, thing, oldpos, oldstackpos) end function onCreatureAppear(creature) npcHandler:onCreatureAppear(creature) end function onCreatureDisappear(id) npcHandler:onCreatureDisappear(id) end function onCreatureTurn(creature) npcHandler:onCreatureTurn(creature) end function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end function onCreatureChangeOutfit(creature) npcHandler:onCreatureChangeOutfit(creature) end function onThink() npcHandler:onThink() end -- OTServ event handling functions end -- Keyword handling functions start function sayMessage(cid, message, keywords, parameters) return npcHandler:defaultMessageHandler(cid, message, keywords, parameters) end function greet(cid, message, keywords, parameters) -- We do not want to use the default "Welcome to my shop" thingie for this npc, so we'll just make this ourselves! if npcHandler.focus == cid then selfSay('I am already talking to you.') npcHandler.talkStart = os.clock() elseif npcHandler.focus > 0 or not(npcHandler.queue:isEmpty()) then selfSay('Please, ' .. creatureGetName(cid) .. '. Wait for your turn!.') if(not npcHandler.queue:isInQueue(cid)) then npcHandler.queue:pushBack(cid) end elseif(npcHandler.focus == 0) and (npcHandler.queue:isEmpty()) then selfSay(creatureGetName(cid) .. '! Are you prepared you face your destiny?') npcHandler.focus = cid voc = 0 npcHandler.talkStart = os.clock() end return true end function farewell(cid, message, keywords, parameters) return npcHandler:defaultFarewellHandler(cid, message, keywords, parameters) end -- Keyword handling functions end function confirmAction(cid, message, keywords, parameters) if(cid ~= npcHandler.focus) then return false end if(keywords[1] == 'yes') then if(getPlayerLevel(cid) < 8) then selfSay('You are not yet worthy. Come back when you are ready!') npcHandler:resetNpc() voc = 0 return true end if(voc == 0) then selfSay('Allright then. What vocation do you wish to become? A sorcerer, druid, paladin or knight?') else doPlayerSetVocation(npcHandler.focus,voc) local pos = { x=939, y=263, z=7 } doPlayerSetMasterPos(npcHandler.focus,pos) doTeleportThing(npcHandler.focus,pos) voc = 0 end elseif(keywords[1] == 'no') then if(voc == 0) then selfSay('Then come back when you are ready!') npcHandler.focus = 0 voc = 0 if not(queue[1] == nil) then greetNextCostumer(queue) end else selfSay('Allright then. What vocation do you wish to become? A sorcerer, druid, paladin or knight?') voc = 0 end end return true end function selectVocation(cid, message, keywords, parameters) if(cid ~= npcHandler.focus) then return false end selfSay('Are you sure that you wish to become a ' .. keywords[1] .. '? This decition is irreversible!') voc = parameters.voc return true end keywordHandler:addKeyword({'sorcerer'}, selectVocation, {voc = 1}) keywordHandler:addKeyword({'druid'}, selectVocation, {voc = 2}) keywordHandler:addKeyword({'paladin'}, selectVocation, {voc = 3}) keywordHandler:addKeyword({'knight'}, selectVocation, {voc = 4}) -- Confirm sell/buy keywords keywordHandler:addKeyword({'yes'}, confirmAction) keywordHandler:addKeyword({'no'}, confirmAction) keywordHandler:addKeyword({'hi'}, greet, nil) keywordHandler:addKeyword({'hello'}, greet, nil) keywordHandler:addKeyword({'hey'}, greet, nil) keywordHandler:addKeyword({'bye'}, farewell, nil) keywordHandler:addKeyword({'farewell'}, farewell, nil)
Exemplo postal do npc (lhe dá um label “gratis” quando se compra um parcel):
local internalCustomerQueue = {} local keywordHandler = KeywordHandler:new({root = {}}) local npcHandler = ShopNpcHandler:new({}) local customerQueue = CustomerQueue:new({customers = internalCustomerQueue, handler = npcHandler}) npcHandler:init(customerQueue, keywordHandler) -- OTServ event handling functions start function onThingMove(creature, thing, oldpos, oldstackpos) npcHandler:onThingMove(creature, thing, oldpos, oldstackpos) end function onCreatureAppear(creature) npcHandler:onCreatureAppear(creature) end function onCreatureDisappear(id) npcHandler:onCreatureDisappear(id) end function onCreatureTurn(creature) npcHandler:onCreatureTurn(creature) end function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end function onCreatureChangeOutfit(creature) npcHandler:onCreatureChangeOutfit(creature) end function onThink() npcHandler:onThink() end -- OTServ event handling functions end -- Keyword handling functions start function tradeItem(cid, message, keywords, parameters) return npcHandler:defaultTradeHandler(cid, message, keywords, parameters) end --function confirmAction(cid, message, keywords, parameters) return npcHandler:defaultConfirmHandler(cid, message, keywords, parameters) end function sayMessage(cid, message, keywords, parameters) return npcHandler:defaultMessageHandler(cid, message, keywords, parameters) end function greet(cid, message, keywords, parameters) return npcHandler:defaultGreetHandler(cid, message, keywords, parameters) end function farwell(cid, message, keywords, parameters) return npcHandler:defaultFarwellHandler(cid, message, keywords, parameters) end -- Keyword handling functions end function confirmAction(cid, message, keywords, parameters) if(cid ~= npcHandler.focus) then return false end if(keywords[1] == 'yes') then if(talkcount == 1) then talkcount = 0 if(itemid == 2595) then local ret = chargeMoney(itemid, cost) if(ret == 1) then SellItem(focus,itemid,count,0) SellItem(focus,2199,count,0) else selfSay('Sorry, you do not have enough money.') end else SellItem(focus,itemid,count,cost) end elseif(talkcount == 2) then talkcount = 0 if(charges ~= nil and charges ~= 0) then BuyRune(focus, itemid, count, charges, cost) else tradeItem(focus,itemid,count,cost) end end elseif(keywords[1] == 'no') then if(talkcount == 1) then selfSay('I wouldnt sell that either.') talkcount = 0 elseif(talkcount == 2) then selfSay('Too expensive you think?') talkcount = 0 end end return true end -- Buy item keywords keywordHandler:addKeyword({'parcel'}, tradeItem, {itemid = 2595, cost = 15}) keywordHandler:addKeyword({'letter'}, tradeItem, {itemid = 2597, cost = 5}) keywordHandler:addKeyword({'label'}, tradeItem, {itemid = 2199, cost = 2}) -- Confirm sell/buy keywords keywordHandler:addKeyword({'yes'}, confirmAction) keywordHandler:addKeyword({'no'}, confirmAction) -- General message keywords keywordHandler:addKeyword({'offer'}, sayMessage, {text = 'I sell parcels, letters and labels.'}) keywordHandler:addKeyword({'sell'}, sayMessage, {text = 'Why would I need that rubbish?'}) keywordHandler:addKeyword({'job'}, sayMessage, {text = 'I am an official postman of this city!'}) keywordHandler:addKeyword({'quest'}, sayMessage, {text = '...'}) keywordHandler:addKeyword({'mission'},sayMessage, {text = 'I know nothing about that.'}) keywordHandler:addKeyword({'buy'}, sayMessage, {text = 'I do not sell any of those.'}) keywordHandler:addKeyword({'hi'}, greet, nil) keywordHandler:addKeyword({'hello'}, greet, nil) keywordHandler:addKeyword({'hey'}, greet, nil) keywordHandler:addKeyword({'bye'}, farwell, nil) keywordHandler:addKeyword({'farewell'}, farwell, nil)
NPC buys and sells gems
local internalCustomerQueue = {} local keywordHandler = KeywordHandler:new({root = {}}) local npcHandler = ShopNpcHandler:new({}) local customerQueue = CustomerQueue:new({customers = internalCustomerQueue, handler = npcHandler}) npcHandler:init(customerQueue, keywordHandler) -- OTServ event handling functions start function onThingMove(creature, thing, oldpos, oldstackpos) npcHandler:onThingMove(creature, thing, oldpos, oldstackpos) end function onCreatureAppear(creature) npcHandler:onCreatureAppear(creature) end function onCreatureDisappear(id) npcHandler:onCreatureDisappear(id) end function onCreatureTurn(creature) npcHandler:onCreatureTurn(creature) end function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end function onCreatureChangeOutfit(creature) npcHandler:onCreatureChangeOutfit(creature) end function onThink() npcHandler:onThink() end -- OTServ event handling functions end -- Keyword handling functions start function tradeItem(cid, message, keywords, parameters) return npcHandler:defaultTradeHandler(cid, message, keywords, parameters) end function confirmAction(cid, message, keywords, parameters) return npcHandler:defaultConfirmHandler(cid, message, keywords, parameters) end function sayMessage(cid, message, keywords, parameters) return npcHandler:defaultMessageHandler(cid, message, keywords, parameters) end function greet(cid, message, keywords, parameters) return npcHandler:defaultGreetHandler(cid, message, keywords, parameters) end function farwell(cid, message, keywords, parameters) return npcHandler:defaultFarwellHandler(cid, message, keywords, parameters) end -- Keyword handling functions end -- Sell item keywords keywordHandler:addKeyword({'sell', 'small amethyst'}, tradeItem, {itemid = 2150, cost = 200, stackable = true}) keywordHandler:addKeyword({'sell', 'small diamond'}, tradeItem, {itemid = 2145, cost = 300, stackable = true}) keywordHandler:addKeyword({'sell', 'small emerald'}, tradeItem, {itemid = 2145, cost = 250, stackable = true}) keywordHandler:addKeyword({'sell', 'small ruby'}, tradeItem, {itemid = 2147, cost = 250, stackable = true}) keywordHandler:addKeyword({'sell', 'small rubie'}, tradeItem, {itemid = 2147, cost = 250, stackable = true}) keywordHandler:addKeyword({'sell', 'small sapphire'}, tradeItem, {itemid = 2146, cost = 250, stackable = true}) keywordHandler:addKeyword({'sell', 'black pearl'}, tradeItem, {itemid = 2143, cost = 160, stackable = true}) keywordHandler:addKeyword({'sell', 'white pearl'}, tradeItem, {itemid = 2144, cost = 280, stackable = true}) -- Buy item keywords keywordHandler:addKeyword({'small amethyst'}, tradeItem, {itemid = 2150, cost = 420, stackable = true}) keywordHandler:addKeyword({'small diamond'}, tradeItem, {itemid = 2145, cost = 640, stackable = true}) keywordHandler:addKeyword({'small emerald'}, tradeItem, {itemid = 2145, cost = 530, stackable = true}) keywordHandler:addKeyword({'small ruby'}, tradeItem, {itemid = 2147, cost = 540, stackable = true}) keywordHandler:addKeyword({'small rubie'}, tradeItem, {itemid = 2147, cost = 540, stackable = true}) keywordHandler:addKeyword({'small sapphire'}, tradeItem, {itemid = 2146, cost = 520, stackable = true}) keywordHandler:addKeyword({'black pearl'}, tradeItem, {itemid = 2143, cost = 330, stackable = true}) keywordHandler:addKeyword({'white pearl'}, tradeItem, {itemid = 2144, cost = 570, stackable = true}) -- Confirm sell/buy keywords keywordHandler:addKeyword({'yes'}, confirmAction) keywordHandler:addKeyword({'no'}, confirmAction) -- General message keywords keywordHandler:addKeyword({'offer'}, sayMessage, {text = 'I sell the most beutiful gems in the world.'}) keywordHandler:addKeyword({'sell'}, sayMessage, {text = 'Why would I need that rubbish?'}) keywordHandler:addKeyword({'job'}, sayMessage, {text = 'I buy and sell all kinds of pearls, diamonds, rubies, sapphires and amethysts!'}) keywordHandler:addKeyword({'quest'}, sayMessage, {text = 'A quest is nothing I want to be involved in.'}) keywordHandler:addKeyword({'mission'},sayMessage, {text = 'I cannot help you in that area, son.'}) keywordHandler:addKeyword({'buy'}, sayMessage, {text = 'Sorry, but I do not sell any items right now.'}) keywordHandler:addKeyword({'hi'}, greet, nil) keywordHandler:addKeyword({'hello'}, greet, nil) keywordHandler:addKeyword({'hey'}, greet, nil) keywordHandler:addKeyword({'bye'}, farwell, nil) keywordHandler:addKeyword({'farewell'}, farwell, nil)
Atenciosamente,
//Lithium