BLOG Mini-Blog by Javekson

Сообщения
2,143
Реакции
1,225
Помог
44 раз(а)
roten, нет. Это вообще не относится к выдаче флагов. Это для загрузки файла.
 
Сообщения
2,143
Реакции
1,225
Помог
44 раз(а)
roten, не смотрел код, ни первого, ни второго. Так что, ничего сказать по этому поводу не могу.
 
Сообщения
1,306
Реакции
2,309
Помог
57 раз(а)
roten, разница в типе хранения информации. Здесь файл, там nvault-хранилище. Плюс, vip_manager не учитывает сброс флагов при смене ника. Javekson делал его под свои нужды, и он многим не подойдёт. Мой же плагин относительно универсален.
 
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
roten, что бы изменить флаг, достаточно изменить 6 строку на const VIP_FLAG = ADMIN_LEVEL_H
 
Сообщения
143
Реакции
68
Помог
1 раз(а)
Javekson, хотел уточнить еще момент, по поводу самых данных. Через которое время они удаляться, Год, пол года, есть ли возможность самому задать когда очищать данные?
 
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
roten, не удаляются, это сделано для того, что бы игрок не смог повторно активировать привилегии, но в планах я это сделаю, попозже.
 
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
Решил немного оптимизировать плагины Know Players и Admin Access, убрав из них все возможные циклы.

