Jump to content

Pasta Data - Actions


tibiaa4e

Recommended Posts

Pasta Enciclopedia com todos os links de outros tutoriais !

Link

 

Tutorial de Actions

 

 

Se você leu os outros tutoriais deve estar pronto para entender esse. Pelo menos as bases...

Bem na minha ausencia na programação Open Tibia (1 ano) eu fiquei para trás em algumas novidades e por isso

Algumas explicações podem parecer obsoletas, porém funcionam da mesma maneira apenas podem ficar maiores...

 

As Actions (ações) são scripts que são "ativados" ou usados quando se usa o item, ou seja, quando o player clica

com o botão direito no item. Itens que abrem o crosshair (alvo) também são acionados em actions como vara de pescar, pá

e corda.

 

Antigamente elas eram a unica maneira de se programar itens já que não existiam movements, talkactions, global events

e creatures scripts. Portanto elas são a porta de entrada para novos programadores, que pretendem ingressar na vida de ot.

Sintaxe das Actions

 

A sintaxe em tese é igual de todos os scripts, porém em actions existe apenas uma função principal a onUse

 

function onUse(cid, item, fromPosition, itemEx, toPosition)
end

 

Sendo os parametros :

 

cid : O uid no caso apenas cid (creature id) que é o player que usa o item.

item: O item indicado no actions.xml ou seja o principal.

fromPosition: DA posição, ou seja, a posição inicial do item ao ser usado. É a posição do item.

itemEx: Ou item2 (antigamente) é o segundo item relacionado, só existe quando o item tem o crosshair (vara de pescar

o itemEx seria a agua).

toPosition : A posição do itemEx.

 

Lembrando sempre que os parametros indicados ai podem ser qualquer um (de preferencia não mude o cid), sendo essa aqui

a mesma coisa

 

function onUse(cid, itemprimario, DaPosicao, Itemsecundario, ParaPosicao)

 

Claro que usando isso acima, os nomes usados no script devem ser os mesmos

 

item e Item não é mesma coisa, lua tem um recurso que difere letras maisculas e miniculas nas funções (em string ele desconsidera)!!

 

Antes de começar repito que é preferivel dar uma olhada nos tutoriais Basico de Lua, Funções em Lua e Lua intermediario.

 

Depois da introdução basica colocarei um exemplo de action tradicional.

 

function onUse(cid, item, fromPosition, itemEx, toPosition)

if item.itemid == 2148 and item.type == 100 then
	doChangeTypeItem(item.uid, item.type - item.type)
	doPlayerAddItem(cid, 2152, 1)
	doSendAnimatedText(fromPosition, "$$$", TEXTCOLOR_PLATINUMBLUE)
end
end

 

Esse script transforma 100 golds coins (id 2148) em uma platinum coin.

Existem milhares de maneira de fazer isso, porém escolhi a do the forgotten server.

 

Nesse script ele checa se o item é 2148 (gold coin) e tem o type 100.

Se tiver ele muda o tipo do item para o tipo do item 2148 (100) menos o mesmo. Ou seja 100-100 = 0. No caso ele some

Depois ele adiciona um item 2152 (platinum coin), e depois manda um efeito magico na posição que foi usado o item.

 

Esse efeito magico nomeado TEXTCOLOR_PLATINUMBLUE é nomeado no global.lua (ou constant.lua) é usado para simplificar (ou não) a vida

dos scripters.

 

 

Todo item tem um "array" nele, ou seja ele tem certas informações :

item.itemid = é o id do item.
item.uid = Indica o numero unico dele.
item.actionid = O id de ação dele.
item.type = O tipo dele, em itens agrupaveis indica quantidade. Em potes indica o id dos liquidos.

 

Sabendo desses "arrays" você deve entender o uso deles em actions,movements e talk actions.

 

Essa action será executada quando você der use em 100 gold coins e fará tudo isso explicado acima.

