[Tutorial] Descomplicando o ZCMD e SSCANF
#1

Introduзгo
O meu objetivo neste tutorial й ensinar do modo mais fбcil para quem ainda nгo й familiarizado com o uso do ZCMD e SSCANF, que para muita gente й um bixo de sete cabeзas. Antes de comeзar, certifique-se de obter as duas includes.

ZCMD - Download.
SSCANF - Download.

Para instalar й fбcil, vб atй a pasta onde o seu pawno estб e coloque-os na pasta include.
Ex: C:\Program Files (x86)\Rockstar Games\GTA San Andreas\pawno\include

No caso do SSCANF, ele irб vir em um .rar jб com as pastas definidas, entгo basta extrair na pasta onde o seu servidor estб instalado, no meu caso, a pasta principal do jogo.
Ex: C:\Program Files (x86)\Rockstar Games\GTA San Andreas\

Como ele й um plugin, vocк tambem deverб abrir o seu server.cfg e adicionar a seguinte linha:
Код:
echo Executing Server Config...
lanmode 0
rcon_password xxx
maxplayers 32
port 7777
hostname Test server
gamemode0 grandlarc 1
filterscripts gl_actions gl_property gl_realtime gl_mapicon ls_elevator test_cmds ls_mall attachments
plugins sscanf
announce 0
query 1
weburl www.sa-mp.com
onfoot_rate 40
incar_rate 40
weapon_rate 40
stream_distance 300.0
stream_rate 1000
maxnpc 10
logtimeformat [%H:%M:%S]
Entгo adicione as includes no topo do gamemode:
pawn Код:
#include <zcmd>
#include <sscanf2>
Apуs feito isso, tudo iniciarб sem problemas.

Estrutura
Estamos prontos para fazer o nosso primeiro comando! Lembre-se de se certificar que seguiu todos os passos anteriores. Mas antes vamos dar uma olhada na estrutura bбsica dos comandos.

Relembrando que o ZCMD NГO utiliza a callback OnPlayerCommandText, logo vocк poderб criar seus comandos abaixo, exemplo:

pawn Код:
public OnPlayerCommandText(playerid, cmdtext[])
{
    return 0;
}

CMD:meucomando(playerid, params[])
{
    #pragma unused params // <- Й utilizado em comandos que nгo vгo usar os parametros, ou retire o params[]
    return 1;
}
Se vocк pretende criar um filterscript/gamemode completamente baseado no ZCMD, vocк deverб fazer com que a OnPlayerCommandText retorne false, ou uma mensagem de comando inexistente. Vamos a explicaзгo:

Код:
CMD:meucomando(playerid, params[])
{
    #pragma unused params
    return 1;
}
CMD: ou COMMAND: - Funзгo que irб criar nosso comando em ZCMD.
meucomando - nome do comando, no nosso caso seria /meucomando.
playerid, params[] - playerid irб retornar a id do player que executou o comando, params[] sгo os parвmetros, que nуs vamos analizar com o sscanf mais tarde.

O primeiro comando
Vamos comeзar criando um comando simples de setar a sua prуpria vida.

pawn Код:
CMD:setarvida(playerid, params[])
{
    new Float:vida, string[60];
    if(sscanf(params, "f", vida)) return SendClientMessage(playerid, -1, "Use /setarvida [1-100].");
   
    if(vida < 1 || vida > 100) return SendClientMessage(playerid, -1, "Escolha apenas valores entre 1 e 100.");

    format(string, sizeof(string), "Vocк setou sua vida para %.f", vida);
    SendClientMessage(playerid, -1, string);    
    SetPlayerHealth(playerid, vida);
    return 1;
}
Agora vamos explicar todas as partes do comando:

new Float:vida, string[60]; - Criamos uma variбvel float para salvarmos a vida que o jogador colocarб no comando, e uma string para mandar uma mensagem para o mesmo.

