Portal SAMP
[Ajuda] Uso de sscanf em Dialog - Versão de Impressão

+- Portal SAMP (https://portalsamp.com)
+-- Fórum: SA-MP (https://portalsamp.com/forumdisplay.php?fid=5)
+--- Fórum: Área de suporte (https://portalsamp.com/forumdisplay.php?fid=6)
+--- Tópico: [Ajuda] Uso de sscanf em Dialog (/showthread.php?tid=3528)



Uso de sscanf em Dialog - KruCz - 16/04/2023

Oi pessoal, boa noite! Tudo bem?

Recentemente fiz um comando para localizar jogadores próximos, através de dialog. Estou com problema em definir uma variável para o segundo jogador próximo, e como é em dialog, não encontrei algo semelhante ao método padrão (sscanf).

Com isso, ao usar o comando, o valor sempre é 0, no caso apresentado ao ID 0. Após isso, tentei utilizar com um loop, porém, quando efetuo a ação o loop também pega o meu ID e conta como proximidade

 
Código PHP:
public OnPlayerKeyStateChange(playeridnewkeysoldkeys)
{
new 
str[15];

    format(strsizeof(str), "dinheiro: \t\t %i"PPL[playerid][moneyAtPPL]);
    ShowPlayerDialog(playeridtrade_moneyDIALOG_STYLE_LIST"dinheiro"str"Enviar""Fechar");
    return 1;
}

OnDialogResponse(...)
{
    if(dialogid == 613)
    {
        new str[140];

        if(response)
        {
            if(listitem == 0)
            {
                for(new iMAX_PLAYERS; ++i)
                {
                     if(GetDistanceBetweenPlayers(playeridi) <= 3)
                    {
                         format(strsizeof(str), "Quanto deseja enviar para %s?"nomep(i));
                         ShowPlayerDialog(playerid630DIALOG_STYLE_INPUT"dinheiro"str"Enviar""Cancelar");
                    }
                    else
                    {
                         SendClientMessage(playerid, -1"Ninguem por perto.");
 
                   }
                }
            }
      }

    if(dialogid == 630) 
    
{
        if(response)
        {
            new str[120];
            {
                for(new iMAX_PLAYERS; ++i)
                {
                    if(moneyreturn(playerid) < strval(inputtext)) return SendClientMessage(playerid, -1"voce não possui essa quantia");

                    if(GetDistanceBetweenPlayers(playeridi) <= 3))
                    {
                         moneyAtPPL(istrval(inputtext));
                         moneyAtPPL(playerid, - strval(inputtext));

                         format(strsizeof(str), "%i enviado para %s."strval(inputtext), nomep(i));
                         SendClientMessage(playerid, -1str);
                    }
              }
              else 
              
{
                      SendClientMessage(playerid, -1"ninguem por perto.");
              }
         }
     }
}

Alguém poderia me ajudar



RE: Uso de sscanf em Dialog - Carlos Victor - 16/04/2023

Se você quer pegar os dados de jogadores próximo, deverá criar um loop em todos os jogadores e verificar se estão próximos ou não, e também não é recomendado utilizar a callback OnPlayerStateChange da forma que foi apresentada acima, lembre-se que ela é chamada toda vez que um jogador clique em um botão válido, então imagina quantas vezes ela será chamada em uma servidor com 10/20 jogadores, bastante, enfim... Deixarei um código abaixo, não sei se é isso que você quis dizer, mas é o que eu entendi.

Código PHP:
CMD:proximo(playerid)
{
    static
        
_name[MAX_PLAYER_NAME],
        
count,
        
str[32],
        
string[1024];

    
count         0;
    
string[0]     = 0;
    
str[0]         = 0;

    
format(stringsizeof(string), "ID\tNome\tDinheiro\n");
    for(new 
0GetPlayerPoolSize(); <= ji++) 
    {
        if(
IsPlayerConnected(i) && IsPlayerNearPlayer(iplayerid20.0))
        {
            
GetPlayerName(playerid_namesizeof(_name));
            
format(stringsizeof(string), "%s{FFFFFF}%d\t%s\t%d\n"stringi_nameGetPlayerMoney(i));

            
count++;
        }
    }

    if(!
count)
        return 
SendClientMessage(playerid, -1"* Você não está próximo de nenhum jogador.");

    
format(strsizeof(str), "Jogadores Proximos (%d)"count);
    
ShowPlayerDialog(playeridDIALOG_PLAYERS_NEARDIALOG_STYLE_TABLISTstrstring"Selecionar""Fechar");
    return 
1;
}

public 
OnDialogResponse(playeriddialogidresponselistiteminputtext[])
{
    switch(
dialogid)
    {
        case 
DIALOG_PLAYERS_NEAR
        {
            if(
response)
            {
                new 
                    
Float:x,
                    
Float:y,
                    
Float:z,
                    
string[128],
                        
_name[MAX_PLAYER_NAME],
                    
id strval(inputtext);

                if(!
IsPlayerConnected(id))
                    return 
SendClientMessage(playerid, -1"* O jogador selecionado desconectou-se do servidor.");

                
GetPlayerName(id_namesizeof(_name));
                
GetPlayerPos(idxyz);
                
SetPlayerPos(playeridxy1.0);

                
format(stringsizeof(string), "* Você foi até o jogador %s."_name);
                
SendClientMessage(playerid, -1string);
            }
        }
    }
    return 
1;


No código acima utilizei variáveis estáticas no comando para evitar o grande consumo de memória, já que iremos trabalhar com string's grandes, e também o teleporte que eu fiz caso selecionar um X jogador na dialog é um exeplo do que você pode fazer, seja criativo e faça o que quiser usando o paramêtro ID como o jogador selecionado.


RE: Uso de sscanf em Dialog - KruCz - 16/04/2023

(16/04/2023 21:24)Carlos Victor Escreveu: Se você quer pegar os dados de jogadores próximo, deverá criar um loop em todos os jogadores e verificar se estão próximos ou não, e também não é recomendado utilizar a callback OnPlayerStateChange da forma que foi apresentada acima, lembre-se que ela é chamada toda vez que um jogador clique em um botão válido, então imagina quantas vezes ela será chamada em uma servidor com 10/20 jogadores, bastante, enfim... Deixarei um código abaixo, não sei se é isso que você quis dizer, mas é o que eu entendi.

Código PHP:
CMD:proximo(playerid)
{
    static
        
_name[MAX_PLAYER_NAME],
        
count,
        
str[32],
        
string[1024];

    
count         0;
    
string[0]     = 0;
    
str[0]         = 0;

    
format(stringsizeof(string), "ID\tNome\tDinheiro\n");
    for(new 
0GetPlayerPoolSize(); <= ji++) 
    {
        if(
IsPlayerConnected(i) && IsPlayerNearPlayer(iplayerid20.0))
        {
            
GetPlayerName(playerid_namesizeof(_name));
            
format(stringsizeof(string), "%s{FFFFFF}%d\t%s\t%d\n"stringi_nameGetPlayerMoney(i));

            
count++;
        }
    }

    if(!
count)
        return 
SendClientMessage(playerid, -1"* Você não está próximo de nenhum jogador.");

    
format(strsizeof(str), "Jogadores Proximos (%d)"count);
    
ShowPlayerDialog(playeridDIALOG_PLAYERS_NEARDIALOG_STYLE_TABLISTstrstring"Selecionar""Fechar");
    return 
1;
}

public 
OnDialogResponse(playeriddialogidresponselistiteminputtext[])
{
    switch(
dialogid)
    {
        case 
DIALOG_PLAYERS_NEAR
        {
            if(
response)
            {
                new 
                    
Float:x,
                    
Float:y,
                    
Float:z,
                    
string[128],
                
        _name[MAX_PLAYER_NAME],
                    
id strval(inputtext);

                if(!
IsPlayerConnected(id))
                    return 
SendClientMessage(playerid, -1"* O jogador selecionado desconectou-se do servidor.");

                
GetPlayerName(id_namesizeof(_name));
                
GetPlayerPos(idxyz);
                
SetPlayerPos(playeridxy1.0);

                
format(stringsizeof(string), "* Você foi até o jogador %s."_name);
                
SendClientMessage(playerid, -1string);
            }
        }
    }
    return 
1;


No código acima utilizei variáveis estáticas no comando para evitar o grande consumo de memória, já que iremos trabalhar com string's grandes, e também o teleporte que eu fiz caso selecionar um X jogador na dialog é um exeplo do que você pode fazer, seja criativo e faça o que quiser usando o paramêtro ID como o jogador selecionado.

Oi Carlos, boa noite! Primeiramente agradeço a atenção!

A dúvida que postei, foi sobre um "método de transferência", um jogador transferir dinheiro para o jogador mais próximo a ele.
No código publicado, o jogador pressiona a tecla na callback OnPlayerKeyStateChange, e seleciona a opção "Dinheiro" na dialog. Após isso, a ideia é perguntar quanto ele quer transferir para o usuário mais próximo a ele.

Meu problema é que não estou conseguindo definir uma variável para localizar esse jogador mais próximo para efetuar a ação. Se fosse em comando, eu poderia definir uma variável através do sscanf. Porém, estou fazendo em dialog.


RE: Uso de sscanf em Dialog - Carlos Victor - 17/04/2023

O jogador mais próximo dentro de um raio ou o mais próximo valendo o mapa todo?


RE: Uso de sscanf em Dialog - KruCz - 17/04/2023

(17/04/2023 11:53)Carlos Victor Escreveu: O jogador mais próximo dentro de um raio ou o mais próximo valendo o mapa todo?

A ideia era ser o mais próximo dentro de um raio, usei o GetDistanceBetweenPlayers, porém, a a dificuldade é com a variável.


RE: Uso de sscanf em Dialog - White_Blue - 17/04/2023

(17/04/2023 12:29)KruCz Escreveu:
(17/04/2023 11:53)Carlos Victor Escreveu: O jogador mais próximo dentro de um raio ou o mais próximo valendo o mapa todo?

A ideia era ser o mais próximo dentro de um raio, usei o GetDistanceBetweenPlayers, porém, a a dificuldade é com a variável.

Qual o problema?

Para o uso de sscanf em dialog você usa o parâmetro inputtext da OnDialogResponse para escanear a variável

Exemplo:
Código PHP:
public OnDialogResponse(playeriddialogidresponselistiteminputtext[]) {
      if(
dialogid == sua_dialog) {
       new 
id;
       if(
sscanf(inputtext"u"id)) return SendClientMessage(playerid, -1"Digite o ID do jogador!"), ShowPlayerDialog(playeridsua_dialogDIALOG_STYLE_INPUT"Digite o ID do jogador""{FFFFFF}Digite o ID do jogador desejado:");
      }
       return 
1;




RE: Uso de sscanf em Dialog - Carlos Victor - 18/04/2023

Desculpa a demora, mas com base no que você disse, eu fiz o código:

Código PHP:
new targetID[MAX_PLAYERS] = {INVALID_PLAYER_ID, ...};

public 
OnPlayerKeyStateChange(playeridnewkeysoldkeys)
{
    new 
str[32];

    
format(strsizeof(str), "dinheiro: \t\t %i"PPL[playerid][moneyAtPPL]);
    
ShowPlayerDialog(playeridtrade_moneyDIALOG_STYLE_LIST"dinheiro"str"Enviar""Fechar");
    return 
1;
}

OnDialogResponse(...)
{
    if(
dialogid == 613)
    {
        if(
response)
        {
            new 
                
string[128];

            if((
targetID[playerid] = GetNearestPlayer(playerid)) == INVALID_PLAYER_ID)
                return 
SendClientMessage(playerid, -1"Nao tem ninguem proximo de voce.");

            
format(strsizeof(str), "Quanto deseja enviar para %s?"nomep(id));
            
ShowPlayerDialog(playerid630DIALOG_STYLE_INPUT"dinheiro"str"Enviar""Cancelar");
          }
    }

    if(
dialogid == 630
    {
        if(
response)
        {
            new 
                
string[128],
                
id targetID[playerid];

            if(
moneyreturn(playerid) < strval(inputtext)) 
                return 
SendClientMessage(playerid, -1"voce não possui essa quantia");

            if(!
IsPlayerConnected(id))
                return 
SendClientMessage(playerid, -1"O jogador desconectou-se.");

            if(!
IsPlayerNearPlayer(playeridid3.0))
                return 
SendClientMessage(playerid, -1"O jogador se afastou demais!");


            
moneyAtPPL(istrval(inputtext));
            
moneyAtPPL(playerid, - strval(inputtext));

            
format(stringsizeof(string), "Voce enviou $%d para %s."strval(inputtext), nomep(i));
            
SendClientMessage(playerid, -1string);
         }
    }
    return 
1;
}

stock GetNearestPlayer(playerid)
{
    for(new 
0GetPlayerPoolSize(); <= ji++)
    {
        if(
IsPlayerConnected(i) && IsPlayerNearPlayer(playeridi3.0)) {
            return 
i;
        }
    }
    return 
INVALID_PLAYER_ID;
}

stock IsPlayerNearPlayer(playeridtargetidFloat:radius)
{
    static
        
Float:fX,
        
Float:fY,
        
Float:fZ;

    
GetPlayerPos(targetidfXfYfZ);

    return (
GetPlayerInterior(playerid) == GetPlayerInterior(targetid) && GetPlayerVirtualWorld(playerid) == GetPlayerVirtualWorld(targetid)) && IsPlayerInRangeOfPoint(playeridradiusfXfYfZ);


Ele inclui:

- Verificar o jogador mais próximo.
- Enviar dinheiro a esse jogador mais próximo.