07.01.2012, 17:27
(
Последний раз редактировалось rjjj; 08.01.2012 в 02:23.
)
Temporizaзгo.
Por rjjj ou Ken
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 .