Agora vamos entender como funciona o sscanf, com ele vocк poderб separar os termos do comando individualmente, por exemplo, se eu utilizar /criarveiculo 411 0 0, com o sscanf vocк poderб pegar os trкs numeros e os separar. Tudo bem atй agora? Entгo vamos ver as definiзхes bбsicas utilizadas no sscanf:

As definiзхes sгo os tipos de dados que iremos armazenar, ela fica presente entre as aspas, no campo central da funзгo:

if(sscanf(params,"ds", id, mensagem))

i ou d - Integer
Sвo utilizados para numeros INTEIROS, exemplo: 1, 2, 18791...

f - Float
Й utilizados para numeros DECIMAIS, exemplo: 0.1, 5.7, 249.998890220110...

s - String
Utilizado para letras, palavras, frases...

Entгo vamos entender o que utilizamos:
if(sscanf(params, "f", vida))

params - Definimos que a string/variбvel que queremos analizar, sгo os parвmetros do comando.

"f" - Como mostrei na tabela acima, por se tratar de valores relacionados a vida, nуs usaremos Float considerando que o valor poderб ser decimal.

vida - string que iremos armazenar o resultado.

Quando nуs utilizarmos /setarvida 95.5 por exemplo, o sscanf irб analizar os parвmetros (params) e armazenarб o primeiro valor (95.5) float na variбvel vida.

* Lembrando que o SSCANF irб retornar 1 se o comando nгo estiver com todos os parвmetros necessбrios. Por isso fizemos isso:
if(sscanf(params, "f", vida)) return SendClientMessage(playerid, -1, "Use /setarvida [1-100].");

As outras partes do comando sгo auto-explicativas.

Mais exemplos

pawn Код:
CMD:pm(playerid, params[])
{
    new playerdestino, playerNome[MAX_PLAYER_NAME], pdestinoNome[MAX_PLAYER_NAME], mensagem[128], string[128];
    if(sscanf(params, "ds", playerdestino, mensagem)) return SendClientMessage(playerid, -1, "Use /pm [ID] [mensagem].");
   
    if(playerdestino == INVALID_PLAYER_ID) return SendClientMessage(playerid, -1, "ID invбlida ou inexistente.");
   
    if(!strlen(mensagem)) return SendClientMessage(playerid, -1, "Digite uma mensagem.");

    GetPlayerName(playerid, playerNome, MAX_PLAYER_NAME);
    GetPlayerName(playerdestino, pdestinoNome, MAX_PLAYER_NAME);
   
    format(string, sizeof(string), "* PM de %s (%d): %s", playerNome, playerid, mensagem);
    SendClientMessage(playerdestino, 0xFFFF80AA, string);
    format(string, sizeof(string), "* PM para %s(%d): %s", pdestinoNome, playerdestino, mensagem);
    SendClientMessage(playerid, 0x6F6F00AA, string);    
    return 1;
}
if(sscanf(params, "ds", playerdestino, mensagem))

Salvamos a ID (nъmero inteiro, entгo й integer, por isso utilizamos "d") na variбvel playerdestino, e a mensagem (string, entгo colocamos o "s"). O sscanf irб seguir a ordem que colocamos, como coloquei [id] [mensagem], o d vem antes do s.

if(playerdestino == INVALID_PLAYER_ID)

Verificamos se a ID que o player digitou existe.

if(!strlen(mensagem))

Verificamos se algo foi digitado na mensagem, e entгo logo depois, criamos as strings e mandamos a mensagem para ambos os jogadores.

