PT-BR/Introdução ao Scripting: Difference between revisions

From Multi Theft Auto: Wiki
Jump to navigation Jump to search
mNo edit summary
 
(4 intermediate revisions by one other user not shown)
Line 1: Line 1:
{{atenção|Este artigo aguarda atualização, pois está '''incompleto'''.}}
O que será abordado neste artigo são os conceitos básicos de scripting, ou seja, não iremos fazer nada além do que escrever um arquivo em uma linguagem que o computador entenda. Para deixar mais claro, a linguagem de programação utilizada pelo MTA é a Lua. Antes de começar a entender como esta linguagem funciona, é preciso esclarecer o que é um recurso (resource, em inglês).
 
 
O que será abordado neste artigo são os conceitos básicos de scripting, ou seja, não iremos fazer nada além do que escrever um arquivo em uma linguagem que o computador entenda. Para deixar mais claro, a linguagem de programação utilizada pelo MTA é a Lua. Antes de começar a entender como esta linguagem é funciona, é preciso esclarecer o que é um recurso (resource, em inglês).


Um recurso é um componente essencial de um servidor de MTA. Este pode ser caracterizado por uma pasta ou um arquivo comprimido, no qual há um conjunto de arquivos. Dentre eles, está presente o meta.xml, que por sua vez, informa ao servidor como/quais arquivos devem ser carregados e o que estes representam dentro do jogo. Em outras palavras, podemos comparar o recurso como se fosse um "programa de computador", o qual é iniciado ou interrompido sob demanda, além disso, o servidor  tem a funcionalidade de rodar não só um recurso, mas vários ao mesmo tempo.
Um recurso é um componente essencial de um servidor de MTA. Este pode ser caracterizado por uma pasta ou um arquivo comprimido, no qual há um conjunto de arquivos. Dentre eles, está presente o meta.xml, que por sua vez, informa ao servidor como/quais arquivos devem ser carregados e o que estes representam dentro do jogo. Em outras palavras, podemos comparar o recurso como se fosse um "programa de computador", o qual é iniciado ou interrompido sob demanda, além disso, o servidor  tem a funcionalidade de rodar não só um recurso, mas vários ao mesmo tempo.
Line 15: Line 12:
Neste capítulo, vamos aprender a criar um script para permitir o jogador explorar o mundo do San Andreas.
Neste capítulo, vamos aprender a criar um script para permitir o jogador explorar o mundo do San Andreas.
===Onde estão todos os scripts?===
===Onde estão todos os scripts?===
Vamos dar uma olhada na estrutura dos scripts. Vá até a pasta de instalação do seu MTA, que por padrão é C:\Arquivo de Programas\MTA San Andreas 1.x\.
Vamos dar uma olhada na estrutura dos scripts. Vá até a pasta de instalação do seu MTA, que por padrão é C:/Arquivo de Programas/MTA San Andreas 1.x.


# Navegue até a pasta /server/mods/deathmatch/resources/
# Navegue até a pasta /server/mods/deathmatch/resources/
#* Dentro desta há várias outras pastas no formato [nome_da_pasta]. O motivo disto está na necessidade de organizar os recursos em certas categorias.
#* Dentro desta há várias outras pastas no formato [nome_da_pasta]. O motivo disto está na necessidade de organizar os recursos em certas categorias.
#* Como criaremos um modo de jogo totalemente novo, abriremos a pasta [gamemode]
#* Como criaremos um modo de jogo totalemente novo, abriremos a pasta [gamemodes]
#* Para que o MTA possa reconhecer nossa pasta como um recurso, criemos outra dentro de [gamemode] com um nome de sua preferência e sem os colchetes. Nós iremos usar "myserver" neste artigo.
#* Para que o MTA possa reconhecer nossa pasta como um recurso, criemos outra dentro de [gamemodes] com um nome de sua preferência e sem os colchetes. Nós iremos usar "myserver" neste artigo.
# No final, o seu resultado deve ser o seguinte:
# No final, o seu resultado deve ser o seguinte:


Line 31: Line 28:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<meta>
<meta>
     <info author="Seu_Nome" type="gamemode" name="Meu_Servidor" description="Meu primeiro recurso" />
     <info author="Seu_Apelido" type="gamemode" name="Meu_jogo" description="Meu primeiro recurso" />
     <script src="script.lua" />
     <script src="script.lua" />
</meta>
</meta>
</syntaxhighlight>
</syntaxhighlight>


Na tag ''<info />'', existe o campo ''"type"'', que indica que o recurso criado é um ''gamemode''. Pode também ser um ''map'' (mapa), que iremos explicar depois.
Na tag ''<info />'', existem:
Um gamemode é o que você precisa para criar um servidor independente.
* ''type'' - indica que o recurso criado é um ''gamemode''. Pode também ser um ''map'' (mapa), que iremos explicar depois
* ''name'' - o próprio nome já diz: o nome do recurso
* ''description'' - uma breve descrição a fim de outros jogadores e/ou donos de servidores possam saber do que se trata seu recurso
 
A tag ''<script />'' indica o caminho dos arquivos (escritos em Lua) presentes no seu recurso. Criaremos no próximo passo o exemplo (script.lua).
 
{{Dica|Um gamemode é o que você precisa para criar um servidor independente, pois é um recurso que envolve toda a programação principal do jogo online.}}


A tag ''<script />'' indica o caminho dos arquivos (escritos em Lua) presentes no seu recurso. O do exemplo (script.lua), criaremos no próximo passo.


===Criando um script simples===
===Criando um script simples===
Observe que na tag ''<script />'' anterior, o arquivo .lua está presente na pasta principal do recurso (e não em uma subpasta). Então precisamos salvar o script na pasta principal, assim como indicado na tag. Salve o seguinte código no arquivo script.lua:
Observe que na tag ''<script />'' anterior, o arquivo .lua está presente na pasta principal do recurso, e não em uma subpasta. Então precisamos salvar o script na pasta principal, assim como indicado na tag.  
 
* Salve o seguinte código no arquivo script.lua:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
local spawnX, spawnY, spawnZ = 1959.55, -1714.46, 10
local spawnX, spawnY, spawnZ = 1959.55, -1714.46, 10
Line 53: Line 57:
addEventHandler("onPlayerJoin", getRootElement(), joinHandler)
addEventHandler("onPlayerJoin", getRootElement(), joinHandler)
</syntaxhighlight>
</syntaxhighlight>
Este script criado faz parte da esfera do servidor. Ou seja, ele é executado somente no servidor. Caso ele seja definido no cliente, cada um dos jogadores receberá o arquivo contendo o código. Mas neste exemplo, por enquanto, não necessitamos usar funções específicas do cliente. Vamos ao que interessa:
O script irá gerar o seu personagem (seu boneco) nas coordenadas (x, y, z) especificadas assim que você entrar no jogo. Note que a função ''fadeCamera()'' precisa ser usada ou, do contrário, a tela ficará preta (e você não verá nada). Outra função é a ''setCameraTarget()'', que foca a câmera do jogo no seu personagem (do contrário, a câmera estaria virada para o céu).
O script irá gerar o seu personagem (seu boneco) nas coordenadas (x, y, z) especificadas assim que você entrar no jogo. Note que a função ''fadeCamera()'' precisa ser usada ou, do contrário, a tela ficará preta (e você não verá nada). Outra função é a ''setCameraTarget()'', que foca a câmera do jogo no seu personagem (do contrário, a câmera estaria virada para o céu).


A variável '''source''' representa o elemento responsável pela chamada do evento (você verá mais sobre eventos mais adiante). Assim, quando um jogador entra no jogo, o evento "onPlayerJoin" é chamado e, em seguida, chama a função. O evento automaticamente define o jogador na variável ''source'' (obs: a variável ''source'' armazena sempre o elemento que chamou determinado evento. Ou seja, nem sempre ''source'' será o jogador. Cuidado com isso.)
A variável '''source''' representa o elemento responsável pela chamada do evento (haverá um tópico adiante sobre isso). Assim, quando um jogador entra no jogo, o evento "onPlayerJoin" é chamado e, em seguida, chama a função. O evento automaticamente define o jogador na variável ''source''.
 
