Иконка ресурса

New Hats Menu 0.4

Нет прав для скачивания
Установка
  1. Скомпилируйте плагин (инструкция)
  2. Скопируйте скомпилированный .amxx в директорию /amxmodx/plugins/
  3. Пропишите .amxx в файле /amxmodx/configs/plugins.ini
  4. Смените карту или перезапустите сервер.
  5. Автоматически создаются файлы по следующим путям:
    1. /amxmodx/configs/plugins/HatsMenu/NewHatsMenu.ini
    2. /amxmodx/configs/plugins/HatsMenu/NewHatsMenu.cfg
    3. /amxmodx/data/lang/NewHatsMenu.txt
  6. Настройте NewHatsMenu.ini | NewHatsMenu.cfg | NewHatsMenu.txt по своему вкусу
  7. Скопируйте дополнительные файлы плагина (models) в соответствующие директории на сервере
  8. Смените карту или перезапустите сервер.
Исходный код
Код:
/**
    История изменений:
        0.1 (26.07.2022) by b0t.
            - Первый релиз;
        
        0.2 (29.10.2022) by b0t.
            - fix бага с подгрузкой большого кол-ва моделей;
        
        0.4 (31.10.2022) by b0t.
            - fix проверки на флаг доступа к пункту;
            - Добавлен префикс к пункту меню если игрок не имеет к нему доступа;
            - Мелкие правки кода;
*/
new const VERSION[] = "0.4";
#include <amxmodx>
#include <reapi_v>
new const g_szGlobalDir[] = "HatsMenu";             //Имя папки с настройками;
new const g_szSettingsFileName[] = "NewHatsMenu";   //Имя файла с настройками/MultiLang;
const HIDE_HATS_INDEX = 0xA553;
#define var_hats_index      var_euser1
enum {
    SECTION_MENU = 0,
    MENU_NAME,
    MODEL_PATH,
    MODEL_SUB,
    MODEL_SKIN,
    MODEL_ANIMATION,
    MODEL_FRAME_RATE,
    ITEM_FLAG_ACCESS,
    ITEM_NO_ACCESS_MSG,
    NUMBER_OF_CELLS
};
enum _:CVARS_DATA {
    CVAR__CMD_OPEN_MENU[128],
    CVAR__FLAG_ACCESS_MENU[64],
    CVAR__ABILITY_HIDE_HATS,
    CVAR__HIDE_HATS_CMD[128],
    CVAR__REMOVE_HATS_POST_DEATH,
    CVAR__PRINT_CHAT_NEW_HATS
};
enum _:ARRAY_DATA {
    ARRAY__SECTION_MENU[128],
    ARRAY__MENU_NAME[128],
    ARRAY__MODEL_PATH[256],
    ARRAY__MODEL_SUB,
    ARRAY__MODEL_SKIN,
    ARRAY__MODEL_ANIMATION,
    Float:ARRAY__MODEL_FRAME_RATE,
    ARRAY__ITEM_FLAG_ACCESS,
    ARRAY__ITEM_NO_ACCESS_MSG[128]
};
new
    gCvars[CVARS_DATA],
    Array:g_ArrayData,
    Array:g_szArray__MenuIndex;
new
    g_pCvarAbilityHideHats,
    g_pCvarRemoveHatsPostDeath,
    fwd_AddToFullPack,
    HookChain:CBasePlayer_Killed;
new
    p_iEntID[33],
    bool:p_bToggleHats[33],
    p_iHatsUse[33];
