Grande tutorial, muito bom mesmo. Fala tudo sobre actions.
Por min está aprovadisso, agora esperar a moderação.
info
Grupo: Barão
Registrado: 09/01/09
Posts: 236
Reputação: +46
Char no Tibia: Stron Kolosso

Grande tutorial, muito bom mesmo. Fala tudo sobre actions.
Por min está aprovadisso, agora esperar a moderação.
AbalooÔ!
Bom tutorial cara.
APROVADO :button_ok:
Editado Janeiro 20 por Mimow
info
Grupo: Conde
Registrado: 06/11/06
Posts: 850
Reputação: +6
Char no Tibia: Xearius Thor

Muito obrigado por sua colaboração cara, você tem feito um ótimo trabalho. ![]()
Aprovado.
Otimo. Sempre gosto de ler seus tutoriais, são bem compreensiveis.
Agora vamo fazer a Demon Oak 2.0, e o Rashid....HEHEHE
:smile_positivo: Valeu ai mestre.
info
Grupo: Conde
Registrado: 11/02/09
Posts: 559
Reputação: +7
Char no Tibia: Deep Druid

Muito Bom ![]()
info
Grupo: Conde
Registrado: 18/12/05
Posts: 912
Reputação: +86
Gênero: Masculino
Char no Tibia: Kohzete
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
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
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.
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 :
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 endEsse 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 thenO metodo correto de se usar o isInArray (Está dentro do array), é assim
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.
Voltando ao script
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) endEssa 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 endEsse 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.
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
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 endVocê 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 endBem 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 ?
Bem para isso teremos que fazer umas mudanças porém vamos fazer primeiro a função
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 endDiminuimos 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.
Editado Janeiro 30 por tibiaa4e