Se olharmos bem para o [[addEventHandler]], veremos 3 argumentos:
* ''onPlayerJoin'' - define o evento que chamará a função. No caso, esse evento é chamado assim que o jogador entra no jogo, logo, a função é executada assim que o jogador entra no jogo
* ''getRootElement()'' - indica quem poderá chamar o evento. Neste caso, usamos a função getRootElement() para nos retornar um elemento padrão do MTA denominado '''RootElement'''. Ele, por sua vez, representa todos os outros elementos existentes no servidor; ou seja, todos os jogadores estão representados nele. Consequentemente, todo jogador que entrar no servidor, causará o evento e a função será executada.
* ''joinHandler'' - indica o nome da função a ser executada quando o evento ocorrer.
 
Vamos agora rodar nosso servidor e testar o script.
 
{{Dica|A variável ''source'' armazena sempre o elemento que chamou determinado evento. Ou seja, nem sempre ''source'' será o jogador.}}


Se olharmos bem para o [[addEventHandler]], veremos 3 argumentos: 'onPlayerJoin', que indica o evento que chamará a função (no caso, esse evento é chamado assim que o jogador entra no jogo, logo, a função é chamada assim que o jogador entra no jogo); 'getRootElement()', que indica quem poderá chamar o evento (ou seja, todos os elementos, incluindo todos os jogadores); 'joinHandler', que indica o nome da função que será chamada quando o evento for chamado. Maiores detalhes serão explicados mais adiante. Vamos agora simplesmente rodar nosso servidor e testar nosso script.


===Executando o script===
===Executando o script===
Para iniciar o servidor, simplesmente execute o arquivo "MTA Server.exe" (presente na pasta de instalação do MTA:SA). Primeiramente é mostrada uma lista com os principais status do seu servidor; observe o número da porta, que você irá precisar quando entrar no jogo. Logo após, o servidor carrega todos os resources (caso todos estejam corretos) que estão presentes no diretório /resource/ e então "fica pronto para aceitar conexões" (ready to accept connections!).
Para iniciar o servidor, execute o arquivo "MTA Server.exe" situado na pasta ''../server/''. Primeiramente, é mostrada uma lista com os principais status do seu servidor; observe o número da porta, da qual você irá precisar quando entrar no jogo. Logo após, o servidor carrega todos os recursos presentes no diretório ''../server/mods/deathmatch/resources/'', caso estejam corretos. E finalmente "fica pronto para aceitar conexões" (ready to accept connections!).
 
Antes de se conectar ao seu servidor, você precisa executar o gamemode criado. Para isso, digite no console (a janela do MTA Server.exe) o comando ''gamemode myserver'' e pressione Enter. O servidor irá carregar o gamemode e mostrar os erros do seu script, caso existam.


Antes de se conectar ao seu servidor, você precisa executar o gamemode que criou. Para isso, digite no console (a janela do MTA Server.exe) o comando ''gamemode myserver'' (obs: "myserver" é o nome da pasta que você criou no início deste tutorial e, consequentemente, o nome do seu recurso) e pressione Enter. O servidor irá carregar o gamemode que você criou e irá mostrar os erros (caso existam) do seu script. Agora você pode se conectar ao seu servidor de duas diferentes maneiras: clicando em "Quick Connect" e inserindo o endereço IP do seu servidor e o número da porta, ou clicando em "Server Browser", acessando a aba "Local" e clicando duas vezes no seu servidor. Se tudo correr bem, seu personagem será criado nas coordenadas especificadas.
''obs'': "myserver" é o nome da pasta criada no início deste tutorial e, consequentemente, a identificação do seu recurso)
 
 
Agora você pode se conectar ao seu servidor de duas maneiras:  
* Clique em ''Quick Connect'' > Insira o endereço IP do servidor e o número da porta no seguinte formato - IP:Porta
* Navegue até ''Server Browser'' > Aba ''Local'' > Clique duas vezes no seu servidor.  
 
Se tudo correr bem, seu personagem será criado nas coordenadas especificadas.
 
No próximo tópico iremos criar um comando para que o jogador possa gerar um veículo ao seu lado. Se preferir, embora não recomendado caso seja iniciante, você pode visitar alguns scripts mais avançados clicando [[Map manager|aqui]]. Outra parte interessante da seção "Scripting", na qual obviamente você está, é [[PT-BR/Introducão_ao_GUI_scripting|Conhecendo a Interface Gráfica]]. Nela, se discute a criação de interfaces gráficas para seus scripts.


No próximo tópico iremos criar um comando para que o jogador possa gerar um veículo ao seu lado. Se preferir (embora não recomendado caso seja iniciante), você pode visitar alguns scripts mais avançados clicando [[Map manager|aqui]], ou prossiga com este tutorial. Outra parte interessante deste tutorial é [[PT-BR/Introducão_ao_GUI_scripting|Conhecendo a Interface Gráfica]], no qual aborda a criação de interfaces gráficas (janelas, botões, etc) para seus scripts.


<!--
==Criando um comando simples==
==Criando um comando simples==
Vamos voltar ao arquivo ''script.lua'' (abra-o novamente). Como mencionado anteriormente, vamos criar agora um comando (para executá-lo, digite no chat ''/seucomando'') que irá gerar um carro ao lado do seu personagem. Antes de tudo precisamos criar uma função que iremos chamar posteriormente e um [[addCommandHandler]](), responsável por criar o comando.
Como foi mencionado anteriormente, criaremos agora um comando que irá gerar um carro ao lado do seu personagem. Antes de tudo, precisamos adicionar uma função e um evento específico, chamado de [[addCommandHandler]]() ao nosso script.lua.
 
''obs'': Um comando é como se fosse uma função chamada pelo jogador quando ele está no chat. Ele digita seu nome e envia-o argumentos especificando o que ele quer. Sempre no formato: /[nome do comando] <argumentos> Exemplo: /cv 410


<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
-- cria a funcao que sera chamada pelo comando. Os argumentos sao: thePlayer, command, vehicleModel
-- adiciona a função a ser executada pelo comando.
function createVehicleForPlayer(thePlayer, command, vehicleModel)
function createVehicleForPlayer(thePlayer, command, vehicleModel)
   -- cria um veiculo
   -- aqui colocaremos, mais tarde, o código para gerar o veículo
end
end


-- cria um lancador de comandos
-- adiciona um gerenciador de comandos
addCommandHandler("createvehicle", createVehicleForPlayer)
addCommandHandler("createvehicle", createVehicleForPlayer)
</syntaxhighlight>
</syntaxhighlight>
''Nota: Você pode clicar nas funções dos códigos para obter uma explicação de cada uma delas.


