Ir para conteúdo

Criando seu NPC sem Jiddo


Eventide

Posts Recomendados

Pre-requisitos para entender o tutorial

Para entender este tutorial é necessario que você saiba sobre tabelas e condicionais(if, else, elseif), tutorial sobre tabelas pode ser encontrado facilmente neste fórum, mas infelizmente o de condicionais parece estar um pouco corroído pelo tempo.

 

 

Introdução

Pra quem não sabe, Jiddo é um sistema de NPCs que nem sempre foi o padrão, hoje em dia é muito difícil encontrar um NPC na sua pasta data que não tenha sido feito nele, ele é simplesmente uma biblioteca feita por cima do sistema padrão, entretanto não é nada flexivel, faço das palavras que o Mock certa vez usou em uma discussão as minhas: "jiido é um pedaço de ferro fundido e o normal é um pedaço de silicone."

 

Basicamente, se você quer fazer um NPC que não é simplesmente um shopper, não use Jiddo, mas aí você me pergunta, porque eu faria um NPC que não é um shopper?

Tenta advinha que hoje eu to difícil rçrçrçrç.

Brincadeira, fique com um exemplo que seria praticamente impossivel de se fazer com Jiddo:

(relevem a tosquera do video, ele é meio antiguinho, eu mesmo morri de rir revendo ele)

 

Eventos

Como todo tipo de script, os NPCs também tem eventos, eles são:

 

onThink()

Roda sempre.

 

onPlayerEndTrade(cid)

Roda sempre que alguém fecha o shop do NPC.

 

onPlayerCloseChannel(cid)

Roda sempre que alguém fecha o canal NPC.

 

onCreatureSay(cid, type, msg)

Roda quando alguém fala com o NPC.

 

onCreatureDisappear(cid)

Roda quando o player(ou um monstro) sai do radius do npc.

 

onCreatureAppear(cid)

É ativado quando o player(ou um monstro) entra no radius do npc.

 

O padrão

Diferente dos outros tipos de script, os NPCs tem um padrão a ser seguido para poderem funcionar, vou usar neste tutorial o exemplo de como fazer um NPC de compra e venda para que vocês entendam este padrão. Em primeiro lugar você deve copiar e colar isso no seu script:

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

local function addFocus(cid)
if(not isFocused(cid)) then
	table.insert(focuses, cid)
end
end
local function removeFocus(cid)
for i, v in pairs(focuses) do
	if(v == cid) then
		table.remove(focuses, i)
		break
	end
end
end
local function lookAtFocus()
for i, v in pairs(focuses) do
	if(isPlayer(v)) then
		doNpcSetCreatureFocus(v)
		return
	end
end
doNpcSetCreatureFocus(0)
end

 

Se o NPC for de compra e venda, adicione isso também:

local itemWindow = {
{id=2160, subType=0, buy=10000, sell=10000, name="Test1"},
{id=2152, subType=0, buy=100, sell=100, name="Test2"},
{id=2148, subType=0, buy=1, sell=1, name="Test3"},
{id=2173, subType=0, buy=10000, sell=5000, name="Test4"}
}

local items = {}
for _, item in ipairs(itemWindow) do
items[item.id] = {buyPrice = item.buy, sellPrice = item.sell, subType = item.subType, realName = item.name}
end

local function getPlayerMoney(cid)
return ((getPlayerItemCount(cid, 2160) * 10000) +
(getPlayerItemCount(cid, 2152) * 100) +
getPlayerItemCount(cid, 2148))
end

local onBuy = function(cid, item, subType, amount, ignoreCap, inBackpacks)
if(items[item] == nil) then
	selfSay("Ehm.. sorry... this shouldn't be there, I'm not selling it.", cid)
	return
end

if(getPlayerMoney(cid) >= amount * items[item].buyPrice) then
	local itemz, i = doNpcSellItem(cid, item, amount, subType, ignoreCap, inBackpacks)
	if(i < amount) then
		if(i == 0) then
			selfSay("Sorry, but you don't have space to take it.", cid)
		else
			selfSay("I've sold some for you, but it seems you can't carry more than this. I won't take more money than necessary.", cid)
			doPlayerRemoveMoney(cid, i * items[item].buyPrice)
		end
	else
		selfSay("Thanks for the money!", cid)
		doPlayerRemoveMoney(cid, amount * items[item].buyPrice)
	end
