CH

[ Resolvido ]Ajuda No Script Npc

Por chavephilips, 10 de abr. de 2012 em Scripts

otserv
tibia
script
9
3.1k
10 de abril de 2012 às 12:51

Rapaiz, todo dia tenho uma dúvida smile_positivo.gif

 

TFS: 0.4

Cliente: 8.6

 

Bom, eu queria criar um npc que quando o player fosse "male" ele falasse:

"Welcome Mr. |PLAYERNAME|, want look my pearls? {Trade} with me!"

 

e quando fosse "female" falasse:

"Welcome Mrs. |PLAYERNAME|, want look my pearls? {Trade} with me!

 

Ou seja, só muda o Mr. e o Mrs.

 

Eu percebi que não sei nada de LUA quando tentei fazer esse mísero script e não consegui blush.png

 

local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
function onCreatureAppear(cid)
npcHandler:onCreatureAppear(cid)   end
function onCreatureDisappear(cid)  npcHandler:onCreatureDisappear(cid)  
end
function onCreatureSay(cid, type, msg)  npcHandler:onCreatureSay(cid, type, msg)  end
function onThink()  
npcHandler:onThink()	 end

getPlayerSex(cid)
PLAYERSEX_FEMALE = 0
PLAYERSEX_MALE = 1
ifgetPlayerSex(cid) == PLAYERSEX_FEMALE and (msgcontains(msg, 'hi','hello') then
  selfSay('Welcome Mrs. ' .. creatureGetName(cid) .. ',want to look my pearls? {Trade} with me!')
 else
selfSay('Welcome Mr. ' .. creatureGetName(cid) .. 'want to look my pearls? {Trade} with me!')

end
npcHandler:addModule(FocusModule:new())

 

Então, quem puder (e quiser) ajudar essa pobre alma que não sabe fazer nenhum script, por favor.

SkyDangerousS
10 de abril de 2012 às 13:05

Não ha necessidade disso.

 

 

getPlayerSex(cid)

PLAYERSEX_FEMALE = 0

PLAYERSEX_MALE = 1

 

 

 

e isso

 

ifgetPlayerSex(cid) == PLAYERSEX_FEMALE and (msgcontains(msg, 'hi','hello') then

 

deve ter espaço

 

if getPlayerSex(cid) == PLAYERSEX_FEMALE and (msgcontains(msg, 'hi','hello') then

VodkartV
10 de abril de 2012 às 14:30

function onCreatureSay(cid, type, msg)
local cid_Say = msg:lower()
if ((cid_Say == "hi") and not (isFocused(cid, focuses))) then
selfSay('Welcome '.. (getPlayerSex(cid) == PLAYERSEX_FEMALE and 'Mrs' or 'Mr') ..'. ' .. getPlayerName(cid) .. ',want to look my pearls? {Trade} with me!')
end
end

 

 

---

editando a lib do npc fica mais fácil, pq dai da pra fazer pelo xml usando por exemplo |PLAYERSEX|

Editado Abril 10 por Vodkart

10 de abril de 2012 às 14:55

O script não funcionou muito bem, mas como você disse, seria melhor editar a lib.

 

Você poderia me ajudar com isso? seria em modules.lua?

 

Obrigado por enquanto mdr.gif

VodkartV
10 de abril de 2012 às 15:25

O script não funcionou muito bem, mas como você disse, seria melhor editar a lib.

 

Você poderia me ajudar com isso? seria em modules.lua?

 

Obrigado por enquanto mdr.gif

jura que não funcionou? nem passei todo o script, e essa função 'creatureGetName(cid)' não existe.

 

------------------------------------------------------------------

 

 

nome do seu npc.xml

<?xml version="1.0" encoding="UTF-8"?>
<npc name="Nome do seu npc" script="nome do seu script.lua" walkinterval="2000" floorchange="0">
<health now="100" max="100"/>
<look type="133" head="114" body="119" legs="132" feet="114"/>
</npc>

 

 

 

nome do seu script.lua

dofile("data/npc/lib/npc-func.lua")
local focuses = {} -- do not change
function onCreatureSay(cid, type, msg)
local cid_Say = msg:lower()
if ((cid_Say == "hi") and not (isFocused(cid, focuses))) then
selfSay('Welcome '.. (getPlayerSex(cid) == PLAYERSEX_FEMALE and 'Mrs' or 'Mr') ..'. ' .. getPlayerName(cid) .. ',want to look my pearls? {Trade} with me!')
end
end
function onThink()
for _, focus in pairs(focuses) do
	if not isCreature(focus) then
	 removeFocus(focus, focuses)
	  talk_step = 0
	else
	 local distance = getDistanceTo(focus) or 5
		if distance > 4 then
			selfSay("Hmpf!", focus)
			removeFocus(focus, focuses)
		   talk_step = 0
		end
	end
end
setFocus(focuses)
end

 

 

crie um arquivo chamado "npc-func.lua" em "data/npc/lib" e poe isso

 

local focuses = {}
function isFocused(cid, t)
for i, v in pairs(t) do
	if(v == cid) then
		return true
	end
end
return false
end

function addFocus(cid, t)
if(not isFocused(cid, t)) then
	table.insert(t, cid)
end
end

function setFocus(t)
for i, v in pairs(t) do
	if(isPlayer(v)) then
		doNpcSetCreatureFocus(v)
		return
	end
end
doNpcSetCreatureFocus(0)
end

function removeFocus(cid, t)
for i, v in pairs(t) do
	if(v == cid) then
		table.remove(t, i)
		setFocus(focuses)
		break
	end
end
end

function onCreatureDisappear(cid)
if isFocused(cid, focuses) then
 removeFocus(cid, focuses)
	if isPlayer(cid) then
	 closeShopWindow(cid)
	end
end
end

Editado Abril 10 por Vodkart

10 de abril de 2012 às 16:20

Caraca surprised.gif

 

Desculpa falar isso mas, o script não fala no NPC Channel (fala no default), mas o Mr. e o Mrs. funcionaram direito.

 

Não teria como fazer o que você falou lá em cima do |PLAYERSEX| ?

 

 

 

Muitíssimo obrigado por enquanto positive.gif

VodkartV
10 de abril de 2012 às 18:17

Caraca surprised.gif

 

Desculpa falar isso mas, o script não fala no NPC Channel (fala no default), mas o Mr. e o Mrs. funcionaram direito.

 

Não teria como fazer o que você falou lá em cima do |PLAYERSEX| ?

 

 

 

Muitíssimo obrigado por enquanto positive.gif

ok

 

Primeiro vai em Data/lib/functions e adc essa função:

 

function getMrSex(cid)
return (getPlayerSex(cid) == PLAYERSEX_FEMALE and 'Mrs' or 'Mr')
end

 

Agora vamos para lib do npc

 

em Data/npc/lib/npcsystem

 

modules.lua

 

-- Advanced NPC System (Created by Jiddo),
-- Modified by Talaturen.
-- Modified by Elf.

if(Modules == nil) then
-- default words for greeting and ungreeting the npc. Should be a table containing all such words.
FOCUS_GREETWORDS = {'hi', 'hello', 'hey'}
FOCUS_FAREWELLWORDS = {'bye', 'farewell', 'cya'}

-- The words for requesting trade window.
SHOP_TRADEREQUEST = {'offer', 'trade'}

-- The word for accepting/declining an offer. CAN ONLY CONTAIN ONE FIELD! Should be a teble with a single string value.
SHOP_YESWORD = {'yes'}
SHOP_NOWORD = {'no'}

-- Pattern used to get the amount of an item a player wants to buy/sell.
PATTERN_COUNT = '%d+'

-- Constants used to separate buying from selling.
SHOPMODULE_SELL_ITEM = 1
SHOPMODULE_BUY_ITEM = 2
SHOPMODULE_BUY_ITEM_CONTAINER = 3

-- Constants used for shop mode. Notice: addBuyableItemContainer is working on all modes
SHOPMODULE_MODE_TALK = 1 -- Old system used before Tibia 8.2: sell/buy item name
SHOPMODULE_MODE_TRADE = 2 -- Trade window system introduced in Tibia 8.2
SHOPMODULE_MODE_BOTH = 3 -- Both working at one time

-- Used shop mode
SHOPMODULE_MODE = SHOPMODULE_MODE_BOTH

Modules = {
parseableModules = {}
}

StdModule = {}

-- These callback function must be called with parameters.npcHandler = npcHandler in the parameters table or they will not work correctly.
-- Notice: The members of StdModule have not yet been tested. If you find any bugs, please report them to me.
-- Usage:
-- keywordHandler:addKeyword({'offer'}, StdModule.say, {npcHandler = npcHandler, text = 'I sell many powerful melee weapons.'})
function StdModule.say(cid, message, keywords, parameters, node)
local npcHandler = parameters.npcHandler
if(npcHandler == nil) then
error('StdModule.say called without any npcHandler instance.')
end

local onlyFocus = (parameters.onlyFocus == nil or parameters.onlyFocus == true)
if(not npcHandler:isFocused(cid) and onlyFocus) then
return false
end

local parseInfo = {[TAG_PLAYERNAME] = getCreatureName(cid), [TAG_PLAYERSEX] = getMrSex(cid)}
npcHandler:say(npcHandler:parseMessage(parameters.text or parameters.message, parseInfo), cid, parameters.publicize and true)
if(parameters.reset == true) then
npcHandler:resetNpc()
elseif(parameters.moveup ~= nil and type(parameters.moveup) == 'number') then
npcHandler.keywordHandler:moveUp(parameters.moveup)
end

return true
end

--Usage:
-- 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?'})
--  node1:addChildKeyword({'yes'}, StdModule.promotePlayer, {npcHandler = npcHandler, cost = 20000, promotion = 1, level = 20}, text = 'Congratulations! You are now promoted.')
--  node1:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, text = 'Alright then, come back when you are ready.'}, reset = true)
function StdModule.promotePlayer(cid, message, keywords, parameters, node)
local npcHandler = parameters.npcHandler
if(npcHandler == nil) then
error('StdModule.promotePlayer called without any npcHandler instance.')
end

if(not npcHandler:isFocused(cid)) then
return false
end

if(isPlayerPremiumCallback(cid) or not getBooleanFromString(getConfigValue('premiumForPromotion')) or not(parameters.premium)) then
if(getPlayerPromotionLevel(cid) >= parameters.promotion) then
npcHandler:say('You are already promoted!', cid)
elseif(getPlayerLevel(cid) < parameters.level) then
npcHandler:say('I am sorry, but I can only promote you once you have reached level ' .. parameters.level .. '.', cid)
elseif(not doPlayerRemoveMoney(cid, parameters.cost)) then
npcHandler:say('You do not have enough money!', cid)
else
setPlayerPromotionLevel(cid, parameters.promotion)
npcHandler:say(parameters.text, cid)
end
else
npcHandler:say("You need a premium account in order to get promoted.", cid)
end

npcHandler:resetNpc()
return true
end

function StdModule.learnSpell(cid, message, keywords, parameters, node)
local npcHandler = parameters.npcHandler
if(npcHandler == nil) then
error('StdModule.learnSpell called without any npcHandler instance.')
end

if(not npcHandler:isFocused(cid)) then
return false
end

if(isPlayerPremiumCallback(cid) or not(parameters.premium)) then
if(getPlayerLearnedInstantSpell(cid, parameters.spellName)) then
npcHandler:say('You already know this spell.', cid)
elseif(getPlayerLevel(cid) < parameters.level) then
npcHandler:say('You need to obtain a level of ' .. parameters.level .. ' or higher to be able to learn ' .. parameters.spellName .. '.', cid)
elseif(getPlayerVocation(cid) ~= parameters.vocation and getPlayerVocation(cid) ~= parameters.vocation + 4 and vocation ~= 9) then
npcHandler:say('This spell is not for your vocation', cid)
elseif(not doPlayerRemoveMoney(cid, parameters.price)) then
npcHandler:say('You do not have enough money, this spell costs ' .. parameters.price .. ' gold.', cid)
else
npcHandler:say('You have learned ' .. parameters.spellName .. '.', cid)
playerLearnInstantSpell(cid, parameters.spellName)
end
else
npcHandler:say('You need a premium account in order to buy ' .. parameters.spellName .. '.', cid)
end

npcHandler:resetNpc()
return true
end

function StdModule.bless(cid, message, keywords, parameters, node)
local npcHandler = parameters.npcHandler
if(npcHandler == nil) then
error('StdModule.bless called without any npcHandler instance.')
end

if(not npcHandler:isFocused(cid) or getWorldType() == WORLD_TYPE_PVP_ENFORCED) then
return false
end

if(isPlayerPremiumCallback(cid) or not getBooleanFromString(getConfigValue('blessingsOnlyPremium')) or not parameters.premium) then
local price = parameters.baseCost
if(getPlayerLevel(cid) > parameters.startLevel) then
price = (price + ((math.min(parameters.endLevel, getPlayerLevel(cid)) - parameters.startLevel) * parameters.levelCost))
end

if(getPlayerBlessing(cid, parameters.number)) then
npcHandler:say("Gods have already blessed you with this blessing!", cid)
elseif(not doPlayerRemoveMoney(cid, price)) then
npcHandler:say("You don't have enough money for blessing.", cid)
else
npcHandler:say("You have been blessed by one of the five gods!", cid)
doPlayerAddBlessing(cid, parameters.number)
end
else
npcHandler:say('You need a premium account in order to be blessed.', cid)
end

npcHandler:resetNpc()
return true
end

function StdModule.travel(cid, message, keywords, parameters, node)
local npcHandler = parameters.npcHandler
if(npcHandler == nil) then
error('StdModule.travel called without any npcHandler instance.')
end

if(not npcHandler:isFocused(cid)) then
return false
end

if(parameters.premium and not isPlayerPremiumCallback(cid)) then
npcHandler:say('I can only allow premium players to travel with me.', cid)
elseif(parameters.level ~= nil and getPlayerLevel(cid) < parameters.level) then
npcHandler:say('You must reach level ' .. parameters.level .. ' before I can let you go there.', cid)
elseif(parameters.storage ~= nil and getPlayerStorageValue(cid, parameters.storage) <= 0) then
npcHandler:say(parameters.storageInfo or 'You may not travel here.', cid)
elseif(not doPlayerRemoveMoney(cid, parameters.cost)) then
npcHandler:say('You do not have enough money!', cid)
elseif(isPlayerPzLocked(cid)) then
npcHandler:say('Get out of there with this blood.', cid)
else
doTeleportThing(cid, parameters.destination, 0)
doSendMagicEffect(parameters.destination, 10)
end

npcHandler:resetNpc()
return true
end

FocusModule = {
npcHandler = nil
}

-- Creates a new instance of FocusModule without an associated NpcHandler.
function FocusModule:new()
local obj = {}
setmetatable(obj, self)
self.__index = self
return obj
end

-- Inits the module and associates handler to it.
function FocusModule:init(handler)
self.npcHandler = handler
for i, word in pairs(FOCUS_GREETWORDS) do
local obj = {}
table.insert(obj, word)
obj.callback = FOCUS_GREETWORDS.callback or FocusModule.messageMatcher
handler.keywordHandler:addKeyword(obj, FocusModule.onGreet, {module = self})
end

for i, word in pairs(FOCUS_FAREWELLWORDS) do
local obj = {}
table.insert(obj, word)
obj.callback = FOCUS_FAREWELLWORDS.callback or FocusModule.messageMatcher
handler.keywordHandler:addKeyword(obj, FocusModule.onFarewell, {module = self})
end

return true
end

-- Greeting callback function.
function FocusModule.onGreet(cid, message, keywords, parameters)
parameters.module.npcHandler:onGreet(cid)
return true
end

-- UnGreeting callback function.
function FocusModule.onFarewell(cid, message, keywords, parameters)
if(parameters.module.npcHandler:isFocused(cid)) then
parameters.module.npcHandler:onFarewell(cid)
return true
else
return false
end
end

-- Custom message matching callback function for greeting messages.
function FocusModule.messageMatcher(keywords, message)
local spectators = getSpectators(getCreaturePosition(getNpcId()), 7, 7)
for i, word in pairs(keywords) do
if(type(word) == 'string') then
if(string.find(message, word) and not string.find(message, '[%w+]' .. word) and not string.find(message, word .. '[%w+]')) then
if(string.find(message, getCreatureName(getNpcId()))) then
return true
end

for i, uid in ipairs(spectators) do
if(string.find(message, getCreatureName(uid))) then
return false
end
end

return true
end
end
end

return false
end

KeywordModule = {
npcHandler = nil
}
-- Add it to the parseable module list.
Modules.parseableModules['module_keywords'] = KeywordModule

function KeywordModule:new()
local obj = {}
setmetatable(obj, self)
self.__index = self
return obj
end

function KeywordModule:init(handler)
self.npcHandler = handler
return true
end

-- Parses all known parameters.
function KeywordModule:parseParameters()
local ret = NpcSystem.getParameter('keywords')
if(ret ~= nil) then
self:parseKeywords(ret)
end
end

function KeywordModule:parseKeywords(data)
local n = 1
for keys in string.gmatch(data, '[^;]+') do
local i = 1

local keywords = {}
for temp in string.gmatch(keys, '[^,]+') do
table.insert(keywords, temp)
i = i + 1
end

if(i ~= 1) then
local reply = NpcSystem.getParameter('keyword_reply' .. n)
if(reply ~= nil) then
self:addKeyword(keywords, reply)
else
print('[Warning] NpcSystem:', 'Parameter \'' .. 'keyword_reply' .. n .. '\' missing. Skipping...')
end
else
print('[Warning] NpcSystem:', 'No keywords found for keyword set #' .. n .. '. Skipping...')
end

n = n+1
end
end

function KeywordModule:addKeyword(keywords, reply)
self.npcHandler.keywordHandler:addKeyword(keywords, StdModule.say, {npcHandler = self.npcHandler, onlyFocus = true, text = reply, reset = true})
end

TravelModule = {
npcHandler = nil,
destinations = nil,
yesNode = nil,
noNode = nil,
}
-- Add it to the parseable module list.
Modules.parseableModules['module_travel'] = TravelModule

function TravelModule:new()
local obj = {}
setmetatable(obj, self)
self.__index = self
return obj
end

function TravelModule:init(handler)
self.npcHandler = handler
self.yesNode = KeywordNode:new(SHOP_YESWORD, TravelModule.onConfirm, {module = self})
self.noNode = KeywordNode:new(SHOP_NOWORD, TravelModule.onDecline, {module = self})
self.destinations = {}
return true
end

-- Parses all known parameters.
function TravelModule:parseParameters()
local ret = NpcSystem.getParameter('travel_destinations')
if(ret ~= nil) then
self:parseDestinations(ret)

self.npcHandler.keywordHandler:addKeyword({'destination'}, TravelModule.listDestinations, {module = self})
self.npcHandler.keywordHandler:addKeyword({'where'}, TravelModule.listDestinations, {module = self})
self.npcHandler.keywordHandler:addKeyword({'travel'}, TravelModule.listDestinations, {module = self})

end
end

function TravelModule:parseDestinations(data)
for destination in string.gmatch(data, '[^;]+') do
local i = 1

local name = nil
local x = nil
local y = nil
local z = nil
local cost = nil
local premium = false

for temp in string.gmatch(destination, '[^,]+') do
if(i == 1) then
name = temp
elseif(i == 2) then
x = tonumber(temp)
elseif(i == 3) then
y = tonumber(temp)
elseif(i == 4) then
z = tonumber(temp)
elseif(i == 5) then
cost = tonumber(temp)
elseif(i == 6) then
premium = temp == 'true'
else
print('[Warning] NpcSystem:', 'Unknown parameter found in travel destination parameter.', temp, destination)
end
i = i + 1
end

if(name ~= nil and x ~= nil and y ~= nil and z ~= nil and cost ~= nil) then
self:addDestination(name, {x=x, y=y, z=z}, cost, premium)
else
print('[Warning] NpcSystem:', 'Parameter(s) missing for travel destination:', name, x, y, z, cost, premium)
end
end
end

function TravelModule:addDestination(name, position, price, premium)
table.insert(self.destinations, name)

local parameters = {
cost = price,
destination = position,
premium = premium,
module = self
}
local keywords = {}
table.insert(keywords, name)

local keywords2 = {}
table.insert(keywords2, 'bring me to ' .. name)
local node = self.npcHandler.keywordHandler:addKeyword(keywords, TravelModule.travel, parameters)
self.npcHandler.keywordHandler:addKeyword(keywords2, TravelModule.bringMeTo, parameters)
node:addChildKeywordNode(self.yesNode)
node:addChildKeywordNode(self.noNode)
end

function TravelModule.travel(cid, message, keywords, parameters, node)
local module = parameters.module
if(not module.npcHandler:isFocused(cid)) then
return false
end

local npcHandler = module.npcHandler

local cost = parameters.cost
local destination = parameters.destination
local premium = parameters.premium

module.npcHandler:say('Do you want to travel to ' .. keywords[1] .. ' for ' .. cost .. ' gold coins?', cid)
return true

end

function TravelModule.onConfirm(cid, message, keywords, parameters, node)
local module = parameters.module
if(not module.npcHandler:isFocused(cid)) then
return false
end

local npcHandler = module.npcHandler

local parentParameters = node:getParent():getParameters()
local cost = parentParameters.cost
local destination = parentParameters.destination
local premium = parentParameters.premium

if(isPlayerPremiumCallback(cid) or parameters.premium ~= true) then
if(not doPlayerRemoveMoney(cid, cost)) then
npcHandler:say('You do not have enough money!', cid)
elseif(isPlayerPzLocked(cid)) then
npcHandler:say('Get out of there with this blood.', cid)
else
npcHandler:say('It was a pleasure doing business with you.', cid)
npcHandler:releaseFocus(cid)
doTeleportThing(cid, destination, 0)
doSendMagicEffect(destination, 10)
end
else
npcHandler:say('I can only allow premium players to travel there.', cid)
end

npcHandler:resetNpc()
return true
end

-- onDecline keyword callback function. Generally called when the player sais 'no' after wanting to buy an item.
function TravelModule.onDecline(cid, message, keywords, parameters, node)
local module = parameters.module
if(not module.npcHandler:isFocused(cid)) then
return false
end
local parentParameters = node:getParent():getParameters()
local parseInfo = {
[TAG_PLAYERNAME] = getCreatureName(cid),
                       [TAG_PLAYERSEX] = getMrSex(cid),
}
local msg = module.npcHandler:parseMessage(module.npcHandler:getMessage(MESSAGE_DECLINE), parseInfo)
module.npcHandler:say(msg, cid)
module.npcHandler:resetNpc()
return true
end

function TravelModule.bringMeTo(cid, message, keywords, parameters, node)
local module = parameters.module
if(not module.npcHandler:isFocused(cid)) then
return false
end

local cost = parameters.cost
local destination = parameters.destination
local premium = parameters.premium

if(isPlayerPremiumCallback(cid) or parameters.premium ~= true) then
if(doPlayerRemoveMoney(cid, cost)) then
doTeleportThing(cid, destination, 0)
doSendMagicEffect(destination, 10)
end
end
return true
end

function TravelModule.listDestinations(cid, message, keywords, parameters, node)
local module = parameters.module
if(not module.npcHandler:isFocused(cid)) then
return false
end

local msg = 'I can bring you to '
--local i = 1
local maxn = table.maxn(module.destinations)
for i, destination in pairs(module.destinations) do
msg = msg .. "{" .. destination .. "}"
if(i == maxn -1) then
msg = msg .. ' and '
elseif(i == maxn) then
msg = msg .. '.'
else
msg = msg .. ', '
end
i = i + 1
end

module.npcHandler:say(msg, cid)
module.npcHandler:resetNpc()
return true
end

ShopModule = {
npcHandler = nil,
yesNode = nil,
noNode = nil,
noText = '',
maxCount = 100,
amount = 0
}

-- Add it to the parseable module list.
Modules.parseableModules['module_shop'] = ShopModule

-- Creates a new instance of ShopModule
function ShopModule:new()
local obj = {}
setmetatable(obj, self)
self.__index = self
return obj
end

-- Parses all known parameters.
function ShopModule:parseParameters()
local ret = NpcSystem.getParameter('shop_buyable')
if(ret ~= nil) then
self:parseBuyable(ret)
end

local ret = NpcSystem.getParameter('shop_sellable')
if(ret ~= nil) then
self:parseSellable(ret)
end

local ret = NpcSystem.getParameter('shop_buyable_containers')
if(ret ~= nil) then
self:parseBuyableContainers(ret)
end
end

-- Parse a string contaning a set of buyable items.
function ShopModule:parseBuyable(data)
for item in string.gmatch(data, '[^;]+') do
local i = 1

local name = nil
local itemid = nil
local cost = nil
local subType = nil
local realName = nil

for temp in string.gmatch(item, '[^,]+') do
if(i == 1) then
name = temp
elseif(i == 2) then
itemid = tonumber(temp)
elseif(i == 3) then
cost = tonumber(temp)
elseif(i == 4) then
subType = tonumber(temp)
elseif(i == 5) then
realName = temp
else
print('[Warning] NpcSystem:', 'Unknown parameter found in buyable items parameter.', temp, item)
end
i = i + 1
end

if(SHOPMODULE_MODE == SHOPMODULE_MODE_TRADE) then
if(itemid ~= nil and cost ~= nil) then
if((isItemRune(itemid) or isItemFluidContainer(itemid)) and subType == nil) then
print('[Warning] NpcSystem:', 'SubType missing for parameter item:', item)
else
self:addBuyableItem(nil, itemid, cost, subType, realName)
end
else
print('[Warning] NpcSystem:', 'Parameter(s) missing for item:', itemid, cost)
end
else
if(name ~= nil and itemid ~= nil and cost ~= nil) then
if((isItemRune(itemid) or isItemFluidContainer(itemid)) and subType == nil) then
print('[Warning] NpcSystem:', 'SubType missing for parameter item:', item)
else
local names = {}
table.insert(names, name)
self:addBuyableItem(names, itemid, cost, subType, realName)
end
else
print('[Warning] NpcSystem:', 'Parameter(s) missing for item:', name, itemid, cost)
end
end
end
end

-- Parse a string contaning a set of sellable items.
function ShopModule:parseSellable(data)
for item in string.gmatch(data, '[^;]+') do
local i = 1

local name = nil
local itemid = nil
local cost = nil
local realName = nil

for temp in string.gmatch(item, '[^,]+') do
if(i == 1) then
name = temp
elseif(i == 2) then
itemid = tonumber(temp)
elseif(i == 3) then
cost = tonumber(temp)
elseif(i == 4) then
realName = temp
else
print('[Warning] NpcSystem:', 'Unknown parameter found in sellable items parameter.', temp, item)
end
i = i + 1
end

if(SHOPMODULE_MODE == SHOPMODULE_MODE_TRADE) then
if(itemid ~= nil and cost ~= nil) then
self:addSellableItem(nil, itemid, cost, realName)
else
print('[Warning] NpcSystem:', 'Parameter(s) missing for item:', itemid, cost)
end
else
if(name ~= nil and itemid ~= nil and cost ~= nil) then
local names = {}
table.insert(names, name)
self:addSellableItem(names, itemid, cost, realName)
else
print('[Warning] NpcSystem:', 'Parameter(s) missing for item:', name, itemid, cost)
end
end
end
end

-- Parse a string contaning a set of buyable items.
function ShopModule:parseBuyableContainers(data)
for item in string.gmatch(data, '[^;]+') do
local i = 1

local name = nil
local container = nil
local itemid = nil
local cost = nil
local subType = nil
local realName = nil

for temp in string.gmatch(item, '[^,]+') do
if(i == 1) then
name = temp
elseif(i == 2) then
itemid = tonumber(temp)
elseif(i == 3) then
itemid = tonumber(temp)
elseif(i == 4) then
cost = tonumber(temp)
elseif(i == 5) then
subType = tonumber(temp)
elseif(i == 6) then
realName = temp
else
print('[Warning] NpcSystem:', 'Unknown parameter found in buyable items parameter.', temp, item)
end
i = i + 1
end

if(name ~= nil and container ~= nil and itemid ~= nil and cost ~= nil) then
if((isItemRune(itemid) or isItemFluidContainer(itemid)) and subType == nil) then
print('[Warning] NpcSystem:', 'SubType missing for parameter item:', item)
else
local names = {}
table.insert(names, name)
self:addBuyableItemContainer(names, container, itemid, cost, subType, realName)
end
else
print('[Warning] NpcSystem:', 'Parameter(s) missing for item:', name, container, itemid, cost)
end
end
end

-- Initializes the module and associates handler to it.
function ShopModule:init(handler)
self.npcHandler = handler
self.yesNode = KeywordNode:new(SHOP_YESWORD, ShopModule.onConfirm, {module = self})
self.noNode = KeywordNode:new(SHOP_NOWORD, ShopModule.onDecline, {module = self})
self.noText = handler:getMessage(MESSAGE_DECLINE)

if(SHOPMODULE_MODE ~= SHOPMODULE_MODE_TALK) then
for i, word in pairs(SHOP_TRADEREQUEST) do
local obj = {}
table.insert(obj, word)
obj.callback = SHOP_TRADEREQUEST.callback or ShopModule.messageMatcher
handler.keywordHandler:addKeyword(obj, ShopModule.requestTrade, {module = self})
end
end

return true
end

-- Custom message matching callback function for requesting trade messages.
function ShopModule.messageMatcher(keywords, message)
for i, word in pairs(keywords) do
if(type(word) == 'string') then
if string.find(message, word) and not string.find(message, '[%w+]' .. word) and not string.find(message, word .. '[%w+]') then
return true
end
end
end

return false
end

-- Resets the module-specific variables.
function ShopModule:reset()
self.amount = 0
end

-- Function used to match a number value from a string.
function ShopModule:getCount(message)
local ret = 1
local b, e = string.find(message, PATTERN_COUNT)
if b ~= nil and e ~= nil then
ret = tonumber(string.sub(message, b, e))
end

if(ret <= 0) then
ret = 1
elseif(ret > self.maxCount) then
ret = self.maxCount
end

return ret
end

-- Adds a new buyable item.
-- names = A table containing one or more strings of alternative names to this item. Used only for old buy/sell system.
-- itemid = The itemid of the buyable item
-- cost = The price of one single item
-- subType - The subType of each rune or fluidcontainer item. Can be left out if it is not a rune/fluidcontainer. Default value is 1.
-- 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)
function ShopModule:addBuyableItem(names, itemid, cost, subType, realName)
if(SHOPMODULE_MODE ~= SHOPMODULE_MODE_TALK) then
if(self.npcHandler.shopItems[itemid] == nil) then
self.npcHandler.shopItems[itemid] = {buyPrice = -1, sellPrice = -1, subType = 1, realName = ""}
end

