Запомнить игрока вышедшего с сервера

oleg_nelasy

Участник
Сообщения
664
Реакции
46
В общем есть интовый массив по игрокам

int g_iStatusSwapTeams[MAXPLAYERS+1];

В момент когда игрок меняет команду ему присваивается положительное значение, и идет проверка если положительное тогда блокируем смену команды и выводим сообщение. По событиям начало новой карты и дисконект обнуляю донное значение чтобы новому игроку автоматически заблокировало возможность смены команды.
C-подобный:
public void OnClientDisconnect(int iClient)
{
    g_iStatusSwapTeams[iClient] = 0;
    g_bCheckFirstConnection[iClient] = false;
}

public void OnMapStart()
{
    LoopClients(i)
    {
        g_bCheckFirstConnection[i] = false;
        g_iStatusSwapTeams[i] = 0;
    }
}
public Action Event_OnRoundEnd(Handle event, const char[] name, bool dontBroadcast)
{
    LoopIngameClients(i)
    {
        if(g_iStatusSwapTeams[i] != 0)
        {
            g_iStatusSwapTeams[i] --;
            if(g_iStatusSwapTeams[i] == 0)
                CGOPrintToChat(i, "%t", "Open Swap Team", g_sTag);
        }            
    }
}

В данный момент если игрок переподключится то счетчик сбрасывается. Нужно как то запомнить игрока и если вышел с сервера то сохранить для него значение g_bCheckFirstConnection и g_iStatusSwapTeams. Сохранённый g_iStatusSwapTeams должен в конце раунда делать --. Как только сохранённые данные игрока g_iStatusSwapTeams == 0 то удалить сохранённые g_bCheckFirstConnection и g_iStatusSwapTeams и считать его подключение за нового игрока.
 

oleg_nelasy

Участник
Сообщения
664
Реакции
46
Если я правильно понял

C-подобный:
создаю
StringMap hTrie = new StringMap();

Когда игрок отключается
Ключ это айди аканта
If(g_iStatusSwapTeams[iClient])
    hTrie.SetValue(GetSteamAccountID(iClient), g_iStatusSwapTeams[iClient]);

Когда игрок подключается
int iVar1;
    if(hTrie.GetValue(GetSteamAccountID(iClient), iVar1))
    {
         g_iStatusSwapTeams[iClient] = iVar1
    }

Не понял как мне все содержимое StringMap hTrie сделать --
 
Последнее редактирование:

_wS_

Участник
Сообщения
383
Реакции
760
Не понял как мне все содержимое StringMap hTrie сделать --
Вроде очевидно 🙂

1. Get (получаешь)
2. Изменяешь
3. Set (перезаписываешь)

GetSteamAccountID в строку только обернуть не забудь:
PHP:
FormatEx(key, sizeof(key), "%u", GetSteamAccountID(iClient));

И лучше не вызывать GetSteamAccountID до OnClientPostAdminCheck.
И если сохранить нужно 2+ переменных, то в твоём случае наверно лучше будет hTrie.SetArray/hTrie.GetArray, например:

PHP:
#define STATUS 0
#define CHECK_FIRST 1

void ..
{
    // Сохраняешь.
    any info[2];
    info[STATUS] = g_iStatusSwapTeams[iClient];
    info[CHECK_FIRST] = g_bCheckFirstConnection[iClient];
    char key[20];
    FormatEx(key, sizeof(key), "%u", GetSteamAccountID(iClient));
    hTrie.SetArray(key, info, sizeof(info));
    
   // Получаешь, отнимаешь, сохраняешь.
   if (hTrie.GetArray(key, info, sizeof(info))
   {
      info[STATUS]--;
      hTrie.SetArray(key, info, sizeof(info));
   }
}

Вместо #define и any info[2] удобнее было бы enum struct.
 

oleg_nelasy

Участник
Сообщения
664
Реакции
46
@_wS_
Спасибо разобрался подскажите пожалуйста. Проблема следующая нужно после подключения сразу переместить игрока в команду наблюдателей. Потому что если он будет в команде наблюдателей и попытается к не присоединится триггер не сработает, но если попытается зайти за другую команду ct или t его заблокирует.
Сейчас происходит так игрок подключился если он попытался зайти за t или ct ему заблокирует смену команды но если он выберет команду наблюдателей его переместит за эту команду. Но поскольку он был в команде 0 и переместился в команду 1 сработает триггер и ему обновит количество раундов сколько ему куковать в наблюдателях.

C-подобный:
public void OnClientPostAdminCheck(int iClient)
{
    any info[2];
    char key[20];
    FormatEx(key, sizeof(key), "%u", GetSteamAccountID(iClient));
 
    if(hTrie.GetArray(key, info, sizeof(info)))
    {
        PrintToChatAll("Игрок подключился %N из буфера info[STATUS] = %d info[CHECK_FIRST] = %d", iClient, info[STATUS], info[CHECK_FIRST]);
        g_iStatusSwapTeams[iClient] = info[STATUS];
        g_bCheckFirstConnection[iClient] = info[CHECK_FIRST];
    }
 
    if(g_iStatusSwapTeams[iClient])
    {
        //Пробовал
        CS_SwitchTeam(iClient, CS_TEAM_SPECTATOR);
        и
        ChangeClientTeam(iClient, CS_TEAM_SPECTATOR);
    }
}

И еще вопрос?

C-подобный:
any info[2];
char key[20];
 
StringMapSnapshot hTrieSnapshot = hTrie.Snapshot();
int iSize = hTrieSnapshot.Length;
PrintToChatAll("Игроков в буфере %d", iSize);

for(i = 0; i < iSize; ++i)
{
    hTrieSnapshot.GetKey(i, key, sizeof(key)); //По номеру ключа получаю значение
    hTrie.GetString(key, info, sizeof(info)); //По ключу извлекаю данные из буфера
  
    info[STATUS]--;                             
    if(info[STATUS] == 0;)
    {
        hTrie.Remove(key);
      
        Если я удаляю key нумерация сместится на -1?
        Мне надо делать i - 1?
    } 
    hTrie.SetArray(key, info, sizeof(info));//Помещаю данные в буфер обратно
}
 
Последнее редактирование:

_wS_

Участник
Сообщения
383
Реакции
760
Не уверен, что всё правильно понял =)
Если нужно игнорировать переход из команды 0 куда-то, то событие player_team поможет:
Там есть "oldteam" (из какой команды переходит) и "team" (в какую).