else
	selfSay("Stfu noob, you don't have money.", cid)
end
end

local onSell = function(cid, item, subType, amount, ignoreCap, inBackpacks)
if(items[item] == nil) then
	selfSay("Ehm.. sorry... this shouldn't be there, I'm not buying it.", cid)
end

if(subType < 1) then
	subType = -1
end
if(doPlayerRemoveItem(cid, item, amount, subType)) then
	doPlayerAddMoney(cid, items[item].sellPrice * amount)
	selfSay("Here you are.", cid)
else
	selfSay("No item, no deal.", cid)
end
end

dica: mude as strings do selfSay

 

Agora vamos entender o que faz esse código:

isFocused(cid) verifica se o jogador cid está falando com o NPC

addFocus(cid) adiciona o jogador cid a lista de jogadores que estão falando com o NPC.

removeFocus(cid) remove o jogador da lista de jogadores que estão falando com o NPC.

lookAtFocus() força o NPC a olhar pro jogador que está falando com ele.

getPlayerMoney(cid) retorna a quantidade de dinheiro que o jogador cid tem.(alguns servidores já vem com essa função)

onBuy é a função que é executada toda vez que o jogador compra um item.

onSell é a função que é executada quando um jogador vende um item.

 

Agora atenção especial para a tabela itemWindow:

local itemWindow = {
{id=2160, subType=0, buy=10000, sell=10000, name="Test1"},
{id=2152, subType=0, buy=100, sell=100, name="Test2"},
{id=2148, subType=0, buy=1, sell=1, name="Test3"},
{id=2173, subType=0, buy=10000, sell=5000, name="Test4"}
}

Nesta tabela você deve configurar os itens que serão vendidos no shop, se você não sabe como funciona uma tabela, procure um tutorial a respeito, mas pra facilitar, simplesmente edite as variaveis dentro da tabela, mantendo as aspas quanto tiver e quando for para apenas vender o item delete o "buy = valor," e para apenas comprar delete o "sell = valor,", para remover ou adicionar itens, não se esqueça que depois do "}" sempre deve haver uma virgula, exceto para o ultimo valor.

 

Padrão para o evento onThink()

Existe um código que deve ser sempre copiado para o evento onThink(), qualquer modificação no evento deve ser feita após esse código a não ser que você saiba o que está fazendo:

function onThink()
for i, focus in pairs(focuses) do
	if(not isCreature(focus)) then
		removeFocus(focus)
	else
		local distance = getDistanceTo(focus) or -1
		if((distance > 4) or (distance == -1)) then
			selfSay("Hmph!")
			closeShopWindow(focus)
			removeFocus(focus)
		end
	end
end
lookAtFocus()
end

 

Padrão para o evento onCreatureSay(cid, type, msg)

Qual é a primeira coisa que alguem fala pro NPC? Geralmente é o hi, né? Então, você diz hi para o NPC para iniciar uma conversa com ele, portanto devemos verificar antes se o jogador não estava conversando antes, para isso usamos essa condicional:

function onCreatureSay(cid, type, msg)
if((msg == "hi") and not (isFocused(cid))) then

Para só depois o NPC dar as boas vindas ao jogador e adiciona-lo a lista dos conversantes:

function onCreatureSay(cid, type, msg)
if((msg == "hi") and not (isFocused(cid))) then
	selfSay("Welcome, ".. getCreatureName(cid) ..".", cid, true)
	selfSay("Do you want to see my {wares}?", cid)
	addFocus(cid)

Agora, e pra abrir o shop depois que o player disse hi? Verificamos se a variavel do parametro msg é igual a "trade" ou "warez" e tambem verificamos se o jogador está entre a lista de conversantes, afinal ninguem sai falando "deixa eu vê seus item aí mano" sem falar um "oi" antes, né?

elseif((isFocused(cid)) and (msg == "wares" or msg == "trade")) then
	selfSay("Pretty nice, right?", cid)
	openShopWindow(cid, itemWindow, onBuy, onSell)