self.npcHandler.shopItems[itemid].buyPrice = cost
self.npcHandler.shopItems[itemid].realName = realName or getItemNameById(itemid)
self.npcHandler.shopItems[itemid].subType = subType or 1
end

if(names ~= nil and SHOPMODULE_MODE ~= SHOPMODULE_MODE_TRADE) then
for i, name in pairs(names) do
local parameters = {
itemid = itemid,
cost = cost,
eventType = SHOPMODULE_BUY_ITEM,
module = self,
realName = realName or getItemNameById(itemid),
subType = subType or 1
}

keywords = {}
table.insert(keywords, 'buy')
table.insert(keywords, name)
local node = self.npcHandler.keywordHandler:addKeyword(keywords, ShopModule.tradeItem, parameters)
node:addChildKeywordNode(self.yesNode)
node:addChildKeywordNode(self.noNode)
end
end
end

-- Adds a new buyable container of items.
-- names = A table containing one or more strings of alternative names to this item.
-- container = Backpack, bag or any other itemid of container where bought items will be stored
-- itemid = The itemid of the buyable item
-- cost = The price of one single item
-- subType - The subType of each rune or fluidcontainer item. Can be left out if it is not a rune/fluidcontainer. Default value is 1.
-- 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)
function ShopModule:addBuyableItemContainer(names, container, itemid, cost, subType, realName)
if(names ~= nil) then
for i, name in pairs(names) do
local parameters = {
container = container,
itemid = itemid,
cost = cost,
eventType = SHOPMODULE_BUY_ITEM_CONTAINER,
module = self,
realName = realName or getItemNameById(itemid),
subType = subType or 1
}

