Добавление игроков в меню по алфавиту

Kruzya

Участник
Сообщения
12,970
Реакции
10,914
  • Команда форума
  • #1
Может, кому пригодится. Для себя понадобилось написать функцию добавления игроков в меню по Алфавиту с поддержкой commandflags и иммунитета.
Если можно как-то получше сделать - готов выслушать Ваши варианты реализации.
PHP:
/**
 * Добавить игроков в указанное меню по алфавиту с выбранной сортировкой.
 *
 * Добавляет игроков, подходящие под иммунитет игрока и под флаги, в указанное Вами
 * меню, с указанной сортировкой (А-Я, Я-А).
 *
 * @param hMenu             Указатель на меню.
 * @param iSourceClient     Игрок, на чей иммунитет надо опираться при выборе игроков.
 *                                      Передавайте 0, если иммунитет игрока не важен.
 * @param iFlags            Флаги из commandfilters.inc.
 * @param iSortOrderType    Тип сортировки.
 *                          <https://sm.alliedmods.net/new-api/sorting/SortOrder>
 *
 * @return                  Кол-во игроков, добавленных в меню.
 */

stock int AddTargetsToMenuByAlphabet(Menu hMenu, int iSourceClient = 0, int iFlags = 0, SortOrder iSortOrderType = Sort_Ascending) {
    int[] iTargets = new int[MaxClients];
    int iCurrentTarget = 0;

    for (int iTarget = 1; iTarget <= MaxClients; iTarget++) {
        if (!IsClientConnected(iTarget))
            continue;

        if (iFlags & COMMAND_FILTER_CONNECTED && !IsClientInGame(iTarget))
            continue;
        if (iFlags & COMMAND_FILTER_ALIVE && !IsPlayerAlive(iTarget))
            continue;
        if (iFlags & COMMAND_FILTER_DEAD && IsPlayerAlive(iTarget))
            continue;
        if (iFlags & COMMAND_FILTER_NO_BOTS && (IsFakeClient(iTarget) || IsClientSourceTV(iTarget) || IsClientReplay(iTarget)))
            continue;
        if (!CanUserTarget(iSourceClient, iTarget))
            continue;

        iTargets[iCurrentTarget] = iTarget;
        iCurrentTarget++;
    }

    if (!iCurrentTarget)
        return 0;

    int iStringSize = MAX_TARGET_LENGTH+5;
    char[][] szClients = new char[iCurrentTarget][iStringSize];

    for (int iTarget = 0; iTarget < iCurrentTarget; iTarget++) {
        FormatEx(szClients[iTarget], iStringSize-1, "%N\x01%d", iTargets[iTarget], GetClientUserId(iTargets[iTarget]));
    }

    SortStrings(szClients, iCurrentTarget, iSortOrderType);

    int iPos, iTemp;
    char szUserID[5];
    for (int iTarget = 0; iTarget < iCurrentTarget; iTarget++) {
        iPos = FindCharInString(szClients[iTarget], '\x01', true);
        szClients[iTarget][iPos] = 0;

        iTemp = 0;
        while (iTemp > -1) {
            szUserID[iTemp] = szClients[iTarget][iPos+iTemp+1];
            if (!szUserID[iTemp])
                break;
            iTemp++;
        }
        hMenu.AddItem(szUserID, szClients[iTarget]);
    }

    return iCurrentTarget;
}

Пример использования:
PHP:
Menu hMenu = new Menu(SomethingMenuHandler);
AddTargetsToMenuByAlphabet(hMenu, 0, COMMAND_FILTER_NO_BOTS | COMMAND_FILTER_CONNECTED, Sort_Ascending);
hMenu.Display(iClient, 0);

Для тестирования ф-ии, я написал для себя небольшой плагин, который выводит игроков на сервере по алфавиту.
Sort_Descending:
irWogDN.png


Sort_Ascending:
BSA4JXp.png

P.S.: Если Вы используете фильтр COMMAND_FILTER_ALIVE, то не забывайте так же добавлять фильтр COMMAND_FILTER_CONNECTED, иначе возможна ошибка при работе функции.
 
Последнее редактирование:

Vit_ amin

Добрая душа
Сообщения
1,504
Реакции
660
@R1KO, Почему лучше ?
PHP:
int[] iTargets = new int[MaxClients]

P.S. А разве не надо делать delete, если дается место под массив через new или я путаю с динамическими массивами в C++ (голова уже не варит)?
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #4
@Vit_ amin, это не объекты создает, а просто динамический массив. это ж не c++
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
Может, наоборот - COMMAND_FILTER_NOCONNECTED? Оффтоп Так как все прочие проверки так или иначе требуют этого и выдадут ошибку.
Вы конечно можете сказать, что ботам это не обязательно, но когда вы выдели бота "не в игре"? Их полное подключение занимает доли секунды.
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
Функция GetClientName()
Этого не переносит.
FormatEx(szClients[iTarget], iStringSize-1, "%N\x01%d", iTargets[iTarget]
Тут тоже сомнения, надо в исходник FormatEx заглядывать или тест провести, разрешает ли он получать имя игрока с его индекса, когда "преобразуемый" ещё на стадии подключения.
Так что, в любом случае, P.S. напиши хотя бы на этот счёт для малоопытных.
 
Сверху Снизу