Temporizaзгo. - rjjj - 07.01.2012
Temporizaзгo.
Por rjjj ou Ken
Temporizaзгo й a programaзгo da execuзгo de determinado cуdigo para um momento situado apуs um certo intervalo de tempo
.
Em Pawn, hб vбrias tйcnicas que podem ser usadas para a aplicaзгo da temporizaзгo, dentre elas, a mais conhecida й a do
SetTimer .
1 - A funзгo sleep.
O
sleep foi produzido para ser capaz de fazer com que o servidor, antes de ler qualquer outro cуdigo do GM, tenha que aguardar um certo tempo, que й especificado em seu ъnico parвmetro
.
pawn Код:
sleep(/*Tempo em milissegundo.*/); //Obs: 1 segundo (s) й equivalente a 1000 milissegundos (ms).
Essa funзгo sу deve ser usada no
main() do GameMode
.
Exemplo de uso:
pawn Код:
main()
{
print("Aguarde 2 segundos..."); //Mostra uma mensagem no console do samp-server.exe.
sleep(2000); //Faz o GameMode esperar 2 segundos.
print("GameMode carregado :D !"); //Passados 2 segundos, й mostrada uma nova mensagem.
}
Em alguns GameModes cheguei a presenciar execuзхes infinitas de funзхes e erros do tipo Run Time causados pela utilizaзгo do
sleep, por isso recomendo que apуs a inserзгo dele em um cуdigo, um teste seja feito para que se tenha certeza de que tudo funciona sem problemas.
2 - Loops demorados.
Й possнvel gerar o mesmo efeito do
sleep usando loops demorados, veja um exemplo
:
pawn Код:
main()
{
print("Aguarde 2 segundos..."); //Mostra uma mensagem no console do samp-server.exe.
for(new x; x != 100000000;) x++; //Faz o GameMode esperar aproximadamente 2 segundos.
print("GameMode carregado :D !"); //Passados 2 segundos, й mostrada uma nova mensagem.
}
Contudo, esse mйtodo pode ser utilizado em qualquer callback, inclusive de Filterscripts.
Ele tambйm, ao contrбrio do
sleep, funciona no jogo propriamente dito, parando para os players coisas como o chat, como se fosse um tipo de "Lag" passageiro
.
Para tornar esse cуdigo mais prбtico, montei a seguinte macro:
pawn Код:
#define sleep2(%0); for(new _@%0; _@%0 != (%0*50000000);) (_@%0++);
Exemplo de como usб-la:
pawn Код:
SendClientMessageToAll(0x33CCFFAA, "O servidor ficarб travado durante 3 segundos por motivos tйcnicos.");
sleep2(3); //O tempo direcionado ao parвmetro deve estar em segundos.
SendClientMessageToAll(0xFFFFFFAA, "Concluнdo.");
3 - SetTimer.
A funзгo
SetTimer serve para adiar a leitura de um cуdigo, mas sem fazer com que outros parem
.
Й obrigatуrio que esse cуdigo seja uma callback, isto й, seja criado com as estruturas
public e
forward .
A callback por sua vez nгo pode ter parвmetros, devendo ser criada com os parкnteses
() que seguem seu nome, vazios:
Exemplo de callback:
pawn Код:
forward GenkiDama(); //Escolhe-se o nome da callback e escreve-se "forward NomedaCallback();" ou apenas "NomedaCallback();". Veja que os parкnteses () estгo vazios, o que й correto.
public GenkiDama() //Em seguida escreve-se "public NomedaCallback" (sem o ponto e vнrgula) e chaves {}, com o cуdigo a ser executado dentro delas. Veja que os parкnteses () estгo novamente vazios, o que й correto.
{
SendClientMessageToAll(0x33CCFFAA, "Deem um pouco de sua energia !"); //Cуdigo interno.
return true;
}
Bem, estes sгo os parвmetros da funзгo
SetTimer:
pawn Код:
SetTimer("NomeDaCallback", /*Tempo em milissegundos.*/, /*Repetir sempre.*/);
No ъltimo parвmetro (onde estб "Repetir sempre", acima) coloca-se
true para que a callback seja executada sempre que se passar um tempo equivalente aos milissegundos especificados, e
false para que ela seja lida apenas 1 vez
.
Exemplo 1:
pawn Код:
//Dentro de algum comando ou funзгo:
SetTimer("IniciarCorrida", 5000, false); //Programa a exibiзгo de uma mensagem para daqui a 5 segundos. Como no terceiro parвmetro estб o sнmbolo "false", a callback IniciarCorrida serб executada apenas 1 vez, consequentemente, a mensagem serб mandada apenas 1 vez tambйm.
//No Final do GM, fora de qualquer outro cуdigo:
forward IniciarCorrida();
public IniciarCorrida() //Passados 5 segundos, a mensagem й enviada.
{
SendClientMessageToAll(0xFFFFFFAA, "A corrida comeзou !"); //Mensagem.
return true;
}
Exemplo 2:
pawn Код:
//No OnGameModeInit:
SetTimer("SkinWoozie", 1000, true); //Programa uma verificaзгo de todos os jogadores, a fim de saber quem estб com com a skin do Woozie, para daqui a 1 segundo. Como no terceiro parвmetro estб o sнmbolo "true", sempre que 1 segundo se passar a callback "SkinWoozie" serб executada, consequentemente, a verificaзгo serб efetuada.
//No Final do GM, fora de qualquer outro cуdigo:
forward SkinWoozie();
public SkinWoozie() //Passado 1 segundo, os jogadores sгo checados.
{
for(new x = 0; x != MAX_PLAYERS; x++) //Este loop permite que a verificaзгo analise todos os jogadores.
{
if(GetPlayerSkin(x) == 294) //Se a skin for detectada em um jogador.
{
SendClientMessage(x, 0x33CCFFAA, "Vocк estб com a skin do Woozie !");//...Uma mensagem й enviada ao mesmo.
}
}
return true;
}
Vale ressaltar que o perнodo do Temporizador (ou Timer), a entidade criada pelo
SetTimer para cuidar de determinada callback, serб sempre relativo ao momento no qual ele foi gerado.
4 - SetTimerEx.
A diferenзa entre o
SetTimer e o
SetTimerEx й que este ъltimo funciona sem problemas com callbacks que possuem parвmetros, isto й, que sгo criadas com variбveis/constantes dentro de seus parкnteses
() .
Exemplo de callback com parвmetros:
pawn Код:
forward lol(playerid);
public lol(playerid); //Essa callback tem 1 parвmetro, a variбvel "playerid".
{
SendClientMessage(playerid, 0xFFFFFFAA, "Oi !");
return true;
}
Mas como se usaria esse cуdigo de modo que
playerid fosse igual a
4 e assim a mensagem fosse enviada ao jogador de ID 4 apуs um certo tempo
?
Bem, vejamos os parвmetros da funзгo
SetTimerEx:
pawn Код:
SetTimerEx("NomeDaCallback", /*Tempo em milissegundos.*/, /*Repetir sempre*/, /*Caracteres para a identificaзгo dos tipos de valores nos parвmetros da callback.*/, /*Valores passados aos parвmetros.*/);
Os 3 primeiros parвmetros trabalham de maneira idкntica aos correspondentes a eles no
SetTimer .
Quanto aos 2 ъltimos:
O quarto (onde estб escrito "Caracteres para a identificaзгo dos tipos valores nos parвmetros da callback.", acima) deve conter, entre aspas e um ao lado do outro, sнmbolos que identifiquem a natureza dos elementos que serгo colocados nos parвmetros da callback (string, nъmero inteiro, entre outros).
Os principais sгo:
pawn Код:
"d" ou "i" para nъmeiros inteiros (integers).
"f" para nъmeros floating-point (floats, nъmeros racionais com um ponto ".").
"s" para strings (textos).
Jб o quinto (onde estб escrito "Valores passados aos parвmetros", acima) deve conter, entre vнrgulas, os prуprios elementos que serгo direcionados aos parвmetros da callback
.
Por exemplo, se eu quisesse fazer com que, passados 9 segundos, a callback
lol que citei anteriormente (lembra dela ?
) fosse executada a fim de que a mensagem "Oi !" fosse enviada ao jogador de ID 4
:
pawn Код:
SetTimerEx("lol", 9000, false, "i", 4); // 4 por que queremos que o "playerid" da callback seja igual a esse nъmero e "i" por que 4 й um nъmero inteiro.
Outro exemplo, mais complexo:
pawn Код:
//Dentro de algum comando ou funзгo:
new id_jogador= 12;
SetTimerEx("AvisoRegras", 4000, false, "ds", id_jogador, "Cuidado com as regras !"); // "ds" por que a variбvel "id_jogador" e o texto "Cuidado com as regras" podem ser considerados, respectivamente, um nъmero inteiro e uma string. O motivo de "d" (vendo da esquerda para a direita) vir primeiro que "s" em "ds" й o fato de "id_jogador" vir primeiro que o texto "Cuidado com as regras !" na linha do SetTimerEx.
//No Final do GM, fora de qualquer outro cуdigo:
forward AvisoRegras(playerid, texto[]);
public AvisoRegras(playerid, texto[]); //Como o SetTimerEx enviou os seguintes valores, nesta ordem: a variбvel "id_jogador" e a string "Cuidado com as regras !", nesse cуdigo de callback, as variбveis "playerid" e "texto" serгo, respectivamente, iguais a eles.
{
SendClientMessage(playerid, 0xFFFFFFAA, texto); //Mandarб a mensagem "Cuidado com as regras !" ao jogador de ID 12.
return true;
}
5 - KillTimer.
Uma vez criado um Timer, й possнvel parб-lo por meio da funзгo
KillTimer .
Os parвmetros dela sгo:
pawn Код:
KillTimer(/*ID do Temporizador*/);
Mas como saber o ID de um Timer responsбvel por certa callback a fim de bloquear sua execuзгo ?
.
Basta criar uma variбvel e, na hora de usar o
SetTimer/
SetTimerEx, igualб-la a ele.
Assim essa variбvel irб armazenar o ID do Timer e serб possнvel usб-la para chegar atй ele.
Exemplo:
pawn Код:
//Dentro de algum comando ou funзгo:
new TimerID;
TimerID = SetTimer("ServerGMX", 5000, false); //Programa um GMX para daqui a 5 segundos.
KillTimer(TimerID); //Destrуi o Timer da callback ServerGMX, com isso, o GMX que seria feito й cancelado.
//No Final do GM, fora de qualquer outro cуdigo:
forward ServerGMX();
public ServerGMX()
{
SendRconCommand("gmx");
return true;
}
6 - Outros.
Hб tambйm as funзхes
gettime,
getdate,
GetTickCount e
tickcount, que capturam dados de um momento especнfico no tempo, e por isso, podem ser usadas para gerar uma temporizaзгo por meio da criaзгo de sistemas de referкncia entre dados antigos e dados recentes
.
Exemplo:
pawn Код:
//No Topo do GM:
new ComandoBloqueado;
//Em um comando:
if((gettime() - ComandoBloqueado) < 30) return SendClientMessage(playerid, 0xFFFFFFAA, "Comando bloqueado !");
ComandoBloqueado = gettime();
No caso acima, o comando em questгo seria bloqueado se o nъmero de segundos (essa unidade de medida devido ao
gettime) passados desde a ъltima vez que ele foi usado fosse menor que 30.
E й isso
.
Espero ter ajudado
.
Re: Temporizaзгo. -
[O.z]Caroline - 07.01.2012
Bom tutorial, mais esqueceu de citar que o GetTickCount e TickCount comeзam a contar quando o servidor й iniciado..
Re: Temporizaзгo. -
Adrian Fahrenheit Tepes - 07.01.2012
Muito bom! Concordo com a Caroline.
@EDIT
Hб algum tipo de tutorial que ensine essas coisas:
Jб vi scripts impressionantes que tкm essas coisa, e nunca consegui compreender. E como elas se chamam?
Re: Temporizaзгo. -
Bolinha_ProJogos - 07.01.2012
muito bom tuto.
Re: Temporizaзгo. -
[O.z]Caroline - 07.01.2012
Quote:
Originally Posted by Adrian Fahrenheit Tepes
Muito bom! Concordo com a Caroline.
@EDIT
Hб algum tipo de tutorial que ensine essas coisas:
Jб vi scripts impressionantes que tкm essas coisa, e nunca consegui compreender. E como elas se chamam?
|
Isto nгo й nenhum truque.
agore pense comigo:
temos a funзгo "Sleep2"
pawn Код:
#define sleep2(%0); for(new _@%0; _@%0 != (%0*50000000);) (_@%0++); //
public OnGameModeInit()
{
sleep2(20); // 20 Segundos.
return 1;
}
Agora imaginamos que %0 й igual o valor dado a funзгo, no nosso caso, 20 segundos.
o nosso amigo Rjj colocou _@ para criar uma variavel, ficando
_@20
nгo hб segredos algum, porque _@ sгo somente sнmbolos.
Outro exemplo:
pawn Код:
SetTimer("@Tempo", 100, 1);
forward @Tempo();
public @Tempo() return 1;
Agora, se vocк estб falando de operadores avanзados:
terбs que aprender nъmeros binбrios primeiro.
Re: Temporizaзгo. -
Adrian Fahrenheit Tepes - 07.01.2012
AH! Entendi, obrigado.
Re: Temporizaзгo. - rjjj - 07.01.2012
Quote:
Originally Posted by [O.z]Caroline
Bom tutorial, mais esqueceu de citar que o GetTickCount e TickCount comeзam a contar quando o servidor й iniciado..
|
Quote:
Originally Posted by Adrian Fahrenheit Tepes
Muito bom! Concordo com a Caroline.
|
Atй pensei em detalhar as funзхes que citei na ъltima parte do tуpico, mas acabei nгo fazendo isso por que alйm de eu ter ultrapassado o limite de imagens permitido:
.
Eu estaria meio que desviando do assunto central do tуpico, por isso ensinei o raciocнnio que й normalmente usado e deixei que o leitor do tutorial descobrisse sozinho as particularidades de cada uma
.
Quote:
Originally Posted by Adrian Fahrenheit Tepes
@EDIT
Hб algum tipo de tutorial que ensine essas coisas:
Jб vi scripts impressionantes que tкm essas coisa, e nunca consegui compreender. E como elas se chamam?
|
Nгo sei se hб, mas como a Caroline disse, utilizei os caracteres:
_ e
@ por que sгo aceitos como parte do nome de uma variбvel
.
No caso desse cуdigo, usб-los diminui a probabilidade da variбvel do loop ter o mesmo nome de outra do GM/FS
.
Espero ter ajudado
.
Re: Temporizaзгo. -
[O.z]Caroline - 07.01.2012
Quote:
Originally Posted by rjjj
Atй pensei em detalhar as funзхes que citei na ъltima parte do tуpico, mas acabei nгo fazendo isso por que alйm de eu ter ultrapassado o limite de imagens permitido: .
Eu estaria meio que desviando do assunto central do tуpico, por isso ensinei a tйcnica que й normalmente usada e deixei que o leitor do tutorial descobrisse sozinho as particularidades de cada uma .
Nгo sei se hб, mas como o Garfield disse, utilizei os caracteres: _ e @ por que sгo aceitos como parte do nome de uma variбvel .
No caso desse cуdigo, usб-lo diminui a probabilidade da variбvel do loop ter o mesmo nome de outra do GM/FS .
Espero ter ajudado .
|
nomes de loop, nгo hб possibilidade de erros!.
pawn Код:
for(new i; i != 500; ++i) { printf("%d", i); }
for(new i; i != 500; ++i) { printf("%d", i); }
for(new i; i != 500; ++i) { printf("%d", i); }
Ha nгo ser que um loop seja dentro do outro:
pawn Код:
for(new i; i != 500; ++i)
{
for(new i; i != 500; ++i)
{ printf("%d", i);
}
printf("%d", i);
}
Re: Temporizaзгo. - rjjj - 07.01.2012
Quote:
Originally Posted by [O.z]Caroline
nomes de loop, nгo hб possibilidade de erros!.
pawn Код:
for(new i; i != 500; ++i) { printf("%d", i); } for(new i; i != 500; ++i) { printf("%d", i); } for(new i; i != 500; ++i) { printf("%d", i); }
Ha nгo ser que um loop seja dentro do outro:
pawn Код:
for(new i; i != 500; ++i) { for(new i; i != 500; ++i) { printf("%d", i); } printf("%d", i); }
|
Eu quis dizer que diminui a probabilidade de um fato deste tipo ocorrer
:
pawn Код:
//No Topo do GM:
new Contador;
//Em alguma public:
for(new Contador = 0; Contador != MAX_PLAYERS; Contador++)
{
if(IsPlayerConnected(Contador)) printf("%i", Contador);
}
pawn Код:
warning 219: local variable "Contador" shadows a variable at a preceding level.
Por exemplo, se eu tivesse declarado a variбvel do loop com o nome "x" no cуdigo do
sleep2 e o GM de quem o usasse tivesse uma variбvel com este nome tambйm, problemas aconteceriam
.
E desculpe Caroline, percebi que me referi a vocк por outro nome sem querer no meu ъltimo post, mas jб editei o mesmo
.
Qualquer dъvida sobre o assunto do tуpico, perguntem
!
Espero ter ajudado
.
Re: Temporizaзгo. -
JonathanFeitosa - 07.01.2012
tu ainda nгo morreu