keywords = {}
table.insert(keywords, 'buy')
table.insert(keywords, name)
local node = self.npcHandler.keywordHandler:addKeyword(keywords, ShopModule.tradeItem, parameters)
node:addChildKeywordNode(self.yesNode)
node:addChildKeywordNode(self.noNode)
end
end
end

-- Adds a new sellable item.
-- names = A table containing one or more strings of alternative names to this item. Used only by old buy/sell system.
-- itemid = The itemid of the sellable item
-- cost = The price of one single item
-- 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)
function ShopModule:addSellableItem(names, itemid, cost, realName)
if(SHOPMODULE_MODE ~= SHOPMODULE_MODE_TALK) then
if(self.npcHandler.shopItems[itemid] == nil) then
self.npcHandler.shopItems[itemid] = {buyPrice = -1, sellPrice = -1, subType = 1, realName = ""}
end

self.npcHandler.shopItems[itemid].sellPrice = cost
self.npcHandler.shopItems[itemid].realName = realName or getItemNameById(itemid)
end

if(names ~= nil and SHOPMODULE_MODE ~= SHOPMODULE_MODE_TRADE) then
for i, name in pairs(names) do
local parameters = {
itemid = itemid,
cost = cost,
eventType = SHOPMODULE_SELL_ITEM,
module = self,
realName = realName or getItemNameById(itemid)
}

keywords = {}
table.insert(keywords, 'sell')
table.insert(keywords, name)
local node = self.npcHandler.keywordHandler:addKeyword(keywords, ShopModule.tradeItem, parameters)
node:addChildKeywordNode(self.yesNode)
node:addChildKeywordNode(self.noNode)
end
end
end

-- onModuleReset callback function. Calls ShopModule:reset()
function ShopModule:callbackOnModuleReset()
self:reset()
return true
end

-- Callback onBuy() function. If you wish, you can change certain Npc to use your onBuy().
function ShopModule:callbackOnBuy(cid, itemid, subType, amount, ignoreCap, inBackpacks)
if(self.npcHandler.shopItems[itemid] == nil) then
error("[shopModule.onBuy]", "items[itemid] == nil")
return false
end

if(self.npcHandler.shopItems[itemid].buyPrice == -1) then
error("[shopModule.onSell]", "Attempt to buy a non-buyable item")
return false
end

local backpack = 1988
local totalCost = amount * self.npcHandler.shopItems[itemid].buyPrice
if(inBackpacks) then
totalCost = totalCost + (math.max(1, math.floor(amount / getContainerCapById(backpack))) * 20)
end

local parseInfo = {
[TAG_PLAYERNAME] = getPlayerName(cid),
                       [TAG_PLAYERSEX] = getMrSex(cid),
[TAG_ITEMCOUNT] = amount,
[TAG_TOTALCOST] = totalCost,
[TAG_ITEMNAME] = self.npcHandler.shopItems[itemid].realName
}

if(getPlayerMoney(cid) < totalCost) then
local msg = self.npcHandler:getMessage(MESSAGE_NEEDMONEY)
msg = self.npcHandler:parseMessage(msg, parseInfo)
doPlayerSendCancel(cid, msg)
return false
end

local subType = self.npcHandler.shopItems[itemid].subType or 1
local a, b = doNpcSellItem(cid, itemid, amount, subType, ignoreCap, inBackpacks, backpack)
if(a < amount) then
local msgId = MESSAGE_NEEDMORESPACE
if(a == 0) then
msgId = MESSAGE_NEEDSPACE
end

local msg = self.npcHandler:getMessage(msgId)
parseInfo[TAG_ITEMCOUNT] = a
msg = self.npcHandler:parseMessage(msg, parseInfo)
doPlayerSendCancel(cid, msg)
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
self.npcHandler.talkStart[cid] = os.time()
else
self.npcHandler.talkStart = os.time()
end

if(a > 0) then
doPlayerRemoveMoney(cid, ((a * self.npcHandler.shopItems[itemid].buyPrice) + (b * 20)))
return true
end

return false
else
local msg = self.npcHandler:getMessage(MESSAGE_BOUGHT)
msg = self.npcHandler:parseMessage(msg, parseInfo)
doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, msg)
doPlayerRemoveMoney(cid, totalCost)
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
self.npcHandler.talkStart[cid] = os.time()
else
self.npcHandler.talkStart = os.time()
end