pawn Код:
CMD:criarveiculo(playerid,params[])
{
    new id,cor1,cor2,veh, Float:x, Float:y, Float:z, Float:a;
    if(sscanf(params,"ddd",id,cor1,cor2)) return SendClientMessage(playerid,-1,"Use /criarveiculo [ID] [COR1] [COR2]");

    if(id < 400 || id > 611) return SendClientMessage(playerid, -1, "A ID do veiculo deve ser entre 400 e 611.");
    if(c1 > 128 || c2 > 128) return SendClientMessage(playerid, -1, "A ID das cores devem ser atй 128.");
    if(IsPlayerInAnyVehicle(playerid)) DestroyVehicle(GetPlayerVehicleID(playerid));

    GetPlayerPos(playerid,x,y,z);
    GetPlayerFacingAngle(playerid,a);
    veh = CreateVehicle(id,x,y,z,a,c1,c2,-1);
    PutPlayerInVehicle(playerid, veh, 0);
    return 1;
}
if(sscanf(params,"ddd",id,cor1,cor2))

/criarveiculo 411 1 0

Iremos armazenar a id do veiculo (411 - Infernus) na variбvel id, a cor primбria na variбvel cor1 e a cor secundбria na variбvel cor2. Verificamos se o jogador estб em um veiculo, se estiver o destruimos, entгo pegamos a posiзгo dele e o вngulo no qual o corpo estб virado, criamos o carro e o colocamos dentro do mesmo.

Conclusгo
Espero que este tutorial tenha ajudado vocк a compreender mais sobre como eles funcionam, e como й mais fбcil criar comandos com vбrios parвmetros. Se ainda restar alguma duvida sinta-se a vontade para postar no tуpico, e irei responder assim que possнvel. Se eu esqueci de algo, sinta-se а vontade para comentar.

* ESSE TUTORIAL Й DIRECIONADO AOS INICIANTES EM PAWN.
Reply
#2

Duas observaзхes bбsicas, vocк poderia comentar em seu tutorial que o uso disso:

pawn Код:
#pragma unused params
й apenas sу mais um peso ao seu GM, quando vocк nгo estб utilizando, й mais recomendбvel por apenas:

pawn Код:
CMD:cmd(playerid);
e o Segundo Comentбrio a ser fй eito, й em questгo do if e else if para valores, й muito mais facil utilizar:

pawn Код:
if(Var < 1 || Var > 1) ...
do que utilizar o prуprio if e else if. Mas creio que em restante, ficou legal.
Reply
#3

O que hб de complicado em zcmd e sscanf? Creio que vocк escolheu mau o tнtulo do tуpico.

Sobre o nгo uso de parвmetros, nгo й necessбrio usar pragma unused.

pawn Код:
CMD:comando(playerid) {
    SendClientMessage(playerid,-1,"Hello");
    return 1;
}
A respeito dos especificadores, vocк esqueceu de citar muitos.

Sobre o comando /setarvida, nгo era necessбrio o uso de sscanf pois o comando sу possui um parвmetro.

[]s.
Reply
#4

Na minha mera opiniгo ZCMD e Sscanf nгo sгo coisas complicadas, o que acontece й que muitos baixam GM prontos (a maioria em strcmp) e preferem nгo perder tempo (na opiniгo deles) em atualizar o algoritmo.

Good Joob!
Reply
#5

Jб tem muitos tutoriais de zcmd, mas й sempre bem vindo outro, atй porque muitos membros tem perguiзa de usar search, mas vou fazer uma observaзгo.

pawn Код:
CMD:meucomando(playerid, params[])
{
    #pragma unused params // <- Й utilizado em comandos que nгo vгo usar os parametros
    return 1;
}
Em vez de #pragma unused params basta fazer

pawn Код:
CMD:meucomando(playerid)
{
    return 1;
}
Outra coisa