Так-как количество записей users.ini у меня свыше 60, будет целесообразней использовать динамический массиве в связке с ассоциативным массивом, тем самым убрав в коде все циклы, обращение к записи будет происходить напрямую (конечно под нативами скрываются различные find'ы, но это будет работать быстрее, я так думаю).

Теперь в Know Players нету необходимость отдельно считывать файл с юзерами для дальнейшей работы, благодаря предоставляемому API Admin Access'а. За помощь в реализации, обучении работы с нативами отдельная благодарность BlackSignature

Admin Access
  • Оптимизирован/изменен алгоритм выдачи прав
  • Убраны все возможные циклы в коде
  • Предоставлен API для и информации об игроке
Пример для оформления файла users.ini
2018-04-05_120020.jpg

C++:
#include <amxmodx>

#pragma semicolon 1

new const USER_INFO_KEY[] =        "_gmf";        // Ключ при вводе пароля. setinfo "_gmf" "Пароль"

const PATH_STRLEN = 64;
const TEXT_STRLEN = 256;
const AUTHID_STRLEN = 24;
const PASSWORD_STRLEN = 32;
const ACCESS_STRLEN = 24;
const DATE_END_STRLEN = 32;
const PLAYER_NAME_STRLEN = 32;
const FULL_NAME_STRLEN = 64;
const CONTACTS_STRLEN = 32;
const MESSAGE_STRLEN = 256;
const TIME_STRLEN = 32;

enum _:ADMIN_DATA {
    Admin_sAuthID[AUTHID_STRLEN],
    Admin_sPassword[PASSWORD_STRLEN],
    Admin_sAccess[ACCESS_STRLEN],
    Admin_sDateEnd[DATE_END_STRLEN],
    Admin_sFullName[FULL_NAME_STRLEN],
    Admin_sContacts[CONTACTS_STRLEN]
}

new Array:g_aAdmins;
new Trie:g_tAdminsIndexes;
new g_eAdmins[ADMIN_DATA];

new g_sConfigsDir[PATH_STRLEN];
new g_sLogsDir[PATH_STRLEN];
new g_sUsersFile[PATH_STRLEN + 32];

public plugin_natives() {
    register_native("api_admin_info", "API_Admin_Info", false);
}

public plugin_init() {
    register_plugin("Admin Access", "2.0", "Javekson");
    register_srvcmd("reloadadmins", "SrvCmdReloadAdmins");
}

public plugin_cfg() {
    get_localinfo("amxx_logs", g_sLogsDir, charsmax(g_sLogsDir));
    add(g_sLogsDir, charsmax(g_sLogsDir), "/admins_statistic");
    if(!dir_exists(g_sLogsDir)) mkdir(g_sLogsDir);
  
    get_localinfo("amxx_configsdir", g_sConfigsDir, charsmax(g_sConfigsDir));
    formatex(g_sUsersFile, charsmax(g_sUsersFile), "%s/users.ini", g_sConfigsDir);
  
    g_aAdmins = ArrayCreate(ADMIN_DATA);
    g_tAdminsIndexes = TrieCreate();
  
    ReadUsersFile();
}

public client_putinserver(id) {
    SetAdminAccess(id);
}

public plugin_end() {
    ArrayDestroy(g_aAdmins);
    TrieDestroy(g_tAdminsIndexes);
}

ReadUsersFile() {
    if(!file_exists(g_sUsersFile))
        return PLUGIN_CONTINUE;
  
    new iAdminIndex;
    new iFileID = fopen(g_sUsersFile, "rt");
    new sText[TEXT_STRLEN],\
        sAuthID[AUTHID_STRLEN],\
        sPassword[PASSWORD_STRLEN],\
        sAccess[ACCESS_STRLEN],\
        sDateEnd[DATE_END_STRLEN],\
        sFullName[FULL_NAME_STRLEN],\
        sContacts[CONTACTS_STRLEN];
  
    while(!feof(iFileID)) {
        fgets(iFileID, sText, charsmax(sText)); trim(sText);
        if(!sText[0] || sText[0] == ';') continue;
      
        parse(sText,\
            sAuthID, charsmax(sAuthID),\
            sPassword, charsmax(sPassword),\
            sAccess, charsmax(sAccess),\
            sDateEnd, charsmax(sDateEnd),\
            sFullName, charsmax(sFullName),\
            sContacts, charsmax(sContacts)\
        );
      
        if(sDateEnd[0]) {
            if(parse_time(sDateEnd, "%d.%m.%Y") < get_systime())
                continue;
        } else
            formatex(sDateEnd, charsmax(sDateEnd), "Неограничено");
      
        g_eAdmins[Admin_sAuthID] = sAuthID;
        g_eAdmins[Admin_sPassword] = sPassword;
        g_eAdmins[Admin_sAccess] = sAccess;
        g_eAdmins[Admin_sDateEnd] = sDateEnd;
        g_eAdmins[Admin_sFullName] = sFullName;
        g_eAdmins[Admin_sContacts] = sContacts;
      
        ArrayPushArray(g_aAdmins, g_eAdmins);
        TrieSetCell(g_tAdminsIndexes, sAuthID, iAdminIndex++);
    }
    fclose(iFileID);
    return PLUGIN_CONTINUE;
}

SetAdminAccess(const id) {
    remove_user_flags(id);
  
    new sAuthID[AUTHID_STRLEN], iAdminIndex;
    get_user_authid(id, sAuthID, charsmax(sAuthID));
    if(TrieKeyExists(g_tAdminsIndexes, sAuthID)) {
        TrieGetCell(g_tAdminsIndexes, sAuthID, iAdminIndex);
        ArrayGetArray(g_aAdmins, iAdminIndex, g_eAdmins);
        new sPassword[PASSWORD_STRLEN];
        get_user_info(id, USER_INFO_KEY, sPassword, charsmax(sPassword));
        if(equal(sPassword, g_eAdmins[Admin_sPassword])) {
            new sPlayerName[PLAYER_NAME_STRLEN];
            get_user_name(id, sPlayerName, charsmax(sPlayerName));
            set_user_flags(id, read_flags(g_eAdmins[Admin_sAccess]));
            logging(g_sLogsDir, "admins_connection_", "^"%s^" ^"%s^" ^"%s^"", sAuthID, sPlayerName, g_eAdmins[Admin_sAccess]);
        } else
            server_cmd("kick #%d ^"%s^"", get_user_userid(id), "Указан неверный пароль");
    } else
        set_user_flags(id, ADMIN_USER);
}

public SrvCmdReloadAdmins() {
    ArrayClear(g_aAdmins);
    TrieClear(g_tAdminsIndexes);
    ReadUsersFile();
  
    new aPlayersID[MAX_PLAYERS], iPlayersNum;
    get_players(aPlayersID, iPlayersNum, "ch");
    for(new i; i < iPlayersNum; i++)
        SetAdminAccess(aPlayersID[i]);
  
    server_print("administrators reloaded");
}

public API_Admin_Info() {
    new iAdminIndex, sAuthID[AUTHID_STRLEN];
    get_string(1, sAuthID, charsmax(sAuthID));
    if(TrieKeyExists(g_tAdminsIndexes, sAuthID)) {
        TrieGetCell(g_tAdminsIndexes, sAuthID, iAdminIndex);
        ArrayGetArray(g_aAdmins, iAdminIndex, g_eAdmins);
        set_string(2, g_eAdmins[Admin_sDateEnd], charsmax(g_eAdmins[Admin_sDateEnd]));
        set_string(3, g_eAdmins[Admin_sFullName], charsmax(g_eAdmins[Admin_sFullName]));
        set_string(4, g_eAdmins[Admin_sContacts], charsmax(g_eAdmins[Admin_sContacts]));
        return true;
    }
    return false;
}

stock logging(const sLogsDir[], const sFileName[], const sMessage[], any:...) {
    new iFileID, sLogFile[PATH_STRLEN + 32], sFormatMsg[MESSAGE_STRLEN], sTime[TIME_STRLEN];
    vformat(sFormatMsg, charsmax(sFormatMsg), sMessage, 4);
    get_time("%m.%Y.log", sTime, charsmax(sTime));
    formatex(sLogFile, charsmax(sLogFile), "%s/%s%s", sLogsDir, sFileName, sTime);
    iFileID = fopen(sLogFile, "at");
    get_time("%d.%m.%Y - %H:%M:%S", sTime, charsmax(sTime));
    fprintf(iFileID, "^"%s^" %s^n", sTime, sFormatMsg);
    fclose(iFileID);
}

Know Players
  • Убрано собственное считывание/parse файла с пользователями
  • Убраны все возможные циклы в коде
  • Информацию об игроке получаем через API
  • Добавлен предварительный API для вызова меню игроков без использование команды в чате(API для Callfunc'а)
C++:
#include <amxmodx>
#include <reapi>

#pragma semicolon 1

const KNOW_FLAG =    ADMIN_IMMUNITY;                                // Флаги для отображения игроков в меню распознования
const ADMIN_FLAG =    ADMIN_BAN|ADMIN_RCON;                        // Флаги администраторов
const VIP_FLAG =    ADMIN_LEVEL_A|ADMIN_LEVEL_B|ADMIN_LEVEL_C;    // Флаги привилегированных игроков

const TIME_MENU = NULLENT;
const MENU_KEYS = MENU_KEY_0|MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_5|MENU_KEY_6|MENU_KEY_7|MENU_KEY_8|MENU_KEY_9;

const MENU_STRLEN = 512;
const PLAYER_NAME_STRLEN = 32;
const AUTHID_STRLEN = 24;
const DATE_END_STRLEN = 32;
const FULL_NAME_STRLEN = 64;
const CONTACTS_STRLEN = 32;

const ITEMS_PER_PAGE_MENU = 8;

new const MENU_TAB[] = "^t^t^t^t";

new g_iMenuPositions[MAX_PLAYERS + 1];
new g_aPlayersID[MAX_PLAYERS + 1][MAX_PLAYERS];
new g_aPlayersUserID[MAX_PLAYERS + 1][MAX_PLAYERS + 1];

native api_admin_info(sAuthID[], sDateEnd[], sFullName[], sContacts[]);

public plugin_init() {
    register_plugin("Know Players", "2.0", "Javekson");
    register_clcmd("say /know", "ClCmdKnowPlayers");
    register_menucmd(register_menuid("_know_players_menu"), MENU_KEYS, "HandleKnowPlayersMenu");
}

public FuncKnowPlayersMenu(const id) {
    ShowKnowPlayersMenu(id, g_iMenuPositions[id] = 0);
}

public ClCmdKnowPlayers(const id) {
    if(get_user_flags(id) & ADMIN_FLAG) {
        ShowKnowPlayersMenu(id, g_iMenuPositions[id] = 0);
        return PLUGIN_CONTINUE;
    }
    client_print_color(id, print_team_default, "^4* ^1У Вас недостаточно прав для использования этой команды");
    rg_send_audio(id, "events/friend_died.wav");
    return PLUGIN_CONTINUE;
}

ShowKnowPlayersMenu(const id, iMenuPos) {
    if(iMenuPos < 0) return PLUGIN_CONTINUE;
  
    new sMenu[MENU_STRLEN], iLenMenu, iPagesNum, iItemMenu,\
        aPlayersID[MAX_PLAYERS], iPlayerID, iPlayersNum, sPlayerName[PLAYER_NAME_STRLEN], bsPlayerFlags,\
        iCountKnow, iStart, iEnd, bsKeys = MENU_KEY_0;
      
    get_players(aPlayersID, iPlayersNum, "ch");
    for(new i, j; i < iPlayersNum; i++) {
        if(get_user_flags(aPlayersID[i]) & KNOW_FLAG) {
            g_aPlayersID[id][j++] = aPlayersID[i];
            g_aPlayersUserID[id][aPlayersID[i]] = get_user_userid(aPlayersID[i]);
            iCountKnow++;
        }
    }
    iPlayersNum = iCountKnow;
  
    if((iStart = iMenuPos * ITEMS_PER_PAGE_MENU) >= iPlayersNum)
        iStart = iMenuPos = g_iMenuPositions[id] = 0;
  
    if((iEnd = iStart + ITEMS_PER_PAGE_MENU) > iPlayersNum)
        iEnd = iPlayersNum;
  
    if((iPagesNum = iPlayersNum / ITEMS_PER_PAGE_MENU + (iPlayersNum % ITEMS_PER_PAGE_MENU ? 1 : 0)) <= 1)
        iLenMenu = formatex(sMenu, charsmax(sMenu), "%s\yМеню распознования^n^n", MENU_TAB);
    else
        iLenMenu = formatex(sMenu, charsmax(sMenu), "%s\yМеню распознования \d(%d/%d)^n^n", MENU_TAB, iMenuPos + 1, iPagesNum);
  
    while(iStart < iEnd) {
        iPlayerID = g_aPlayersID[id][iStart++];
        get_user_name(iPlayerID, sPlayerName, charsmax(sPlayerName));
        bsPlayerFlags = get_user_flags(iPlayerID);
      
        if(bsPlayerFlags & ADMIN_FLAG) {
            bsKeys |= (1<<iItemMenu);
            iLenMenu += formatex(sMenu[iLenMenu], charsmax(sMenu) - iLenMenu, "%s\y%d. \w%s%s^n", MENU_TAB, ++iItemMenu, sPlayerName, bsPlayerFlags & VIP_FLAG ? " \d|\radm\d|\rvip" : " \d|\radm");
        } else {
            bsKeys |= (1<<iItemMenu);
            iLenMenu += formatex(sMenu[iLenMenu], charsmax(sMenu) - iLenMenu, "%s\y%d. \w%s%s^n", MENU_TAB, ++iItemMenu, sPlayerName, bsPlayerFlags & VIP_FLAG ? " \d|\rvip" : " \d|\r*");
        }
    }
    if(iEnd < iPlayersNum) {
        bsKeys |= MENU_KEY_9;
        formatex(sMenu[iLenMenu], charsmax(sMenu) - iLenMenu, "^n%s\y9. \wДалее^n%s\y0. \w%s", MENU_TAB, MENU_TAB, iMenuPos ? "Назад" : "Выход");
    } else
        formatex(sMenu[iLenMenu], charsmax(sMenu) - iLenMenu, "^n%s\y0. \w%s", MENU_TAB, iMenuPos ? "Назад" : "Выход");
  
    show_menu(id, bsKeys, sMenu, TIME_MENU, "_know_players_menu");
    return PLUGIN_CONTINUE;
}

public HandleKnowPlayersMenu(const id, const iKey) {
    switch(iKey) {
        case 8: ShowKnowPlayersMenu(id, ++g_iMenuPositions[id]);
        case 9: ShowKnowPlayersMenu(id, --g_iMenuPositions[id]);
        default: {
            new iPlayerIDTarget = g_aPlayersID[id][g_iMenuPositions[id] * ITEMS_PER_PAGE_MENU + iKey];
            if(IsValidPlayer(id, iPlayerIDTarget)) {
                new sAuthID[AUTHID_STRLEN], sDateEnd[DATE_END_STRLEN], sFullName[FULL_NAME_STRLEN], sContacts[CONTACTS_STRLEN];
                get_user_authid(iPlayerIDTarget, sAuthID, charsmax(sAuthID));
                if(api_admin_info(sAuthID, sDateEnd, sFullName, sContacts)) {
                    client_print_color(id, print_team_default, "^4* ^1ФИО: %s; Контакты: %s", sFullName, sContacts);
                    client_print_color(id, print_team_default, "^4* ^1Дата окончания срока действия полномочий/привилегий: %s", sDateEnd);
                    rg_send_audio(id, "events/tutor_msg.wav");
                    return PLUGIN_CONTINUE;
                }
                client_print_color(id, print_team_default, "^4* ^1Распознать игрока не удалось, возможно имеет привилегии по акции");
                rg_send_audio(id, "events/tutor_msg.wav");
            }
        }
    }
    return PLUGIN_HANDLED;
}

stock IsValidPlayer(const id, const iPlayerIDTarget) {
    if(get_user_userid(iPlayerIDTarget) == g_aPlayersUserID[id][iPlayerIDTarget]) return true;
    client_print_color(id, print_team_default, "^4* ^1Выбранный Вами игрок отключился от сервера");
    rg_send_audio(id, "events/friend_died.wav");
    return false;
}
 

Download all Attachments

Последнее редактирование:
Сообщения
8
Реакции
19
Javekson, можно мне тоже оптимизированную версию, только поправить немного Know Players? :smile3:
 
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
VIP Manager

Тем времени решил тоже обновить и перевести VIP Manager на работу с Nvault системой.
Как ранее говорилось, файл может достигать сотни записей, поэтому целесообразней в данном случае использования данной системы, дабы убрать возможные циклы и parse файла каждую смену карта.
  • Оптимизирован/изменен алгоритм, теперь работает с Nvault системой
  • Убраны все возможные pars'ы/циклы в коде
  • Удаление записи об игроке, незаходящего на сервер свыше 7 дней
  • Добавлено логирование для удобства просмотра получивших привилегию
C++:
#include <amxmodx>
#include <nvault>
#include <reapi>

#pragma semicolon 1

const NUMBER_DAYS_ACTIONS = 30;                                                    // Количество дней бесплатного действия VIP-привилегий
const NUMBER_DAYS_INACTIVITY = 7;                                                // Через сколько дней удалять игрока, незаходящего на сервер
const SECONDS_IN_DAY = 86400;                                                    // Количество секунд в одном дне
const VIP_FLAG = ADMIN_IMMUNITY|ADMIN_LEVEL_A|ADMIN_LEVEL_B|ADMIN_LEVEL_C;        // Флаги привилегированных игроков

const PATH_STRLEN = 64;
const AUTHID_STRLEN = 24;
const PLAYER_NAME_STRLEN = 32;
const DATE_END_STRLEN = 15;
const MESSAGE_STRLEN = 256;
const TIME_STRLEN = 32;

new g_iVaultID;
new g_sLogsDir[PATH_STRLEN];

public plugin_init() {
    register_plugin("VIP Manager", "2.0", "Javekson");
    register_clcmd("say /vip", "ClCmdSetPrivileges");
}

public plugin_cfg() {
    get_localinfo("amxx_logs", g_sLogsDir, charsmax(g_sLogsDir));
    g_iVaultID = nvault_open("vip_players");
    nvault_prune(g_iVaultID, 0, get_systime() - (SECONDS_IN_DAY * NUMBER_DAYS_INACTIVITY));
}

public client_putinserver(id) {
    if(get_user_flags(id) & VIP_FLAG)
        return PLUGIN_CONTINUE;
    
    new iTimeStampEnd, sAuthID[AUTHID_STRLEN];
    get_user_authid(id, sAuthID, charsmax(sAuthID));
    if((iTimeStampEnd = nvault_get(g_iVaultID, sAuthID))) {
        nvault_touch(g_iVaultID, sAuthID);
        if(iTimeStampEnd + SECONDS_IN_DAY >= get_systime()) {
            remove_user_flags(id, ADMIN_USER);
            set_user_flags(id, VIP_FLAG);
        }
    }
    return PLUGIN_CONTINUE;
}

public plugin_end() {
    nvault_close(g_iVaultID);
}

public ClCmdSetPrivileges(const id) {
    new iTimeStampEnd, sAuthID[AUTHID_STRLEN], sDateEnd[DATE_END_STRLEN];
    get_user_authid(id, sAuthID, charsmax(sAuthID));
    if((iTimeStampEnd = nvault_get(g_iVaultID, sAuthID))) {
        if(iTimeStampEnd + SECONDS_IN_DAY < get_systime()) {
            client_print_color(id, print_team_default, "^4* ^1Срок действия VIP-привилегий уже истек");
            client_print_color(id, print_team_default, "^4* ^1Для покупки обращаться в нашу группу vk.com/gmforce");
            rg_send_audio(id, "events/friend_died.wav");
            return PLUGIN_CONTINUE;
        }
        format_time(sDateEnd, charsmax(sDateEnd), "%d.%m.%Y", iTimeStampEnd);
        client_print_color(id, print_team_default, "^4* ^1У Вас уже установлены VIP-привилегии сроком до %s", sDateEnd);
        client_print_color(id, print_team_default, "^4* ^1Введите в чате /guns или /pguns для покупки оружия");
        client_print_color(id, print_team_default, "^4* ^1Используйте бинд bind ^"Клавиша^" ^"say /guns^" для быстрого доступа к меню");
        rg_send_audio(id, "events/friend_died.wav");
        return PLUGIN_CONTINUE;
    }
    if(get_user_flags(id) & VIP_FLAG) {
        client_print_color(id, print_team_default, "^4* ^1У Вас уже имееются привилегии, участие в акции невозможно");
        rg_send_audio(id, "events/friend_died.wav");
        return PLUGIN_CONTINUE;
    }
    new sTimeStampEnd[DATE_END_STRLEN];
    iTimeStampEnd = get_systime() + SECONDS_IN_DAY * NUMBER_DAYS_ACTIONS;
    num_to_str(iTimeStampEnd, sTimeStampEnd, charsmax(sTimeStampEnd));
    nvault_set(g_iVaultID, sAuthID, sTimeStampEnd);
    nvault_close(g_iVaultID); g_iVaultID = nvault_open("vip_players");
    
    new sPlayerName[PLAYER_NAME_STRLEN];
    get_user_name(id, sPlayerName, charsmax(sPlayerName));
    format_time(sDateEnd, charsmax(sDateEnd), "%d.%m.%Y", iTimeStampEnd);
    logging(g_sLogsDir, "vip_players_", "^"%s^" ^"%s^" ^"%s^"", sAuthID, sPlayerName, sDateEnd);
    
    client_print_color(id, print_team_default, "^4* ^1У Вас установлены VIP-привилегии сроком до %s", sDateEnd);
    client_print_color(id, print_team_default, "^4* ^1Пожалуйста перезайдите на сервер для полной активации");
    client_print_color(id, print_team_default, "^4* ^1Введите повторно в чате /vip для получения подробной информации");
    rg_send_audio(id, "events/tutor_msg.wav");
    return PLUGIN_CONTINUE;
}

stock logging(const sLogsDir[], const sFileName[], const sMessage[], any:...) {
    new iFileID, sLogFile[PATH_STRLEN + 32], sFormatMsg[MESSAGE_STRLEN], sTime[TIME_STRLEN];
    vformat(sFormatMsg, charsmax(sFormatMsg), sMessage, 4);
    get_time("%Y.log", sTime, charsmax(sTime));
    formatex(sLogFile, charsmax(sLogFile), "%s/%s%s", sLogsDir, sFileName, sTime);
    iFileID = fopen(sLogFile, "at");
    get_time("%d.%m.%Y - %H:%M:%S", sTime, charsmax(sTime));
    fprintf(iFileID, "^"%s^" %s^n", sTime, sFormatMsg);
    fclose(iFileID);
}

P.s.: nvault-файл сохраняю каждую выдачу новых привилегий и каждый plugin_end, для того, что бы во время работы был наименьший риск потери данных, хоть и целесообразней сохранять только при plugin_end, но для себя решил иначе, так-как после достижения свыше 100 игроков количество ежедневных выдач привилегий сократилось до 5 за сутки, поэтому считаю не критичным делать сохранение базы каждую новую выдачу.
 

Вложения

Последнее редактирование:
Сообщения
59
Реакции
6
Не верный раздел форума
Обратите внимание, если вы хотите заключить сделку с этим пользователем, он заблокирован
Javekson, не компилируется под 1.8.2 , в чём причина? инклюды новые все дела:DD
 
Сообщения
263
Реакции
335
Помог
4 раз(а)
andrei123123, добавь после #include <reapi>
Код:
#if AMXX_VERSION_NUM < 183
    #include <colorchat>
#endif
 
Сообщения
59
Реакции
6
Обратите внимание, если вы хотите заключить сделку с этим пользователем, он заблокирован
SonG, Спасибо дружище )
 
Сообщения
12
Реакции
2
удалил файл vip_players.dat, теперь заново не создается, что делать?(
 
Сообщения
1,420
Реакции
2,511
Помог
58 раз(а)
l3x1s, нужно удалять при выключенном сервере, если не ошибаюсь. Выключите сервер и тогда он должен появиться и тогда уже нужно его удалять.
 
Сообщения
12
Реакции
2
w0w, в том то и косяк, что я удалил его при включенном сервере, уже рестарт сервера сделал, но так и не создался(

может скинет кто свой файл?
11 Апр 2018
Автор помог разобраться)
 

Вложения

Сообщения
1,032
Реакции
828
Помог
10 раз(а)
Advertising Manager
Пока появилось немного времени решил быстренько слепить плагин для показа информационных сообщений.
Как и всегда название плагина не совсем корректное, но делается с учетом того, что в дальнейшем возможно он будет усовершенствоваться.

На сегодняшней момент плагин выполняет следующие функции:
  • Показ рекламных сообщений, осуществляется, как в Hud'e, так и в чате только для мертвых или зрителей
  • Показ только одного рекламного сообщения в Hude с эффектом печатание и переливанием текста в качестве единственного приветствия
  • Показ нескольких рекламных сообщений в чате последовательно друг за другом для каждого игрока в отдельности
  • Возможность включить/выключить показ рекламы командой в чате /adv, сохранение осуществляется с помощью nvault-системы
  • Если в течение одной недели игрок не появлялся на сервере, то настройки показа рекламных сообщений сбиваются по умолчанию
  • Ведется отдельный лог для игроков включивших/выключивших рекламные сообщения
de_dust200017.jpg

C++:
#include <amxmodx>
#include <nvault>
#include <reapi>

#pragma semicolon 1

const NUMBER_DAYS_INACTIVITY =        7;                // Через сколько дней удалять игрока, незаходящего на сервер
const SECONDS_IN_DAY =                86400;            // Количество секунд в одном дне

const Float:REPEAT_CHAT =            15.0;            // Время повторного показа рекламы в чате
const Float:REPEAT_HUD =            10.0;            // Время повторного показа hud рекламы

const COLOR_RED =                    255;                // Интенсивность красного цвета
const COLOR_GREEN =                    0;                // Интенсивность зеленого цвета
const COLOR_BLUE =                    0;                // Интенсивность голубого цвета
const Float:CORD_X =                0.02;            // Координата X
const Float:CORD_Y =                0.2;            // Координата Y
const EFFECTS =                        2;                // Эффект сообщения
const Float:FX_TIME =                1.0;            // Время сохранения блеска во втором эффекте
const Float:HOLD_TIME =                REPEAT_HUD;        // Время показа сообщения на экране
const Float:FADE_IN_TIME =            0.04;            // Скорость печатания текста во втором эффекте
const Float:FADE_OUT_TIME =            1.0;            // Время плавного исчезновение сообщение
const CHANNEL =                        -1;                // Канал сообщения

const TASK_ID_CHAT = 1000;
const TASK_ID_HUD = 1001;

const PATH_STRLEN = 64;
const AUTHID_STRLEN = 24;
const PLAYER_NAME_STRLEN = 32;
const MESSAGE_STRLEN = 256;
const TIME_STRLEN = 32;

new const ADV_CHAT_LIST[][] = {
    "^4* Отключить/включить рекламу можно командной в чате /adv",
    "^4* Ждем Вас в нашей группе сервера Вконтакте: vk.com/gmforce",
    "^4* Для получения бесплатных привилегий по акции - напишите в чате /vip",
    "^4* Откройте меню сервера командой /menu и установите любой префикс бесплатно",
    "^4* Если Вы постоянный и адекватный игрок, то Вам права администратора в подарок",
    "^4* Стоимость привилегий от 50 рублей, подробности в нашей группе: vk.com/gmforce",
    "^4* Надоело слепить самого себя? Приобретите VIP-Lite привилегии и играйте в удовольствие"
};

new const ADV_HUD[] = {
    "Мы рады приветсвовать тебя^n\
    Заходи к нам, проявляй активность^n\
    И получай привилегии в подарок^n^n\
    МЫ ВКОНТАКТЕ: VK.COM/GMFORCE"
};

new g_bAdvDisabled[MAX_PLAYERS + 1];
new g_aPlayersID[MAX_PLAYERS], g_iPlayersNum;

new g_sLogsDir[PATH_STRLEN];
new g_iVaultID;

public plugin_init() {
    register_plugin("Advertising Manager", "2.0", "Javekson");
    register_clcmd("say /adv", "ClCmdAdvertising");
}

public plugin_cfg() {
    get_localinfo("amxx_logs", g_sLogsDir, charsmax(g_sLogsDir));
  
    set_task(REPEAT_CHAT, "AdvTaskChat", TASK_ID_CHAT, .flags = "b");
    set_task(REPEAT_HUD, "AdvTaskHud", TASK_ID_HUD, .flags = "b");
  
    g_iVaultID = nvault_open("advertising");
    nvault_prune(g_iVaultID, 0, get_systime() - SECONDS_IN_DAY * NUMBER_DAYS_INACTIVITY);
}

public client_putinserver(id) {
    new sAuthID[AUTHID_STRLEN];
    get_user_authid(id, sAuthID, charsmax(sAuthID));
    if((g_bAdvDisabled[id] = nvault_get(g_iVaultID, sAuthID)))
        nvault_touch(g_iVaultID, sAuthID);
}

public plugin_end() {
    nvault_close(g_iVaultID);
}

public ClCmdAdvertising(const id) {
    new sAuthID[AUTHID_STRLEN], sPlayerName[PLAYER_NAME_STRLEN];
    get_user_authid(id, sAuthID, charsmax(sAuthID));
    get_user_name(id, sPlayerName, charsmax(sPlayerName));
    if(g_bAdvDisabled[id]) {
        g_bAdvDisabled[id] = false;
        nvault_remove(g_iVaultID, sAuthID);
        logging(g_sLogsDir, "advertising_", "^"%s^" ^"%s^" ^"Enabled^"", sAuthID, sPlayerName);
        client_print_color(id, print_team_default, "^4* ^1Вы активировали показ рекламы");
        rg_send_audio(id, "events/tutor_msg.wav");
        return PLUGIN_CONTINUE;
    }
    g_bAdvDisabled[id] = true;
    nvault_set(g_iVaultID, sAuthID, "1");
    logging(g_sLogsDir, "advertising_", "^"%s^" ^"%s^" ^"Disabled^"", sAuthID, sPlayerName);
    client_print_color(id, print_team_default, "^4* ^1Вы деактивировали показ рекламы");
    rg_send_audio(id, "events/tutor_msg.wav");
    return PLUGIN_CONTINUE;
}

public AdvTaskChat() {
    get_players(g_aPlayersID, g_iPlayersNum, "bch");
    for(new i; i < g_iPlayersNum; i++) {
        if(!g_bAdvDisabled[g_aPlayersID[i]]) {
            static iNextAdvChat[MAX_PLAYERS + 1];
            iNextAdvChat[g_aPlayersID[i]] = ++iNextAdvChat[g_aPlayersID[i]] % sizeof ADV_CHAT_LIST;
            client_print_color(g_aPlayersID[i], print_team_default, ADV_CHAT_LIST[iNextAdvChat[g_aPlayersID[i]]]);
        }
    }
}

public AdvTaskHud() {
    get_players(g_aPlayersID, g_iPlayersNum, "bch");
    for(new i; i < g_iPlayersNum; i++) {
        if(!g_bAdvDisabled[g_aPlayersID[i]]) {
            set_hudmessage(COLOR_RED, COLOR_GREEN, COLOR_BLUE, CORD_X, CORD_Y, EFFECTS, FX_TIME, HOLD_TIME, FADE_IN_TIME, FADE_OUT_TIME, CHANNEL);
            show_hudmessage(g_aPlayersID[i], ADV_HUD);
        }
    }
}

stock logging(const sLogsDir[], const sFileName[], const sMessage[], any:...) {
    new iFileID, sLogFile[PATH_STRLEN + 32], sFormatMsg[MESSAGE_STRLEN], sTime[TIME_STRLEN];
    vformat(sFormatMsg, charsmax(sFormatMsg), sMessage, 4);
    get_time("%Y.log", sTime, charsmax(sTime));
    formatex(sLogFile, charsmax(sLogFile), "%s/%s%s", sLogsDir, sFileName, sTime);
    iFileID = fopen(sLogFile, "at");
    get_time("%d.%m.%Y - %H:%M:%S", sTime, charsmax(sTime));
    fprintf(iFileID, "^"%s^" %s^n", sTime, sFormatMsg);
    fclose(iFileID);
}

P.s.: Снова напоминаю, что плагин разрабатывал для себя, своего проекта, и он не подойдет для большинства числа пользователей этого форума, это мини-блог и основная задумка - поделиться с Вами идеями, некими наработками. У каждого есть возможность переделать мои наработки под Ваши нужды, единственное только, меня не беспокоить )
 

Download all Attachments

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

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу