Portal SAMP
[Ajuda] CHECAR DIA E ANO - 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] CHECAR DIA E ANO (/showthread.php?tid=3013)



CHECAR DIA E ANO - Woorz - 24/11/2022

Salve familia!

Rapa, a callback não está CHECANDO CORRETAMENTE a DATA, MES, ANO do script.

Exemplo: Setei o DONATER para o player até 01/12/2022 porém quando player conecta ao servidor, na DATA Correta nada acontece. Não funciona. Se ele conecta na data SETADA seria para resetar tudo.

Testei com DATAS ANTERIORES E POSTERIORES a SETADA e também sem resultados.

Código:
forward checkvipaut(playerid);
public checkvipaut(playerid)
{
    for(new i; i<MAX_PLAYERS; i++) if(IsPlayerConnected(i))
    {
        if(PlayerData[i][pDoador] != 0)
        {
            static
                date[4];

            getdate(date[0], date[1], date[2]);

            new Dia = PlayerData[i][pDiaDoacao];
            new Mes = PlayerData[i][pMesDoacao];
            new Ano = PlayerData[i][pAnoDoacao];

            if(date[2] > Dia && date[1] > Mes)
            {
                SendServerMessage(i, "Seu Donater foi expirado (%d/%d/%d).", Dia, Mes, Ano);
                PlayerData[i][pDoador] = 0;
                PlayerData[i][pDNamecUs] = 0;
                PlayerData[i][pDTrocanUs] = 0;
                PlayerData[i][pDiaDoacao] = 0; PlayerData[i][pMesDoacao] = 0; PlayerData[i][pAnoDoacao] = 0;
                return 1;
            }
        }
    }
    return 1;
}



RE: CHECAR DIA E ANO - Woorz - 24/11/2022

Alguém??


RE: CHECAR DIA E ANO - xbruno1000x - 24/11/2022

Essa função getdate é nativa? creio que não. Quando for assim, envie a função juntamente para analisarmos também.

Partindo do pressuposto que getdate retorna corretamente, a condicional tem um erro. Por exemplo, se você analisa a data 24/11(doação) e 25/01(encerramento) irá notar que o mês 11 é maior que o mês 1.

date[2] maior que 24? Verdadeiro.
date[1] maior que 11? Falso, pois 1 é menor que 11.
Logo a condicional inteira retornaria falsa e o que está ali não seria executado.

Pode ser que esse nem seja o problema do código, mas futuramente vai te gerar um "bug do milênio". Eu recomendo que pegue um daqueles sistemas de vip que usam a função gettime() e tente adaptar para o seu sistema, será mais fácil.


RE: CHECAR DIA E ANO - Woorz - 29/11/2022

(24/11/2022 19:02)xbruno1000x Escreveu: Essa função getdate é nativa? creio que não. Quando for assim, envie a função juntamente para analisarmos também.

Partindo do pressuposto que getdate retorna corretamente, a condicional tem um erro. Por exemplo, se você analisa a data 24/11(doação) e 25/01(encerramento) irá notar que o mês 11 é maior que o mês 1.

date[2] maior que 24? Verdadeiro.
date[1] maior que 11? Falso, pois 1 é menor que 11.
Logo a condicional inteira retornaria falsa e o que está ali não seria executado.

Pode ser que esse nem seja o problema do código, mas futuramente vai te gerar um "bug do milênio". Eu recomendo que pegue um daqueles sistemas de vip que usam a função gettime() e tente adaptar para o seu sistema, será mais fácil.

https://open.mp/docs/scripting/functions/getdate - Essa no caso eu uso para checar a data atual, dia, mes, ano.

Sobre a função: gettime() . Ela faz a contagem mesmo com Player estando OFF?
Queria que a contagem você mesmo com ele OFF, saca?

Pensei nessa função também: `VarialvelTempo` = DATE_ADD(NOW(), INTERVAL 1 MONTH)

Na primeira opção que Iniciei, na parte de setar a doacao, ocorre da seguinte maneira:
Código:
PlayerData[userid][pDiaDoacao] = dia; PlayerData[userid][pMesDoacao] = mes; PlayerData[userid][pAnoDoacao] = ano;



RE: CHECAR DIA E ANO - Carlos Victor - 29/11/2022

"Sobre a função: gettime() . Ela faz a contagem mesmo com Player estando OFF?"
R: Sim e não, não sei como explico isso, mas basicamente a função gettime retorna o timestamp, ou seja o atual segundo que estamos desde 01/01/1970, que é mais ou menos 1669744360 (14:53:20 29/11/2022) atualmente, ou seja, a variável vai só armazenar esses segundos todos, vou dar um exemplo:
Código:
enum PlayerInfo
{
    pName[MAX_PLAYER_NAME],
    pDonation
};
new PlayerData[MAX_PLAYERS][PlayerInfo];

Supondo que o jogador ganhou 30 dias de VIP, sei lá só um exeplo...