public plugin_precache() {
    Func__CreateCvars();
    Func__CreateFiles();
    Func__CreateMultiLangFile();
    for(new iItem,aData[ARRAY_DATA];iItem<ArraySize(g_ArrayData);iItem++) {
        ArrayGetArray(g_ArrayData,iItem,aData);
        
        precache_model(fmt("models/%s",aData[ARRAY__MODEL_PATH]));
    }
}
public plugin_init() {
    register_plugin("New Hats Menu",VERSION,"b0t.");
    UTIL__RegisterClCmd(gCvars[CVAR__HIDE_HATS_CMD],"Func__ToggleHideHats");
    UTIL__RegisterClCmd(gCvars[CVAR__CMD_OPEN_MENU],"Func__ShowMainHatsMenu_Pre");
    if(gCvars[CVAR__ABILITY_HIDE_HATS])
        fwd_AddToFullPack = register_forward(FM_AddToFullPack,"FM_AddToFullPack_Post",true);
    
    hook_cvar_change(g_pCvarAbilityHideHats,"Func__HookCvarChange_AbilityHideHats");
    hook_cvar_change(g_pCvarRemoveHatsPostDeath,"Func__HookCvarChange_RemoveHatsPostDeath");
    if(gCvars[CVAR__REMOVE_HATS_POST_DEATH])
        CBasePlayer_Killed = RegisterHookChain(RG_CBasePlayer_Killed,"CBasePlayer_Killed_Post", .post = true);
    register_dictionary(fmt("%s.txt",g_szSettingsFileName));
}
public Func__ToggleHideHats(const id) {
    p_bToggleHats[id] ^= true;
    return PLUGIN_HANDLED;
}
public Func__ShowMainHatsMenu_Pre(const id) {
    Func__ShowMainHatsMenu_Post(id,0);
    return PLUGIN_HANDLED;
}
public Func__ShowMainHatsMenu_Post(const id,const iPages) {
    if(gCvars[CVAR__FLAG_ACCESS_MENU][0]) {
        if(~get_user_flags(id) & read_flags(gCvars[CVAR__FLAG_ACCESS_MENU])) {
            client_print_color(id,print_team_default,"%L",LANG_SERVER,"NHM_CHAT_DONT_ACCESS");
            return PLUGIN_HANDLED;
        }
    }
    ArrayClear(g_szArray__MenuIndex);
    new iBitFlags = get_user_flags(id);
    new iMenu = menu_create(fmt("%L\R\d",LANG_SERVER,"NHM_MAIN_MENU_NAME"),"ShowMainHatsMenu_Post__Handler");
    menu_additem(iMenu,fmt("%L%L",LANG_SERVER,!is_nullent(p_iEntID[id]) ? "NHM_COLOR_HATS_YES" : "NHM_COLOR_HATS_NO",LANG_SERVER,"NHM_ITEM_REMOVE_HATS"),"remove_hats");
    for(new iItem,aData[ARRAY_DATA];iItem<ArraySize(g_ArrayData);iItem++) {
        ArrayGetArray(g_ArrayData,iItem,aData);
        if((ArrayFindString(g_szArray__MenuIndex,aData[ARRAY__SECTION_MENU])) != -1)
            continue;
        if(contain(aData[ARRAY__SECTION_MENU],"_") != -1) {
            if(p_iHatsUse[id] == iItem) {
                UTIL__ReplaceSimbols(aData[ARRAY__MENU_NAME],charsmax(aData),true);
                add(aData[ARRAY__MENU_NAME],charsmax(aData),fmt(" %L",LANG_SERVER,"NHM_HATS_USE"));
            }
            if(aData[ARRAY__ITEM_FLAG_ACCESS] && ~iBitFlags & aData[ARRAY__ITEM_FLAG_ACCESS]) {
                UTIL__ReplaceSimbols(aData[ARRAY__MENU_NAME],charsmax(aData),true);
                add(aData[ARRAY__MENU_NAME],charsmax(aData),fmt(" %s",aData[ARRAY__ITEM_NO_ACCESS_MSG]));
            }
            menu_additem(iMenu,fmt("%s",aData[ARRAY__MENU_NAME]),fmt("_%i",iItem),aData[ARRAY__ITEM_FLAG_ACCESS]);
        }
        else {
            ArrayPushString(g_szArray__MenuIndex,aData[ARRAY__SECTION_MENU]);
            menu_additem(iMenu,fmt("%s",aData[ARRAY__SECTION_MENU]));
        }
    }
    new iItem = menu_items(iMenu);
    if(!iItem) {
        client_print_color(id,print_team_default,"%L",LANG_SERVER,"NHM_CHAT_EMPTY_MENU");
        menu_destroy(iMenu);
        return PLUGIN_HANDLED;
    }
    if(iItem == 8)
        menu_addblank2(iMenu);
    
    if(iItem >= 8 && iItem <= 9) {
        menu_setprop(iMenu,MPROP_EXIT,MEXIT_FORCE);
        menu_setprop(iMenu,MPROP_PERPAGE,0);
    }
    UTIL__RegisterMenu(id,iMenu, .szExitName = "Выход", .szNumberColor = "\y", .iPage = iPages);
    return PLUGIN_HANDLED;
}
public ShowMainHatsMenu_Post__Handler(const id,const iMenu,const iItem) {
    if(iItem == MENU_EXIT) {
        menu_destroy(iMenu);
        return PLUGIN_HANDLED;
    }
    
    new iNewMenu = iMenu;
    new iPage;
    player_menu_info(id,iNewMenu,iNewMenu,iPage);
    new szData[64],szName[256];
    menu_item_getinfo(iMenu,iItem, .info = szData, .infolen = charsmax(szData), .name = szName, .namelen = charsmax(szName));
    menu_destroy(iMenu);
    if(equal(szData,"remove_hats")) {
        Func__RemoveHats(id);
        return Func__ShowMainHatsMenu_Post(id,iPage);
    }
    if(contain(szData,"_") != -1) {
        replace_all(szData,charsmax(szData),"_","");
        if(p_iHatsUse[id] == str_to_num(szData)) {
            client_print_color(id,print_team_default,"%L",LANG_SERVER,"NHM_CHAT_HATS_USE");
            return Func__ShowMainHatsMenu_Post(id,iPage);
        }
        new aData[ARRAY_DATA];
        ArrayGetArray(g_ArrayData,str_to_num(szData),aData);
        Func__CreateHats(id,str_to_num(szData));
        Func__ShowMainHatsMenu_Post(id,iPage);
        if(gCvars[CVAR__PRINT_CHAT_NEW_HATS]) {
            UTIL__ReplaceSimbols(aData[ARRAY__MENU_NAME],charsmax(aData),true);
            client_print_color(id,print_team_default,"%L",LANG_SERVER,"NHM_CHAT_PUT_HAT",aData[ARRAY__MENU_NAME]);
        }
    }
    else
        Func__ShowSecondaryHatsMenu(id,szName,0);
    
    return PLUGIN_HANDLED;
}
public Func__ShowSecondaryHatsMenu(const id,const szName[],const iPages) {
    new iMenu = menu_create(szName,"ShowSecondaryHatsMenu__Handler");
    new iBitFlags = get_user_flags(id);
    for(new iItem,aData[ARRAY_DATA];iItem<ArraySize(g_ArrayData);iItem++) {
        ArrayGetArray(g_ArrayData,iItem,aData);
        if(contain(aData[ARRAY__SECTION_MENU],"_") != -1)
            continue;
        
        if(!equal(aData[ARRAY__SECTION_MENU],szName))
            continue;
        if(p_iHatsUse[id] == iItem) {
            UTIL__ReplaceSimbols(aData[ARRAY__MENU_NAME],charsmax(aData),true);
            add(aData[ARRAY__MENU_NAME],charsmax(aData),fmt(" %L",LANG_SERVER,"NHM_HATS_USE"));
        }
        if(aData[ARRAY__ITEM_FLAG_ACCESS] && ~iBitFlags & aData[ARRAY__ITEM_FLAG_ACCESS]) {
            UTIL__ReplaceSimbols(aData[ARRAY__MENU_NAME],charsmax(aData),true);
            add(aData[ARRAY__MENU_NAME],charsmax(aData),fmt(" %s",aData[ARRAY__ITEM_NO_ACCESS_MSG]));
        }
        menu_additem(iMenu,fmt("%s",aData[ARRAY__MENU_NAME]),fmt("%i|%s",iItem,szName),aData[ARRAY__ITEM_FLAG_ACCESS]);
    }
    new iItem = menu_items(iMenu);
    if(iItem == 8)
        menu_addblank2(iMenu);
    
    if(iItem >= 8 && iItem <= 9) {
        menu_setprop(iMenu,MPROP_EXIT,MEXIT_FORCE);
        menu_setprop(iMenu,MPROP_PERPAGE,0);
    }
    UTIL__RegisterMenu(id,iMenu, .szExitName = "В меню", .szNumberColor = "\y", .iPage = iPages);
    return PLUGIN_HANDLED;
}
public ShowSecondaryHatsMenu__Handler(const id,const iMenu,const iItem) {
    if(iItem == MENU_EXIT) {
        menu_destroy(iMenu);
        return Func__ShowMainHatsMenu_Pre(id);
    }
    new iMenuNew = iMenu;
    new iPage;
    player_menu_info(id,iMenuNew,iMenuNew,iPage);
    new szData[64];
    menu_item_getinfo(iMenu,iItem, .info = szData, .infolen = charsmax(szData));
    menu_destroy(iMenu);
    new szItem[64],szName[256];
    strtok(szData,szItem,charsmax(szItem),szName,charsmax(szName),'|');
    trim(szItem);
    trim(szName);
    if(p_iHatsUse[id] == str_to_num(szItem)) {
        client_print_color(id,print_team_default,"%L",LANG_SERVER,"NHM_CHAT_HATS_USE");
        return Func__ShowSecondaryHatsMenu(id,szName,iPage);
    }
    new aData[ARRAY_DATA];
    ArrayGetArray(g_ArrayData,str_to_num(szItem),aData);
    Func__CreateHats(id,str_to_num(szItem));
    Func__ShowSecondaryHatsMenu(id,szName,iPage);
    if(gCvars[CVAR__PRINT_CHAT_NEW_HATS]) {
        UTIL__ReplaceSimbols(aData[ARRAY__MENU_NAME],charsmax(aData),true);
        client_print_color(id,print_team_default,"%L",LANG_SERVER,"NHM_CHAT_PUT_HAT",aData[ARRAY__MENU_NAME]);
    }
    return PLUGIN_HANDLED;
}
public FM_AddToFullPack_Post(iEs,iE,iEnt,pHost,BitHostFlags,Player,pSet) {
    if(!is_user_connected(pHost))
        return FMRES_IGNORED;
    if(p_bToggleHats[pHost] && get_entvar(iEnt,var_hats_index) == HIDE_HATS_INDEX)
        set_es(iEs,ES_Effects,EF_NODRAW);
    
    return FMRES_IGNORED;
}
public CBasePlayer_Killed_Post(const pVictim,const pAttacker) {
    if(!is_nullent(p_iEntID[pVictim]))
        Func__RemoveHats(pVictim);
}
public Func__HookCvarChange_AbilityHideHats(pCvar,const szOldValue[],const szNewValue[]) {
    new iNewValue = str_to_num(szNewValue);
    new iOldValue = str_to_num(szOldValue);
    if(iNewValue != iOldValue) {
        switch(iNewValue) {
            case 1: fwd_AddToFullPack = register_forward(FM_AddToFullPack,"FM_AddToFullPack_Post",true);
            case 0: {
                unregister_forward(FM_AddToFullPack,fwd_AddToFullPack,true);
                arrayset(p_bToggleHats,0,sizeof(p_bToggleHats));
            }
        }
    }
}
public Func__HookCvarChange_RemoveHatsPostDeath(pCvar,const szOldValue[],const szNewValue[]) {
    new iNewValue = str_to_num(szNewValue);
    new iOldValue = str_to_num(szOldValue);
    if(iNewValue != iOldValue) {
        switch(iNewValue) {
            case 1: EnableHookChain(CBasePlayer_Killed);
            case 0: DisableHookChain(CBasePlayer_Killed);
        }
    }
}
public client_putinserver(id) {
    p_iEntID[id] = p_iHatsUse[id] = -1;
    p_bToggleHats[id] = false;
}
public Func__CreateHats(const id,const iItem) {
    if(!is_nullent(p_iEntID[id]))
        Func__RemoveHats(id);
    
    new iEnt = rg_create_entity("info_target");
    if(is_nullent(iEnt))
        return;
    
    new aData[ARRAY_DATA];
    ArrayGetArray(g_ArrayData,iItem,aData);
    engfunc(EngFunc_SetModel,iEnt,fmt("models/%s",aData[ARRAY__MODEL_PATH]));
    set_entvar(iEnt,var_movetype,MOVETYPE_FOLLOW);
    set_entvar(iEnt,var_aiment,id);
    set_entvar(iEnt,var_body,aData[ARRAY__MODEL_SUB]);
    set_entvar(iEnt,var_skin,aData[ARRAY__MODEL_SKIN]);
    set_entvar(iEnt,var_sequence,aData[ARRAY__MODEL_ANIMATION]);
    set_entvar(iEnt,var_framerate,aData[ARRAY__MODEL_FRAME_RATE]);
    set_entvar(iEnt,var_hats_index,HIDE_HATS_INDEX);
    p_iEntID[id] = iEnt;
    p_iHatsUse[id] = iItem;
}
public Func__RemoveHats(const id) {
    if(!is_nullent(p_iEntID[id]))
        set_entvar(p_iEntID[id],var_flags,FL_KILLME);
    p_iEntID[id] = p_iHatsUse[id] = -1;
}
public Func__CreateFiles() {
    new szData[256];
    formatex(szData,charsmax(szData),"addons/amxmodx/configs/plugins/%s",g_szGlobalDir);
    if(!dir_exists(szData))
        mkdir(szData);
    
    add(szData,charsmax(szData),fmt("/%s.ini",g_szSettingsFileName));
    if(!file_exists(szData))
        write_file(szData,
            "; Название секции где будет пункт | Имя в меню | Путь до модели | SubModel(Если есть) | Skin(Если есть) | Номер анимации(если есть) | Скорость анимации | Флаг доступа к пункту | Отображение если нету доступа^n\
            ;   *Путь до модели указывать без корневой папки 'models'^n\
            ;   *Если пункт необходимо добавить в основное меню, в имени секции указать '_'^n\
            ;   *Если отсутствует SubModel/Skin/Анимация указать 0 ^n\
            ;   *Если пункт будет доступен всем указать '_'^n\
            ;   *Отображение если нету доступа, то что будет писаться если не будет доступа к пункту^n\
            ;       Если не требуется указать '_'"
        );
    
    new f = fopen(szData,"r");
    new aData[ARRAY_DATA];
    new szFileData[NUMBER_OF_CELLS][256];
    
    g_szArray__MenuIndex = ArrayCreate(256);
    g_ArrayData = ArrayCreate(ARRAY_DATA);
    new iLine;
    while(!feof(f)) {
        fgets(f,szData,charsmax(szData));
        trim(szData);
        iLine++;
        if(szData[0] == ';' || szData[0] == EOS)
            continue;
        if(explode_string(szData," | ",szFileData,sizeof(szFileData),charsmax(szFileData[])) == NUMBER_OF_CELLS) {
            copy(aData[ARRAY__SECTION_MENU],charsmax(aData),szFileData[SECTION_MENU]);
            copy(aData[ARRAY__MENU_NAME],charsmax(aData),szFileData[MENU_NAME]);
            copy(aData[ARRAY__MODEL_PATH],charsmax(aData),szFileData[MODEL_PATH]);
            aData[ARRAY__MODEL_SUB] = str_to_num(szFileData[MODEL_SUB]);
            aData[ARRAY__MODEL_SKIN] = str_to_num(szFileData[MODEL_SKIN]);
            aData[ARRAY__MODEL_ANIMATION] = str_to_num(szFileData[MODEL_ANIMATION]);
            aData[ARRAY__MODEL_FRAME_RATE] = str_to_float(szFileData[MODEL_FRAME_RATE]);
            aData[ARRAY__ITEM_FLAG_ACCESS] = strcmp(szFileData[ITEM_FLAG_ACCESS],"_") != 0 ? read_flags(szFileData[ITEM_FLAG_ACCESS]) : ADMIN_ALL;
            copy(aData[ARRAY__ITEM_NO_ACCESS_MSG],charsmax(aData),szFileData[ITEM_NO_ACCESS_MSG]);
            if(!file_exists(fmt("models/%s",aData[ARRAY__MODEL_PATH]))) {
                server_print("[HATS MENU] Модель не найдена! Пункт удалён! [models/%s]",aData[ARRAY__MODEL_PATH]);
                continue;
            }
            ArrayPushArray(g_ArrayData,aData);
        }
        else {
            server_print("[HATS MENU] Файл [NewHatsMenu.ini] заполнен не верно! Строка: %i",iLine);
            pause("a");
            break;
        }
        continue;
    }
    fclose(f);
}
public Func__CreateCvars() {
    bind_pcvar_string(
        create_cvar(
            .name = "nhm_cmd_open_menu",
            .string = "hats",
            .description = "Команда для открытия меню(все чаты + консоль)"
        ),
        gCvars[CVAR__CMD_OPEN_MENU],charsmax(gCvars)
    );
    bind_pcvar_string(
        create_cvar(
            .name = "nhm_flag_access_menu",
            .string = "",
            .description = "Флаг доступа к меню^nОставить пустым если доступно всем"
        ),
        gCvars[CVAR__FLAG_ACCESS_MENU],charsmax(gCvars)
    );
    bind_pcvar_num(
        g_pCvarAbilityHideHats = create_cvar(
            .name = "nhm_ability_hide_hats",
            .string = "1",
            .description = "Возможность скрывать шапки^nВНИМАНИЕ: возможность использует FullPack"
        ),
        gCvars[CVAR__ABILITY_HIDE_HATS]
    );
    bind_pcvar_string(
        create_cvar(
            .name = "nhm_hide_hats_cmd",
            .string = "toggle_hats",
            .description = "Команда для отключения/включения отображения шляп^nВсе чаты + консоль"
        ),
        gCvars[CVAR__HIDE_HATS_CMD],charsmax(gCvars)
    );
    bind_pcvar_num(
        g_pCvarRemoveHatsPostDeath = create_cvar(
            .name = "nhm_remove_hats_post_death",
            .string = "0",
            .description = "Снимать шляпу с игрока после смерти"
        ),
        gCvars[CVAR__REMOVE_HATS_POST_DEATH]
    );
    bind_pcvar_num(
        create_cvar(
            .name = "nhm_print_chat_new_hats",
            .string = "1",
            .description = "Выводить ли игроку в чат информацию о надетой шапке"
        ),
        gCvars[CVAR__PRINT_CHAT_NEW_HATS]
    );
    AutoExecConfig(.name = g_szSettingsFileName, .folder = g_szGlobalDir);
}
public Func__CreateMultiLangFile() {
    new szData[256];
    formatex(szData,charsmax(szData),"addons/amxmodx/data/lang/%s.txt",g_szSettingsFileName);
    if(file_exists(szData))
        return;
    
    write_file(szData,
        "[ru]^n^n\
        NHM_MAIN_MENU_NAME = Меню шапок^n^n\
        NHM_COLOR_HATS_YES = \r^n\
        NHM_COLOR_HATS_NO = \d^n\
        NHM_ITEM_REMOVE_HATS = Снять шапку^^n^n^n\
        NHM_HATS_USE = \r[\dИспользуется\r]^n^n\
        NHM_CHAT_DONT_ACCESS = ^^3[^^4HATS^^3] ^^1У вас нет доступа^^4!^n\
        NHM_CHAT_EMPTY_MENU = ^^3[^^4HATS^^3] ^^1Увы, в меню пусто^^4!^n\
        NHM_CHAT_HATS_USE = ^^3[^^4HATS^^3] ^^1Шапка уже надета^^4!^n\
        NHM_CHAT_PUT_HAT = ^^3[^^4HATS^^3] ^^1Вы надели ^^4%s"
    );
}
public plugin_natives() {
    register_native("nhm_get_user_hats","native_nhm_get_user_hats");
    register_native("nhm_remove_user_hats","native_nhm_remove_user_hats");
    register_native("nhm_get_user_show_hats","native_nhm_get_user_show_hats");
    register_native("nhm_set_user_show_hats","native_nhm_set_user_show_hats");
}
public bool:native_nhm_get_user_hats() {
    return bool:(!is_nullent(p_iEntID[get_param(1)]));
}
public native_nhm_remove_user_hats() {
    Func__RemoveHats(get_param(1));
}
public bool:native_nhm_get_user_show_hats() {
    return bool:(p_bToggleHats[get_param(1)]);
}
public native_nhm_set_user_show_hats() {
    p_bToggleHats[get_param(1)] = bool:get_param(2);
}
Настройки
Код:
// This file was auto-generated by AMX Mod X (v1.10.0.5402)
// Cvars for plugin "New Hats Menu" by "b0t." (NewHatsMenu.amxx, v0.1)