E o "bye"? como fica nessa história? Praticamente a mesma coisa do trade, só que ao invez de abrir o shop, ele fecha:

elseif((isFocused(cid)) and (msg == "bye" or msg == "goodbye" or msg == "cya")) then
	selfSay("Goodbye!", cid, true)
	closeShopWindow(cid)
	removeFocus(cid)

E se eu quiser fazer outro tipo de conversa, mais voltada para uma quest, por exemplo?

Então você, alem de ter que verificar o que foi dito, deve verificar se algo já foi dito antes, confuso? Vou dar um exemplo pratico, o jogador fala quest para o NPC, então o NPC responde que ele precisa de ajuda mas que é algo complicado e pergunta se você tem certeza, então se você responde que não ele desiste e se responde que sim dá a quest, como fazer isso?

Simples, você deve fazer uma variavel com valor zero antes do evento onCreatureSay, quando o jogador falar quest, você dá o valor um pra ela, então quando o player falar yes, você verifica se o valor da variavel é um, não entendeu? De uma olhada em como isso ficaria no script:

elseif((isFocused(cid)) and (msg == "quest")) then
	count = 1
	selfSay("Hmm, não sei se você é capaz de fazer o que eu quero, você tem certeza que quer fazer isso?", cid)
elseif((isFocused(cid)) and (msg == "yes") and (count == 1)) then
	selfSay("Então tá! Traga um copo d'agua pra mim que eu te dou um real.", cid)
elseif((isFocused(cid)) and (msg == "quest")) then
	selfSay("Então porque perguntou?", cid)

O código final ficaria assim:

local count = 0
function onCreatureSay(cid, type, msg)
if((msg == "hi") and not (isFocused(cid))) then
	selfSay("Welcome, ".. getCreatureName(cid) ..".", cid, true)
	selfSay("Do you want to see my {wares}?", cid)
	addFocus(cid)
elseif((isFocused(cid)) and (msg == "wares" or msg == "trade")) then
	selfSay("Pretty nice, right?", cid)
	openShopWindow(cid, itemWindow, onBuy, onSell)
elseif((isFocused(cid)) and (msg == "bye" or msg == "goodbye" or msg == "cya")) then
	selfSay("Goodbye!", cid, true)
	closeShopWindow(cid)
	removeFocus(cid)
elseif((isFocused(cid)) and (msg == "quest")) then
	count = 1
	selfSay("Hmm, não sei se você é capaz de fazer o que eu quero, você tem certeza que quer fazer isso?", cid)
elseif((isFocused(cid)) and (msg == "yes") and (count == 1)) then
	selfSay("Então tá! Traga um copo d'agua pra mim que eu te dou um real.", cid)
elseif((isFocused(cid)) and (msg == "quest")) then
	selfSay("Então porque perguntou?", cid)
end
end

 

Bom, esse é o tutorial, qualquer duvida pode recorrer a este tópico ou a seção de dúvidas. vlwflw.

Só como consideração final eu gostaria de dizer que esse script de exemplo foi tirado do TFS 0.3.6, não garanto o uso deste metodo em qualquer outra distribuição.

Editado por Eventide
Link para o comentário
Compartilhar em outros sites

Muito legal, ás vezes não é nada fácil entender tais NPCS.

Obrigado por compartilhar com a comunidade, seu tutorial será aprovado de 3 a 7 dias.

Link para o comentário
Compartilhar em outros sites

Cara, que tutorial em? curti muito!

 

Tava precisando de algo assim, ODEIO Jiddo System com todas minhas forças...

 

O ruim é justamente o que você disse, o tutorial de if else e etc tá uma bosta, alguém deveria refazê-lo com mais exemplos.. (fica a dica pra quem sabe).

 

amanhã tem seu REP+ hoje esgotei e_e

Link para o comentário
Compartilhar em outros sites

Seu tutorial foi aprovado e movido, obrigado por compartilhar com a comunidade ÉksTibiana :]

Obrigado por move-lo roscas, ele ainda está um pouco incompleto mas vou edita-lo ainda hoje...

Editado por Eventide
Link para o comentário
Compartilhar em outros sites

×
×
  • Criar Novo...