Provavelmente o explicado acima você ja sabia, então vamos a um script mais avançado.

 

Acão com item com crosshair

 

Esse script é da shovel (pá).

 

local holes = {468, 481, 483}

function onUse(cid, item, fromPosition, itemEx, toPosition)

if isInArray(holes, itemEx.itemid) == TRUE then
	doTransformItem(itemEx.uid, itemEx.itemid + 1)
	doDecayItem(itemEx.uid)
elseif itemEx.itemid == 7932 then
	doTransformItem(itemEx.uid, itemEx.itemid + 1)
elseif itemEx.itemid == 231 then
	local rand = math.random(1, 100)
	if rand == 1 then
		doCreateItem(2159, 1, toPosition)
	elseif rand > 95 then
		doSummonCreature("Scarab", toPosition)
	end	
	doSendMagicEffect(toPosition, CONST_ME_POFF)
else
	return FALSE
end
return TRUE
end

 

Esse script contém array,nomeações no global.lua (ou constant)randons e returns. Ou seja é uma bela revisão!!!

 

Vou explica-lo por partes.

Primeiro apenas a pá é direcionado para esse script sendo desnecessario indicar o item nas condicionais.

Então ele só checa os itemEx. No caso ele checa se o itemEx é os ids 468, 481, 483, 7932 e 231.

 

local holes = {468, 481, 483}
if isInArray(holes, itemEx.itemid) == TRUE then

 

O metodo correto de se usar o isInArray (Está dentro do array), é assim

 

if IsInArray (vetor, tipodoitem.tipodele) == BOOLEANO then

 

Ou seja no exemplo do script ele checa o array holes se eles são o itemEx (que no caso são buracos fechados).

Isso é usado para não ficar usando varios and sendo outra maneira de usar isso seria.

 

if item.itemid == 468 or item.itemid == 481 or item.itemid == 483 then

 

Voltando ao script

 

	if isInArray(holes, itemEx.itemid) == TRUE then
	doTransformItem(itemEx.uid, itemEx.itemid + 1)
	doDecayItem(itemEx.uid)
	...
else
	return FALSE
end

 

Se ele tiver dentro do array dele ele transforma o item para o id dele + 1 (se for 468 vira 469)

E depois manda ele decair ("aprodecer" como diria meu amigo, sendo que ele se transforma em outro, o tempo é indicado

no items.xml)

 

 

...
elseif itemEx.itemid == 231 then
	local rand = math.random(1, 100)
	if rand == 1 then
		doCreateItem(2159, 1, toPosition)
	elseif rand > 95 then
		doSummonCreature("Scarab", toPosition)
	end

 

Essa parte é mais interessante já que usa o math.random . No caso o scripter acima armazenou na variavel rand o valor

Ou seja toda vez que alguem acessar essa variavel ele irá dar um numero de 1 a 100.

Se der o valor 1 ele cria o scarab coin na posição da areia usada pela pá.(toPosition).

Se for maior que 95 sumona o scarab na posição da areia usada pela pá.

 

 

Bem sinceramente actions em tese é só isso... O resto é criatividade eu poderia ficar aqui criando o dia inteiro

citando exemplos para melhor entender. Espero que essa base faça você entender o resto dos scripts. Por que 90% dos scripters

fazem isso, copiam outros e editam (dificilmente fazem do zero). Claro que se você usar praticamente toda a base deve

colocar os creditos...

 

Exemplos de actions para melhor compreensão :

 

Alavanca

 

function onUse(cid, item, frompos, item2, topos)

local gatepos = {x=1069, y=653, z=15, stackpos=1}
local telepos = {x=1071, y=652, z=15, stackpos=1}
local gopos = {x=1073, y=653, z=14, stackpos=1}

local getgate = getThingfromPos(gatepos)
local gettele = getThingfromPos(telepos)

