Наконец руки дошли ко второй версии Админ-Бота и постарался учесть все пожелания. Нам потребуется Pawn.CMD, sscanf2
*Простота в использовании
*При отправке запроса, проверяется на наличие всех аргументов.
*Возможность отправлять до 8 запросов (опционально)
*Возможность открывать список запросов
*Возможность просматривать информацию о запросе/отклонить/принять прямо из списка
*При выходе админа, который отправил запрос или наказуемого - запрос автоматически удаляется
Автор: Я
Версия: 2.1.0
Скрины: https://imgur.com/a/mCd67KF
Админ-Бот v.1: https://pro-pawn.ru/showthread.php?1...0%BE%D1%82-v-1
GitHub: https://github.com/execution-lab/adminbot-include
Ко всем константам
PHP код:
#define MAX_PLAYER_LISTITEM 25 // Количество принимаемых listitem
#define MAX_ADMIN_BOT_REQUEST 3 // Максимальное количество принимаемых команд для запроса
#define MAX_ADMIN_BOT_REQUEST_LENGTH 8 // Максимальная длина команды для запроса
#define MAX_ADMIN_BOT_SUPPORT_COUNT 8 // Максимальное количество запросов
#define MIN_ADMIN_BOT_SUPPORT_COUNT 0 // Минимальное количество запросов
#define MAX_ADMIN_BOT_PUNISH_REASON 50 // Максимальная длина причины в запросе
#define MAX_ADMIN_BOT_PUNISN_NAME_LENGTH 24 // Максимальная длина названия вида наказания
#define ADMIN_BOT_INVALID_REQUEST_ID MAX_ADMIN_BOT_SUPPORT_COUNT + 1 // Недействительный ID запроса
#define ADMIN_BOT_HEX_COLOR 0xFF6347FF // Цвета сообщения админ-бота
enum // Константы ID диалогов
{
dAbot_reqinfo,
dAbot_reqmenu,
dAbot_reqlist
}
enum // Константы ошибок при проверке запроса
{
CA_REQUEST_NOT_FOUND,
CA_REQUEST_FOUND,
CA_NO_PLACE_IN_REQUEST,
CA_MISSING_ARGUMENT,
CA_INVALID_TARGET_ID
}
enum e_ADMIN_BOT_INFO
{
aBot_punish_type,
aBot_punish_time,
aBot_punish_reason[MAX_ADMIN_BOT_PUNISH_REASON + 1],
aBot_targetid,
aBot_adminid,
aBot_unix_time
}
Ко всем глобал. переменным
PHP код:
new
AdminBotInfo[MAX_ADMIN_BOT_SUPPORT_COUNT][e_ADMIN_BOT_INFO], // Информация запросов
PlayerListitem[MAX_PLAYERS][MAX_PLAYER_LISTITEM] // Хранение записанных значений
;
new
const ADMIN_BOT_PUNISH_NAME[MAX_ADMIN_BOT_REQUEST][MAX_ADMIN_BOT_PUNISN_NAME_LENGTH + 1] = // Название всех видов наказаний
{
"Заглушить",
"Посадить в админ. тюрьму",
"Посадить в тюрьму"
};
new
const ADMIN_BOT_SUPPORT_COMMAND[MAX_ADMIN_BOT_REQUEST][MAX_ADMIN_BOT_REQUEST_LENGTH] = // Название команд всех видов наказаний
{
"/mute",
"/prison",
"/jail"
};
new
const ADMIN_BOT_LEVEL_USING_CMD[MAX_ADMIN_BOT_REQUEST] = // Уровень возможности опирировать со всеми видами наказаний
{
3,
3,
3
};
new
gADMIN_BOT_SUPPORT_TOTAL_COUNT = 0, // Переменная записывающая количество запросов
pAdminChoseRequest[MAX_PLAYERS char] // Массив хранения ID выбранного запроса
;
Ко всем stock
PHP код:
/*
Функция:
ShowPlayerAdminBotRequestInfo
Аргументы:
playerid - ID игрока, которому показываем
Вернёт:
1 - Показан успешно
0 - Не удалось показать
Заметки:
Показываем информацию о запросе выбранного из списка.
*/
stock ShowPlayerAdminBotRequestInfo(playerid)
{
if(pAdminChoseRequest{playerid} == ADMIN_BOT_INVALID_REQUEST_ID)
return 0;
new
count = pAdminChoseRequest{playerid},
string[MAX_CHATBUBBLE_LEGNTH + 1]
;
format(string, sizeof string, "\n\
{C0F08E}Запросил: {FFFFFF}%s\n\
{ED8473}Наказать: {FFFFFF}%s\n\n\
Тип: %s\n\
Время: %d мин\n\
Причина: %s\n\n\n\
%s",
PlayerName(AdminBotInfo[count][aBot_adminid]),
PlayerName(AdminBotInfo[count][aBot_targetid]),
ADMIN_BOT_PUNISH_NAME[AdminBotInfo[count][aBot_punish_type]],
AdminBotInfo[count][aBot_punish_time],
AdminBotInfo[count][aBot_punish_reason],
ADMIN_BOT_LEVEL_USING_CMD[AdminBotInfo[count][aBot_punish_type]] > AdminLevel(playerid)
? ("{AFAFAF}Вы не можете принять запрос") : ("{E2BE1D}Вы можете принять запрос")
);
return ShowPlayerDialog(
playerid,
dAbot_reqinfo,
DIALOG_STYLE_MSGBOX,
!" ",
string,
!"Хорошо", !""
);
}
/*
Функция:
ShowPlayerAdminBotRequestMenu
Аргументы:
playerid - ID игрока, которому показываем
Вернёт:
1 - Показан успешно
0 - Не удалось показать
Заметки:
Показываем меню запроса из списка.
*/
stock ShowPlayerAdminBotRequestMenu(playerid)
{
if(pAdminChoseRequest{playerid} == ADMIN_BOT_INVALID_REQUEST_ID)
return 0;
return ShowPlayerDialog(
playerid,
dAbot_reqmenu,
DIALOG_STYLE_LIST,
PlayerName(AdminBotInfo[pAdminChoseRequest{playerid}][aBot_targetid]),
!"{C0F08E}Наказать\n{FFFFFF}Информация\nОтклонить",
!"Далее", !"Выход"
);
}
/*
Функция:
ShowPlayerAdminBotRequestList
Аргументы:
playerid - ID игрока, которому показываем
Вернёт:
1 - Показан успешно
Заметки:
Показываем весь список запросов.
*/
stock ShowPlayerAdminBotRequestList(playerid)
{
new
string[(4 + ((MAX_PLAYER_NAME + 1 - 2) * 2) + (- 2 + MAX_ADMIN_BOT_PUNISH_REASON) + (- 2 + MAX_ADMIN_BOT_PUNISN_NAME_LENGTH)
+ (- 2 + 4)) * MAX_ADMIN_BOT_SUPPORT_COUNT + 46] =
{
"Запросил\tДейсвтие(время)\tНаказать\tПричина\n"
},
count = 0
;
for(new iter = 0; iter < MAX_ADMIN_BOT_SUPPORT_COUNT; iter ++)
{
if(IsEmptyRequestInAdminBotList(iter))
continue;
format(string, sizeof string, "%s%s\t%s(%d мин)\t%s\t%s\n",
string,
PlayerName(AdminBotInfo[iter][aBot_adminid]),
ADMIN_BOT_PUNISH_NAME[AdminBotInfo[iter][aBot_punish_type]],
AdminBotInfo[iter][aBot_punish_time],
PlayerName(AdminBotInfo[iter][aBot_targetid]),
AdminBotInfo[iter][aBot_punish_reason]
);
PlayerListitem[playerid][count++] = iter;
}
return ShowPlayerDialog(
playerid,
dAbot_reqlist,
DIALOG_STYLE_TABLIST_HEADERS,
!"Запросы админ-боту",
string,
!"Далее", !""
);
}
/*
Функция:
GetLastRequestInAdminBot
Аргументы:
-
Вернёт:
Вернёт ID последнего запроса.
Вернёт -1, если спиоск запросов пуст.
Заметки:
Получить ID последнего добавленного запроса.
*/
stock GetLastRequestInAdminBot()
{
new
tmp_ = -1;
if(CountRequestInAdminBotList() == MIN_ADMIN_BOT_SUPPORT_COUNT)
return tmp_;
for(new iter = 0; iter < MAX_ADMIN_BOT_SUPPORT_COUNT; iter ++)
{
if(IsEmptyRequestInAdminBotList(iter))
continue;
if((tmp_ == -1) || (tmp_ != -1 && AdminBotInfo[iter][aBot_unix_time] > AdminBotInfo[tmp_][aBot_unix_time]))
{
tmp_ = iter;
}
}
return tmp_;
}
/*
Функция:
CountRequestInAdminBotList
Аргументы:
-
Вернёт:
Число созданных запросов.
Заметки:
-
*/
stock CountRequestInAdminBotList()
{
return gADMIN_BOT_SUPPORT_TOTAL_COUNT;
}
/*
Функция:
CheckAvailabilityInAdminBot
Аргументы:
playerid - ID игрока, подающий запрос
parmas[] - Массив с хранением запроса
Вернёт:
CA_REQUEST_NOT_FOUND - Запрос не найден
CA_REQUEST_FOUND - Запрос создан/найден
CA_NO_PLACE_IN_REQUEST - Лист с запросами переполнен
CA_MISSING_ARGUMENT - Указаны не все аргументы
CA_INVALID_TARGET_ID - Наказуемый не в сети
Заметки:
Проверяем наличие элементов запроса.
*/
stock CheckAvailabilityInAdminBot(playerid, params[])
{
new
bool:IsFinedCommand = false,
strFindPos,
supportCommand[MAX_ADMIN_BOT_REQUEST_LENGTH + 1],
supportTargetid,
supportTime,
supportReason[MAX_ADMIN_BOT_PUNISH_REASON + 1],
supportUnixtTime = gettime(),
string[MAX_CHATBUBBLE_LENGTH + 1]
;
for(new i = 0; i < MAX_ADMIN_BOT_REQUEST; ++i)
{
if((strFindPos = strfind(params, ADMIN_BOT_SUPPORT_COMMAND[i], true)) != -1)
{
if(CountRequestInAdminBotList() >= MAX_ADMIN_BOT_SUPPORT_COUNT)
return CA_NO_PLACE_IN_REQUEST;
strdel(params, 0, strFindPos);
if(sscanf(params, "s[8]uds[50]",
supportCommand, supportTargetid, supportTime, supportReason))
return CA_MISSING_ARGUMENT;
if(supportTargetid == INVALID_PLAYER_ID)
return CA_INVALID_TARGET_ID;
for(new j = 0; j < MAX_ADMIN_BOT_SUPPORT_COUNT; j ++)
{
if(!IsEmptyRequestInAdminBotList(j))
continue;
format(string, sizeof string, "[ADMIN-BOT] {FFFFFF}%s запросил %s игрока %s на %d мин, причина: %s",
PlayerName(playerid),
ADMIN_BOT_PUNISH_NAME[i],
PlayerName(supportTargetid),
supportTime,
supportReason
);
SendAdminMessage(ADMIN_BOT_HEX_COLOR, string);
SendAdminMessage(ADMIN_BOT_HEX_COLOR, !"Нажмите Y для одобрения, N для отказа. (/viewreq для просмотра всех запросов)");
SetRequestInAdminBotList(
j,
i,
supportTime,
playerid,
supportTargetid,
supportUnixtTime,
supportReason
);
IsFinedCommand = true;
break;
}
break;
}
}
return (IsFinedCommand ? CA_REQUEST_FOUND : CA_REQUEST_NOT_FOUND);
}
/*
Функция:
RejectRequestInAdminBotList
Аргументы:
playerid - ID игрока, отклоняющий запрос
index - ID запроса
Вернёт:
-
Заметки:
Отклоняем запрос.
*/
stock RejectRequestInAdminBotList(playerid, index)
{
new
string[MAX_CHATBUBBLE_LENGTH + 1];
format(string, sizeof string, "[ADMIN-BOT] {FFFFFF}%s отклонил запрос №%d",
PlayerName(playerid), index + 1);
SendAdminMessage(ADMIN_BOT_HEX_COLOR, string);
format(string, sizeof string, "(Отправитель: %s | Просьба: %s | Наказуемый: %s | Причина: %s)",
PlayerName(AdminBotInfo[index][aBot_targetid]),
ADMIN_BOT_PUNISH_NAME[AdminBotInfo[index][aBot_punish_type]],
PlayerName(AdminBotInfo[index][aBot_adminid]),
AdminBotInfo[index][aBot_punish_reason]
);
SendAdminMessage(ADMIN_BOT_HEX_COLOR, string);
DeleteRequestInAdminBotList(index);
}
/*
Функция:
ApproveRequestInAdminBotList
Аргументы:
playerid - ID игрока, принимающий запрос
index - ID запроса
Вернёт:
-
Заметки:
Принимаем запрос.
*/
stock ApproveRequestInAdminBotList(playerid, index)
{
new
string[MAX_CHATBUBBLE_LENGTH + 1];
format(string, MAX_CHATBUBBLE_LENGTH + 1, "%s %d %d %s // %s",
ADMIN_BOT_SUPPORT_COMMAND[AdminBotInfo[index][aBot_punish_type]],
AdminBotInfo[index][aBot_targetid],
AdminBotInfo[index][aBot_punish_time],
AdminBotInfo[index][aBot_punish_reason],
PlayerName(AdminBotInfo[index][aBot_adminid])
);
PC_EmulateCommand(playerid, string);
DeleteRequestInAdminBotList(index);
}
/*
Функция:
IsEmptyRequestInAdminBotList
Аргументы:
index - ID запроса
Вернёт:
1 - Запрос пустой
0 - Запрос не пустой
Заметки:
Смотрим, пустой ли запрос.
*/
stock IsEmptyRequestInAdminBotList(index)
{
return ((AdminBotInfo[index][aBot_punish_reason][0] == '\0') ? (1) : (0));
}
/*
Функция:
DeleteRequestInAdminBotList
Аргументы:
index - ID запроса
Вернёт:
1 - Запрос успешно удалён
0 - Запрос не был удалён
Заметки:
Удаляем запрос из списка.
*/
stock DeleteRequestInAdminBotList(index)
{
if(!IsEmptyRequestInAdminBotList(index))
{
AdminBotInfo[index][aBot_targetid] = INVALID_PLAYER_ID;
AdminBotInfo[index][aBot_punish_reason][0] = '\0';
gADMIN_BOT_SUPPORT_TOTAL_COUNT --;
return 1;
}
else
{
return 0;
}
}
/*
Функция:
SetRequestInAdminBotList
Аргументы:
index - ID запроса
type - Тип запроса (заглушка и т.п.)
&time - Время в минутах
&adminid - ID админа, оставившего запрос
&targetid - ID наказуемого
&unix_time - Unix время на момент добавления запроса
reason[] - Причина наказания
size - Размер массива с причиной (по-умолчании установлен)
Вернёт:
-
Заметки:
Добавляем запрос в список
*/
stock SetRequestInAdminBotList(index, type, &time, &adminid, &targetid, &unix_time, reason[], const size = sizeof reason)
{
AdminBotInfo[index][aBot_punish_type] = type;
AdminBotInfo[index][aBot_punish_time] = time;
strmid(
AdminBotInfo[index][aBot_punish_reason],
reason,
0,
MAX_ADMIN_BOT_PUNISH_REASON,
size
);
AdminBotInfo[index][aBot_targetid] = targetid;
AdminBotInfo[index][aBot_adminid] = adminid;
AdminBotInfo[index][aBot_unix_time] = unix_time;
gADMIN_BOT_SUPPORT_TOTAL_COUNT ++;
}
Ко всем командам
PHP код:
CMD:viewreq(playerid) // Для просмотра всех запросов
{
if(!AdminLevel(playerid))
return 1;
if(CountRequestInAdminBotList() == MIN_ADMIN_BOT_SUPPORT_COUNT)
return SendClientMessage(playerid, -1, !"Список запросов пуст.");
ShowPlayerAdminBotRequestList(playerid)
return 1;
}
CMD:admin(playerid, params[]) // Админ-чат
{
if(AdminLevel(playerid))
{
if(!(0 < strlen(params) < 90))
return SendClientMessage(playerid, -1, !"Используйте больше 1 символа и меньше 90");
new
string[128];
format(string, sizeof(string), "[A] %s [%d]: %s", PlayerName(playerid), playerid, params);
SendAdminMessage(-1, string);
new
ret = CheckAvailabilityInAdminBot(playerid, params),
retrunMessage[][] =
{
!"Не удалось найти элементов запросов",
!"Запрос успешно найден и зарегистрирован",
!"К сожалению лист с запросами переполнен.",
!"Указаны не все аргументы. (Например: /mute (Id/Nick) (Time) (Reason)",
!"Данного игрока нет на сервере."
}
;
SendClientMessage(playerid, -1, retrunMessage[ret]);
}
return 1;
}
alias:admin("a");
OnDialogResponse
PHP код:
case dAbot_reqinfo:
{
return ShowPlayerAdminBotRequestMenu(playerid);
}
case dAbot_reqmenu:
{
if(!response)
{
pAdminChoseRequest{playerid} = ADMIN_BOT_INVALID_REQUEST_ID;
return 1;
}
if(IsEmptyRequestInAdminBotList(pAdminChoseRequest{playerid}))
return SendClientMessage(playerid, -1, !"Данный запрос был удалён");
new
count = pAdminChoseRequest{playerid};
switch(listitem)
{
case 0:
{
if(ADMIN_BOT_LEVEL_USING_CMD[AdminBotInfo[count][aBot_punish_type]] > AdminLevel(playerid))
{
pAdminChoseRequest{playerid} = ADMIN_BOT_INVALID_REQUEST_ID;
return SendClientMessage(playerid, -1, !"Вы неуполномочены принимать данный запрос.");
}
pAdminChoseRequest{playerid} = ADMIN_BOT_INVALID_REQUEST_ID;
ApproveRequestInAdminBotList(playerid, count);
return 1;
}
case 1:
{
return ShowPlayerAdminBotRequestInfo(playerid);
}
case 2:
{
if((AdminBotInfo[count][aBot_adminid] != playerid)
&& (ADMIN_BOT_LEVEL_USING_CMD[AdminBotInfo[count][aBot_punish_type]] > AdminLevel(playerid)))
{
pAdminChoseRequest{playerid} = ADMIN_BOT_INVALID_REQUEST_ID;
return SendClientMessage(playerid, -1, !"Вы не уполномочены отклонять данный запрос");
}
pAdminChoseRequest{playerid} = ADMIN_BOT_INVALID_REQUEST_ID;
RejectRequestInAdminBotList(playerid, count);
return 1;
}
}
return 1;
}
case dAbot_reqlist:
{
if(!response)
return 1;
new
count = PlayerListitem[playerid][listitem];
if(IsEmptyRequestInAdminBotList(count))
{
SendClientMessage(playerid, -1, !"Данный запрос был удалён");
return ShowPlayerAdminBotRequestList(playerid);
}
pAdminChoseRequest{playerid} = count;
return ShowPlayerAdminBotRequestMenu(playerid);
}
OnPlayerConnect
PHP код:
pAdminChoseRequest{playerid} = ADMIN_BOT_INVALID_REQUEST_ID;
OnPlayerDisconnect
PHP код:
if(CountRequestInAdminBotList() != MIN_ADMIN_BOT_SUPPORT_COUNT) // Если список запрос не пуст
{
for(new iter = 0; iter < MAX_ADMIN_BOT_SUPPORT_COUNT; iter ++) // Перебираем все запросы
{
if(AdminBotInfo[iter][aBot_adminid] != playerid && AdminBotInfo[iter][aBot_targetid] != playerid) // Если ID игрока не равен админу, который запросил и наказуемого - пропускаем
continue;
DeleteRequestInAdminBotList(iter); // Удаляем запрос
}
}
OnPlayerKeyStateChange
PHP код:
if(newkeys & KEY_NO)
{
if(CountRequestInAdminBotList() != MIN_ADMIN_BOT_SUPPORT_COUNT)
{
if(AdminLevel(playerid))
{
new
iter = GetLastRequestInAdminBot();
if(iter != -1)
{
if(ADMIN_BOT_LEVEL_USING_CMD[AdminBotInfo[iter][aBot_punish_type]] > AdminLevel(playerid))
{
SendClientMessage(playerid, -1, !"Малый уровень администрирования для отказа.");
return 1;
}
RejectRequestInAdminBotList(playerid, iter);
return 1;
}
}
}
}
if(newkeys & KEY_YES)
{
if(CountRequestInAdminBotList() != MIN_ADMIN_BOT_SUPPORT_COUNT)
{
if(AdminLevel(playerid))
{
new
iter = GetLastRequestInAdminBot();
if(iter != -1)
{
if(ADMIN_BOT_LEVEL_USING_CMD[AdminBotInfo[iter][aBot_punish_type]] > AdminLevel(playerid))
{
SendClientMessage(playerid, -1, !"Малый уровень администрирования для принятия.");
return 1;
}
ApproveRequestInAdminBotList(playerid, iter);
}
}
}
}
Заменяемые под себя функции / макросы
SendAdminMessage
В
начало мода или ко всем итераторам
PHP код:
new
Iterator:Connect_Admin<MAX_PLAYERS>; // Итератор , где будем хранить всех администраторов
При добавлении/заходе администратора
PHP код:
if(!Iter_Contains(Connect_Admin, /*админ*/)) Iter_Add(Connect_Admin, /*админ*/);
При выходе/снятии администратора
PHP код:
if(Iter_Contains(Connect_Admin, /*админ*/)) Iter_Remove(Connect_Admin, /*админ*/);
Сток для отправки сообщения администраторам
PHP код:
stock SendAdminMessage(color, const string[])
{
foreach(new i : Connect_Admin)
{
SendClientMessage(i, color, string);
}
return 1;
}
Макросы
PHP код:
#define PlayerName(%0) /*Массив с хранением имени игрока*/
#define AdminLevel(%0) /*Массив с хранением админ-уровня*/