CMD:darvip(playerid, params[])
{
    //...

    PlayerData[id][pDonation] = gettime() + (days * 86400); // Como o gettime retorna segundos, temos que trabalhar em segundos, eu multiplico os dias de VIP dele por 86400 que é o equivalente a 1 dia em segundos, então sei lá se eu der 30 dias de VIP, vai ser 30 * 86400 = 2592000

    // ^^ Ai, basicamente vai ser gettime() + 2592000; que vai ficar armazenado na variável, sabemos que daqui a 2592000 segundos, o VIP dele irá se expirar
    return 1;
}

Para uma verificação é simples, faz assim:

if((PlayerData[playerid][pDonation] - gettime()) <= 0)
{
    //Caso os 2592000 segundos tenham passado, vai negativar, menor que zero por conta da regra da subtração, o maior número primeiro e depois o menor, enfim...
} else {
    SendClientMessage(playerid, -1, "* Você possui %s de VIP.", ConvertDate(PlayerData[playerid][pDonation] - gettime()));
}

stock ConvertTime(number) // Função que "formata" os segundos em datas, ou seja se for +60 segundos, 1 minuto, +3600 segundos = 1 hora e assim vai...
{
    new hours, mins, secs, string[64], days = 0;
    hours = floatround(number / 3600.0, floatround_floor);
    mins = floatround((number / 60.0) - (hours * 60.0), floatround_floor);
    secs = floatround((number % 60));

    if(hours >= 24)
    {
        days = floatround((hours/24.0), floatround_floor);
        hours = hours % 24;
    }

    if(days > 0)
        format(string, 64, "%d dia(s) e %d hora(s)", days, hours);
    else if(hours > 0)
        format(string, 64, "%d hora(s) e %d minuto(s)", hours, mins);
    else if(mins > 0)
        format(string, 64, "%d minuto(s)", mins, secs);
    else
        format(string, 64, "%d segundo(s)", secs);
    return string;
}

Qualquer dúvida, só avisar, mas basicamente é assim que funciona, não sei se expliquei bem.

Eu talvez faria dessa forma:

Código:
#include <a_samp>
#include <sscanf2>
#include <zcmd>
#include <foreach>

public OnGameModeInit()
{
    SetTimer("OnUpdateAllPlayers", 1000, true);
    return 1;
}

forward OnUpdateAllPlayers();
public OnUpdateAllPlayers()
{
    foreach(new i : Player)
    {
        if(PlayerData[i][pDonate] != -1 && (PlayerData[i][pDonate] - gettime()) <= 0)
        {
            SendClientMessage(playerid, -1, "* Seus privilégios de doação acabou.");
            PlayerData[i][pDonate] = -1;
        }
    }
    return 1;
}

CMD:setdonate(playerid, params[])
{
    new
        id,
        days;

    if(sscanf(params, "uD(31)", id, days))
        return SendClientMessage(playerid, -1, "* /setdonate [id] [days (optional)]");

    if(!IsPlayerConnected(id))
        return SendClientMessage(playerid, -1, "* Jogador não está conectado.");

    new
        string[128];

    PlayerData[id][pDonate] = gettime() + (days * 86400);

    format(string, sizeof(string), "* Você recebeu %s de privilégios de doador.", ConvertTime(PlayerData[playerid][pDonate] - gettime()));
    SendClientMessage(id, -1, string);
    return 1;
}

stock ConvertTime(number)
{
    new hours, mins, secs, string[64], days = 0;
    hours = floatround(number / 3600.0, floatround_floor);
    mins = floatround((number / 60.0) - (hours * 60.0), floatround_floor);
    secs = floatround((number % 60));

    if(hours >= 24)
    {
        days = floatround((hours/24.0), floatround_floor);
        hours = hours % 24;
    }

    if(days > 0)
        format(string, 64, "%d dia(s) e %d hora(s)", days, hours);
    else if(hours > 0)
        format(string, 64, "%d hora(s) e %d minuto(s)", hours, mins);
    else if(mins > 0)
        format(string, 64, "%d minuto(s)", mins, secs);
    else
        format(string, 64, "%d segundo(s)", secs);
    return string;
}



RE: CHECAR DIA E ANO - Woorz - 29/11/2022

(29/11/2022 15:01)Carlos Victor Escreveu: "Sobre a função: gettime() . Ela faz a contagem mesmo com Player estando OFF?"
R: Sim e não, não sei como explico isso, mas basicamente a função gettime retorna o timestamp, ou seja o atual segundo que estamos desde 01/01/1970, que é mais ou menos 1669744360 (14:53:20 29/11/2022) atualmente, ou seja, a variável vai só armazenar esses segundos todos, vou dar um exemplo:
Código:
enum PlayerInfo
{
    pName[MAX_PLAYER_NAME],
    pDonation
};
new PlayerData[MAX_PLAYERS][PlayerInfo];