return true
end
end

-- Callback onSell() function. If you wish, you can change certain Npc to use your onSell().
function ShopModule:callbackOnSell(cid, itemid, subType, amount, ignoreCap, inBackpacks)
if(self.npcHandler.shopItems[itemid] == nil) then
error("[shopModule.onSell]", "items[itemid] == nil")
return false
end

if(self.npcHandler.shopItems[itemid].sellPrice == -1) then
error("[shopModule.onSell]", "Attempt to sell a non-sellable item")
return false
end

local parseInfo = {
[TAG_PLAYERNAME] = getPlayerName(cid),
                       [TAG_PLAYERSEX] = getMrSex(cid),
[TAG_ITEMCOUNT] = amount,
[TAG_TOTALCOST] = amount * self.npcHandler.shopItems[itemid].sellPrice,
[TAG_ITEMNAME] = self.npcHandler.shopItems[itemid].realName
}

if(subType < 1) then
subType = -1
end

if(doPlayerRemoveItem(cid, itemid, amount, subType)) then
local msg = self.npcHandler:getMessage(MESSAGE_SOLD)
msg = self.npcHandler:parseMessage(msg, parseInfo)
doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, msg)
doPlayerAddMoney(cid, amount * self.npcHandler.shopItems[itemid].sellPrice)
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
self.npcHandler.talkStart[cid] = os.time()
else
self.npcHandler.talkStart = os.time()
end
return true
else
local msg = self.npcHandler:getMessage(MESSAGE_NEEDITEM)
msg = self.npcHandler:parseMessage(msg, parseInfo)
doPlayerSendCancel(cid, msg)
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
self.npcHandler.talkStart[cid] = os.time()
else
self.npcHandler.talkStart = os.time()
end
return false
end
end

-- Callback for requesting a trade window with the NPC.
function ShopModule.requestTrade(cid, message, keywords, parameters, node)
local module = parameters.module
if(not module.npcHandler:isFocused(cid)) then
return false
end

local itemWindow = {}
for itemid, attr in pairs(module.npcHandler.shopItems) do
local item = {id = itemid, buy = attr.buyPrice, sell = attr.sellPrice, subType = attr.subType, name = attr.realName}
table.insert(itemWindow, item)
end

if(itemWindow[1] == nil) then
local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid), [TAG_PLAYERSEX] = getMrSex(cid) }
local msg = module.npcHandler:parseMessage(module.npcHandler:getMessage(MESSAGE_NOSHOP), parseInfo)
module.npcHandler:say(msg, cid)
return true
end

local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid), [TAG_PLAYERSEX] = getMrSex(cid) }
local msg = module.npcHandler:parseMessage(module.npcHandler:getMessage(MESSAGE_SENDTRADE), parseInfo)
openShopWindow(cid, itemWindow,
function(cid, itemid, subType, amount, ignoreCap, inBackpacks) module.npcHandler:onBuy(cid, itemid, subType, amount, ignoreCap, inBackpacks) end,
function(cid, itemid, subType, amount, ignoreCap, inBackpacks) module.npcHandler:onSell(cid, itemid, subType, amount, ignoreCap, inBackpacks) end)
module.npcHandler:say(msg, cid)
return true
end

-- onConfirm keyword callback function. Sells/buys the actual item.
function ShopModule.onConfirm(cid, message, keywords, parameters, node)
local module = parameters.module
if(not module.npcHandler:isFocused(cid)) then
return false
end

local parentParameters = node:getParent():getParameters()
local parseInfo = {
[TAG_PLAYERNAME] = getPlayerName(cid),
                       [TAG_PLAYERSEX] = getMrSex(cid),
[TAG_ITEMCOUNT] = module.amount,
[TAG_TOTALCOST] = parentParameters.cost * module.amount,
[TAG_ITEMNAME] = parentParameters.realName
}

if(parentParameters.eventType == SHOPMODULE_SELL_ITEM) then
local ret = doPlayerSellItem(cid, parentParameters.itemid, module.amount, parentParameters.cost * module.amount)
if(ret) then
local msg = module.npcHandler:getMessage(MESSAGE_ONSELL)
msg = module.npcHandler:parseMessage(msg, parseInfo)
module.npcHandler:say(msg, cid)
else
local msg = module.npcHandler:getMessage(MESSAGE_MISSINGITEM)
msg = module.npcHandler:parseMessage(msg, parseInfo)
module.npcHandler:say(msg, cid)
end
elseif(parentParameters.eventType == SHOPMODULE_BUY_ITEM) then
local ret = doPlayerBuyItem(cid, parentParameters.itemid, module.amount, parentParameters.cost * module.amount, parentParameters.subType)
if(ret) then
if parentParameters.itemid == ITEM_PARCEL then
doPlayerBuyItem(cid, ITEM_LABEL, module.amount, 0, parentParameters.subType)
end
local msg = module.npcHandler:getMessage(MESSAGE_ONBUY)
msg = module.npcHandler:parseMessage(msg, parseInfo)
module.npcHandler:say(msg, cid)
else
local msg = module.npcHandler:getMessage(MESSAGE_MISSINGMONEY)
msg = module.npcHandler:parseMessage(msg, parseInfo)
module.npcHandler:say(msg, cid)
end
elseif(parentParameters.eventType == SHOPMODULE_BUY_ITEM_CONTAINER) then
local ret = doPlayerBuyItemContainer(cid, parentParameters.container, parentParameters.itemid, module.amount, parentParameters.cost * module.amount, parentParameters.subType)
if(ret) then
local msg = module.npcHandler:getMessage(MESSAGE_ONBUY)
msg = module.npcHandler:parseMessage(msg, parseInfo)
module.npcHandler:say(msg, cid)
else
local msg = module.npcHandler:getMessage(MESSAGE_MISSINGMONEY)
msg = module.npcHandler:parseMessage(msg, parseInfo)
module.npcHandler:say(msg, cid)
end
end

module.npcHandler:resetNpc()
return true
end

-- onDecliune keyword callback function. Generally called when the player sais 'no' after wanting to buy an item.
function ShopModule.onDecline(cid, message, keywords, parameters, node)
local module = parameters.module
if(not module.npcHandler:isFocused(cid)) then
return false
end

local parentParameters = node:getParent():getParameters()
local parseInfo = {
[TAG_PLAYERNAME] = getPlayerName(cid),
                       [TAG_PLAYERSEX] = getMrSex(cid),
[TAG_ITEMCOUNT] = module.amount,
[TAG_TOTALCOST] = parentParameters.cost * module.amount,
[TAG_ITEMNAME] = parentParameters.realName
}

local msg = module.npcHandler:parseMessage(module.noText, parseInfo)
module.npcHandler:say(msg, cid)
module.npcHandler:resetNpc()
return true
end

-- tradeItem callback function. Makes the npc say the message defined by MESSAGE_BUY or MESSAGE_SELL
function ShopModule.tradeItem(cid, message, keywords, parameters, node)
local module = parameters.module
if(not module.npcHandler:isFocused(cid)) then
return false
end

local count = module:getCount(message)
module.amount = count
local parseInfo = {
[TAG_PLAYERNAME] = getPlayerName(cid),
                       [TAG_PLAYERSEX] = getMrSex(cid),
[TAG_ITEMCOUNT] = module.amount,
[TAG_TOTALCOST] = parameters.cost * module.amount,
[TAG_ITEMNAME] = parameters.realName
}

if(parameters.eventType == SHOPMODULE_SELL_ITEM) then
local msg = module.npcHandler:getMessage(MESSAGE_SELL)
msg = module.npcHandler:parseMessage(msg, parseInfo)
module.npcHandler:say(msg, cid)
elseif(parameters.eventType == SHOPMODULE_BUY_ITEM) then
local msg = module.npcHandler:getMessage(MESSAGE_BUY)
msg = module.npcHandler:parseMessage(msg, parseInfo)
module.npcHandler:say(msg, cid)
elseif(parameters.eventType == SHOPMODULE_BUY_ITEM_CONTAINER) then
local msg = module.npcHandler:getMessage(MESSAGE_BUY)
msg = module.npcHandler:parseMessage(msg, parseInfo)
module.npcHandler:say(msg, cid)
end

return true
end
end

 

 

npchandler.lua

 

-- Advanced NPC System (Created by Jiddo),
-- Modified by Talaturen.

if(NpcHandler == nil) then
-- Constant talkdelay behaviors.
TALKDELAY_NONE = 0 -- No talkdelay. Npc will reply immedeatly.
TALKDELAY_ONTHINK = 1 -- Talkdelay handled through the onThink callback function. (Default)
TALKDELAY_EVENT = 2 -- Not yet implemented

-- Currently applied talkdelay behavior. TALKDELAY_ONTHINK is default.
NPCHANDLER_TALKDELAY = TALKDELAY_ONTHINK

-- Constant conversation behaviors.
CONVERSATION_DEFAULT = 0 -- Conversation through default window, like it was before 8.2 update.
CONVERSATION_PRIVATE = 1 -- Conversation through NPCs chat window, as of 8.2 update. (Default)
--Small Note: Private conversations also means the NPC will use multi-focus system.