Если я удаляю key нумерация сместится на -1?
Мне надо делать i - 1?
Нет, i - 1 не нужно. hTrieSnapshot никак не связан с hTrie оригиналом.
Кст на 11 строке не hTrie.GetString, а hTrie.GetArray.
 
Последнее редактирование:

oleg_nelasy

Участник
Сообщения
664
Реакции
46
Не уверен, что всё правильно понял =)
Если нужно игнорировать переход из команды 0 куда-то, то событие player_team поможет:
Нет. Надо как только игрок подключился к серверу переместить его в наблюдатели. До того как он начал выбирать команду.
Сообщения автоматически склеены:

Нет, i - 1 не нужно. hTrieSnapshot никак не связан с hTrie оригиналом.
Хорошо допустим в буфере лежать 3 игрока. Под номерами 0 1 2. Я делаю hTrie.Remove(1);
Они останутся под номерами 0 2 если так то при проверки hTrieSnapshot.Length; я получу 2 или 3? Если я получаю 2 то при следующей проверки получается не будет учтён номер 3? Поскольку условие for будет выглядеть так i < 2 то-есть игрок под номером 2 не будет проверен?
 
Последнее редактирование:

_wS_

Участник
Сообщения
383
Реакции
760
Надо как только игрок подключился к серверу переместить его в наблюдатели.
Мне кажется можно было и с player_team. Кинуть в spec после входа можно и так:

PHP:
bool g_bFirstJoin[MAXPLAYERS + 1];

public void OnPluginStart()
{
    AddCommandListener(OnJointeam, "jointeam");
}

public void OnClientConnected(int client)
{
    g_bFirstJoin[client] = true;
}

public Action OnJointeam(int client, const char[] command, int argc)
{
    if (g_bFirstJoin[client])
    {
        g_bFirstJoin[client] = false;
        
        if (IsClientInGame(client)) {
            ChangeClientTeam(client, 1);
        }
        
        return Plugin_Stop;
    }
    return Plugin_Continue;
}

Но игрок всё равно какое-то время будет в команде 0.
Чтобы его вообще в 0 не было, это уже уровень расширений/смещений и т.д. скорее всего, если вообще возможно.

Хорошо допусти в буфере лежать 3 игрока. Под номерами 0 1 2. Я делаю hTrie.Remove(1);
Разве сложно проверить?)
Могу повторить, hTrieSnapshot никак не связан с hTrie оригиналом.
Если сделать hTrie.Remove, или даже CloseHandle(hTrie), то hTrieSnapshot каким был, таким и остаётся, ибо не связаны они.
 

oleg_nelasy

Участник
Сообщения
664
Реакции
46
C-подобный:
any info[2];
    char key[20];
 
    StringMapSnapshot hTrieSnapshot = hTrie.Snapshot();
    int iSize = hTrieSnapshot.Length;
 
    for(int i = 0; i < iSize; ++i)
    {
        hTrieSnapshot.GetKey(i, key, sizeof(key)); //По номеру ключа получаю значение
        hTrie.GetArray(key, info, sizeof(info)); //По ключу извлекаю данные из буфера
    
        if(info[BlockStatusSwapTeamT])
            info[BlockStatusSwapTeamT]--;
    
        if(info[BlockStatusSwapTeamCT])
            info[BlockStatusSwapTeamCT]--;
    
        if(!info[BlockStatusSwapTeamT] && !info[BlockStatusSwapTeamCT]) //Нужно ли удалять учитывая? что по событию смена карты буфер очищается раз 30-50 минут.
            hTrie.Remove(key);     

        if(info[BlockStatusSwapTeamT] || info[BlockStatusSwapTeamCT])
            hTrie.SetArray(key, info, sizeof(info));//Помещаю изменённые данные в буфер обратно
    }

Вопрос в коментарии
 
Последнее редактирование:

_wS_

Участник
Сообщения
383
Реакции
760
//Нужно ли удалять учитывая? что по событию смена карты буфер очищается раз 30-50 минут.
Вопрос в коментарии
А ответ только у тебя и богов 🙏
Никто не знает, как именно используется info.
Если уверен, что запись уже не нужна, то наверно же лучше удалить её и освободить чуть памяти.
 
Сверху Снизу