if item.uid == 8550 and item.itemid == 1945 and getgate.itemid == 1355 then
	doRemoveItem(getgate.uid,1)
	doTransformItem(item.uid,item.itemid+1)
	doCreateTeleport(1387, gopos, telepos)
elseif item.uid == 8550 and item.itemid == 1946	and getgate.itemid == 0 then
	doCreateItem(1355,1,gatepos)
	doTransformItem(item.uid,item.itemid-1)
	doRemoveItem(gettele.uid,1)
else
	doPlayerSendCancel(cid,"Sorry, not possible.")
end

return 1
end

 

Esse codigo é o da pedra da demon helmet, ele remove a pedra,transforma a alavanca,cria um teleport.

E com a alavanca ativada ele coloca a pedra,remove o teleport e transforma a alavanca.

 

Quando se quer adicionar "terceiros itens" ao script deve se usar o getThingfromPos, essa função checa o item no tile

correspondente e o seu devido stackpos (tomare que você tenha aprendido isso). No caso ai o "terceiro item" seria a pedra

Isso é muito util para 90% dos scripts descentes.

 

 

Quest basica e boa.

 

function onUse(cid, item, frompos, item2, topos)

local itemWeight = getItemWeightById(item, 1)
local playerCap = getPlayerFreeCap(cid)

if item.uid == 2300 then
	if getPlayerStorageValue(cid,2300) == -1 then
		if playerCap >= itemWeight then
			doPlayerSendTextMessage(cid,MESSAGE_INFO_DESCR,"You have found a demon helmet.")
			doPlayerAddItem(cid,2493,1)
			setPlayerStorageValue(cid,2300,1)
		else
			doPlayerSendTextMessage(cid,MESSAGE_INFO_DESCR,"You have found a demon helmet. Weighing 29.50 oz it is too heavy.")
		end
	else
		doPlayerSendTextMessage(cid,MESSAGE_INFO_DESCR,"The chest is empty.")
	end
end
end

 

Nesse caso ele checa varias coisas e depois ele adiciona os items, existe uma função que substitui isso, porém não fica boa. Pois

devido ao tfs ela abre o bau como se ele fosse vazio (porém adicionar certinho e checa tudo).

 

 

Esses dois exemplo são um dos mais questionados tem outros que serão vocês que irão fazer num futuro tutorial de exercicios.

 

Simplificação de Scripts

 

Em certos casos de scripts, existe a famosa repetição continua de comandos deixando ele grande atoa.

Usando varios exemplos de diminuição diminuirei o script da minha obsidian knife drasticamente.

 

 

Original 99 linhas

function onUse(cid,item,frompos,item2,topos)
local number = math.random(1,100)
local chance = 30

--minos--
if item2.itemid == 2830 or item2.itemid == 2871 or item2.itemid == 2876 or item2.itemid == 2866 then
	if number <= chance then
		doSendMagicEffect(topos,14)
		doPlayerAddItem(cid,5878,1)
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,3)
		doTransformItem(item2.uid,item2.itemid+1)
	end
	return 1

--lizard--
elseif item2.itemid == 4259 or item2.itemid == 4262 or item2.itemid == 4256 then
	if number <= chance then
		doSendMagicEffect(topos,14)
		doPlayerAddItem(cid,5876,1)
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,3)
		doTransformItem(item2.uid,item2.itemid+1)
	end
	return 1

--dragon
elseif item2.itemid == 3104 or item2.itemid == 2844 then
	if number <= chance then
		doSendMagicEffect(topos,14)
		doPlayerAddItem(cid,5877,1)
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,3)
		doTransformItem(item2.uid,item2.itemid+1)
	end
	return 1

--dragon lord
elseif item2.itemid == 2881 then
	if number <= chance then
		doSendMagicEffect(topos,14)
		doPlayerAddItem(cid,5948,1)
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,3)
		doTransformItem(item2.uid,item2.itemid+1)
	end
	return 1