pawn Код:
CMD:pm(playerid, params[])
{
    new playerdestino, playerNome[MAX_PLAYER_NAME], pdestinoNome[MAX_PLAYER_NAME], mensagem[128], string[128], stringsender[128];
    if(sscanf(params, "ds", playerdestino, mensagem)) return SendClientMessage(playerid, -1, "Use /pm [ID] [mensagem].");
   
    if(playerdestino == INVALID_PLAYER_ID) return SendClientMessage(playerid, -1, "ID invбlida ou inexistente.");
   
    if(!strlen(mensagem)) return SendClientMessage(playerid, -1, "Digite uma mensagem.");

    GetPlayerName(playerid, playerNome, MAX_PLAYER_NAME);
    GetPlayerName(playerdestino, pdestinoNome, MAX_PLAYER_NAME);
   
    format(string, sizeof(string), "* PM de %s (%d): %s", playerNome, playerid, mensagem);
    format(stringsender, sizeof(stringsender), "* PM para %s(%d): %s", pdestinoNome, playerdestino, mensagem);
    SendClientMessage(playerdestino, 0xFFFF80AA, string);
    SendClientMessage(playerid, 0x6F6F00AA, stringsender);    
    return 1;
}
pawn Код:
if(sscanf(params, "ds", playerdestino, mensagem)) return SendClientMessage(playerid, -1, "Use /pm [ID] [mensagem].");
lembre-se sempre de definir o tamanho mбximo de caracteres, ou seja.

pawn Код:
if(sscanf(params, "ds[128]", playerdestino, mensagem))
Assim o sscanf irб funcionar corretamente.

Deu para ver que vocк usou 2 strings, eu no inicio do sa-mp tinha uma confusгo porque pensava que cada string ficava com os dados ocupados lб para sempre entгo fazia o que vocк fez.

pawn Код:
format(string, sizeof(string), "* PM de %s (%d): %s", playerNome, playerid, mensagem);
format(stringsender, sizeof(stringsender), "* PM para %s(%d): %s", pdestinoNome, playerdestino, mensagem);
SendClientMessage(playerdestino, 0xFFFF80AA, string);
SendClientMessage(playerid, 0x6F6F00AA, stringsender);
Em vez disso faзa

pawn Код:
format(string, sizeof(string), "* PM de %s (%d): %s", playerNome, playerid, mensagem);
SendClientMessage(playerdestino, 0xFFFF80AA, string);
format(stringsender, sizeof(string), "* PM para %s(%d): %s", pdestinoNome, playerdestino, mensagem);
SendClientMessage(playerid, 0x6F6F00AA, string);
Assim vocк nгo irб usar variaveis desnecessбrias obviamente.

Mais uma coisa

pawn Код:
if(playerdestino == INVALID_PLAYER_ID) return SendClientMessage(playerid, -1, "ID invбlida ou inexistente.");
Covem vocк juntar outra verificaзгo, ou seja, verificar se o jogador estб conectado.

pawn Код:
if(playerdestino == INVALID_PLAYER_ID && !IsPlayerConnected(playerid)) return SendClientMessage(playerid, -1, "ID invбlida ou inexistente.");
Bem, por agora й sу isto.

Todos nуs cometemos erros, esses erros nгo sгo erros de sintaxe em si, sгo outro tipos de erros que nem sempre vemos mas que tambйm contam muito, espero que isto o ajude

Fora isso bom tutorial
Reply
#6

Belo Tutorial!

Acredito que jб tenha 3473575 tutoriais do mesmo assunto na бrea BR ;/
Reply
#7

o tutorial esta leganzin mais desde quando zcmd e sscanf й complicado ?quer complicaзгo usa strcmp+strtok isso sim й chato de usar e lembrar a sintaxe.jб zcmd e sscanf nunca vi jeito mais facil de criar seus comandos de forma rapida e facil edite o titulo do tуpico e tente explicar um pouco mais.

Nota: 6/10
Reply
#8

Quote:
Originally Posted by [Full]Garfield[XDB]
Посмотреть сообщение
Belo Tutorial!

Acredito que jб tenha 3473575 tutoriais do mesmo assunto na бrea BR ;/
І ...

7/10
Reply
#9

Ficou bom, mas poderia adicionar esses detalhes que eles falaram.
Reply
#10

Outra coisa

Com apenas 1 paramкtro pode ser usado,

pawn Код:
if(isnull(params)) return SendClientMessage(playerid, -1, "Digite uma mensagem.");
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)