-- Currently applied conversation behavior. CONVERSATION_PRIVATE is default.
NPCHANDLER_CONVBEHAVIOR = CONVERSATION_PRIVATE

-- Constant indexes for defining default messages.
MESSAGE_GREET  = 1 -- When the player greets the npc.
MESSAGE_FAREWELL  = 2 -- When the player unGreets the npc.
MESSAGE_BUY  = 3 -- When the npc asks the player if he wants to buy something.
MESSAGE_ONBUY  = 4 -- When the player successfully buys something via talk.
MESSAGE_BOUGHT = 5 -- When the player bought something through the shop window.
MESSAGE_SELL  = 6 -- When the npc asks the player if he wants to sell something.
MESSAGE_ONSELL  = 7 -- When the player successfully sells something via talk.
MESSAGE_SOLD = 8 -- When the player sold something through the shop window.
MESSAGE_MISSINGMONEY = 9 -- When the player does not have enough money.
MESSAGE_NEEDMONEY = 10 -- Same as above, used for shop window.
MESSAGE_MISSINGITEM = 11 -- When the player is trying to sell an item he does not have.
MESSAGE_NEEDITEM = 12 -- Same as above, used for shop window.
MESSAGE_NEEDSPACE  = 13 -- When the player don't have any space to buy an item
MESSAGE_NEEDMORESPACE = 14 -- When the player has some space to buy an item, but not enough space
MESSAGE_IDLETIMEOUT = 15 -- When the player has been idle for longer then idleTime allows.
MESSAGE_WALKAWAY = 16 -- When the player walks out of the talkRadius of the npc.
MESSAGE_DECLINE = 17 -- When the player says no to something.
MESSAGE_SENDTRADE = 18 -- When the npc sends the trade window to the player
MESSAGE_NOSHOP = 19 -- When the npc's shop is requested but he doesn't have any
MESSAGE_ONCLOSESHOP = 20 -- When the player closes the npc's shop window
MESSAGE_ALREADYFOCUSED = 21 -- When the player already has the focus of this npc.
MESSAGE_PLACEDINQUEUE = 22 -- When the player has been placed in the costumer queue.

-- Constant indexes for callback functions. These are also used for module callback ids.
CALLBACK_CREATURE_APPEAR  = 1
CALLBACK_CREATURE_DISAPPEAR = 2
CALLBACK_CREATURE_SAY  = 3
CALLBACK_ONTHINK  = 4
CALLBACK_GREET  = 5
CALLBACK_FAREWELL  = 6
CALLBACK_MESSAGE_DEFAULT  = 7
CALLBACK_PLAYER_ENDTRADE  = 8
CALLBACK_PLAYER_CLOSECHANNEL = 9
CALLBACK_ONBUY = 10
CALLBACK_ONSELL = 11

-- Addidional module callback ids
CALLBACK_MODULE_INIT = 12
CALLBACK_MODULE_RESET = 13

-- Constant strings defining the keywords to replace in the default messages.
TAG_PLAYERNAME = '|PLAYERNAME|'
TAG_ITEMCOUNT = '|ITEMCOUNT|'
TAG_TOTALCOST = '|TOTALCOST|'
TAG_ITEMNAME = '|ITEMNAME|'
TAG_QUEUESIZE = '|QUEUESIZE|'
       TAG_PLAYERSEX = '|PLAYERSEX|'

NpcHandler = {
keywordHandler = nil,
focuses = nil,
talkStart = nil,
idleTime = 90,
talkRadius = 4,
talkDelayTime = 1, -- Seconds to delay outgoing messages.
queue = nil,
talkDelay = nil,
callbackFunctions = nil,
modules = nil,
shopItems = nil, -- They must be here since ShopModule uses "static" functions
messages = {
-- These are the default replies of all npcs. They can/should be changed individually for each npc.
[MESSAGE_GREET]  = 'Welcome, |PLAYERNAME|! I have been expecting you.',
[MESSAGE_FAREWELL]  = 'Good bye, |PLAYERNAME|!',
[MESSAGE_BUY]  = 'Do you want to buy |ITEMCOUNT| |ITEMNAME| for |TOTALCOST| gold coins?',
[MESSAGE_ONBUY]  = 'It was a pleasure doing business with you.',
[MESSAGE_BOUGHT]  = 'Bought |ITEMCOUNT|x |ITEMNAME| for |TOTALCOST| gold.',
[MESSAGE_SELL]  = 'Do you want to sell |ITEMCOUNT| |ITEMNAME| for |TOTALCOST| gold coins?',
[MESSAGE_ONSELL]  = 'Thank you for this |ITEMNAME|, |PLAYERNAME| gold.',
[MESSAGE_SOLD]   = 'Sold |ITEMCOUNT|x |ITEMNAME| for |TOTALCOST| gold.',
[MESSAGE_MISSINGMONEY] = 'Sorry, you don\'t have enough money.',
[MESSAGE_NEEDMONEY]  = 'You do not have enough money.',
[MESSAGE_MISSINGITEM]  = 'You don\'t even have that item, |PLAYERNAME|!',
[MESSAGE_NEEDITEM] = 'You do not have this object.',
[MESSAGE_NEEDSPACE] = 'You do not have enough capacity.',
[MESSAGE_NEEDMORESPACE] = 'You do not have enough capacity for all items.',
[MESSAGE_IDLETIMEOUT]  = 'Next, please!',
[MESSAGE_WALKAWAY]  = 'How rude!',
[MESSAGE_DECLINE] = 'Not good enough, is it... ?',
[MESSAGE_SENDTRADE] = 'Here\'s my offer, |PLAYERNAME|. Don\'t you like it?',
[MESSAGE_NOSHOP] = 'Sorry, I\'m not offering anything.',
[MESSAGE_ONCLOSESHOP] = 'Thank you, come back when you want something more.',
[MESSAGE_ALREADYFOCUSED]= '|PLAYERNAME|! I am already talking to you...',
[MESSAGE_PLACEDINQUEUE] = '|PLAYERNAME|, please wait for your turn. There are |QUEUESIZE| customers before you.'
}
}

-- Creates a new NpcHandler with an empty callbackFunction stack.
function NpcHandler:new(keywordHandler)
local obj = {}
obj.callbackFunctions = {}
obj.modules = {}
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
obj.focuses = {}
obj.talkStart = {}
else
obj.queue = Queue:new(obj)
obj.focuses = 0
obj.talkStart = 0
end
obj.talkDelay = {}
obj.keywordHandler = keywordHandler
obj.messages = {}
obj.shopItems = {}

setmetatable(obj.messages, self.messages)
self.messages.__index = self.messages

setmetatable(obj, self)
self.__index = self
return obj
end

-- Re-defines the maximum idle time allowed for a player when talking to this npc.
function NpcHandler:setMaxIdleTime(newTime)
self.idleTime = newTime
end

-- Attackes a new keyword handler to this npchandler
function NpcHandler:setKeywordHandler(newHandler)
self.keywordHandler = newHandler
end

-- Function used to change the focus of this npc.
function NpcHandler:addFocus(newFocus)
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
if(self:isFocused(newFocus)) then
return
end

table.insert(self.focuses, newFocus)
else
self.focuses = newFocus
end

self:updateFocus()
end
NpcHandler.changeFocus = NpcHandler.addFocus --"changeFocus" looks better for CONVERSATION_DEFAULT

-- Function used to verify if npc is focused to certain player
function NpcHandler:isFocused(focus)
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
for k,v in pairs(self.focuses) do
if v == focus then
return true
end
end

return false
end

return (self.focuses == focus)
end

-- This function should be called on each onThink and makes sure the npc faces the player it is talking to.
-- Should also be called whenever a new player is focused.
function NpcHandler:updateFocus()
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
for pos, focus in pairs(self.focuses) do
if(focus ~= nil) then
doNpcSetCreatureFocus(focus)
return
end
end

doNpcSetCreatureFocus(0)
else
doNpcSetCreatureFocus(self.focuses)
end
end

-- Used when the npc should un-focus the player.
function NpcHandler:releaseFocus(focus)
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
if(not self:isFocused(focus)) then
return
end

local pos = nil
for k,v in pairs(self.focuses) do
if v == focus then
pos = k
end
end
table.remove(self.focuses, pos)
self.talkStart[focus] = nil
closeShopWindow(focus) --Even if it can not exist, we need to prevent it.
self:updateFocus()
else
closeShopWindow(focus)
self:changeFocus(0)
end
end

-- Returns the callback function with the specified id or nil if no such callback function exists.
function NpcHandler:getCallback(id)
local ret = nil
if(self.callbackFunctions ~= nil) then
ret = self.callbackFunctions[id]
end

return ret
end

-- Changes the callback function for the given id to callback.
function NpcHandler:setCallback(id, callback)
if(self.callbackFunctions ~= nil) then
self.callbackFunctions[id] = callback
end
end

-- Adds a module to this npchandler and inits it.
function NpcHandler:addModule(module)
if(self.modules ~= nil) then
table.insert(self.modules, module)
module:init(self)
end
end