--behemoth
elseif item2.itemid == 2931 then
	if number <= chance then
		doSendMagicEffect(topos,14)
		doPlayerAddItem(cid,5893,1)
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,3)
		doTransformItem(item2.uid,item2.itemid+1)
	end
	return 1

--bone beast
elseif item2.itemid == 3031 then
	if number <= chance then
		doSendMagicEffect(topos,14)
		doPlayerAddItem(cid,5925,1)
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,3)
		doTransformItem(item2.uid,item2.itemid+1)
	end
	return 1

--ice cubes--
elseif item2.itemid == 7441 or item2.itemid == 7444 or item2.itemid == 7445 then
	if number <= 55 then
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,9)
		doRemoveItem(item2.uid,1)
		doCreatureSay(cid, 'The attempt at sculpting failed miserably.', TALKTYPE_ORANGE_1)
	end
	return 1

elseif item2.itemid == 7442 then
	if number <= 55 then
		doTransformItem(item2.uid,item2.itemid+2)
	else
		doSendMagicEffect(topos,9)
		doRemoveItem(item2.uid,1)
		doCreatureSay(cid, 'The attempt at sculpting failed miserably.', TALKTYPE_ORANGE_1)
	end
	return 1
end

return 0
end

 

Usando arrays iremos aumentar linhas, porém deixaremos mais compreensivel.

Ficando assim :

 

105 linhas

function onUse(cid,item,frompos,item2,topos)
local number = math.random(1,100)
local chance = 30
local minoS = {2830,2871,2876,2866}
local lizardS = {4259,4262,4256}
local dragonS = {3104,2844}
local iceS = {7441,7444,7445}

--minos--
if isInArray(minoS, item2.itemid) == TRUE then
	if number <= chance then
		doSendMagicEffect(topos,14)
		doPlayerAddItem(cid,5878,1)
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,3)
		doTransformItem(item2.uid,item2.itemid+1)
	end
	return 1

--lizard--
elseif isInArray(lizardS, item2.itemid) == TRUE then
	if number <= chance then
		doSendMagicEffect(topos,14)
		doPlayerAddItem(cid,5876,1)
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,3)
		doTransformItem(item2.uid,item2.itemid+1)
	end
	return 1

--dragon
elseif isInArray(dragonS, item2.itemid) == TRUE then
	if number <= chance then
		doSendMagicEffect(topos,14)
		doPlayerAddItem(cid,5877,1)
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,3)
		doTransformItem(item2.uid,item2.itemid+1)
	end
	return 1

--dragon lord
elseif item2.itemid == 2881 then
	if number <= chance then
		doSendMagicEffect(topos,14)
		doPlayerAddItem(cid,5948,1)
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,3)
		doTransformItem(item2.uid,item2.itemid+1)
	end
	return 1

--behemoth
elseif item2.itemid == 2931 then
	if number <= chance then
		doSendMagicEffect(topos,14)
		doPlayerAddItem(cid,5893,1)
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,3)
		doTransformItem(item2.uid,item2.itemid+1)
	end
	return 1

--bone beast
elseif item2.itemid == 3031 then
	if number <= chance then
		doSendMagicEffect(topos,14)
		doPlayerAddItem(cid,5925,1)
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,3)
		doTransformItem(item2.uid,item2.itemid+1)
	end
	return 1

--ice cubes--
elseif isInArray(iceS, item2.itemid) == TRUE then
	if number <= 55 then
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,9)
		doRemoveItem(item2.uid,1)
		doCreatureSay(cid, 'The attempt at sculpting failed miserably.', TALKTYPE_ORANGE_1)
	end
	return 1

elseif item2.itemid == 7442 then
	if number <= 55 then
		doTransformItem(item2.uid,item2.itemid+2)
	else
		doSendMagicEffect(topos,9)
		doRemoveItem(item2.uid,1)
		doCreatureSay(cid, 'The attempt at sculpting failed miserably.', TALKTYPE_ORANGE_1)
	end
	return 1