// Команда для открытия меню(все чаты + консоль)
// -
// Default: "hats"
nhm_cmd_open_menu "hats"
// Флаг доступа к меню
// Оставить пустым если доступно всем
// -
// Default: ""
nhm_flag_access_menu ""
// Возможность скрывать шапки
// ВНИМАНИЕ: возможность использует FullPack
// -
// Default: "1"
nhm_ability_hide_hats "1"
// Команда для отключения/включения отображения шляп
// Все чаты + консоль
// -
// Default: "toggle_hats"
nhm_hide_hats_cmd "toggle_hats"
// Снимать шляпу с игрока после смерти
// -
// Default: "0"
nhm_remove_hats_post_death "0"
// Выводить ли игроку в чат информацию о надетой шапке
// -
// Default: "1"
nhm_print_chat_new_hats "1"

Код:
; Название секции где будет пункт | Имя в меню | Путь до модели | SubModel(Если есть) | Skin(Если есть) | Номер анимации(если есть) | Скорость анимации | Флаг доступа к пункту
;   *Путь до модели указывать без корневой папки 'models'
;   *Если пункт необходимо добавить в основное меню, в имени секции указать '_'
;   *Если отсутствует SubModel/Skin/Анимация указать 0
;   *Если пункт будет доступен всем указать '_'
Интерфейсы (API)
Код:
#if defined _Hats_API_included
    #endinput
#endif
#define _Hats_API_included
/**
    * Вернёт true, если на игроке надета шляпа.
    *
    *   @param pPlayer      Игрок.
    *
    *   @return             bool
*/
native bool:nhm_get_user_hats(const pPlayer);
/**
    * Насильно заставить игрока снять шляпу.
    *
    *   @param pPlayer      Игрок.
    *
    *   @return             -
*/
native nhm_remove_user_hats(const pPlayer);
/**
    * Вернёт true, если на игрок видит шляпы.
    *
    *   @param pPlayer      Игрок.
    *
    *   @return             bool
*/
native bool:nhm_get_user_show_hats(const pPlayer);
/**
    * Насильно изменить видимость шапок для игрока.
    *   @NOTE: Должен быть активен квар 'nhm_ability_hide_hats'
    *
    *   @param pPlayer      Игрок.
    *   @param bHide        false/true.
    *
    *   @return             -
*/
native nhm_set_user_show_hats(const pPlayer,const bool:bHide = false);
Сверху Снизу