-- Calls the callback function represented by id for all modules added to this npchandler with the given arguments.
function NpcHandler:processModuleCallback(id, ...)
local ret = true
for i, module in pairs(self.modules) do
local tmpRet = true
if(id == CALLBACK_CREATURE_APPEAR and module.callbackOnCreatureAppear ~= nil) then
tmpRet = module:callbackOnCreatureAppear(unpack(arg))
elseif(id == CALLBACK_CREATURE_DISAPPEAR and module.callbackOnCreatureDisappear ~= nil) then
tmpRet = module:callbackOnCreatureDisappear(unpack(arg))
elseif(id == CALLBACK_CREATURE_SAY and module.callbackOnCreatureSay ~= nil) then
tmpRet = module:callbackOnCreatureSay(unpack(arg))
elseif(id == CALLBACK_PLAYER_ENDTRADE and module.callbackOnPlayerEndTrade ~= nil) then
tmpRet = module:callbackOnPlayerEndTrade(unpack(arg))
elseif(id == CALLBACK_PLAYER_CLOSECHANNEL and module.callbackOnPlayerCloseChannel ~= nil) then
tmpRet = module:callbackOnPlayerCloseChannel(unpack(arg))
elseif(id == CALLBACK_ONBUY and module.callbackOnBuy ~= nil) then
tmpRet = module:callbackOnBuy(unpack(arg))
elseif(id == CALLBACK_ONSELL and module.callbackOnSell ~= nil) then
tmpRet = module:callbackOnSell(unpack(arg))
elseif(id == CALLBACK_ONTHINK and module.callbackOnThink ~= nil) then
tmpRet = module:callbackOnThink(unpack(arg))
elseif(id == CALLBACK_GREET and module.callbackOnGreet ~= nil) then
tmpRet = module:callbackOnGreet(unpack(arg))
elseif(id == CALLBACK_FAREWELL and module.callbackOnFarewell ~= nil) then
tmpRet = module:callbackOnFarewell(unpack(arg))
elseif(id == CALLBACK_MESSAGE_DEFAULT and module.callbackOnMessageDefault ~= nil) then
tmpRet = module:callbackOnMessageDefault(unpack(arg))
elseif(id == CALLBACK_MODULE_RESET and module.callbackOnModuleReset ~= nil) then
tmpRet = module:callbackOnModuleReset(unpack(arg))
end

if(not tmpRet) then
ret = false
break
end
end

return ret
end

-- Returns the message represented by id.
function NpcHandler:getMessage(id)
local ret = nil
if(self.messages ~= nil) then
ret = self.messages[id]
end

return ret
end

-- Changes the default response message with the specified id to newMessage.
function NpcHandler:setMessage(id, newMessage)
if(self.messages ~= nil) then
self.messages[id] = newMessage
end
end

-- Translates all message tags found in msg using parseInfo
function NpcHandler:parseMessage(msg, parseInfo)
local ret = msg
for search, replace in pairs(parseInfo) do
ret = string.gsub(ret, search, replace)
end

return ret
end

-- Makes sure the npc un-focuses the currently focused player
function NpcHandler:unGreet(cid)
if(not self:isFocused(cid)) then
return
end

local callback = self:getCallback(CALLBACK_FAREWELL)
if(callback == nil or callback()) then
if(self:processModuleCallback(CALLBACK_FAREWELL)) then
if(self.queue == nil or not self.queue:greetNext()) then
local msg = self:getMessage(MESSAGE_FAREWELL)
local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid), [TAG_PLAYERSEX] = getMrSex(cid) }
msg = self:parseMessage(msg, parseInfo)

self:say(msg, cid)
self:releaseFocus(cid)
self:say(msg)
end
end
end
end

-- Greets a new player.
function NpcHandler:greet(cid)
if(cid ~= 0) then
local callback = self:getCallback(CALLBACK_GREET)
if(callback == nil or callback(cid)) then
if(self:processModuleCallback(CALLBACK_GREET, cid)) then
local msg = self:getMessage(MESSAGE_GREET)
local parseInfo = { [TAG_PLAYERNAME] = getCreatureName(cid), [TAG_PLAYERSEX] = getMrSex(cid) }
msg = self:parseMessage(msg, parseInfo)

self:say(msg)
self:addFocus(cid)
self:say(msg, cid)
end
end
end
end

-- Handles onCreatureAppear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_APPEAR callback.
function NpcHandler:onCreatureAppear(cid)
local callback = self:getCallback(CALLBACK_CREATURE_APPEAR)
if(callback == nil or callback(cid)) then
if(self:processModuleCallback(CALLBACK_CREATURE_APPEAR, cid)) then
--
end
end
end

-- Handles onCreatureDisappear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_DISAPPEAR callback.
function NpcHandler:onCreatureDisappear(cid)
local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR)
if(callback == nil or callback(cid)) then
if(self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid)) then
if(self:isFocused(cid)) then
self:unGreet(cid)
end
end
end
end

-- Handles onCreatureSay events. If you with to handle this yourself, please use the CALLBACK_CREATURE_SAY callback.
function NpcHandler:onCreatureSay(cid, class, msg)
local callback = self:getCallback(CALLBACK_CREATURE_SAY)
if(callback == nil or callback(cid, class, msg)) then
if(self:processModuleCallback(CALLBACK_CREATURE_SAY, cid, class, msg)) then
if(not self:isInRange(cid)) then
return
end

if(self.keywordHandler ~= nil) then
if((self:isFocused(cid) and (class == TALKTYPE_PRIVATE_PN or NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT)) or not self:isFocused(cid)) then
local ret = self.keywordHandler:processMessage(cid, msg)
if(not ret) then
local callback = self:getCallback(CALLBACK_MESSAGE_DEFAULT)
if(callback ~= nil and callback(cid, class, msg)) then
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
self.talkStart[cid] = os.time()
else
self.talkStart = os.time()
end
end
else
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
self.talkStart[cid] = os.time()
else
self.talkStart = os.time()
end
end
end
end
end
end
end

-- Handles onPlayerEndTrade events. If you wish to handle this yourself, use the CALLBACK_PLAYER_ENDTRADE callback.
function NpcHandler:onPlayerEndTrade(cid)
local callback = self:getCallback(CALLBACK_PLAYER_ENDTRADE)
if(callback == nil or callback(cid)) then
if(self:processModuleCallback(CALLBACK_PLAYER_ENDTRADE, cid, class, msg)) then
if(self:isFocused(cid)) then
local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid), [TAG_PLAYERSEX] = getMrSex(cid) }
local msg = self:parseMessage(self:getMessage(MESSAGE_ONCLOSESHOP), parseInfo)
self:say(msg, cid)
end
end
end
end

-- Handles onPlayerCloseChannel events. If you wish to handle this yourself, use the CALLBACK_PLAYER_CLOSECHANNEL callback.
function NpcHandler:onPlayerCloseChannel(cid)
local callback = self:getCallback(CALLBACK_PLAYER_CLOSECHANNEL)
if(callback == nil or callback(cid)) then
if(self:processModuleCallback(CALLBACK_PLAYER_CLOSECHANNEL, cid, class, msg)) then
if(self:isFocused(cid)) then
self:unGreet(cid)
end
end
end
end

-- Handles onBuy events. If you wish to handle this yourself, use the CALLBACK_ONBUY callback.
function NpcHandler:onBuy(cid, itemid, subType, amount, ignoreCap, inBackpacks)
local callback = self:getCallback(CALLBACK_ONBUY)
if(callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
if(self:processModuleCallback(CALLBACK_ONBUY, cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
--
end
end
end

-- Handles onSell events. If you wish to handle this yourself, use the CALLBACK_ONSELL callback.
function NpcHandler:onSell(cid, itemid, subType, amount, ignoreCap, inBackpacks)
local callback = self:getCallback(CALLBACK_ONSELL)
if(callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
if(self:processModuleCallback(CALLBACK_ONSELL, cid, itemid, subType, amount, ignoreCap, inBackpacks)) then
--
end
end
end

-- Handles onThink events. If you wish to handle this yourself, please use the CALLBACK_ONTHINK callback.
function NpcHandler:onThink()
local callback = self:getCallback(CALLBACK_ONTHINK)
if(callback == nil or callback()) then
if(NPCHANDLER_TALKDELAY == TALKDELAY_ONTHINK) then
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
for cid, talkDelay in pairs(self.talkDelay) do
if(talkDelay.time ~= nil and talkDelay.message ~= nil and os.time() >= talkDelay.time) then
selfSay(talkDelay.message, cid)
self.talkDelay[cid] = nil
end
end
elseif(self.talkDelay.time ~= nil and self.talkDelay.message ~= nil and os.time() >= self.talkDelay.time) then
selfSay(self.talkDelay.message)
self.talkDelay.time = nil
self.talkDelay.message = nil
end
end

if(self:processModuleCallback(CALLBACK_ONTHINK)) then
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
for pos, focus in pairs(self.focuses) do
if(focus ~= nil) then
if(not self:isInRange(focus)) then
self:onWalkAway(focus)
elseif((os.time() - self.talkStart[focus]) > self.idleTime) then
self:unGreet(focus)
else
self:updateFocus()
end
end
end
elseif(self.focuses ~= 0) then
if(not self:isInRange(self.focuses)) then
self:onWalkAway(self.focuses)
elseif(os.time()-self.talkStart > self.idleTime) then
self:unGreet(self.focuses)
else
self:updateFocus()
end
end
end
end
end

-- Tries to greet the player with the given cid.
function NpcHandler:onGreet(cid)
if(self:isInRange(cid)) then
if(NPCHANDLER_CONVBEHAVIOR == CONVERSATION_PRIVATE) then
if(not self:isFocused(cid)) then
self:greet(cid)
return
end
elseif(NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT) then
if(self.focuses == 0) then
self:greet(cid)
elseif(self.focuses == cid) then
local msg = self:getMessage(MESSAGE_ALREADYFOCUSED)
local parseInfo = { [TAG_PLAYERNAME] = getCreatureName(cid), [TAG_PLAYERSEX] = getMrSex(cid) }
msg = self:parseMessage(msg, parseInfo)
self:say(msg)
else
if(not self.queue:isInQueue(cid)) then
self.queue:push(cid)
end

local msg = self:getMessage(MESSAGE_PLACEDINQUEUE)
local parseInfo = { [TAG_PLAYERNAME] = getCreatureName(cid),[TAG_PLAYERSEX] = getMrSex(cid), [TAG_QUEUESIZE] = self.queue:getSize() }
msg = self:parseMessage(msg, parseInfo)
self:say(msg)
end
end
end
end

-- Simply calls the underlying unGreet function.
function NpcHandler:onFarewell(cid)
self:unGreet(cid)
end

-- Should be called on this npc's focus if the distance to focus is greater then talkRadius.
function NpcHandler:onWalkAway(cid)
if(self:isFocused(cid)) then
local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR)
if(callback == nil or callback()) then
if(self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid)) then
if(self.queue == nil or not self.queue:greetNext()) then
local msg = self:getMessage(MESSAGE_WALKAWAY)
local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid), [TAG_PLAYERSEX] = getMrSex(cid) }
msg = self:parseMessage(msg, parseInfo)