end

return 0
end

 

Você pode observar que nos monstros sempre o monstro é transformado em um item maior, então não é necessario colocar

ele na condicional e no else. E também esse return 1 não é necessario. então vamos remove-lo

Podendo deixar assim

 

89 linhas

function onUse(cid,item,frompos,item2,topos)
local number = math.random(1,100)
local chance = 30
local minoS = {2830,2871,2876,2866}
local lizardS = {4259,4262,4256}
local dragonS = {3104,2844}
local iceS = {7441,7444,7445}

--minos--
if isInArray(minoS, item2.itemid) == TRUE then
	doTransformItem(item2.uid,item2.itemid+1)
		if number <= chance then
			doSendMagicEffect(topos,14)
			doPlayerAddItem(cid,5878,1)
		else
			doSendMagicEffect(topos,3)
		end

--lizard--
elseif isInArray(lizardS, item2.itemid) == TRUE then
	doTransformItem(item2.uid,item2.itemid+1)
		if number <= chance then
			doSendMagicEffect(topos,14)
			doPlayerAddItem(cid,5876,1)
		else
			doSendMagicEffect(topos,3)
		end

--dragon
elseif isInArray(dragonS, item2.itemid) == TRUE then
	doTransformItem(item2.uid,item2.itemid+1)
		if number <= chance then
			doSendMagicEffect(topos,14)
			doPlayerAddItem(cid,5877,1)
		else
			doSendMagicEffect(topos,3)
		end

--dragon lord
elseif item2.itemid == 2881 then
	doTransformItem(item2.uid,item2.itemid+1)
		if number <= chance then
			doSendMagicEffect(topos,14)
			doPlayerAddItem(cid,5948,1)
		else
			doSendMagicEffect(topos,3)
		end

--behemoth
elseif item2.itemid == 2931 then
	doTransformItem(item2.uid,item2.itemid+1)
		if number <= chance then
			doSendMagicEffect(topos,14)
			doPlayerAddItem(cid,5893,1)
		else
			doSendMagicEffect(topos,3)
		end

--bone beast
elseif item2.itemid == 3031 then
	doTransformItem(item2.uid,item2.itemid+1)
		if number <= chance then
			doSendMagicEffect(topos,14)
			doPlayerAddItem(cid,5925,1)
		else
			doSendMagicEffect(topos,3)
		end

--ice cubes--
elseif isInArray(iceS, item2.itemid) == TRUE then
	if number <= 55 then
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,9)
		doRemoveItem(item2.uid,1)
		doCreatureSay(cid, 'The attempt at sculpting failed miserably.', TALKTYPE_ORANGE_1)
	end

elseif item2.itemid == 7442 then
	if number <= 55 then
		doTransformItem(item2.uid,item2.itemid+2)
	else
		doSendMagicEffect(topos,9)
		doRemoveItem(item2.uid,1)
		doCreatureSay(cid, 'The attempt at sculpting failed miserably.', TALKTYPE_ORANGE_1)
	end
end

return FALSE 
end

 

Bem diminuimos 6 linhas apenas. Podemos observar que ele faz sempre as mesmas ações, apenas muda os ids. Se vc leu

um tutorial passado podemos muito bem criar uma função para isso mais como ?

 

elseif isInArray(dragonS, item2.itemid) == TRUE then
	doTransformItem(item2.uid,item2.itemid+1)
		if number <= chance then
			doSendMagicEffect(topos,14)
			doPlayerAddItem(cid,5877,1)
		else
			doSendMagicEffect(topos,3)
		end

 

Bem para isso teremos que fazer umas mudanças porém vamos fazer primeiro a função

 

function onSkin(cid,skin,topos,item2)

local number = math.random(1,100)
local chance = 30

doTransformItem(item2.uid,item2.itemid+1)
if number <= chance then
	doSendMagicEffect(topos,14)
	doPlayerAddItem(cid,skin,1)