====Sobre os lançadores de comandos (responsáveis por criar os comandos)====
{{Dica|As funções nativas do MTA são clicáveis em todo o Wiki e lhe redirecionam à páginas sobre elas.}}
O primeiro argumento do [[addCommandHandler]] é o nome do comando que o jogador precisará digitar (no exemplo, ele precisará digitar no chat ''/createvehicle <argumento>''. O segundo argumento é a função que será chamada quando o comando for digitado (nesse caso, a função ''createVehicleForPlayer()''.
 
 
====Sobre os gerenciadores de comandos====
Esse é um ponto interessante a ser discutido, já que envolve eventos e seus derivados. No MTA, para se criar um comando, usamos um tipo específico de evento que ocorre quando um jogador entra com um comando. Usamos a função [[addCommandHandler]] para cria-los. Como um comando é necessariamente um evento, vale a teoria de eventos para ele:
* Um evento é criado por uma função para determinar suas propriedades
* Todo evento ativa quando algo acontece no jogo e este sempre envia à função determinadas informações sobre o que ocoreu
* A relação evento-função é nada mais que uma troca de argumentos, de propriedades


Se você já possui alguma experiência em programação, sabe que você chama uma função desta forma:
Deve-se prestar atenção nesta troca, pois envolve conceitos fundamentais de Lua. Se você já teve alguma experiência com programação, deve se lembrar como funciona os argumentos de uma função:


<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
Line 90: Line 121:
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
nomeDaFuncao(thePlayer, commandName, argumento3, ..)
addCommandHandler("createvehicle", createVehicleForPlayer, ..)
createVehicleForPlayer(thePlayer, commandName, vehicleModel, ..)
</syntaxhighlight>
</syntaxhighlight>


Se observarmos bem o exemplo acima, podemos ver que o argumento1 é o jogador (quem digita o comando) e o argumento2 é o nome do comando (nesse caso, ''createvehicle''). O argumento3 é o argumento digitado depois do comando (por exemplo, se o jogador digitou ''/createvehicle Infernus'', então a variável argumento3 irá armazenar o texto "Infernus"). Nunca se esqueça que os dois primeiros argumentos são padrões (ou seja, precisam existir), mas você pode nomeá-los com outro nome (mas isto não é necessário agora).
Como você observa no exemplo acima, nas duas funções se define quem são os argumentos para indicar como o código deve-se comportar:
* [[addCommandHandler]] é uma na qual se define que quando o jogador digitar o comando ''createvehicle'', a função ''createVehicleForPlayer'' irá ser executada.
* Em createVehicleForPlayer há o recebimento de certas informações enviadas pelo evento, na sequência:
# ''thePlayer'' - Qual é o jogador que ativou o evento?
# ''commandName'' - Qual foi o comando digitado?
# ''vehicleModel'' - Qual foi o ID digitado pelo jogador?


Nós chamamos a função [[addCommandHandler]], que chama a função ''createVehicleForPlayer''.
Nota-se nesse caso uma clara troca de informações entre o evento e a função determinada. Quem define como será essa troca é o próprio tipo de evento, que neste caso é um comando. Como ele está sendo executado no servidor, ele sempre enviará na ordem: Quem Digitou? Qual Comando? Quais Argumentos digitados por este jogador? E aí será sua função quem decidirá o que fazer com essas informações; você, programador, dá o nome a esses argumentos e pode até não querer recebê-los, caso elas não forem necessárias.


Por exemplo: alguém digita "createvehicle 468" no chat para gerar uma Sanchez (468 é o ID da Sanchez. Veja mais [[Vehicle_IDs|aqui]]), então o lançador de comandos (quando dizemos "lançador de comandos", é o mesmo que "criador de comandos") chama a função createVehicleForPlayer(), como '''se''' nós tivéssemos a seguinte linha no script:
Vamos a um exemplo prático: alguém digita ''/createvehicle 468'' no chat para gerar uma Sanchez (ID dela é 468. Veja outros [[Vehicle_IDs|neste link]]), então o gerenciador de comandos chama a função determinada de uma forma como se o jogador tivesse feito o script dele e digitado no arquivo:


<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
createVehicleForPlayer(thePlayer,"createvehicle","468") -- thePlayer é o jogador que digitou o comando
createVehicleForPlayer(thePlayer,"createvehicle","468") -- thePlayer seria o próprio jogador
</syntaxhighlight>
</syntaxhighlight>


Como podemos ver, a função fornece alguns parâmetros: o jogador quem chamou o comando (armazenado na variável thePlayer), o comando que o jogador executou (nesse caso, "createvehicle") e o ID do veículo desejado (nesse caso, "468", referente à Sanchez). Os primeiros dois parâmetros são padrões nos lançadores de comando. Ou seja, sempre que usarmos o addCommandHandler(), teremos automaticamente essas duas primeiras variáveis. Assim, toda função que você desejar chamar usando [[addCommandHandler]] deverá possuir esses dois primeiros parâmetros caso você deseje usar um terceiro parâmetro (por exemplo, colocar uma variável para armazenar o ID do veículo).
É claro que ele não vai querer seguir este tutorial para fazer isso, e desta forma você está aqui para fazer um comando pra ele. Simplesmente ele digita no chat e seu script cria o veículo desejado.


''Nota: você precisa adicionar o lançador de comandos DEPOIS que escrever uma função (depois do "end" da função que será chamada) ou, do contrário, a função não será encontrada.''
''obs'': Os dois primeiros argumentos colocados na função addCommandHandler ''sempre'' serão do mesmo tipo: quem foi? o que digitou? Em diante, você pode definir quantas variáveis quiser, de acordo com sua necessidade. Se o comando precisar criar um cavalo (pouco provável) e precisar que o jogador diga qual é a cor dele, a raça, a altura, o humor, poderá definir quantas quiser. Algo nesse estilo: addCommandHandler("criarcavalo" criarCavaloParaJodador(), cor, raça, altura, humor)


====Escrevendo a função====
{{Dica|A função sempre deverá existir antes de você criar o comando (vale para eventos também). O computador é uma coisa linear, portanto se você pedir pra ele definir algo que não existe ainda, vai dar erro! Então sempre coloque a função em cima (lógico, é lido de cima pra baixo) do addEventHandler()}}
Para preencher a função que criamos, nós precisamos pensar sobre o que temos que fazer:
* Comece a posição de jogadores, por isso sabemos onde desovar o veículo (queremos que ele apareça ao lado do jogador)
* Calcular a posição que queremos para desovar o veículo (que não queremos que ele apareça no player)
* Gerar o veículo
* Verifique se ele foi gerado com sucesso, ou uma mensagem de saída


Para alcançar nossos objetivos, temos que usar várias funções. Para encontrar uma função que precisamos usar, devemos visitar o [[Scripting Functions|Lista de funções de servidor]]. Primeiro precisamos de uma função para obter a posição de jogadores. Since players are Elements, we first jump to the '''Element functions''' where we find the [[getElementPosition]] function. By clicking on the function name in the list, you get to the function description. There we can see the syntax, what it returns and usually an example. The syntax shows us what arguments we can or have to submit.


For [[getElementPosition]], the syntax is:
====Elaborando a função====
É hora de escrever nossa função; Sempre que for fazer isso é necessário pensar como faremos um veículo ser criado de forma mais simples o possível:
* Obter a posição do jogador, para sabermos onde desovar o veículo
* Calcular essa posição favorável para que a máquina de, em média, 450 quilos não cair em cima do coitado
* Pedir ao jogo gerar este veículo
* Verificar se foi gerado com sucesso, ou informá-lo um erro
 
Para fazer isso, teremos que usar várias funções. Portanto, nós nos direcionamos à página contendo uma [[Scripting Functions|Lista de funções de servidor]] para achá-las. Já que precisamos obter a posição do jogador e como jogador é um Elemento, clicamos primeiro em '''Element functions''' onde haverá a função [[getElementPosition]] para tal fim. Ao clicar no link, uma página contendo detalhes sobre essa função será mostrada. Nela contém a sintaxe a ser usada, acompanhada de um exemplo. Como a sintaxe do português, a de programação indica como/quais argumentos se pode usar ou omitir.
 
Para [[getElementPosition]], a sintaxe é:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
float, float, float getElementPosition ( element theElement )
float, float, float getElementPosition ( element theElement )
</syntaxhighlight>
</syntaxhighlight>


The three ''float'' in front of the function name are the return type. In this case it means the function returns three floating point numbers. (x, y and z) Within the parentheses, you can see what arguments you have to submit. In this case only the element whose position you want to get, which is the player in our example.
Os três itens na frente do nome da função indica o tipo de informação que ela retorna. Neste caso, são ''float'' (números com decimais). Em outras palavras, é retornado ao programador três números decimais indicando a posição (x, y, z). Depois do nome, sempre em parênteses, é o que você precisa mandar pra função funcionar. Neste caso, só é preciso de um elemento do qual a posição será retornada e no nosso exemplo, este elemento é o jogador:


<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function createVehicleForPlayer(thePlayer, command, vehicleModel)
function createVehicleForPlayer(thePlayer, command, vehicleModel)
-- get the position and put it in the x,y,z variables
-- retorna a posição do jogador nas variáveis (x, y, z)
-- (local means, the variables only exist in the current scope, in this case, the function)
-- o termo "local" significa que as três variáveis só existirão dentro do bloco - este é a função
local x,y,z = getElementPosition(thePlayer)
local x,y,z = getElementPosition(thePlayer)
end
end
</syntaxhighlight>
</syntaxhighlight>


Next we want to ensure that the vehicle won't spawn directly in the player, so we add a few units to the ''x'' variable, which will make it spawn east from the player.
Neste passo precisamos garantir que o veículo não esmagará o jogador, então adicionamos algumas unidades no eixo x; fazendo este gerar a leste dele


<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function createVehicleForPlayer(thePlayer, command, vehicleModel)
function createVehicleForPlayer(thePlayer, command, vehicleModel)
local x,y,z = getElementPosition(thePlayer) -- get the position of the player
local x,y,z = getElementPosition(thePlayer) -- retorna a posição do jogador
x = x + 5 -- add 5 units to the x position
x = x + 5 adiciona 5 unidades na variável x
end
end
</syntaxhighlight>
</syntaxhighlight>


Now we need another function, one to spawn a vehicle. We once again search for it on the [[Scripting Functions|Server Functions List]], this time - since we are talking about vehicles - in the '''Vehicle functions''' section, where we will choose [[createVehicle]]. In this function's syntax, we only have one return type (which is more common), a vehicle element that points to the vehicle we just created. Also, we see that some arguments are enclosed within [ ] which means that those are optional.
Agora precisamos de outra função para gerar o veículo. Novamente, procuramos na [[Scripting Functions|Lista de funções de servidor]]. Só que como estamos falando de veículos, procuramos na seção '''Vehicle functions'''; onde encontraremos [[createVehicle]]. Na sintaxe desta função, temos somente um tipo de retorno (o qual é mais comum): um elemento do tipo veículo criado pela própria função. Além do mais, percebemos alguns argumentos inseridos em colchetes ([]), indicando opcionalidade.


We already have all arguments we need for [[createVehicle]] in our function: The position we just calculated in the ''x,y,z'' variables and the model id that we provided through the command ("createvehicle 468") and can access in the function as ''vehicleModel'' variable.
Oras, já temos todos os argumentos necessários para a função funcionar: os (x, y, z) calculados anteriormente e o ID do veículo fornecido pelo jogador através do comando; na variável (vehicleModel). É só digitar:


<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
Line 153: Line 193:
</syntaxhighlight>
</syntaxhighlight>


Of course this code can be improved in many ways, but at least we want to add a check whether the vehicle was created successfully or not. As we can read on the [[createVehicle]] page under '''Returns''', the function returns ''false'' when it was unable to create the vehicle. Thus, we check the value of the ''createVehicle'' variable.
É claro que esse código pode melhorar em vários aspectos, mas pelo menos adicionaremos uma condição para verificar o sucesso na criação do veículo. Como foi lido (e infelizmente para uns, era pra ter sido) na página do [[createVehicle]]; em baixo de '''Returns''', a função retorna ''false'' quando não é possível criar o veículo. Portanto, verificaremos o valor retornado pela variável ''createdVehicle''


Now we have our complete script:
Agora temos o script completo:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function createVehicleForPlayer(thePlayer, command, vehicleModel)
function createVehicleForPlayer(thePlayer, command, vehicleModel)
local x,y,z = getElementPosition(thePlayer) -- get the position of the player
local x,y,z = getElementPosition(thePlayer) -- retorna a posição do jogador
x = x + 5 -- add 5 units to the x position
x = x + 5 adiciona 5 unidades na variável x
local createdVehicle = createVehicle(tonumber(vehicleModel),x,y,z)
local createdVehicle = createVehicle(tonumber(vehicleModel),x,y,z)
-- check if the return value was ''false''
-- verifica se o retorno foi falso
if (createdVehicle == false) then
if (createdVehicle == false) then
-- if so, output a message to the chatbox, but only to this player.
-- Se sim, retorne uma mensagem de erro somente para o jogador
outputChatBox("Failed to create vehicle.",thePlayer)
outputChatBox("Não foi possível criar o veículo. A sintaxe é: /createvehicle [id]",thePlayer)
end
end
end
end
Line 170: Line 210:
</syntaxhighlight>
</syntaxhighlight>


As you can see, we introduced another function with [[outputChatBox]]. By now, you should be able to explore the function's documentation page yourself. For more advanced scripting, please check out the [[Map manager|Map Manager]].
Deve-se destacar os seguintes pontos:
* Quando tentamos usar qualquer função que crie algum elemento no MTA e esta criação falha, uma ''bool'' é retornada como falso. Isso quer dizer: ou há um erro de sintaxe/programação no seu script, ou realmente o servidor não conseguiu computar essa informação
* Foi introduzida outra função denominada [[outputChatBox]], a qual simplesmente escreve no chat a mensagem de erro
 
A partir de agora, você pode dar uma olhada na documentação sobre as funções aqui no Wiki. Se desejar, há a página do [[Map manager|Map Manager]] só falando de scripting avançado.


==What you need to know==
==Importante Saber==
You already read some things about resources, command handlers and finding functions in the documentation in the first paragraph, but there is much more to learn. This section will give you a rather short overview over some of these things, while linking to related pages if possible.
Já foi dito anteriormente algumas coisas sobre os recursos, gerenciadores de comandos e funções, porém há muita coisa ainda pra aprender. Essa seção lhe fornecerá outras coisas importantes sobre o funcionamento do MTA, ao mesmo tempo linkando à páginas relacionadas se possível.
===Clientside and Serverside scripts===
You may have already noticed these or similiar terms (Server/Client) somewhere on this wiki, mostly in conjunction with functions. MTA not only supports scripts that run on the server and provide commands (like the one we wrote above) or other features, but also scripts that run on the MTA client the players use to connect to the server. The reason for this is, that some features MTA provides have to be clientside (like a GUI - Graphical User Interface), others should be because they work better and still others are better off to be serverside or just don't work clientside.


Most scripts you will make (gamemodes, maps) will probably be serverside, like the one we wrote in the first section. If you run into something that can't be solved serverside, you will probably have to make it clientside. For a clientside script for example, you would create a ordinary script file (for example called ''client.lua'') and specify it in the meta.xml, like this:
===Lado do Cliente e Servidor===
É notório a semelhança dos termos (Cliente/Servidor) em várias partes do site, até mesmo nas funções. O MTA não suporta scripts somente rodando no servidor e oferecendo aos seus jogadores comandos como aquele do exemplo acima ou algo parecido. Ele também oferece a possibilidade de rodar um script no computador de cada jogador logado. Isso porque algumas vantagens oferecidas pelo programa precisam rodar no computador deles. Imagine um servidor mandar o todo tempo informações para desenhar a interface gráfica, sendo esta necessitar uma renderização em uma faixa de 30 vezes por segundo. Não faz o menor sentido, e nem é viável! Ainda mais em PC's antigos com ping alto. Há outras razões além da performance, como o fato de alguns funcionarem melhor em um dos lados ou justamente porque não rola.
 
A maioria dos scripts (gamemodes ou mapas) provavelmente serão no lado do servidor, como foi feito anteriormente. Se caso acontecer de algo não poder ser resolvido com script do servidor, vá tranquilo pro cliente. Um exemplo de fazer isso seria criar um arquivo pacato chamado client.lua e defini-lo no meta.xml, como a seguir:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<script src="client.lua" type="client" />
<script src="client.lua" type="client" />
</syntaxhighlight>
</syntaxhighlight>
The ''type'' attribute defaults to 'server', so you only need to specify it for clientside scripts. When you do this, the clientside script will be downloaded to the player's computer once he connects to the server. Read more about [[Client side scripts]].
O atributo ''type'' define automaticamente o arquivo como servidor, então só precisa especificar se for rodado no cliente. Quando terminar, este arquivo será baixado para o computador do brother quando ele conectar ao servidor. Para mais informações, segue o [[Client side scripts|link]] (Em inglês).


===More complex resources===
===Recursos Complicados===
The previous section showed briefly how to add clientside scripts to the resource, but there is also much more possible. As mentioned at the very top of this page, resources can be pretty much everything. Their purpose is defined by what they do. Let's have some theoretical resources, by looking at the files it contains, the ''meta.xml'' and what they might do:
A última seção explicou brevemente como adicionar um script no cliente, mas há muita coisa possível a ser feita. Como foi dito nesta página, recursos praticamente são a alma do jogo. Sua função é definida pelo que eles podem fazer. Então vão aí uns exemplos de recursos hipotéticos retirados da instalação, mostrando suas distintas funções:  


====First example - A utility script====
====Primeiro exemplo - Um utilitário====
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
/admin_commands
/admin_commands
Line 201: Line 246:
</syntaxhighlight>
</syntaxhighlight>


* The ''commands.lua'' provides some admin commands, like banning a player, muting or something else that can be used to admin the server
* O ''commands.lua'' oferece alguns comandos de administrador, como banir algum pateta ou algo útil para se administrar o servidor
* The ''client.lua'' provides a GUI to be able to perform the mentioned actions easily
* O ''client.lua'' cria janelas para executar-los de forma muito mais clara e rápida


This example might be running all the time (maybe even auto-started when the server starts) as it's useful during the whole gaming experience and also wont interfere with the gameplay, unless an admin decides to take some action of course.
Este exemplo pode estar rodando o tempo todo (talvez até auto-carregado quando o servidor iniciar) se útil durante a jogatina, e claro, não interferir no processo; só se o administrador decidir intervir.


====Second example - A gamemode====
====Segundo exemplo - Um gamemode====
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
/counterstrike
/counterstrike
Line 221: Line 266:
</syntaxhighlight>
</syntaxhighlight>


* The ''counterstrike.lua'' contains similiar to the following features:
* O ''counterstrike.lua'' oferece:
** Let players choose their team and spawn them
** A possibilidade dos jogadores escolherem o time e nascerem
** Provide them with weapons, targets and instructions (maybe read from a Map, see below)
** Lhe dá armas, alvos e instruções (talvez tiradas do Mapa, veja adiante)
** Define the game's rules, e.g. when does the round end, what happens when a player dies
** Define as regras do jogo; exemplos: o que acontece no fim da partida ou quando um jogador falece?
** .. and maybe some more
** E muita coisa que não dá ser citada aqui...
* The ''buymenu.lua'' is a clientside script and creates a menu to buy weapons
* O ''buymenu.lua'' é um script do cliente e adiciona um menu para adquirir armas


This example can be called a gamemode, since it not only intereferes with the gameplay, but actually defines the rules of it. The ''type'' attribute indicates that this example works with the [[Map manager]], yet another resource that was written by the QA Team to manage gamemodes and map loading. It is highly recommended that you base your gamemodes on the techniques it provides.
Esse exemplo pode ser denominado um ''gamemode'', pois não só complementa a partida, como também define as regras dela. O atributo ''type'' indica que este recurso funciona com o [[Map manager]] ou outro escrito pelos desenvolvedores com finalidade de gerenciar os gamemodes e carregamento de mapas. É bem recomendado começar seu gamemode a partir do diferencial que este apresenta.


This also means that the gamemode probably won't run without a map. Gamemodes should always be as generic as possible. An example for a map is stated in the next example.
E mais, um gamemode provavelmente não rodará sem um mapa. Gamemodes sempre precisarão ser o mais genérico possível. Um exemplo de mapa pode ser visto no próximo exemplo.  


====Third example - A Map====
====Terceiro exemplo - Um mapa====
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
/cs-airport
/cs-airport
Line 247: Line 292:
</syntaxhighlight>
</syntaxhighlight>


* The ''airport.map'' in a XML file that provides information about the map to the gamemode, these may include:
* O ''airport.map'' no arquivo XML acima oferece diversas informações sobre o mapa do gamemode, podendo incluir:
** Where the players should spawn, with what weapons, what teams there are
** Onde os jogadores deverão nascer, com quais armas, em qual time
** What the targets are
** Quais são os alvos
** Weather, World Time, Timelimit
** Clima, horário e limite de tempo da partida.
** Provide vehicles
** Veículos espalhados pelo local
* The ''airport.lua'' might contain map-specific features, that may include:
* O ''airport.lua'' também pode conter objetos específicos, como:
** Opening some door/make something explode when something specific happens
** Abrir alguma porta/fazer algo explodir quando uma coisa acontece
** Create or move some custom objects, or manipulate objects that are created through the .map file
** Criar ou mover objetos customizados, ou manipular objetos criados no arquivo .map
** .. anything else map-specific you can think of
** .. ou infinitas coisas limitadas pela sua imaginação


As you can see, the ''type'' attribute changed to 'map', telling the [[Map manager]] that this resource is a map, while the ''gamemodes'' attribute tells it for which gamemodes this map is valid, in this case the gamemode from the above example.
Nota-se a presença do atributo ''type'' classificando o recurso como um mapa, consequentemente avisando o [[Map manager]] disso; Enquanto o atributo ''gamemodes'' indica com qual o gamemode ele é compatível. Neste caso é o próprio gamemode do exemplo acima.
What may come as a surprise is that there is also a script in the Map resource. Of course this is not necessarily needed in a map, but opens a wide range of possibilities for map makers to create their own world within the rules of the gamemode they create it for.
O que pode incomodar é a presença de um script em um mapa. É claro, não há a necessidade de haver isso nele. Entretanto, isso abre uma gama de possibilidades para criadores de mapas concretizarem seus próprios mundos nas regras do gamemode pra ele criado.


The ''airport.map'' file might look similiar to this:
O arquivo ''airport.map'' contém algo parecido com isso:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<map mode="deathmatch" version="1.0">
<map mode="deathmatch" version="1.0">
Line 277: Line 322:
</syntaxhighlight>
</syntaxhighlight>


When a gamemode is started with a map, the map resources is automatically started by the mapmanager and the information it contains can be read by the gamemode resource. When the map changes, the current map resource is stopped and the next map resource is started. For a more in-depth explanation and examples of how map resources are utilized in the main script, please visit the [[Writing Gamemodes]] page.
Quando um gamemode é iniciado com um mapa, este é automaticamente iniciado pelo Map manager e a informação contida é lida pelo gamemode. Quando um mapa muda durante a partida, o atual é fechado e o escolhido, iniciado. Para mais detalhes e exemplos sobre como os mapas são utilizados na programação principal, visite a página [[Writing Gamemodes|Escrevendo Gamemodes]] (Em inglês).


===Events===
===Eventos===
Events are the way MTA tells scripts about things that happen. For example when a player dies, the [[onPlayerWasted]] event is triggered. In order to perform any actions when a player dies, you have to prepare yourself similiar to adding a command handler, as shown in [[#Writing_the_script|the first chapter]].
Foi dada uma breve explicação no inicio da página, mas um conceito mais formal (criado pelo pessoal do MTA) nunca é demais:
* Eventos são a forma como o MTA diz aos scripts sobre as coisas que acontecem. Por exemplo, quando um jogador morre, o evento [[onPlayerWasted]] é ativado. Com o objetivo de providenciar ações caso isso aconteça, deve ser adicionado um evento, como mostrado no [[#Criando_nosso_primeiro_script|primeiro capítulo]].


This example will output a message with the name of the player who died:
Este exemplo irá escrever uma mensagem no chat com o apelido do jogador falecido:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function playerDied(totalAmmo, killer, killerWeapon, bodypart)
function playerDied(totalAmmo, killer, killerWeapon, bodypart)
outputChatBox(getPlayerName(source).." died!")
outputChatBox(getPlayerName(source).." feleceu!")
end
end
addEventHandler("onPlayerWasted",getRootElement(),playerDied)
addEventHandler("onPlayerWasted",getRootElement(),playerDied)
</syntaxhighlight>
</syntaxhighlight>


Instead of showing what arguments are needed, the documentation page for Events shows what parameters are passed to the handler function, similiar to the way a [[#About_command_handlers|command handler]] does, just that it is different from event to event. Another important point is the ''source'' variable, that exists in handler functions. It doesn't have to be added to the parameter list of the function, but it still exists. It has a different value from event to event, for player events (as in the example above) it is the player element. As another example, you can take a look at the basic spawning player script in the first section to get an idea how ''source'' is used.
Em vez de mostrar aqui todos os tipos de eventos, uma página específica foi criada no Wiki só para especificar este tipo de coisa; o mesmo serve para os [[#About_command_handlers|gerenciadores de comandos]]. Um outro ponto importante é com relação a variável ''source''. Ela é automaticamente declarada na hora de a função ser executada. Ela agrega um diferente valor para cada tipo de evento, como no exemplo acima: para eventos relacionados a jogadores, ele retorna um elemento do tipo jogador. Uma outra forma de como a variável source é usada está no script básico de fazer o jogador nascer no topo da página.
 
==Para onde ir a partir daqui==
Agora você deve estar bem mais familiarizado com os aspectos básicos de scripting para o MTA e também com o Wiki. A [[PT-BR/Página_Inicial|Página Inicial]] contém todos os links para mais informações, tutoriais e referências para lhe propiciar todas as fontes necessárias a um estudo mais aprofundado.
 
{{Dica|Recomendamos ler o tutorial de [[debugging]] a partir daqui. Um bom treinamento em tirar os bugs de seus scripts é fundamental. Também é recomendado dar uma olhada nas variáveis pré-definidas para ajudá-lo com certas tarefas, e claro "scriptar" de forma mais rápida e prática.}}
 
'''Veja mais:'''
* [[Advanced Topics|Tópicos Avançados]] (Em inglês)


==Where to go from here==
You should now be familiar with the most basic aspects of MTA scripting and also a bit with the documentation. The [[Main Page]] provides you with links to more information, Tutorials and References that allow a deeper look into the topics you desire to learn about.
{{note|From here we recommend reading the [[debugging]] tutorial. Good debugging skills are an absolute necessity when you are making scripts. We also recommend you to use the [[predefined variables list]] to help you with certain tasks and make scripting easier and faster.}}
'''See also:'''
* [[Advanced Topics]]
-->
[[en:Scripting Introduction]]
[[en:Scripting Introduction]]
[[ru:Scripting Introduction]]
[[ru:Scripting Introduction]]

Latest revision as of 02:10, 6 December 2014

O que será abordado neste artigo são os conceitos básicos de scripting, ou seja, não iremos fazer nada além do que escrever um arquivo em uma linguagem que o computador entenda. Para deixar mais claro, a linguagem de programação utilizada pelo MTA é a Lua. Antes de começar a entender como esta linguagem funciona, é preciso esclarecer o que é um recurso (resource, em inglês).

Um recurso é um componente essencial de um servidor de MTA. Este pode ser caracterizado por uma pasta ou um arquivo comprimido, no qual há um conjunto de arquivos. Dentre eles, está presente o meta.xml, que por sua vez, informa ao servidor como/quais arquivos devem ser carregados e o que estes representam dentro do jogo. Em outras palavras, podemos comparar o recurso como se fosse um "programa de computador", o qual é iniciado ou interrompido sob demanda, além disso, o servidor tem a funcionalidade de rodar não só um recurso, mas vários ao mesmo tempo.

Obs: Os recursos são comprimidos em .zip e não em .rar

Tudo relacionado a scripting tem relação com os recursos, afinal, os recursos são nada mais que, geralmente, um conjunto de scripts destinados a realizar alguma tarefa. Um recurso pode ser classificado, via o meta.xml, como um gamemode, um mapa ou qualquer outra coisa. O MTA já vem por padrão com alguns recursos interessantes que você pode, além de reaproveitá-los, adaptá-los às suas necessidades. Por exemplo, você pode editar as texturas do gamemode race para deixar-lo com a cara do seu servidor ou mudar o comportamento do modo de jogo perante a mudança de mapa.

[[{{{image}}}|link=|]] Dica: Para facilitar seus primeiros passos na programação em linguagem Lua, é recomendado utilizar um editor de textos com highlight, ou seja, o programa vai destacar cada tipo de instrução com uma cor distinta. Isso facilita a leitura e escrita de qualquer código independente da linguagem. Muito utilizado e recomendado por nós é o Notepad++ ou LuaEdit.
Há também um editor de códigos (criado por fãs do MTA) com foco na linguagem Lua para o MTA: MTA Script Editor (ainda em fase de desenvolvimento, mas você já pode testá-lo).


Criando nosso primeiro script

Neste capítulo, vamos aprender a criar um script para permitir o jogador explorar o mundo do San Andreas.

Onde estão todos os scripts?

Vamos dar uma olhada na estrutura dos scripts. Vá até a pasta de instalação do seu MTA, que por padrão é C:/Arquivo de Programas/MTA San Andreas 1.x.

  1. Navegue até a pasta /server/mods/deathmatch/resources/
    • Dentro desta há várias outras pastas no formato [nome_da_pasta]. O motivo disto está na necessidade de organizar os recursos em certas categorias.
    • Como criaremos um modo de jogo totalemente novo, abriremos a pasta [gamemodes]
    • Para que o MTA possa reconhecer nossa pasta como um recurso, criemos outra dentro de [gamemodes] com um nome de sua preferência e sem os colchetes. Nós iremos usar "myserver" neste artigo.
  2. No final, o seu resultado deve ser o seguinte:

/server/mods/deathmatch/resources/[gamemodes]/myserver

Identificando seu recurso

Para que o servidor reconheça os arquivos de um determinado recurso (para carregá-los), um arquivo meta.xml deve ser criado, contendo uma lista de todo o conteúdo do recurso. O arquivo meta.xml deve ser salvo na pasta principal (nesse caso, na pasta "myserver"). Então, abra um editor de textos (recomenda-se o Notepad++) e salve-o com o nome de "meta.xml".

Entre com as seguintes linhas no arquivo meta.xml:

<meta>
     <info author="Seu_Apelido" type="gamemode" name="Meu_jogo" description="Meu primeiro recurso" />
     <script src="script.lua" />
</meta>

Na tag <info />, existem:

  • type - indica que o recurso criado é um gamemode. Pode também ser um map (mapa), que iremos explicar depois
  • name - o próprio nome já diz: o nome do recurso
  • description - uma breve descrição a fim de outros jogadores e/ou donos de servidores possam saber do que se trata seu recurso

A tag <script /> indica o caminho dos arquivos (escritos em Lua) presentes no seu recurso. Criaremos no próximo passo o exemplo (script.lua).


[[{{{image}}}|link=|]] Dica: Um gamemode é o que você precisa para criar um servidor independente, pois é um recurso que envolve toda a programação principal do jogo online.


Criando um script simples

Observe que na tag <script /> anterior, o arquivo .lua está presente na pasta principal do recurso, e não em uma subpasta. Então precisamos salvar o script na pasta principal, assim como indicado na tag.

  • Salve o seguinte código no arquivo script.lua:
local spawnX, spawnY, spawnZ = 1959.55, -1714.46, 10
function joinHandler()
	spawnPlayer(source, spawnX, spawnY, spawnZ)
	fadeCamera(source, true)
	setCameraTarget(source, source)
	outputChatBox("Bem-vindo ao meu servidor!", source)
end
addEventHandler("onPlayerJoin", getRootElement(), joinHandler)

Este script criado faz parte da esfera do servidor. Ou seja, ele é executado somente no servidor. Caso ele seja definido no cliente, cada um dos jogadores receberá o arquivo contendo o código. Mas neste exemplo, por enquanto, não necessitamos usar funções específicas do cliente. Vamos ao que interessa:

O script irá gerar o seu personagem (seu boneco) nas coordenadas (x, y, z) especificadas assim que você entrar no jogo. Note que a função fadeCamera() precisa ser usada ou, do contrário, a tela ficará preta (e você não verá nada). Outra função é a setCameraTarget(), que foca a câmera do jogo no seu personagem (do contrário, a câmera estaria virada para o céu).

A variável source representa o elemento responsável pela chamada do evento (haverá um tópico adiante sobre isso). Assim, quando um jogador entra no jogo, o evento "onPlayerJoin" é chamado e, em seguida, chama a função. O evento automaticamente define o jogador na variável source.

Se olharmos bem para o addEventHandler, veremos 3 argumentos:

  • onPlayerJoin - define o evento que chamará a função. No caso, esse evento é chamado assim que o jogador entra no jogo, logo, a função é executada assim que o jogador entra no jogo
  • getRootElement() - indica quem poderá chamar o evento. Neste caso, usamos a função getRootElement() para nos retornar um elemento padrão do MTA denominado RootElement. Ele, por sua vez, representa todos os outros elementos existentes no servidor; ou seja, todos os jogadores estão representados nele. Consequentemente, todo jogador que entrar no servidor, causará o evento e a função será executada.
  • joinHandler - indica o nome da função a ser executada quando o evento ocorrer.

Vamos agora rodar nosso servidor e testar o script.


[[{{{image}}}|link=|]] Dica: A variável source armazena sempre o elemento que chamou determinado evento. Ou seja, nem sempre source será o jogador.


Executando o script

Para iniciar o servidor, execute o arquivo "MTA Server.exe" situado na pasta ../server/. Primeiramente, é mostrada uma lista com os principais status do seu servidor; observe o número da porta, da qual você irá precisar quando entrar no jogo. Logo após, o servidor carrega todos os recursos presentes no diretório ../server/mods/deathmatch/resources/, caso estejam corretos. E finalmente "fica pronto para aceitar conexões" (ready to accept connections!).

Antes de se conectar ao seu servidor, você precisa executar o gamemode criado. Para isso, digite no console (a janela do MTA Server.exe) o comando gamemode myserver e pressione Enter. O servidor irá carregar o gamemode e mostrar os erros do seu script, caso existam.

obs: "myserver" é o nome da pasta criada no início deste tutorial e, consequentemente, a identificação do seu recurso)


Agora você pode se conectar ao seu servidor de duas maneiras:

  • Clique em Quick Connect > Insira o endereço IP do servidor e o número da porta no seguinte formato - IP:Porta
  • Navegue até Server Browser > Aba Local > Clique duas vezes no seu servidor.

Se tudo correr bem, seu personagem será criado nas coordenadas especificadas.

No próximo tópico iremos criar um comando para que o jogador possa gerar um veículo ao seu lado. Se preferir, embora não recomendado caso seja iniciante, você pode visitar alguns scripts mais avançados clicando aqui. Outra parte interessante da seção "Scripting", na qual obviamente você está, é Conhecendo a Interface Gráfica. Nela, se discute a criação de interfaces gráficas para seus scripts.


Criando um comando simples

Como foi mencionado anteriormente, criaremos agora um comando que irá gerar um carro ao lado do seu personagem. Antes de tudo, precisamos adicionar uma função e um evento específico, chamado de addCommandHandler() ao nosso script.lua.

obs: Um comando é como se fosse uma função chamada pelo jogador quando ele está no chat. Ele digita seu nome e envia-o argumentos especificando o que ele quer. Sempre no formato: /[nome do comando] <argumentos> Exemplo: /cv 410

-- adiciona a função a ser executada pelo comando.
function createVehicleForPlayer(thePlayer, command, vehicleModel)
   -- aqui colocaremos, mais tarde, o código para gerar o veículo
end

-- adiciona um gerenciador de comandos
addCommandHandler("createvehicle", createVehicleForPlayer)


[[{{{image}}}|link=|]] Dica: As funções nativas do MTA são clicáveis em todo o Wiki e lhe redirecionam à páginas sobre elas.


Sobre os gerenciadores de comandos

Esse é um ponto interessante a ser discutido, já que envolve eventos e seus derivados. No MTA, para se criar um comando, usamos um tipo específico de evento que ocorre quando um jogador entra com um comando. Usamos a função addCommandHandler para cria-los. Como um comando é necessariamente um evento, vale a teoria de eventos para ele:

  • Um evento é criado por uma função para determinar suas propriedades
  • Todo evento ativa quando algo acontece no jogo e este sempre envia à função determinadas informações sobre o que ocoreu
  • A relação evento-função é nada mais que uma troca de argumentos, de propriedades

Deve-se prestar atenção nesta troca, pois envolve conceitos fundamentais de Lua. Se você já teve alguma experiência com programação, deve se lembrar como funciona os argumentos de uma função:

nomeDaFuncao(argumento1, argumento2, argumento3, ..)
addCommandHandler("createvehicle", createVehicleForPlayer, ..)
createVehicleForPlayer(thePlayer, commandName, vehicleModel, ..)

Como você observa no exemplo acima, nas duas funções se define quem são os argumentos para indicar como o código deve-se comportar:

  • addCommandHandler é uma na qual se define que quando o jogador digitar o comando createvehicle, a função createVehicleForPlayer irá ser executada.
  • Em createVehicleForPlayer há o recebimento de certas informações enviadas pelo evento, na sequência:
  1. thePlayer - Qual é o jogador que ativou o evento?
  2. commandName - Qual foi o comando digitado?
  3. vehicleModel - Qual foi o ID digitado pelo jogador?

Nota-se nesse caso uma clara troca de informações entre o evento e a função determinada. Quem define como será essa troca é o próprio tipo de evento, que neste caso é um comando. Como ele está sendo executado no servidor, ele sempre enviará na ordem: Quem Digitou? Qual Comando? Quais Argumentos digitados por este jogador? E aí será sua função quem decidirá o que fazer com essas informações; você, programador, dá o nome a esses argumentos e pode até não querer recebê-los, caso elas não forem necessárias.

Vamos a um exemplo prático: alguém digita /createvehicle 468 no chat para gerar uma Sanchez (ID dela é 468. Veja outros neste link), então o gerenciador de comandos chama a função determinada de uma forma como se o jogador tivesse feito o script dele e digitado no arquivo:

createVehicleForPlayer(thePlayer,"createvehicle","468") -- thePlayer seria o próprio jogador

É claro que ele não vai querer seguir este tutorial para fazer isso, e desta forma você está aqui para fazer um comando pra ele. Simplesmente ele digita no chat e seu script cria o veículo desejado.

obs: Os dois primeiros argumentos colocados na função addCommandHandler sempre serão do mesmo tipo: quem foi? o que digitou? Em diante, você pode definir quantas variáveis quiser, de acordo com sua necessidade. Se o comando precisar criar um cavalo (pouco provável) e precisar que o jogador diga qual é a cor dele, a raça, a altura, o humor, poderá definir quantas quiser. Algo nesse estilo: addCommandHandler("criarcavalo" criarCavaloParaJodador(), cor, raça, altura, humor)


[[{{{image}}}|link=|]] Dica: A função sempre deverá existir antes de você criar o comando (vale para eventos também). O computador é uma coisa linear, portanto se você pedir pra ele definir algo que não existe ainda, vai dar erro! Então sempre coloque a função em cima (lógico, é lido de cima pra baixo) do addEventHandler()


Elaborando a função

É hora de escrever nossa função; Sempre que for fazer isso é necessário pensar como faremos um veículo ser criado de forma mais simples o possível:

  • Obter a posição do jogador, para sabermos onde desovar o veículo
  • Calcular essa posição favorável para que a máquina de, em média, 450 quilos não cair em cima do coitado
  • Pedir ao jogo gerar este veículo
  • Verificar se foi gerado com sucesso, ou informá-lo um erro

Para fazer isso, teremos que usar várias funções. Portanto, nós nos direcionamos à página contendo uma Lista de funções de servidor para achá-las. Já que precisamos obter a posição do jogador e como jogador é um Elemento, clicamos primeiro em Element functions onde haverá a função getElementPosition para tal fim. Ao clicar no link, uma página contendo detalhes sobre essa função será mostrada. Nela contém a sintaxe a ser usada, acompanhada de um exemplo. Como a sintaxe do português, a de programação indica como/quais argumentos se pode usar ou omitir.

Para getElementPosition, a sintaxe é:

float, float, float getElementPosition ( element theElement )

Os três itens na frente do nome da função indica o tipo de informação que ela retorna. Neste caso, são float (números com decimais). Em outras palavras, é retornado ao programador três números decimais indicando a posição (x, y, z). Depois do nome, sempre em parênteses, é o que você precisa mandar pra função funcionar. Neste caso, só é preciso de um elemento do qual a posição será retornada e no nosso exemplo, este elemento é o jogador:

function createVehicleForPlayer(thePlayer, command, vehicleModel)
	-- retorna a posição do jogador nas variáveis (x, y, z)
	-- o termo "local" significa que as três variáveis só existirão dentro do bloco - este é a função
	local x,y,z = getElementPosition(thePlayer)
end

Neste passo precisamos garantir que o veículo não esmagará o jogador, então adicionamos algumas unidades no eixo x; fazendo este gerar a leste dele

function createVehicleForPlayer(thePlayer, command, vehicleModel)
	local x,y,z = getElementPosition(thePlayer) -- retorna a posição do jogador
	x = x + 5 adiciona 5 unidades na variável x
end

Agora precisamos de outra função para gerar o veículo. Novamente, procuramos na Lista de funções de servidor. Só que como estamos falando de veículos, procuramos na seção Vehicle functions; onde encontraremos createVehicle. Na sintaxe desta função, temos somente um tipo de retorno (o qual é mais comum): um elemento do tipo veículo criado pela própria função. Além do mais, percebemos alguns argumentos inseridos em colchetes ([]), indicando opcionalidade.

Oras, já temos todos os argumentos necessários para a função funcionar: os (x, y, z) calculados anteriormente e o ID do veículo fornecido pelo jogador através do comando; na variável (vehicleModel). É só digitar:

function createVehicleForPlayer(thePlayer, command, vehicleModel)
	local x,y,z = getElementPosition(thePlayer) -- get the position of the player
	x = x + 5 -- add 5 units to the x position
	-- create the vehicle and store the returned vehicle element in the ''createdVehicle'' variable
	local createdVehicle = createVehicle(tonumber(vehicleModel),x,y,z)
end

É claro que esse código pode melhorar em vários aspectos, mas pelo menos adicionaremos uma condição para verificar o sucesso na criação do veículo. Como foi lido (e infelizmente para uns, era pra ter sido) na página do createVehicle; em baixo de Returns, a função retorna false quando não é possível criar o veículo. Portanto, verificaremos o valor retornado pela variável createdVehicle

Agora temos o script completo:

function createVehicleForPlayer(thePlayer, command, vehicleModel)
	local x,y,z = getElementPosition(thePlayer) -- retorna a posição do jogador
	x = x + 5 adiciona 5 unidades na variável x
	local createdVehicle = createVehicle(tonumber(vehicleModel),x,y,z)
	-- verifica se o retorno foi falso
	if (createdVehicle == false) then
		-- Se sim, retorne uma mensagem de erro somente para o jogador
		outputChatBox("Não foi possível criar o veículo. A sintaxe é: /createvehicle [id]",thePlayer)
	end
end
addCommandHandler("createvehicle", createVehicleForPlayer)

Deve-se destacar os seguintes pontos:

  • Quando tentamos usar qualquer função que crie algum elemento no MTA e esta criação falha, uma bool é retornada como falso. Isso quer dizer: ou há um erro de sintaxe/programação no seu script, ou realmente o servidor não conseguiu computar essa informação
  • Foi introduzida outra função denominada outputChatBox, a qual simplesmente escreve no chat a mensagem de erro

A partir de agora, você pode dar uma olhada na documentação sobre as funções aqui no Wiki. Se desejar, há a página do Map Manager só falando de scripting avançado.

Importante Saber

Já foi dito anteriormente algumas coisas sobre os recursos, gerenciadores de comandos e funções, porém há muita coisa ainda pra aprender. Essa seção lhe fornecerá outras coisas importantes sobre o funcionamento do MTA, ao mesmo tempo linkando à páginas relacionadas se possível.

Lado do Cliente e Servidor

É notório a semelhança dos termos (Cliente/Servidor) em várias partes do site, até mesmo nas funções. O MTA não suporta scripts somente rodando no servidor e oferecendo aos seus jogadores comandos como aquele do exemplo acima ou algo parecido. Ele também oferece a possibilidade de rodar um script no computador de cada jogador logado. Isso porque algumas vantagens oferecidas pelo programa precisam rodar no computador deles. Imagine um servidor mandar o todo tempo informações para desenhar a interface gráfica, sendo esta necessitar uma renderização em uma faixa de 30 vezes por segundo. Não faz o menor sentido, e nem é viável! Ainda mais em PC's antigos com ping alto. Há outras razões além da performance, como o fato de alguns funcionarem melhor em um dos lados ou justamente porque não rola.

A maioria dos scripts (gamemodes ou mapas) provavelmente serão no lado do servidor, como foi feito anteriormente. Se caso acontecer de algo não poder ser resolvido com script do servidor, vá tranquilo pro cliente. Um exemplo de fazer isso seria criar um arquivo pacato chamado client.lua e defini-lo no meta.xml, como a seguir:

<script src="client.lua" type="client" />

O atributo type define automaticamente o arquivo como servidor, então só precisa especificar se for rodado no cliente. Quando terminar, este arquivo será baixado para o computador do brother quando ele conectar ao servidor. Para mais informações, segue o link (Em inglês).

Recursos Complicados

A última seção explicou brevemente como adicionar um script no cliente, mas há muita coisa possível a ser feita. Como foi dito nesta página, recursos praticamente são a alma do jogo. Sua função é definida pelo que eles podem fazer. Então vão aí uns exemplos de recursos hipotéticos retirados da instalação, mostrando suas distintas funções:

Primeiro exemplo - Um utilitário

/admin_commands
	/meta.xml
	/commands.lua
	/client.lua
<meta>
	<info author="Someguy" description="admin commands" />
	<script src="commands.lua" />
	<script src="client.lua" type="client" />
</meta>
  • O commands.lua oferece alguns comandos de administrador, como banir algum pateta ou algo útil para se administrar o servidor
  • O client.lua cria janelas para executar-los de forma muito mais clara e rápida

Este exemplo pode estar rodando o tempo todo (talvez até auto-carregado quando o servidor iniciar) se útil durante a jogatina, e claro, não interferir no processo; só se o administrador decidir intervir.

Segundo exemplo - Um gamemode

/counterstrike
	/meta.xml
	/counterstrike.lua
	/buymenu.lua
<meta>
	<info author="Someguy" description="Counterstrike remake" type="gamemode" />
	<script src="counterstrike.lua" />
	<script src="buymenu.lua" type="client" />
</meta>
  • O counterstrike.lua oferece:
    • A possibilidade dos jogadores escolherem o time e nascerem
    • Lhe dá armas, alvos e instruções (talvez tiradas do Mapa, veja adiante)
    • Define as regras do jogo; exemplos: o que acontece no fim da partida ou quando um jogador falece?
    • E muita coisa que não dá ser citada aqui...
  • O buymenu.lua é um script do cliente e adiciona um menu para adquirir armas

Esse exemplo pode ser denominado um gamemode, pois não só complementa a partida, como também define as regras dela. O atributo type indica que este recurso funciona com o Map manager ou outro escrito pelos desenvolvedores com finalidade de gerenciar os gamemodes e carregamento de mapas. É bem recomendado começar seu gamemode a partir do diferencial que este apresenta.

E mais, um gamemode provavelmente não rodará sem um mapa. Gamemodes sempre precisarão ser o mais genérico possível. Um exemplo de mapa pode ser visto no próximo exemplo.

Terceiro exemplo - Um mapa

/cs-airport
	/meta.xml
	/airport.map
	/airport.lua
<meta>
	<info author="Someguy" description="Counterstrike airport map" type="map" gamemodes="counterstrike" />
	<map src="airport.map" />
	<script src="airport.lua" />
</meta>
  • O airport.map no arquivo XML acima oferece diversas informações sobre o mapa do gamemode, podendo incluir:
    • Onde os jogadores deverão nascer, com quais armas, em qual time
    • Quais são os alvos
    • Clima, horário e limite de tempo da partida.
    • Veículos espalhados pelo local
  • O airport.lua também pode conter objetos específicos, como:
    • Abrir alguma porta/fazer algo explodir quando uma coisa acontece
    • Criar ou mover objetos customizados, ou manipular objetos criados no arquivo .map
    • .. ou infinitas coisas limitadas pela sua imaginação

Nota-se a presença do atributo type classificando o recurso como um mapa, consequentemente avisando o Map manager disso; Enquanto o atributo gamemodes indica com qual o gamemode ele é compatível. Neste caso é o próprio gamemode do exemplo acima. O que pode incomodar é a presença de um script em um mapa. É claro, não há a necessidade de haver isso nele. Entretanto, isso abre uma gama de possibilidades para criadores de mapas concretizarem seus próprios mundos nas regras do gamemode pra ele criado.

O arquivo airport.map contém algo parecido com isso:

<map mode="deathmatch" version="1.0">
	<terrorists>
		<spawnpoint posX="2332.23" posY="-12232.33" posZ="4.42223" skins="23-40" />
	</terrorists>
	<counterterrorists>
		<spawnpoint posX="2334.23443" posY="-12300.233" posZ="10.2344" skins="40-50" />
	</counterterrorists>

	<bomb posX="23342.23" posY="" posZ="" />
	
	<vehicle posX="" posY="" posZ="" model="602" />	
	<vehicle posX="" posY="" posZ="" model="603" />	
</map>

Quando um gamemode é iniciado com um mapa, este é automaticamente iniciado pelo Map manager e a informação contida é lida pelo gamemode. Quando um mapa muda durante a partida, o atual é fechado e o escolhido, iniciado. Para mais detalhes e exemplos sobre como os mapas são utilizados na programação principal, visite a página Escrevendo Gamemodes (Em inglês).

Eventos

Foi dada uma breve explicação no inicio da página, mas um conceito mais formal (criado pelo pessoal do MTA) nunca é demais:

  • Eventos são a forma como o MTA diz aos scripts sobre as coisas que acontecem. Por exemplo, quando um jogador morre, o evento onPlayerWasted é ativado. Com o objetivo de providenciar ações caso isso aconteça, deve ser adicionado um evento, como mostrado no primeiro capítulo.

Este exemplo irá escrever uma mensagem no chat com o apelido do jogador falecido:

function playerDied(totalAmmo, killer, killerWeapon, bodypart)
	outputChatBox(getPlayerName(source).." feleceu!")
end
addEventHandler("onPlayerWasted",getRootElement(),playerDied)

Em vez de mostrar aqui todos os tipos de eventos, uma página específica foi criada no Wiki só para especificar este tipo de coisa; o mesmo serve para os gerenciadores de comandos. Um outro ponto importante é com relação a variável source. Ela é automaticamente declarada na hora de a função ser executada. Ela agrega um diferente valor para cada tipo de evento, como no exemplo acima: para eventos relacionados a jogadores, ele retorna um elemento do tipo jogador. Uma outra forma de como a variável source é usada está no script básico de fazer o jogador nascer no topo da página.

Para onde ir a partir daqui

Agora você deve estar bem mais familiarizado com os aspectos básicos de scripting para o MTA e também com o Wiki. A Página Inicial contém todos os links para mais informações, tutoriais e referências para lhe propiciar todas as fontes necessárias a um estudo mais aprofundado.


[[{{{image}}}|link=|]] Dica: Recomendamos ler o tutorial de debugging a partir daqui. Um bom treinamento em tirar os bugs de seus scripts é fundamental. Também é recomendado dar uma olhada nas variáveis pré-definidas para ajudá-lo com certas tarefas, e claro "scriptar" de forma mais rápida e prática.

Veja mais: