(english)
Concluindo esta parte você vai:
Saber responder o que são e como usar as condições IF e o loop WHILE;
Em geral, saber controlar um script para direcionar ele onde e quando quiser.
Já aprendemos a direcionar o código para onde quisermos. Mas, e
quando quisermos?
É agora que você aprenderá a, realmente, criar um script.
Nesta parte do tutorial você aprenderá a usar condições/conditions. Controlar
o fluxo.
Opcional: Se você é completamente iniciante em programação e fala português, você pode querer antes assistir
este vídeo do Manual do Mundo. Lá ele prepara a sua mente para o que você verá aqui.
IF
IF é "se". Pronto.
Mas vamos ver melhor o que um "se" quer dizer numa programação:
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
PRINT_STRING_NOW "Segurando a tecla H" 1
ENDIF
GOTO main_loop
}
SCRIPT_END
IMPORTANTE:
Digite o código você mesmo. Veja que o momento em que você digita "VK_" aparece uma lista de teclas para você escolher.
Note que antes de PRINT_STRING_NOW
eu adicionei um espaço, mas não é um espaço comum, é uma tabulação (aperte a tecla TAB
). É cosmético mas obrigatório. Ainda explicarei melhor o motivo de usarmos e tentarei introduzir você naturalmente até lá, simplesmente olhe os códigos.
Assim como estas linhas vazias, são totalmente opcionais e mudam em nada no produto final. Somente cosmético, e opcional. Use-as para melhor leitura.
Teste o código acima dentro do seu jogo. O resultado é simples: Enquanto estiver segurando a tecla
H
, aparecerá o texto.
Sim eu quero que você teste, pare de ler e vá ver.
Note que eu fiz com que o texto apareça somente 1 milissegundo na tela, assim só aparecerá caso estiver segurando a tecla. Experimente mudar o tempo para
1000
, assim o texto ficará aparecendo na sua tela mesmo depois de 1 segundo após soltar a tecla! (na verdade, até pouquinho mais de 1)
Se você entende inglês, não há dúvida alguma sobre o código acima. Basta ler:
"
IF IS_KEY_PRESSED"
Tradução livre: "
se a tecla está pressionada".
Realmente muito simples. O "
IF" é um "
SE", onde checa
SE alguma coisa é verdadeira.
Perceba também o sentido literal da coisa: "pressionada", e não "pressionou".
Outro exemplo:
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_PC_VERSION
PRINT_STRING_NOW "Sim, seu GTA eh de PC" 1
ENDIF
GOTO main_loop
}
SCRIPT_END
Ou seja, se o seu GTA é versão para PC, aparecerá a mensagem "Sim, seu GTA é de PC" — é óbvio que aparecerá!
E este?
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_AUSTRALIAN_GAME
PRINT_STRING_NOW "Sim, seu GTA eh versao australiana" 1
ENDIF
GOTO main_loop
}
SCRIPT_END
Agora aparecer a mensagem "Sim, seu GTA é versão australiana" caso seja. O que não é! Ou seja, não aparecerá nada na sua tela, pois não deu verdadeiro, deu falso.
Lembre-se: Os comandos que você pode usar com
IF
são comandos que se iniciam com
IS_
,
HAS_
ou
DOES_
(além de alguns outros comandos, que você aprenderá com o decorrer do tempo, normalmente chamados de "if and set").
Caso o
IF
ser verdadeiro, será feito tudo o que está aqui dentro:
Até o
ENDIF
.
O
ENDIF
é só um marcador dizendo "
acabou o IF!". Simples assim.
Veja este exemplo:
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
PRINT_STRING_NOW "1" 1000
WAIT 1000
PRINT_STRING_NOW "2" 1000
WAIT 1000
PRINT_STRING_NOW "3" 1000
WAIT 1000
PRINT_STRING_NOW "4" 1000
WAIT 1000
PRINT_STRING_NOW "5" 1000
ENDIF
GOTO main_loop
}
SCRIPT_END
O que você diria?
Opção 1. Aparecerá uma contagem enquanto estiver segurando a tecla.
Opção 2. Após apertar a tecla começará uma contagem e ela continuará mesmo com a tecla solta.
O que você acha que aconteceria?
Tente lembrar de como os scripts funcionam.
Onde eles vão sempre indo pra baixo, lendo o que está embaixo.
Se você respondeu "2".
Certa resposta!
Só depois de terminar a contagem que o script chegará no
GOTO main_loop
e voltará para cima fazer tudo de novo.
Enquanto a contagem, o script não sabe que você soltou a tecla, ele só sabe que você esteve com ela apertada, e depois disso ele começou a mostrar coisas na tela. É assim que um script funciona. Nada mais. Por isso o nome "thread", onde a palavra "thread" em português quer dizer "fio", onde vemos isso no sentido de "caminho", "rastro".
Um script não lê duas linhas ao mesmo tempo e eu quero deixar isso claro para você entender bem como um script anda.
Se você achou essa pergunta fácil, então aí vai outra mais desafiadora:
Se você ficar segurando a tecla durante toda a contagem, e continuar segurando mesmo após a contagem acabar, quais números aparecerão na tela?
Veja o código de novo, pense.
Perceba que não há
WAIT 1000
após aparecer o número "5". Após aparecer "5", dará
GOTO
, voltará na parte de cima do loop no
WAIT 0
, processará 1 frame com o número "5" na tela, e em seguida voltará no
IF IS_KEY_PRESSED
que dará verdadeiro e recomeçará a contagem no "1".
Ou seja, a resposta é que aparecerá "5" em somente 1 frame do jogo. Se você estiver em 60 FPS, o "5" ficará na sua tela durante 16,666 milissegundos (você quase nem verá o número aparecendo!).
Voltando ao assunto, e se eu quiser fazer mais do que um IF?
Oras bolas!...
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
PRINT_STRING_NOW "Segurando H" 1000
ENDIF
IF IS_KEY_PRESSED VK_KEY_J
PRINT_STRING_NOW "Segurando J" 1000
ENDIF
GOTO main_loop
}
SCRIPT_END
Tudo muito simples, né?
Acredite ou não, é comum você ver pessoas não sabendo fazer isso, e assim elas criam um novo arquivo .cs para fazer um comando diferente... Só porque não aprendeu a fazer isso!
Mas e se eu apertar H e J ao mesmo tempo?
Ele irá mostrar "Segurando J".
Por quê?
Porque o script é lido de cima pra baixo! E um texto sobrescreverá o outro.
O comando
PRINT_STRING_NOW
faz mostrar um texto, mas se já ter algum texto sendo mostrado, ele sobrescreve.
Assim, o script acima, ao segurar as duas teclas juntas, irá "mostrar" primeiro o "H", mas quando chegar no "J" o texto "H" deixará de ser mostrado, será mostrado na verdade o "J".
Em seguida o script irá para o
main_loop
e assim processará o jogo. E durante o processamento do jogo será finalmente mostrado a mensagem "Segurando J".
ELSE / NOT
E se eu quero fazer outra coisa caso NÃO seja verdadeiro?
Usamos
ELSE
, que em português quer dizer "senão".
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
PRINT_STRING_NOW "Segurando H" 1
ELSE
PRINT_STRING_NOW "Nao esta segurando H" 1
ENDIF
GOTO main_loop
}
SCRIPT_END
Veja que legal!
É tudo muito simples.
E ainda, nós temos esta opção:
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF NOT IS_KEY_PRESSED VK_KEY_H
PRINT_STRING_NOW "Nao esta segurando H" 1
ELSE
PRINT_STRING_NOW "Segurando H" 1
ENDIF
GOTO main_loop
}
SCRIPT_END
Preste muita atenção na diferença.
A diferença é que usei um
NOT
no
IS_KEY_PRESSED
, assim dará verdadeiro só quando "não está pressionando"! E caso estiver pressionado, dará falso, e assim será feito o que está dentro do
ELSE
. Somente inverteu...
Há até mesmo como fazer
IFNOT
em vez de "IF". Há muitas possibilidades (isso era suportado no original GTA3script do GTA III mas nunca foi usado) Nota: Não há como fazer
IFNOT NOT
(pra quê você faria isso??). Mas para programadores mais experimentes: infelizmente não é possível fazer
ELSEIF
(a não ser que alguém crie uma extensão que adicione isto).
E se?
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
PRINT_STRING_NOW "Segurando H" 1
IF IS_KEY_PRESSED VK_KEY_J
PRINT_STRING_NOW "Segurando H e J" 1
ENDIF
ENDIF
GOTO main_loop
}
SCRIPT_END
Está começando a ficar interessante agora.
Caso você segurar "H" aparecerá a mensagem de que está segurando o "H", e em seguida checará se você está também segurando "J", caso verdadeiro, aparecerá na verdade a mensagem "Segurando H e J".
Como sempre, na programação há vários modos de se fazer a mesma coisa. Você também pode usar
ELSE
neste exemplo, na qual o código ficará bem diferente, mas com o mesmo resultado:
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
IF IS_KEY_PRESSED VK_KEY_J
PRINT_STRING_NOW "Segurando H e J" 1
ELSE
PRINT_STRING_NOW "Segurando somente H" 1
ENDIF
ENDIF
GOTO main_loop
}
SCRIPT_END
E que tal mais um ELSE ali embaixo?
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
IF IS_KEY_PRESSED VK_KEY_J
PRINT_STRING_NOW "Segurando H e J" 1
ELSE
PRINT_STRING_NOW "Segurando somente H" 1
ENDIF
ELSE
PRINT_STRING_NOW "Nao esta segurando H" 1
ENDIF
GOTO main_loop
}
SCRIPT_END
O script está começando a ficar grande, e eu espero que você saiba explicar cada linha deste código.
Note que cada mensagem escrita ali é a descrição literal do que está acontecendo.
Se você está segurando "J" sem segurar "H", o que aparecerá na tela é "Não está segurando H", pois o script nunca saberá que você está segurando "J" caso não esteja segurando "H", pois ele só irá checar se você está segurando "J" caso você esteja segurando "H".
Em outras palavras, se você não está segurando "H", não há como o script saber se você está ou não segurando "J", a única coisa que o script sabe é que você não está segurando "H", nada mais nada menos...
Você pode usar quantos IFs você quiser, um dentro do outro, sem problemas. Isso é extremamente comum de se fazer.
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
IF IS_KEY_PRESSED VK_KEY_J
PRINT_STRING_NOW "Segurando H e J" 1
ELSE
IF IS_KEY_PRESSED VK_KEY_G
PRINT_STRING_NOW "Segurando H e G, sem segurar J" 1
ELSE
PRINT_STRING_NOW "Segurando somente H" 1
ENDIF
ENDIF
ELSE
PRINT_STRING_NOW "Nao esta segurando H" 1
ENDIF
GOTO main_loop
}
SCRIPT_END
Wow, é melhor pararmos por aqui, né?
Se você entendeu cada linha deste código acima, você entendeu muito bem como usar IF! Parabéns, é um grande passo, o IF será muito usado enquanto você cria mods.
AND / OR
E que tal assim?
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
AND IS_KEY_PRESSED VK_KEY_J
PRINT_STRING_NOW "Segurando H e J" 1
ENDIF
GOTO main_loop
}
SCRIPT_END
Nós checamos duas teclas, ao mesmo tempo!
Isso usando o
AND
, que é, simplesmente, um "e".
Ou seja, é um "
se apertou uma tecla" "
e apertou outra".
Que tal três?
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
AND IS_KEY_PRESSED VK_KEY_J
AND IS_KEY_PRESSED VK_KEY_K
PRINT_STRING_NOW "Segurando H e J, e K!" 1
ENDIF
GOTO main_loop
}
SCRIPT_END
Você pode colocar até 8! O limite também vale para o OR:
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
OR IS_KEY_PRESSED VK_KEY_J
PRINT_STRING_NOW "Segurando H ou J" 1
ENDIF
GOTO main_loop
}
SCRIPT_END
OR
de inglês é "ou". Não há mistério, o funcionamento é igual ao
AND
, mas agora é "ou" em vez de "e".
Ou seja, só dará verdadeiro SE (
IF
) você apertou uma tecla, OU (
OR
) outra! — Mas, também dá verdadeiro caso tenha apertado as duas juntas :) (senão seria ruim em certos casos, né?)
Mas e se eu quiser misturar
AND
com
OR
no mesmo IF? ...Opa, assim não! Isso não funciona. GTA3script é uma linguagem simples demais.
WHILE
Vamos agora fazer as coisas diferentes:
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
WHILE IS_KEY_PRESSED VK_KEY_H
WAIT 0
PRINT_STRING_NOW "Enquanto segurando H" 1
ENDWHILE
GOTO main_loop
}
SCRIPT_END
WHILE
, como o nome diz, é "enquanto".
Mais outra coisa auto-explicativa, pois, simplesmente é "enquanto você está segurando a tecla".
Nota que eu adicionei um
WAIT 0
dentro do
WHILE
, pois,
literalmente, enquanto você está segurando a tecla o script ficará rodando ali dentro, se você não colocar um
WAIT
, o jogo irá parar de processar. Pois o
WHILE é um loop!
Às vezes na prática — principalmente no exemplo acima — o
WHILE
é muito semelhante ao o que vimos anteriormente no
IF
, mas na real, são coisas muito diferentes, e com o tempo você notará muita diferença.
Geralmente, você irá querer usar
WHILE
para coisas do tipo "enquanto o CJ está dentro do carro", "enquanto a tecla está sendo segurada", "enquanto você está num local", "enquanto o CJ está vivo" etc. Também muito comum em contagens.
Por outro lado, o
WHILE
não é uma coisa "obrigatória", você pode fazer mods complexos até mesmo usando somente
IF
, sem nenhum
WHILE
! Mas às vezes, você pode acabar preferindo o
WHILE
, é você quem escolhe.
Veja só este exemplo que você usará muito em seus mods:
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
PRINT_STRING_NOW "Pressionou H" 1000
WHILE IS_KEY_PRESSED VK_KEY_H
WAIT 0
ENDWHILE
ENDIF
GOTO main_loop
}
SCRIPT_END
Teste isso dentro do seu jogo. Segure a tecla "H" para ver.
O que acontecerá será isso:
- Pressionou H;
- Apareceu na tela a mensagem;
- Enquanto você está segurando H, o script ficará dentro do
WHILE
, somente processando o jogo (rodando no WAIT 0
);
- Quando você soltar, sairá de dentro do
WHILE
, o script continuará, voltará, e você poderá apertar o H novamente para aparecer a mensagem novamente.
Teste também mudando os
1000
milissegundos para
10
ou
100
, para entender melhor o que está acontecendo — assim a mensagem somente piscará rapidamente na tela!
Isso é muito interessante, pois o script irá parar enquanto você ainda não tenha soltado a tecla H! Se você remover o
WHILE
ali, o script ficará igual
um script que vemos no início desta parte do tutorial, um script onde você segura a tecla, e a mensagem continua aparecendo sem parar, mas o nosso WHILE não deixará isso, pois ele está servindo de "enquanto você ainda está segurando a tecla, não mostre de novo, espere!".
Então pense, e se na nossa mensagem estaria na verdade, um código onde cria um carro? Sem o uso do WHILE ficaria criando carros sem parar! Se você está rodando o jogo em 60 FPS, irá criar 60 carros por segundo enquanto você segura a tecla!!! Isso é loucura, e para evitar isso, basta adicionar um "enquanto está segurando a tecla, faça nada", para assim, você necessitar soltar a tecla, e assim apertar de novo, e ativar de novo — e assim criar o carro de novo.
O quê? Você quer testar isso? Então tá:
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
SPAWN_VEHICLE_BY_CHEATING ELEGY
WHILE IS_KEY_PRESSED VK_KEY_H
WAIT 0
ENDWHILE
ENDIF
GOTO main_loop
}
SCRIPT_END
Este acima é um bom código (bem usável para até deixar em seu jogo) onde você dará spawn de um carro Elegy, como se fosse um cheat (aparecendo na frente do CJ).
Nota que funciona perfeitamente como deveria, é realmente um mod usável.
Mas e se removermos aquele WHILE que espera soltar a tecla?
Teste isso dentro do seu jogo. Irá criar 1 carro por frame!
Mas felizmente, um carro "sobrescreverá" o outro por serem criados no mesmo local, assim você só verá um carro mudando de cor a cada frame do jogo (a não ser que o seu Elegy não tenha diferentes cores), mas na verdade não é só mudar de cor, e sim são carros novos sendo criados numa velocidade absurda. Uma coisa totalmente errada! E o
WHILE
com
IS_KEY_PRESSED
pode ser usado para evitar isso. Usar um
WAIT
de alguns segundos também resolveria, mas não fica nada legal, evite ao máximo fazer coisa assim.
Se estivéssemos criando um carro usando outro método (o método mais usado para a criação de carros) iria virar uma chuva de carros e até crashar o jogo.
Este é só um dos incontáveis exemplos.
Outro exemplo útil:
Código: Selecionar tudo
WHILE IS_CHAR_SITTING_IN_ANY_CAR scplayer
WAIT 0
PRINT_STRING_NOW "Enquanto o CJ esta em algum carro" 1
ENDWHILE
Nota: Somente mostrei a parte do
WHILE
ao invés do script inteiro. Ainda temos que aprender mais coisas até lá!
Quando o CJ sair do carro, o script sairá do
WHILE
e continuará na linha debaixo do "ENDWHILE".
WHILE AND / OR
Assim como o
IF
, o
WHILE
também aceita
AND
e
OR
!
(você que já sabe Sanny Builder, veja aí uma novidade boa)
Código: Selecionar tudo
SCRIPT_START
{
NOP
main_loop:
WAIT 0
IF IS_KEY_PRESSED VK_KEY_H
AND IS_KEY_PRESSED VK_KEY_J
PRINT_STRING_NOW "Pressionou H+J" 1000
WHILE IS_KEY_PRESSED VK_KEY_H
AND IS_KEY_PRESSED VK_KEY_J
WAIT 0
ENDWHILE
ENDIF
GOTO main_loop
}
SCRIPT_END
Ou seja, eu apertei H junto com J, mostra a mensagem na tela, e enquanto eu estiver segurando H+J, o script ficará rodando dentro do
WHILE
. Se eu soltar H ou J, dará falso no
AND
e o script sairá do
WHILE
para continuar rodando novamente, assim podendo apertar as teclas novamente, e assim ativar novamente.
Se você mudar o
WHILE | AND
para
WHILE | OR
você terá um efeito diferente, pois ele ficará dando verdadeiro no WHILE caso
alguma das duas condições sejam verdadeiras (ou seja, dará verdadeiro se você ainda está segurando uma, ou outra tecla!)
Peço para que teste estas duas maneiras dentro do seu jogo e veja as diferenças :) assim você aprende na prática.
Dica: Adicione também uma mensagem dizendo "Soltou a tecla!" Embaixo do
ENDWHILE
, para você saber exatamente o momento em que o WHILE deu falso e entender melhor o que está se passando.
Como eu disse, o
WHILE
é muito opcional e tem muito a ver com a opinião do programador e o que ele quer fazer. Na maioria das vezes você pode preferir o uso do
IF
— essa coisa de "enquanto está no carro" eu dificilmente uso, mas serve como bom exemplo.
Pra mim em particular, o uso mais comum do
WHILE
é ao segurar a tecla ou fazer algum tipo de contagem.
Nota para programadores do Sanny Builder (e outras programações): Não há nenhum WHILE_TRUE aqui! O loop é feito por lowlevel mesmo, usando GOTO, mas o fato de termos WHILE AND/OR pode ser uma forma de substituir um WHILE_TRUE, né?
Mesmo assim, mais de 1 ano após escrever este tutorial, eu criei uma solução e estou adicionando como bônus:
WHILE TRUE
WHILE TRUE
é um substituto ao
main_loop | GOTO main_loop
, você provavelmente vai preferir utilizá-lo, pois é mais agradável, mais "high level". De fato, com
WHILE TRUE
,
BREAK
e
CONTINUE
você nunca vai precisar usar
GOTO
em seus scripts (mesmo que você ainda possa querer usar).
Você pode adicionar isto ao seu GTA3script seguindo o meu tópico:
"WHILE TRUE", "RETURN_TRUE" e "RETURN_FALSE" para GTA3script
Nota: no tópico acima há coisa que você ainda não aprendeu! Ignore o que você não entender, logo você aprenderá.
O motivo de não existir isso nativamente no GTA3script é, que como eu já expliquei, isto é uma cópia da linguagem que a Rockstar North criou, e no GTA3script original isto não existe (a Rockstar North usou
GOTO
).
É claro que é opcional, sinta-se livre para escolher usar ou não.
Isto não será usado neste tutorial.
Só isso?
NÃO!
Ainda há mais algumas coisas, até mesmo algumas técnicas de uso, mas até o momento você não precisa aprendê-las e não quero te sobrecarregar agora. Quando chegar a hora, você será ensinado.
Você ainda nem ao menos sabe o que são "variáveis", que é um coisa que anda muito junto com condições, portanto, você aprenderá em seguida e logo logo voltará a se aprofundar mais em condições, assim aprendendo a usar por exemplo
REPEAT
.
Mas antes, você terá um pequeno "tutorial" (que é mais um ensinamento opcional) explicando um pouco sobre o funcionamento de um PC (de uma maneira bem legal), e em seguida, você aprenderá o que são as tais "variáveis".
Próxima parte:
8. Bits & Bytes