else
	doSendMagicEffect(topos,3)
end
end

 

Bem essa função pode parecer confusa, porém todos esses dados são chamados Dados tecnicos. Pois dai

apenas o skin deve ser modificado o resto só existe para a função principal (no caso onUse) não se confuda e funcione.

 

O script diminuido e muito mais simples fica assim :

65 linhas

 

function onUse(cid,item,frompos,item2,topos)
local minoS = {2830,2871,2876,2866,3090,5969}
local lizardS = {4259,4262,4256}
local dragonS = {3104,2844}
local iceS = {7441,7444,7445}

--minos--
if isInArray(cid,minoS, item2.itemid) == TRUE then
	onSkin(cid,5878,topos,item2)

--lizard--
elseif isInArray(lizardS, item2.itemid) == TRUE then
	onSkin(cid,5876,topos,item2)

--dragon
elseif isInArray(dragonS, item2.itemid) == TRUE then
	onSkin(cid,5877,topos,item2)

--dragon lord
elseif item2.itemid == 2881 then
	onSkin(cid,5948,topos,item2)

--behemoth
elseif item2.itemid == 2931 then
	onSkin(cid,5893,topos,item2)

--bone beast
elseif item2.itemid == 3031 then
	onSkin(cid,5925,topos,item2)

--ice cubes--
elseif isInArray(iceS, item2.itemid) == TRUE then
	if number <= 55 then
		doTransformItem(item2.uid,item2.itemid+1)
	else
		doSendMagicEffect(topos,9)
		doRemoveItem(item2.uid,1)
		doCreatureSay(cid, 'The attempt at sculpting failed miserably.', TALKTYPE_ORANGE_1)
	end

elseif item2.itemid == 7442 then
	if number <= 55 then
		doTransformItem(item2.uid,item2.itemid+2)
	else
		doSendMagicEffect(topos,9)
		doRemoveItem(item2.uid,1)
		doCreatureSay(cid, 'The attempt at sculpting failed miserably.', TALKTYPE_ORANGE_1)
	end
end
return FALSE
end

function onSkin(cid,skin,topos,item2)

local number = math.random(1,100)
local chance = 30

doTransformItem(item2.uid,item2.itemid+1)
if number <= chance then
	doSendMagicEffect(topos,14)
	doPlayerAddItem(cid,skin,1)
else
	doSendMagicEffect(topos,3)
end
end

 

Diminuimos 34 linhas, e deixamos ele muito mais simples, pode parecer pouco até. Mas a ideia é você pegar essa base

para outros scripts e começar a criar novas funções. Você pode observar que para adicionar um novo monstro é necessario

2 linhas antes era necessario 6.

 

Uma dica é fazer diversas funções dentro do script para até mesmo simplificar e treinar sua programação.

 

LEMBRANDO SEMPRE : Se você por acaso quiser usar a função onSkin em outros itens deve coloca-la no global.lua (ou functions.lua)

e fazendo isso dependendo do script pode ser que ele não funcione com o prefixo local. De preferencia retire sempre os locais

quando for colocar algo no global.lua (ou functions.lua)

 

Outro jeito de buscar "inspiração" é olhar nos scripts do the forgotten server. É impressionante como eles

inventam maneiras mirabolantes de usar vetores e matrizes (as vezes desnecessario). Que para eles deve ser normal,

já que eu programo desde quando nem tinha for nas distros (se tinha ninguem usava).

 

Bem eu acho que fiz minha parte, provavelmente eu lembrarei de algo e atualizarei ele futuramente (ou não).

Se acontecer postarei na descrição dele. Espero que gostem e que seja util.

 

EM breve postarei alguns exercicios e abrirei espaço para duvidas comuns.

Edited by tibiaa4e
Link to comment
Share on other sites

  • 6 months later...
×
×
  • Create New...