self:say(msg, cid)
self:releaseFocus(cid)
self:say(msg)
end
end
end
end
end

-- Returns true if cid is within the talkRadius of this npc.
function NpcHandler:isInRange(cid)
local distance = getDistanceTo(cid) or -1
if(distance == -1) then
return false
end

return (distance <= self.talkRadius)
end

-- Resets the npc into it's initial state (in regard of the keyrodhandler).
-- All modules are also receiving a reset call through their callbackOnModuleReset function.
function NpcHandler:resetNpc()
if(self:processModuleCallback(CALLBACK_MODULE_RESET)) then
self.keywordHandler:reset()
end
end

-- Makes the npc represented by this instance of NpcHandler say something.
-- This implements the currently set type of talkdelay.
-- shallDelay is a boolean value. If it is false, the message is not delayed. Default value is false.
function NpcHandler:say(message, focus, shallDelay)
local shallDelay = shallDelay or false
if(NPCHANDLER_TALKDELAY == TALKDELAY_NONE or not shallDelay) then
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
selfSay(message, focus)
return
else
selfSay(message)
return
end
end

-- TODO: Add an event handling method for delayed messages
if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
self.talkDelay[focus] = {
message = message,
time = os.time() + self.talkDelayTime,
}
else
self.talkDelay = {
message = message,
time = os.time() + self.talkDelayTime
}
end
end
end

 

 

npcsystem.lua

 

-- Advanced NPC System (Created by Jiddo),
-- Modified by Talaturen.

if(NpcSystem == nil) then
-- Loads the underlying classes of the npcsystem.
dofile(getDataDir() .. 'npc/lib/npcsystem/keywordhandler.lua')
dofile(getDataDir() .. 'npc/lib/npcsystem/queue.lua')
dofile(getDataDir() .. 'npc/lib/npcsystem/npchandler.lua')
dofile(getDataDir() .. 'npc/lib/npcsystem/modules.lua')

-- Global npc constants:

-- Keyword nestling behavior. For more information look at the top of keywordhandler.lua
KEYWORD_BEHAVIOR = BEHAVIOR_NORMAL_EXTENDED

-- Greeting and unGreeting keywords. For more information look at the top of modules.lua
FOCUS_GREETWORDS = {'hi', 'hello', 'hey'}
FOCUS_FAREWELLWORDS = {'bye', 'farewell', 'cya'}

-- The word for requesting trade window. For more information look at the top of modules.lua
SHOP_TRADEREQUEST = {'offer', 'trade'}

-- The word for accepting/declining an offer. CAN ONLY CONTAIN ONE FIELD! For more information look at the top of modules.lua
SHOP_YESWORD = {'yes'}
SHOP_NOWORD = {'no'}

-- Pattern used to get the amount of an item a player wants to buy/sell.
PATTERN_COUNT = '%d+'

-- Talkdelay behavior. For more information, look at the top of npchandler.lua.
NPCHANDLER_TALKDELAY = TALKDELAY_ONTHINK

-- Conversation behavior. For more information, look at the top of npchandler.lua.
NPCHANDLER_CONVBEHAVIOR = CONVERSATION_PRIVATE

-- Constant strings defining the keywords to replace in the default messages.
-- For more information, look at the top of npchandler.lua...
TAG_PLAYERNAME = '|PLAYERNAME|'
TAG_ITEMCOUNT = '|ITEMCOUNT|'
TAG_TOTALCOST = '|TOTALCOST|'
TAG_ITEMNAME = '|ITEMNAME|'
TAG_QUEUESIZE = '|QUEUESIZE|'
       TAG_PLAYERSEX = '|PLAYERSEX|'

NpcSystem = {}

-- Gets an npcparameter with the specified key. Returns nil if no such parameter is found.
function NpcSystem.getParameter(key)
local ret = getNpcParameter(tostring(key))
if((type(ret) == 'number' and ret == 0) or ret == nil) then
return nil
else
return ret
end
end

-- Parses all known parameters for the npc. Also parses parseable modules.
function NpcSystem.parseParameters(npcHandler)
local ret = NpcSystem.getParameter('idletime')
if(ret ~= nil) then
npcHandler.idleTime = tonumber(ret)
end
local ret = NpcSystem.getParameter('talkradius')
if(ret ~= nil) then
npcHandler.talkRadius = tonumber(ret)
end
local ret = NpcSystem.getParameter('message_greet')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_GREET, ret)
end
local ret = NpcSystem.getParameter('message_farewell')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_FAREWELL, ret)
end
local ret = NpcSystem.getParameter('message_decline')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_DECLINE, ret)
end
local ret = NpcSystem.getParameter('message_needmorespace')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_NEEDMORESPACE, ret)
end
local ret = NpcSystem.getParameter('message_needspace')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_NEEDSPACE, ret)
end
local ret = NpcSystem.getParameter('message_sendtrade')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_SENDTRADE, ret)
end
local ret = NpcSystem.getParameter('message_noshop')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_NOSHOP, ret)
end
local ret = NpcSystem.getParameter('message_oncloseshop')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_ONCLOSESHOP, ret)
end
local ret = NpcSystem.getParameter('message_onbuy')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_ONBUY, ret)
end
local ret = NpcSystem.getParameter('message_onsell')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_ONSELL, ret)
end
local ret = NpcSystem.getParameter('message_missingmoney')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_MISSINGMONEY, ret)
end
local ret = NpcSystem.getParameter('message_needmoney')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_NEEDMONEY, ret)
end
local ret = NpcSystem.getParameter('message_missingitem')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_MISSINGITEM, ret)
end
local ret = NpcSystem.getParameter('message_needitem')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_NEEDITEM, ret)
end
local ret = NpcSystem.getParameter('message_idletimeout')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_IDLETIMEOUT, ret)
end
local ret = NpcSystem.getParameter('message_walkaway')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_WALKAWAY, ret)
end
local ret = NpcSystem.getParameter('message_alreadyfocused')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_ALREADYFOCUSED, ret)
end
local ret = NpcSystem.getParameter('message_placedinqueue')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_PLACEDINQUEUE, ret)
end
local ret = NpcSystem.getParameter('message_buy')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_BUY, ret)
end
local ret = NpcSystem.getParameter('message_sell')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_SELL, ret)
end
local ret = NpcSystem.getParameter('message_bought')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_BOUGHT, ret)
end
local ret = NpcSystem.getParameter('message_sold')
if(ret ~= nil) then
npcHandler:setMessage(MESSAGE_SOLD, ret)
end

-- Parse modules.
for parameter, module in pairs(Modules.parseableModules) do
local ret = NpcSystem.getParameter(parameter)
if(ret ~= nil) then
local number = tonumber(ret)
if(number ~= 0 and module.parseParameters ~= nil) then
local instance = module:new()
npcHandler:addModule(instance)
instance:parseParameters()
end
end
end
end
end

 

 

agora você pode usar assim:

 

<?xml version="1.0"?>
<npc name="Nome do seu npc" script="data/npc/scripts/script do seu npc.lua" walkinterval="50000" floorchange="0">
<health now="100" max="100"/>
<look type="129" head="95" body="116" legs="121" feet="115" addons="3"/>
<parameters>
<parameter key="message_greet" value="Hello |PLAYERSEX| |PLAYERNAME|. want to look my pearls? {Trade} with me!" />
</parameters>
</npc>

11 de abril de 2012 às 11:22

Se eu pudesse te dava uns 10 REP+ mdr.gif

 

Muito obrigado pela ajuda Vodkart, fazer isso deve ter dado trabalho.

 

 

Abraço e tudo de bom aí happy.png

Gabriel CoutoG
11 de abril de 2012 às 13:06

Tópico resolvido.