Supondo que o jogador ganhou 30 dias de VIP, sei lá só um exeplo...

CMD:darvip(playerid, params[])
{
    //...

    PlayerData[id][pDonation] = gettime() + (days * 86400); // Como o gettime retorna segundos, temos que trabalhar em segundos, eu multiplico os dias de VIP dele por 86400 que é o equivalente a 1 dia em segundos, então sei lá se eu der 30 dias de VIP, vai ser 30 * 86400 = 2592000

    // ^^ Ai, basicamente vai ser gettime() + 2592000; que vai ficar armazenado na variável, sabemos que daqui a 2592000 segundos, o VIP dele irá se expirar
    return 1;
}

Para uma verificação é simples, faz assim:

if((PlayerData[playerid][pDonation] - gettime()) <= 0)
{
    //Caso os 2592000 segundos tenham passado, vai negativar, menor que zero por conta da regra da subtração, o maior número primeiro e depois o menor, enfim...
} else {
    SendClientMessage(playerid, -1, "* Você possui %s de VIP.", ConvertDate(PlayerData[playerid][pDonation] - gettime()));
}

stock ConvertTime(number) // Função que "formata" os segundos em datas, ou seja se for +60 segundos, 1 minuto, +3600 segundos = 1 hora e assim vai...
{
    new hours, mins, secs, string[64], days = 0;
    hours = floatround(number / 3600.0, floatround_floor);
    mins = floatround((number / 60.0) - (hours * 60.0), floatround_floor);
    secs = floatround((number % 60));

    if(hours >= 24)
    {
        days = floatround((hours/24.0), floatround_floor);
        hours = hours % 24;
    }

    if(days > 0)
        format(string, 64, "%d dia(s) e %d hora(s)", days, hours);
    else if(hours > 0)
        format(string, 64, "%d hora(s) e %d minuto(s)", hours, mins);
    else if(mins > 0)
        format(string, 64, "%d minuto(s)", mins, secs);
    else
        format(string, 64, "%d segundo(s)", secs);
    return string;
}

Qualquer dúvida, só avisar, mas basicamente é assim que funciona, não sei se expliquei bem.

Eu talvez faria dessa forma:

Código:
#include <a_samp>
#include <sscanf2>
#include <zcmd>
#include <foreach>

public OnGameModeInit()
{
    SetTimer("OnUpdateAllPlayers", 1000, true);
    return 1;
}

forward OnUpdateAllPlayers();
public OnUpdateAllPlayers()
{
    foreach(new i : Player)
    {
        if(PlayerData[i][pDonate] != -1 && (PlayerData[i][pDonate] - gettime()) <= 0)
        {
            SendClientMessage(playerid, -1, "* Seus privilégios de doação acabou.");
            PlayerData[i][pDonate] = -1;
        }
    }
    return 1;
}

CMD:setdonate(playerid, params[])
{
    new
        id,
        days;

    if(sscanf(params, "uD(31)", id, days))
        return SendClientMessage(playerid, -1, "* /setdonate [id] [days (optional)]");

    if(!IsPlayerConnected(id))
        return SendClientMessage(playerid, -1, "* Jogador não está conectado.");

    new
        string[128];

    PlayerData[id][pDonate] = gettime() + (days * 86400);

    format(string, sizeof(string), "* Você recebeu %s de privilégios de doador.", ConvertTime(PlayerData[playerid][pDonate] - gettime()));
    SendClientMessage(id, -1, string);
    return 1;
}

stock ConvertTime(number)
{
    new hours, mins, secs, string[64], days = 0;
    hours = floatround(number / 3600.0, floatround_floor);
    mins = floatround((number / 60.0) - (hours * 60.0), floatround_floor);
    secs = floatround((number % 60));

    if(hours >= 24)
    {
        days = floatround((hours/24.0), floatround_floor);
        hours = hours % 24;
    }

    if(days > 0)
        format(string, 64, "%d dia(s) e %d hora(s)", days, hours);
    else if(hours > 0)
        format(string, 64, "%d hora(s) e %d minuto(s)", hours, mins);
    else if(mins > 0)
        format(string, 64, "%d minuto(s)", mins, secs);
    else
        format(string, 64, "%d segundo(s)", secs);
    return string;
}

Top demais meu amigo. irei testar ele.

E por curiosidade, mesmo o player estando OFFLINE ele faz essa contagem?


RE: CHECAR DIA E ANO - Carlos Victor - 29/11/2022

Sim, o tempo não para, mesmo o jogador offline, na vida real o tempo vai continuar contando.

Como eu disse, a função gettime retorna o Unix Timestamp, que é um método de data universal, ele se mede por segundos(algo padrão e nível global), e toda vez que você chama a função gettime, vai perceber que vai aumentando por conta dos segundos, que sempre avança a cada segundo(obviamente) qualquer coisa só dar uma pesquisada, alguns meses atrás eu estava na mesma dúvida publicando meu primeiro tópico aqui no portal.