Raised This Month: $30 Target: $400
 7% 

Knife Models [XP System & Skills Support]


Post New Thread Reply   
 
Thread Tools Display Modes
Taha_rajper
Member
Join Date: Jun 2021
Location: Under The Sea
Old 06-21-2022 , 08:53   Re: Knife Models [XP System & Skills Support]
Reply With Quote #341

Hey OcixCrom
Can You Add Sub Category For This Knife System

Example:
V_Model = Model Directory
P_model= model directory
DMG= 160
FLAG = b
Category= VIPs Knifes

Example 2:
V_Model = Model Directory
P_model= model directory
DMG= 400
FLAG = M
Category= PREMIUM


Example 3:
V_Model = Model Directory
P_model= model directory
DMG= 700
FLAG = l
Category= OWNERS KNIFE

And SOMEONE TYPES /KNIFE AND 3 OF THESE SUB MENUS OPEN

ALSO MAKE IT POSSIBLE IF WE WANT MORE THAN 3 SUB CATEGORY'S
Taha_rajper is offline
OciXCrom
Veteran Member
Join Date: Oct 2013
Location: Macedonia
Old 06-21-2022 , 17:16   Re: Knife Models [XP System & Skills Support]
Reply With Quote #342

That is planned for the next update which I can't tell when it would be.
Of course I won't make it have only 3 categories. That's amateur work.

This is a beta-version of what I tried some time ago. Not sure if it works properly but you can test it.
Make sure to spell CATEGORY with capital letters in the .ini file.

PHP Code:
#include <amxmodx>
#include <amxmisc>
#include <crxknives_const>
#include <cromchat>
#include <fakemeta>
#include <hamsandwich>
#include <nvault>

native crxranks_get_max_levels()
native crxranks_get_rank_by_level(levelbuffer[], len)
native crxranks_get_user_level(id)
native crxranks_get_user_xp(id)

new const 
g_szNatives[][] =
{
    
"crxranks_get_max_levels",
    
"crxranks_get_rank_by_level",
    
"crxranks_get_user_level",
    
"crxranks_get_user_xp"
}

#if !defined m_pPlayer
const m_pPlayer 41
#endif

#if !defined client_disconnected
    #define client_disconnected client_disconnect
#endif

new const PLUGIN_VERSION[] = "3.2-beta"
const Float:DELAY_ON_CONNECT 3.0

#if !defined MAX_AUTHID_LENGTH
const MAX_AUTHID_LENGTH 35
#endif

#if !defined MAX_NAME_LENGTH
const MAX_NAME_LENGTH 32
#endif

#if !defined MAX_PLAYERS
const MAX_PLAYERS 32
#endif

const INVALID_CATEGORY = -1
new const INVALID_CATEGORY_STR[] = "Other"

enum
{
    
SOUND_NONE 0,
    
SOUND_DEPLOY,
    
SOUND_HIT,
    
SOUND_HITWALL,
    
SOUND_SLASH,
    
SOUND_STAB
}

enum _:Knives
{
    
NAME[MAX_NAME_LENGTH],
    
V_MODEL[CRXKNIVES_MAX_SOUND_LENGTH],
    
P_MODEL[CRXKNIVES_MAX_SOUND_LENGTH],
    
DEPLOY_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
    
HIT_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
    
HITWALL_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
    
SLASH_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
    
STAB_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
    
SELECT_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
    
FLAG,
    
LEVEL,
    
XP,
    
SELECT_MESSAGES_NUM,
    
CATEGORY,
    
bool:SHOW_RANK,
    
bool:HAS_CUSTOM_SOUND,
    Array:
SELECT_MESSAGES,
    
Trie:ATTRIBUTES
}

enum _:CvarsReg
{
    
cvar_km_open_at_spawn,
    
cvar_km_save_choice,
    
cvar_km_only_dead,
    
cvar_km_select_message,
    
cvar_km_knife_only_skills,
    
cvar_km_admin_bypass,
    
cvar_km_categories
}

enum _:Cvars
{
    
km_open_at_spawn,
    
km_save_choice,
    
km_only_dead,
    
km_select_message,
    
km_knife_only_skills,
    
km_admin_bypass,
    
km_categories
}

new Array:
g_aKnives,
    Array:
g_aCategories,
    
Trie:g_tCategories,
    
Trie:g_tKnivesInCategory,
    
bool:g_bFirstTime[MAX_PLAYERS 1],
    
bool:g_bRankSystem,
    
bool:g_bGetLevel,
    
bool:g_bGetXP,
    
g_eCvars[Cvars],
    
g_eCvarsReg[CvarsReg],
    
g_eKnife[MAX_PLAYERS 1][Knives],
    
g_szAuth[MAX_PLAYERS 1][MAX_AUTHID_LENGTH],
    
g_iKnife[MAX_PLAYERS 1],
    
g_fwdKnifeUpdated,
    
g_fwdAttemptChange,
    
g_iMenuFlags,
    
g_iKnivesNum,
    
g_iCategories,
    
g_iCallback,
    
g_iVault

new _unused[1]

public 
plugin_init()
{
    
register_plugin("Knife Models"PLUGIN_VERSION"OciXCrom")
    
register_cvar("CRXKnifeModels"PLUGIN_VERSIONFCVAR_SERVER|FCVAR_SPONLY|FCVAR_UNLOGGED)

    if(!
g_iKnivesNum)
    {
        
set_fail_state("No knives found in the configuration file.")
    }

    
register_dictionary("KnifeModels.txt")

    
RegisterHam(Ham_Spawn"player""OnPlayerSpawn"1)
    
register_forward(FM_EmitSound,    "OnEmitSound")
    
RegisterHam(Ham_Item_Deploy"weapon_knife""OnSelectKnife"1)

    
register_clcmd("say /knife",       "Cmd_Knife")
    
register_clcmd("say_team /knife",  "Cmd_Knife")
    
register_clcmd("crxknives_select""Cmd_Select"_"<knife id>")

    
g_fwdKnifeUpdated  CreateMultiForward("crxknives_knife_updated",  ET_IGNOREFP_CELLFP_CELLFP_CELL)
    
g_fwdAttemptChange CreateMultiForward("crxknives_attempt_change"ET_STOP,   FP_CELLFP_CELL)

    
g_iCallback menu_makecallback("CheckKnifeAccess")

    
g_eCvarsReg[cvar_km_open_at_spawn]     = register_cvar("km_open_at_spawn",     "0")
    
g_eCvarsReg[cvar_km_save_choice]       = register_cvar("km_save_choice",       "1")
    
g_eCvarsReg[cvar_km_only_dead]         = register_cvar("km_only_dead",         "0")
    
g_eCvarsReg[cvar_km_select_message]    = register_cvar("km_select_message",    "1")
    
g_eCvarsReg[cvar_km_knife_only_skills] = register_cvar("km_knife_only_skills""1")
    
g_eCvarsReg[cvar_km_admin_bypass]      = register_cvar("km_admin_bypass",      "0")
    
g_eCvarsReg[cvar_km_categories]        = register_cvar("km_categories",        "1")
}

public 
plugin_precache()
{
    if(
LibraryExists("crxranks"LibType_Library))
    {
        
g_bRankSystem true
    
}

    
g_aKnives           ArrayCreate(Knives)
    
g_aCategories       ArrayCreate(MAX_NAME_LENGTH)
    
g_tCategories       TrieCreate()
    
g_tKnivesInCategory TrieCreate()
    
ReadFile()
}

public 
plugin_cfg()
{
    
g_eCvars[km_save_choice]       = get_pcvar_num(g_eCvarsReg[cvar_km_save_choice])
    
g_eCvars[km_open_at_spawn]     = get_pcvar_num(g_eCvarsReg[cvar_km_open_at_spawn])
    
g_eCvars[km_only_dead]         = get_pcvar_num(g_eCvarsReg[cvar_km_only_dead])
    
g_eCvars[km_select_message]    = get_pcvar_num(g_eCvarsReg[cvar_km_select_message])
    
g_eCvars[km_knife_only_skills] = get_pcvar_num(g_eCvarsReg[cvar_km_knife_only_skills])
    
g_eCvars[km_admin_bypass]      = get_pcvar_num(g_eCvarsReg[cvar_km_admin_bypass])
    
g_eCvars[km_categories]        = get_pcvar_num(g_eCvarsReg[cvar_km_categories])

    if(
g_eCvars[km_save_choice])
    {
        
g_iVault nvault_open("KnifeModels")
    }
}

public 
plugin_end()
{
    for(new 
eKnife[Knives], ig_iKnivesNumi++)
    {
        
ArrayGetArray(g_aKnivesieKnife)
        
ArrayDestroy(eKnife[SELECT_MESSAGES])
        
TrieDestroy(eKnife[ATTRIBUTES])
    }

    
ArrayDestroy(g_aKnives)
    
ArrayDestroy(g_aCategories)
    
TrieDestroy(g_tCategories)
    
TrieDestroy(g_tKnivesInCategory)

    if(
g_eCvars[km_save_choice])
    {
        
nvault_close(g_iVault)
    }
}

ReadFile()
{
    new 
szFilename[256]
    
get_configsdir(szFilenamecharsmax(szFilename))
    
add(szFilenamecharsmax(szFilename), "/KnifeModels.ini")
    new 
iFilePointer fopen(szFilename"rt")

    if(
iFilePointer)
    {
        new 
szData[160], szKey[32], szValue[128], szSound[128], iMaxLevelsiCategoryiNum
        
new eKnife[Knives], bool:bCustom

        
if(g_bRankSystem)
        {
            
iMaxLevels crxranks_get_max_levels()
        }

        while(!
feof(iFilePointer))
        {
            
fgets(iFilePointerszDatacharsmax(szData))
            
trim(szData)

            switch(
szData[0])
            {
                case 
EOS'#'';': continue
                case 
'[':
                {
                    if(
szData[strlen(szData) - 1] == ']')
                    {
                        if(
g_iKnivesNum)
                        {
                            
push_knife(eKnife)
                        }

                        
g_iKnivesNum++
                        
replace(szDatacharsmax(szData), "[""")
                        
replace(szDatacharsmax(szData), "]""")
                        
copy(eKnife[NAME], charsmax(eKnife[NAME]), szData)

                        
eKnife[V_MODEL][0]          = EOS
                        eKnife
[P_MODEL][0]          = EOS
                        eKnife
[DEPLOY_SOUND][0]     = EOS
                        eKnife
[HIT_SOUND][0]        = EOS
                        eKnife
[HITWALL_SOUND][0]    = EOS
                        eKnife
[SLASH_SOUND][0]      = EOS
                        eKnife
[STAB_SOUND][0]       = EOS
                        eKnife
[SELECT_SOUND][0]     = EOS
                        eKnife
[FLAG]                = ADMIN_ALL
                        eKnife
[HAS_CUSTOM_SOUND]    = false
                        eKnife
[CATEGORY]            = INVALID_CATEGORY
                        eKnife
[SELECT_MESSAGES_NUM] = 0
                        eKnife
[SELECT_MESSAGES]     = _:ArrayCreate(CRXKNIVES_MAX_MESSAGE_LENGTH)
                        
eKnife[ATTRIBUTES]          = _:TrieCreate()

                        if(
g_bRankSystem)
                        {
                            
eKnife[LEVEL] = 0
                            eKnife
[SHOW_RANK] = false
                            eKnife
[XP] = 0
                        
}

                        static const 
ATTRIBUTE_NAME[] = "NAME"
                        
TrieSetString(eKnife[ATTRIBUTES], ATTRIBUTE_NAMEszData)
                    }
                    else continue
                }
                default:
                {
                    
strtok(szDataszKeycharsmax(szKey), szValuecharsmax(szValue), '=')
                    
trim(szKey); trim(szValue)
                    
bCustom true

                    TrieSetString
(eKnife[ATTRIBUTES], szKeyszValue)

                    if(
equal(szKey"FLAG"))
                    {
                        
eKnife[FLAG] = read_flags(szValue)
                        
g_iMenuFlags |= eKnife[FLAG]
                    }
                    else if(
equal(szKey"LEVEL") && g_bRankSystem)
                    {
                        
eKnife[LEVEL] = clamp(str_to_num(szValue), 0iMaxLevels)

                        if(!
g_bGetLevel)
                        {
                            
g_bGetLevel true
                        
}
                    }
                    else if(
equal(szKey"SHOW_RANK") && g_bRankSystem)
                    {
                        
eKnife[SHOW_RANK] = _:clamp(str_to_num(szValue), falsetrue)
                    }
                    else if(
equal(szKey"XP") && g_bRankSystem)
                    {
                        
eKnife[XP] = _:clamp(str_to_num(szValue), 0)

                        if(!
g_bGetXP)
                        {
                            
g_bGetXP true
                        
}
                    }
                    else if(
equal(szKey"V_MODEL"))
                    {
                        
copy(eKnife[V_MODEL], charsmax(eKnife[V_MODEL]), szValue)
                    }
                    else if(
equal(szKey"P_MODEL"))
                    {
                        
copy(eKnife[P_MODEL], charsmax(eKnife[P_MODEL]), szValue)
                    }
                    else if(
equal(szKey"DEPLOY_SOUND"))
                    {
                        
copy(eKnife[DEPLOY_SOUND], charsmax(eKnife[DEPLOY_SOUND]), szValue)
                    }
                    else if(
equal(szKey"HIT_SOUND"))
                    {
                        
copy(eKnife[HIT_SOUND], charsmax(eKnife[HIT_SOUND]), szValue)
                    }
                    else if(
equal(szKey"HITWALL_SOUND"))
                    {
                        
copy(eKnife[HITWALL_SOUND], charsmax(eKnife[HITWALL_SOUND]), szValue)
                    }
                    else if(
equal(szKey"SLASH_SOUND"))
                    {
                        
copy(eKnife[SLASH_SOUND], charsmax(eKnife[SLASH_SOUND]), szValue)
                    }
                    else if(
equal(szKey"STAB_SOUND"))
                    {
                        
copy(eKnife[STAB_SOUND], charsmax(eKnife[STAB_SOUND]), szValue)
                    }
                    else if(
equal(szKey"SELECT_SOUND"))
                    {
                        
bCustom false
                        copy
(eKnife[SELECT_SOUND], charsmax(eKnife[SELECT_SOUND]), szValue)
                    }
                    else if(
equal(szKey"SELECT_MESSAGE"))
                    {
                        
ArrayPushString(eKnife[SELECT_MESSAGES], szValue)
                        
eKnife[SELECT_MESSAGES_NUM]++
                    }
                    else if(
equal(szKey"CATEGORY"))
                    {
                        if(!
TrieGetCell(g_tCategoriesszValueiCategory))
                        {
                            
TrieSetCell(g_tCategoriesszValueg_iCategories)
                            
TrieSetCell(g_tKnivesInCategoryszValue1)
                            
ArrayPushString(g_aCategoriesszValue)
                            
iCategory g_iCategories++
                        }
                        else
                        {
                            
TrieGetCell(g_tKnivesInCategoryszValueiNum)
                            
TrieSetCell(g_tKnivesInCategoryszValue, ++iNum)
                        }

                        
eKnife[CATEGORY] = iCategory
                    
}
                    else continue

                    static const 
szModelArg[] = "_MODEL"
                    
static const szSoundArg[] = "_SOUND"

                    
if(contain(szKeyszModelArg) != -1)
                    {
                        if(!
file_exists(szValue))
                        {
                            
log_amx("ERROR: model ^"%s^" not found!"szValue)
                        }
                        else
                        {
                            
precache_model(szValue)
                        }
                    }
                    else if(
contain(szKeyszSoundArg) != -1)
                    {
                        
formatex(szSoundcharsmax(szSound), "sound/%s"szValue)

                        if(!
file_exists(szSound))
                        {
                            
log_amx("ERROR: sound ^"%s^" not found!"szSound)
                        }
                        else
                        {
                            
precache_sound(szValue)
                        }

                        if(
bCustom)
                        {
                            
eKnife[HAS_CUSTOM_SOUND] = true
                        
}
                    }
                }
            }
        }

        if(
g_iKnivesNum)
        {
            
push_knife(eKnife)
        }

        
fclose(iFilePointer)
    }
}

public 
client_connect(id)
{
    
g_bFirstTime[id] = true
    ArrayGetArray
(g_aKnives0g_eKnife[id])
    
g_iKnife[id] = 0

    
new iReturn
    ExecuteForward
(g_fwdKnifeUpdatediReturnidg_iKnife[id], true)

    if(
g_eCvars[km_save_choice])
    {
        
get_user_authid(idg_szAuth[id], charsmax(g_szAuth[]))
        
set_task(DELAY_ON_CONNECT"load_data"id)
    }
}

public 
client_disconnected(id)
{
    if(
g_eCvars[km_save_choice])
    {
        
use_vault(idtrue)
    }
}

public 
OnEmitSound(idiChannel, const szSample[])
{
    if(!
is_user_connected(id) || !g_eKnife[id][HAS_CUSTOM_SOUND] || !is_knife_sound(szSample))
    {
        return 
FMRES_IGNORED
    
}

    switch(
detect_knife_sound(szSample))
    {
        case 
SOUND_DEPLOY:         if(g_eKnife[id][DEPLOY_SOUND][0])         { play_knife_sound(idg_eKnife[id][DEPLOY_SOUND][0]);      return FMRES_SUPERCEDE; }
        case 
SOUND_HIT:         if(g_eKnife[id][HIT_SOUND][0])             { play_knife_sound(idg_eKnife[id][HIT_SOUND][0]);         return FMRES_SUPERCEDE; }
        case 
SOUND_HITWALL:        if(g_eKnife[id][HITWALL_SOUND][0])         { play_knife_sound(idg_eKnife[id][HITWALL_SOUND][0]);     return FMRES_SUPERCEDE; }
        case 
SOUND_SLASH:         if(g_eKnife[id][SLASH_SOUND][0])         { play_knife_sound(idg_eKnife[id][SLASH_SOUND][0]);       return FMRES_SUPERCEDE; }
        case 
SOUND_STAB:         if(g_eKnife[id][STAB_SOUND][0])         { play_knife_sound(idg_eKnife[id][STAB_SOUND][0]);        return FMRES_SUPERCEDE; }
    }

    return 
FMRES_IGNORED
}

public 
Cmd_Knife(id)
{
    
ShowMainMenu(id)
    return 
PLUGIN_HANDLED
}

ShowMainMenu(idiCategory INVALID_CATEGORY)
{
    if(
g_eCvars[km_only_dead] && is_user_alive(id))
    {
        
CC_SendMessage(id"%L %L"id"KM_CHAT_PREFIX"id"KM_ONLY_DEAD")
        return 
PLUGIN_HANDLED
    
}

    new 
szTitle[128], szItem[128], szId[8], iMenu

    
if(g_eCvars[km_categories] && g_iCategories && iCategory == INVALID_CATEGORY)
    {
        
formatex(szTitlecharsmax(szTitle), "%L"id"KM_MENU_TITLE2")
        
iMenu menu_create(szTitle"CategoriesHandler")

        for(new 
iiNumg_iCategoriesi++)
        {
            
ArrayGetString(g_aCategoriesiszItemcharsmax(szItem))
            
TrieGetCell(g_tKnivesInCategoryszItemiNum)
            
format(szItemcharsmax(szItem), "%L"id"KM_MENU_CATEGORY"szItemiNum)
            
num_to_str(iszIdcharsmax(szId))
            
menu_additem(iMenuszItemszId)
        }

        
menu_display(idiMenu)
        return 
PLUGIN_HANDLED
    
}

    static 
eKnife[Knives]
    new 
iLeveliXP

    
if(g_bGetLevel)
    {
        
iLevel crxranks_get_user_level(id)
    }

    if(
g_bGetXP)
    {
        
iXP crxranks_get_user_xp(id)
    }

    
formatex(szTitlecharsmax(szTitle), "%L"id"KM_MENU_TITLE")
    
iMenu menu_create(szTitle"MenuHandler")

    for(new 
iFlags get_user_flags(id), ig_iKnivesNumi++)
    {
        
ArrayGetArray(g_aKnivesieKnife)

        if(
g_eCvars[km_categories] && iCategory != INVALID_CATEGORY && eKnife[CATEGORY] != iCategory)
        {
            continue
        }

        
copy(szItemcharsmax(szItem), eKnife[NAME])

        if(
g_bRankSystem)
        {
            if(
eKnife[LEVEL] && iLevel eKnife[LEVEL])
            {
                if(
eKnife[SHOW_RANK])
                {
                    static 
szRank[32]
                    
crxranks_get_rank_by_level(eKnife[LEVEL], szRankcharsmax(szRank))
                    
format(szItemcharsmax(szItem), "%s %L"szItemid"KM_MENU_RANK"szRank)
                }
                else
                {
                    
format(szItemcharsmax(szItem), "%s %L"szItemid"KM_MENU_LEVEL"eKnife[LEVEL])
                }
            }

            if(
eKnife[XP] && iXP eKnife[XP])
            {
                
format(szItemcharsmax(szItem), "%s %L"szItemid"KM_MENU_XP"eKnife[XP])
            }
        }

        if(
eKnife[FLAG] != ADMIN_ALL && !(iFlags eKnife[FLAG]))
        {
            
format(szItemcharsmax(szItem), "%s %L"szItemid"KM_MENU_VIP_ONLY")
        }

        if(
g_iKnife[id] == i)
        {
            
format(szItemcharsmax(szItem), "%s %L"szItemid"KM_MENU_SELECTED")
        }

        
num_to_str(iszIdcharsmax(szId))
        
menu_additem(iMenuszItemszIdeKnife[FLAG], g_iCallback)
    }

    if(
menu_pages(iMenu) > 1)
    {
        
formatex(szItemcharsmax(szItem), "%s%L"szTitleid"KM_MENU_TITLE_PAGE")
        
menu_setprop(iMenuMPROP_TITLEszItem)
    }

    
menu_display(idiMenu)
    return 
PLUGIN_HANDLED
}

public 
Cmd_Select(idiLeveliCid)
{
    if(!
cmd_access(idiLeveliCid2))
    {
        return 
PLUGIN_HANDLED
    
}

    if(
g_eCvars[km_only_dead] && is_user_alive(id))
    {
        
CC_SendMessage(id"%L %L"id"KM_CHAT_PREFIX"id"KM_ONLY_DEAD")
        return 
PLUGIN_HANDLED
    
}

    new 
szKnife[4]
    
read_argv(1szKnifecharsmax(szKnife))

    new 
iKnife str_to_num(szKnife)

    if(!
is_knife_valid(iKnife))
    {
        
console_print(id"%l""KM_INVALID_KNIFE"g_iKnivesNum 1)
        return 
PLUGIN_HANDLED
    
}

    if(!
has_knife_access(idiKnife))
    {
        
console_print(id"%l""KM_NO_ACCESS")
        return 
PLUGIN_HANDLED
    
}

    
select_knife(idiKnife)
    return 
PLUGIN_HANDLED
}

public 
CategoriesHandler(idiMenuiItem)
{
    new 
szCategoryId[8]
    
menu_item_getinfo(iMenuiItem_unused[0], szCategoryIdcharsmax(szCategoryId), _unusedcharsmax(_unused), _unused[0])

    
menu_destroy(iMenu)

    if(
iItem != MENU_EXIT)
    {
        
ShowMainMenu(idstr_to_num(szCategoryId))
    }

    return 
PLUGIN_HANDLED
}

public 
MenuHandler(idiMenuiItem)
{
    if(
g_eCvars[km_only_dead] && is_user_alive(id))
    {
        
CC_SendMessage(id"%L %L"id"KM_CHAT_PREFIX"id"KM_ONLY_DEAD")
        goto @
MENU_DESTROY
    
}

    if(!
is_user_connected(id))
    {
        goto @
MENU_DESTROY
    
}

    if(
iItem != MENU_EXIT)
    {
        new 
szKnifeId[8]
        
menu_item_getinfo(iMenuiItem_unused[0], szKnifeIdcharsmax(szKnifeId), _unusedcharsmax(_unused), _unused[0])
        
select_knife(idstr_to_num(szKnifeId))
    }

    @
MENU_DESTROY:
    
menu_destroy(iMenu)
    return 
PLUGIN_HANDLED
}

select_knife(idiKnife)
{
    new 
iReturn
    ExecuteForward
(g_fwdAttemptChangeiReturnidiKnife)

    if(
iReturn == PLUGIN_HANDLED)
    {
        return
    }

    
g_iKnife[id] = iKnife
    ArrayGetArray
(g_aKnivesiKnifeg_eKnife[id])
    
ExecuteForward(g_fwdKnifeUpdatediReturnidiKnifefalse)

    if(
is_user_alive(id) && get_user_weapon(id) == CSW_KNIFE)
    {
        
refresh_knife_model(id)
    }

    if(
g_eCvars[km_select_message])
    {
        new 
szMessage[160]
        
formatex(szMessagecharsmax(szMessage), "%L %L"id"KM_CHAT_PREFIX"id"KM_CHAT_SELECTED"g_eKnife[id][NAME])
        
CC_RemoveColors(szMessagecharsmax(szMessage), falsetrue)
        
CC_SendMessage(idszMessage)
    }

    if(
g_eKnife[id][SELECT_MESSAGES_NUM])
    {
        for(new 
ig_eKnife[id][SELECT_MESSAGES_NUM]; i++)
        {
            
CC_SendMessage(id"%a"ArrayGetStringHandle(g_eKnife[id][SELECT_MESSAGES], i))
        }
    }

    if(
g_eKnife[id][SELECT_SOUND][0])
    {
        
play_knife_sound(idg_eKnife[id][SELECT_SOUND])
    }
}

public 
load_data(id)
{
    if(
is_user_connected(id))
    {
        
use_vault(idfalse)
    }
}

public 
CheckKnifeAccess(idiMenuiItem)
{
    new 
szKnifeId[8]
    
menu_item_getinfo(iMenuiItem_unused[0], szKnifeIdcharsmax(szKnifeId), _unusedcharsmax(_unused), _unused[0])

    new 
iKnife str_to_num(szKnifeId)

    return ((
g_iKnife[id] == iKnife) || !has_knife_access(idiKnife)) ? ITEM_DISABLED ITEM_ENABLED
}

public 
OnPlayerSpawn(id)
{
    if(
is_user_alive(id) && g_eCvars[km_open_at_spawn] && !g_iKnife[id] && g_bFirstTime[id] && (g_iMenuFlags ADMIN_USER || get_user_flags(id) & g_iMenuFlags))
    {
        
g_bFirstTime[id] = false
        Cmd_Knife
(id)
    }
}

public 
OnSelectKnife(iEnt)
{
    new 
id get_pdata_cbase(iEntm_pPlayer4)

    if(
is_user_connected(id))
    {
        
refresh_knife_model(id)
    }
}

refresh_knife_model(const id)
{
    
set_pev(idpev_viewmodel2g_eKnife[id][V_MODEL])
    
set_pev(idpev_weaponmodel2g_eKnife[id][P_MODEL])
}

push_knife(eKnife[Knives])
{
    if(!
eKnife[V_MODEL][0])
    {
        
copy(eKnife[V_MODEL], charsmax(eKnife[V_MODEL]), CRXKNIVES_DEFAULT_V)
    }

    if(!
eKnife[P_MODEL][0])
    {
        
copy(eKnife[P_MODEL], charsmax(eKnife[P_MODEL]), CRXKNIVES_DEFAULT_P)
    }

    if(!
eKnife[FLAG])
    {
        
g_iMenuFlags |= ADMIN_USER
    
}

    if(
eKnife[CATEGORY] == INVALID_CATEGORY)
    {
        new 
iNum
        TrieGetCell
(g_tKnivesInCategoryINVALID_CATEGORY_STRiNum)
        
TrieSetCell(g_tKnivesInCategoryINVALID_CATEGORY_STR, ++iNum)
    }

    
ArrayPushArray(g_aKniveseKnife)
}

bool:has_knife_access(const id, const iKnife)
{
    static 
eKnife[Knives]
    
ArrayGetArray(g_aKnivesiKnifeeKnife)

    if(
eKnife[FLAG] != ADMIN_ALL)
    {
        if(
get_user_flags(id) & eKnife[FLAG])
        {
            if(
g_eCvars[km_admin_bypass])
            {
                return 
true
            
}
        }
        else
        {
            return 
false
        
}
    }

    if(
g_bRankSystem)
    {
        if(
eKnife[LEVEL] && crxranks_get_user_level(id) < eKnife[LEVEL])
        {
            return 
false
        
}

        if(
eKnife[XP] && crxranks_get_user_xp(id) < eKnife[XP])
        {
            return 
false
        
}
    }

    return 
true
}

bool:is_knife_sound(const szSample[])
{
    return 
bool:equal(szSample[8], "kni"3)
}

detect_knife_sound(const szSample[])
{
    static 
iSound
    iSound 
SOUND_NONE

    
if(equal(szSample"weapons/knife_deploy1.wav"))
    {
        
iSound SOUND_DEPLOY
    
}
    else if(
equal(szSample[14], "hit"3))
    {
        
iSound szSample[17] == 'w' SOUND_HITWALL SOUND_HIT
    
}
    else if(
equal(szSample[14], "sla"3))
    {
        
iSound SOUND_SLASH
    
}
    else if(
equal(szSample[14], "sta"3))
    {
        
iSound SOUND_STAB
    
}

    return 
iSound
}

use_vault(const id, const bool:bSave)
{
    if(
bSave)
    {
        new 
szData[4]
        
num_to_str(g_iKnife[id], szDatacharsmax(szData))
        
nvault_set(g_iVaultg_szAuth[id], szData)
    }
    else
    {
        new 
iKnife
        iKnife 
nvault_get(g_iVaultg_szAuth[id])

        if(!
is_knife_valid(iKnife))
        {
            
iKnife 0
        
}
        else if(
has_knife_access(idiKnife))
        {
            
g_iKnife[id] = iKnife

            
new iReturn
            ArrayGetArray
(g_aKnivesiKnifeg_eKnife[id])
            
ExecuteForward(g_fwdKnifeUpdatediReturnidiKnifefalse)

            if(
is_user_alive(id) && get_user_weapon(id) == CSW_KNIFE)
            {
                
refresh_knife_model(id)
            }
        }
    }
}

play_knife_sound(const id, const szSound[])
{
    
engfunc(EngFunc_EmitSoundidCHAN_AUTOszSound1.0ATTN_NORM0PITCH_NORM)
}

bool:is_knife_valid(const iKnife)
{
    return 
<= iKnife g_iKnivesNum
}

public 
plugin_natives()
{
    
register_library("crxknives")
    
register_native("crxknives_can_use_skill",       "_crxknives_can_use_skill")
    
register_native("crxknives_get_attribute_int",   "_crxknives_get_attribute_int")
    
register_native("crxknives_get_attribute_float""_crxknives_get_attribute_float")
    
register_native("crxknives_get_attribute_str",   "_crxknives_get_attribute_str")
    
register_native("crxknives_get_knives_num",      "_crxknives_get_knives_num")
    
register_native("crxknives_get_user_knife",      "_crxknives_get_user_knife")
    
register_native("crxknives_has_knife_access",    "_crxknives_has_knife_access")
    
register_native("crxknives_is_knife_valid",      "_crxknives_is_knife_valid")
    
set_native_filter("native_filter")
}

public 
native_filter(const szNative[], idiTrap)
{
    if(!
iTrap)
    {
        static 
i

        
for(0sizeof(g_szNatives); i++)
        {
            if(
equal(szNativeg_szNatives[i]))
            {
                return 
PLUGIN_HANDLED
            
}
        }
    }

    return 
PLUGIN_CONTINUE
}

public 
bool:_crxknives_can_use_skill(iPluginiParams)
{
    return !
g_eCvars[km_knife_only_skills] || (get_user_weapon(get_param(1)) == CSW_KNIFE)
}

public 
bool:_crxknives_get_attribute_int(iPluginiParams)
{
    static 
szAttribute[MAX_NAME_LENGTH], szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], id
    get_string
(2szAttributecharsmax(szAttribute))
    
id get_param(1)

    if(!
get_param(4))
    {
        if(!
is_knife_valid(id))
        {
            return 
false
        
}

        static 
eKnife[Knives]
        
ArrayGetArray(g_aKnivesideKnife)

        if(!
TrieKeyExists(eKnife[ATTRIBUTES], szAttribute))
        {
            return 
false
        
}

        
TrieGetString(eKnife[ATTRIBUTES], szAttributeszValuecharsmax(szValue))
        goto @
SET_ATTRIBUTE
    
}

    if(!
TrieKeyExists(g_eKnife[id][ATTRIBUTES], szAttribute))
    {
        return 
false
    
}

    
TrieGetString(g_eKnife[id][ATTRIBUTES], szAttributeszValuecharsmax(szValue))

    @
SET_ATTRIBUTE:
    
set_param_byref(3str_to_num(szValue))
    return 
true
}

public 
bool:_crxknives_get_attribute_float(iPluginiParams)
{
    static 
szAttribute[MAX_NAME_LENGTH], szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], id
    get_string
(2szAttributecharsmax(szAttribute))
    
id get_param(1)

    if(!
get_param(4))
    {
        if(!
is_knife_valid(id))
        {
            return 
false
        
}

        static 
eKnife[Knives]
        
ArrayGetArray(g_aKnivesideKnife)

        if(!
TrieKeyExists(eKnife[ATTRIBUTES], szAttribute))
        {
            return 
false
        
}

        
TrieGetString(eKnife[ATTRIBUTES], szAttributeszValuecharsmax(szValue))
        goto @
SET_ATTRIBUTE
    
}

    if(!
TrieKeyExists(g_eKnife[id][ATTRIBUTES], szAttribute))
    {
        return 
false
    
}

    
TrieGetString(g_eKnife[id][ATTRIBUTES], szAttributeszValuecharsmax(szValue))

    @
SET_ATTRIBUTE:
    
set_float_byref(3str_to_float(szValue))
    return 
true
}

public 
bool:_crxknives_get_attribute_str(iPluginiParams)
{
    static 
szAttribute[MAX_NAME_LENGTH], szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], id
    get_string
(2szAttributecharsmax(szAttribute))
    
id get_param(1)

    if(!
get_param(5))
    {
        if(!
is_knife_valid(id))
        {
            return 
false
        
}

        static 
eKnife[Knives]
        
ArrayGetArray(g_aKnivesideKnife)

        if(!
TrieKeyExists(eKnife[ATTRIBUTES], szAttribute))
        {
            return 
false
        
}

        
TrieGetString(eKnife[ATTRIBUTES], szAttributeszValuecharsmax(szValue))
        goto @
SET_ATTRIBUTE
    
}

    if(!
TrieKeyExists(g_eKnife[id][ATTRIBUTES], szAttribute))
    {
        return 
false
    
}

    
TrieGetString(g_eKnife[id][ATTRIBUTES], szAttributeszValuecharsmax(szValue))

    @
SET_ATTRIBUTE:
    
set_string(3szValueget_param(4))
    return 
true
}

public 
_crxknives_get_knives_num(iPluginiParams)
{
    return 
g_iKnivesNum
}

public 
_crxknives_get_user_knife(iPluginiParams)
{
    return 
g_iKnife[get_param(1)]
}

public 
bool:_crxknives_has_knife_access(iPluginiParams)
{
    return 
has_knife_access(get_param(1), get_param(2))
}

public 
bool:_crxknives_is_knife_valid(iPluginiParams)
{
    return 
is_knife_valid(get_param(1))

__________________

Last edited by OciXCrom; 06-21-2022 at 17:18.
OciXCrom is offline
Send a message via Skype™ to OciXCrom
Old 07-04-2022, 01:55
MeliMeli
This message has been deleted by MeliMeli. Reason: Fixed
MeliMeli
Member
Join Date: Apr 2022
Old 07-04-2022 , 18:53   Re: Knife Models [XP System & Skills Support]
Reply With Quote #343

To have you support for Zombie Plague would be perfect, or some cvar to disable the skills when the human turns into Zombie.
MeliMeli is offline
Erra
Member
Join Date: Jun 2021
Old 07-18-2022 , 13:08   Re: Knife Models [XP System & Skills Support]
Reply With Quote #344

Quote:
Originally Posted by OciXCrom View Post
That is planned for the next update which I can't tell when it would be.
Of course I won't make it have only 3 categories. That's amateur work.

This is a beta-version of what I tried some time ago. Not sure if it works properly but you can test it.
Make sure to spell CATEGORY with capital letters in the .ini file.

PHP Code:
#include <amxmodx>
#include <amxmisc>
#include <crxknives_const>
#include <cromchat>
#include <fakemeta>
#include <hamsandwich>
#include <nvault>

native crxranks_get_max_levels()
native crxranks_get_rank_by_level(levelbuffer[], len)
native crxranks_get_user_level(id)
native crxranks_get_user_xp(id)

new const 
g_szNatives[][] =
{
    
"crxranks_get_max_levels",
    
"crxranks_get_rank_by_level",
    
"crxranks_get_user_level",
    
"crxranks_get_user_xp"
}

#if !defined m_pPlayer
const m_pPlayer 41
#endif

#if !defined client_disconnected
    #define client_disconnected client_disconnect
#endif

new const PLUGIN_VERSION[] = "3.2-beta"
const Float:DELAY_ON_CONNECT 3.0

#if !defined MAX_AUTHID_LENGTH
const MAX_AUTHID_LENGTH 35
#endif

#if !defined MAX_NAME_LENGTH
const MAX_NAME_LENGTH 32
#endif

#if !defined MAX_PLAYERS
const MAX_PLAYERS 32
#endif

const INVALID_CATEGORY = -1
new const INVALID_CATEGORY_STR[] = "Other"

enum
{
    
SOUND_NONE 0,
    
SOUND_DEPLOY,
    
SOUND_HIT,
    
SOUND_HITWALL,
    
SOUND_SLASH,
    
SOUND_STAB
}

enum _:Knives
{
    
NAME[MAX_NAME_LENGTH],
    
V_MODEL[CRXKNIVES_MAX_SOUND_LENGTH],
    
P_MODEL[CRXKNIVES_MAX_SOUND_LENGTH],
    
DEPLOY_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
    
HIT_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
    
HITWALL_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
    
SLASH_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
    
STAB_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
    
SELECT_SOUND[CRXKNIVES_MAX_SOUND_LENGTH],
    
FLAG,
    
LEVEL,
    
XP,
    
SELECT_MESSAGES_NUM,
    
CATEGORY,
    
bool:SHOW_RANK,
    
bool:HAS_CUSTOM_SOUND,
    Array:
SELECT_MESSAGES,
    
Trie:ATTRIBUTES
}

enum _:CvarsReg
{
    
cvar_km_open_at_spawn,
    
cvar_km_save_choice,
    
cvar_km_only_dead,
    
cvar_km_select_message,
    
cvar_km_knife_only_skills,
    
cvar_km_admin_bypass,
    
cvar_km_categories
}

enum _:Cvars
{
    
km_open_at_spawn,
    
km_save_choice,
    
km_only_dead,
    
km_select_message,
    
km_knife_only_skills,
    
km_admin_bypass,
    
km_categories
}

new Array:
g_aKnives,
    Array:
g_aCategories,
    
Trie:g_tCategories,
    
Trie:g_tKnivesInCategory,
    
bool:g_bFirstTime[MAX_PLAYERS 1],
    
bool:g_bRankSystem,
    
bool:g_bGetLevel,
    
bool:g_bGetXP,
    
g_eCvars[Cvars],
    
g_eCvarsReg[CvarsReg],
    
g_eKnife[MAX_PLAYERS 1][Knives],
    
g_szAuth[MAX_PLAYERS 1][MAX_AUTHID_LENGTH],
    
g_iKnife[MAX_PLAYERS 1],
    
g_fwdKnifeUpdated,
    
g_fwdAttemptChange,
    
g_iMenuFlags,
    
g_iKnivesNum,
    
g_iCategories,
    
g_iCallback,
    
g_iVault

new _unused[1]

public 
plugin_init()
{
    
register_plugin("Knife Models"PLUGIN_VERSION"OciXCrom")
    
register_cvar("CRXKnifeModels"PLUGIN_VERSIONFCVAR_SERVER|FCVAR_SPONLY|FCVAR_UNLOGGED)

    if(!
g_iKnivesNum)
    {
        
set_fail_state("No knives found in the configuration file.")
    }

    
register_dictionary("KnifeModels.txt")

    
RegisterHam(Ham_Spawn"player""OnPlayerSpawn"1)
    
register_forward(FM_EmitSound,    "OnEmitSound")
    
RegisterHam(Ham_Item_Deploy"weapon_knife""OnSelectKnife"1)

    
register_clcmd("say /knife",       "Cmd_Knife")
    
register_clcmd("say_team /knife",  "Cmd_Knife")
    
register_clcmd("crxknives_select""Cmd_Select"_"<knife id>")

    
g_fwdKnifeUpdated  CreateMultiForward("crxknives_knife_updated",  ET_IGNOREFP_CELLFP_CELLFP_CELL)
    
g_fwdAttemptChange CreateMultiForward("crxknives_attempt_change"ET_STOP,   FP_CELLFP_CELL)

    
g_iCallback menu_makecallback("CheckKnifeAccess")

    
g_eCvarsReg[cvar_km_open_at_spawn]     = register_cvar("km_open_at_spawn",     "0")
    
g_eCvarsReg[cvar_km_save_choice]       = register_cvar("km_save_choice",       "1")
    
g_eCvarsReg[cvar_km_only_dead]         = register_cvar("km_only_dead",         "0")
    
g_eCvarsReg[cvar_km_select_message]    = register_cvar("km_select_message",    "1")
    
g_eCvarsReg[cvar_km_knife_only_skills] = register_cvar("km_knife_only_skills""1")
    
g_eCvarsReg[cvar_km_admin_bypass]      = register_cvar("km_admin_bypass",      "0")
    
g_eCvarsReg[cvar_km_categories]        = register_cvar("km_categories",        "1")
}

public 
plugin_precache()
{
    if(
LibraryExists("crxranks"LibType_Library))
    {
        
g_bRankSystem true
    
}

    
g_aKnives           ArrayCreate(Knives)
    
g_aCategories       ArrayCreate(MAX_NAME_LENGTH)
    
g_tCategories       TrieCreate()
    
g_tKnivesInCategory TrieCreate()
    
ReadFile()
}

public 
plugin_cfg()
{
    
g_eCvars[km_save_choice]       = get_pcvar_num(g_eCvarsReg[cvar_km_save_choice])
    
g_eCvars[km_open_at_spawn]     = get_pcvar_num(g_eCvarsReg[cvar_km_open_at_spawn])
    
g_eCvars[km_only_dead]         = get_pcvar_num(g_eCvarsReg[cvar_km_only_dead])
    
g_eCvars[km_select_message]    = get_pcvar_num(g_eCvarsReg[cvar_km_select_message])
    
g_eCvars[km_knife_only_skills] = get_pcvar_num(g_eCvarsReg[cvar_km_knife_only_skills])
    
g_eCvars[km_admin_bypass]      = get_pcvar_num(g_eCvarsReg[cvar_km_admin_bypass])
    
g_eCvars[km_categories]        = get_pcvar_num(g_eCvarsReg[cvar_km_categories])

    if(
g_eCvars[km_save_choice])
    {
        
g_iVault nvault_open("KnifeModels")
    }
}

public 
plugin_end()
{
    for(new 
eKnife[Knives], ig_iKnivesNumi++)
    {
        
ArrayGetArray(g_aKnivesieKnife)
        
ArrayDestroy(eKnife[SELECT_MESSAGES])
        
TrieDestroy(eKnife[ATTRIBUTES])
    }

    
ArrayDestroy(g_aKnives)
    
ArrayDestroy(g_aCategories)
    
TrieDestroy(g_tCategories)
    
TrieDestroy(g_tKnivesInCategory)

    if(
g_eCvars[km_save_choice])
    {
        
nvault_close(g_iVault)
    }
}

ReadFile()
{
    new 
szFilename[256]
    
get_configsdir(szFilenamecharsmax(szFilename))
    
add(szFilenamecharsmax(szFilename), "/KnifeModels.ini")
    new 
iFilePointer fopen(szFilename"rt")

    if(
iFilePointer)
    {
        new 
szData[160], szKey[32], szValue[128], szSound[128], iMaxLevelsiCategoryiNum
        
new eKnife[Knives], bool:bCustom

        
if(g_bRankSystem)
        {
            
iMaxLevels crxranks_get_max_levels()
        }

        while(!
feof(iFilePointer))
        {
            
fgets(iFilePointerszDatacharsmax(szData))
            
trim(szData)

            switch(
szData[0])
            {
                case 
EOS'#'';': continue
                case 
'[':
                {
                    if(
szData[strlen(szData) - 1] == ']')
                    {
                        if(
g_iKnivesNum)
                        {
                            
push_knife(eKnife)
                        }

                        
g_iKnivesNum++
                        
replace(szDatacharsmax(szData), "[""")
                        
replace(szDatacharsmax(szData), "]""")
                        
copy(eKnife[NAME], charsmax(eKnife[NAME]), szData)

                        
eKnife[V_MODEL][0]          = EOS
                        eKnife
[P_MODEL][0]          = EOS
                        eKnife
[DEPLOY_SOUND][0]     = EOS
                        eKnife
[HIT_SOUND][0]        = EOS
                        eKnife
[HITWALL_SOUND][0]    = EOS
                        eKnife
[SLASH_SOUND][0]      = EOS
                        eKnife
[STAB_SOUND][0]       = EOS
                        eKnife
[SELECT_SOUND][0]     = EOS
                        eKnife
[FLAG]                = ADMIN_ALL
                        eKnife
[HAS_CUSTOM_SOUND]    = false
                        eKnife
[CATEGORY]            = INVALID_CATEGORY
                        eKnife
[SELECT_MESSAGES_NUM] = 0
                        eKnife
[SELECT_MESSAGES]     = _:ArrayCreate(CRXKNIVES_MAX_MESSAGE_LENGTH)
                        
eKnife[ATTRIBUTES]          = _:TrieCreate()

                        if(
g_bRankSystem)
                        {
                            
eKnife[LEVEL] = 0
                            eKnife
[SHOW_RANK] = false
                            eKnife
[XP] = 0
                        
}

                        static const 
ATTRIBUTE_NAME[] = "NAME"
                        
TrieSetString(eKnife[ATTRIBUTES], ATTRIBUTE_NAMEszData)
                    }
                    else continue
                }
                default:
                {
                    
strtok(szDataszKeycharsmax(szKey), szValuecharsmax(szValue), '=')
                    
trim(szKey); trim(szValue)
                    
bCustom true

                    TrieSetString
(eKnife[ATTRIBUTES], szKeyszValue)

                    if(
equal(szKey"FLAG"))
                    {
                        
eKnife[FLAG] = read_flags(szValue)
                        
g_iMenuFlags |= eKnife[FLAG]
                    }
                    else if(
equal(szKey"LEVEL") && g_bRankSystem)
                    {
                        
eKnife[LEVEL] = clamp(str_to_num(szValue), 0iMaxLevels)

                        if(!
g_bGetLevel)
                        {
                            
g_bGetLevel true
                        
}
                    }
                    else if(
equal(szKey"SHOW_RANK") && g_bRankSystem)
                    {
                        
eKnife[SHOW_RANK] = _:clamp(str_to_num(szValue), falsetrue)
                    }
                    else if(
equal(szKey"XP") && g_bRankSystem)
                    {
                        
eKnife[XP] = _:clamp(str_to_num(szValue), 0)

                        if(!
g_bGetXP)
                        {
                            
g_bGetXP true
                        
}
                    }
                    else if(
equal(szKey"V_MODEL"))
                    {
                        
copy(eKnife[V_MODEL], charsmax(eKnife[V_MODEL]), szValue)
                    }
                    else if(
equal(szKey"P_MODEL"))
                    {
                        
copy(eKnife[P_MODEL], charsmax(eKnife[P_MODEL]), szValue)
                    }
                    else if(
equal(szKey"DEPLOY_SOUND"))
                    {
                        
copy(eKnife[DEPLOY_SOUND], charsmax(eKnife[DEPLOY_SOUND]), szValue)
                    }
                    else if(
equal(szKey"HIT_SOUND"))
                    {
                        
copy(eKnife[HIT_SOUND], charsmax(eKnife[HIT_SOUND]), szValue)
                    }
                    else if(
equal(szKey"HITWALL_SOUND"))
                    {
                        
copy(eKnife[HITWALL_SOUND], charsmax(eKnife[HITWALL_SOUND]), szValue)
                    }
                    else if(
equal(szKey"SLASH_SOUND"))
                    {
                        
copy(eKnife[SLASH_SOUND], charsmax(eKnife[SLASH_SOUND]), szValue)
                    }
                    else if(
equal(szKey"STAB_SOUND"))
                    {
                        
copy(eKnife[STAB_SOUND], charsmax(eKnife[STAB_SOUND]), szValue)
                    }
                    else if(
equal(szKey"SELECT_SOUND"))
                    {
                        
bCustom false
                        copy
(eKnife[SELECT_SOUND], charsmax(eKnife[SELECT_SOUND]), szValue)
                    }
                    else if(
equal(szKey"SELECT_MESSAGE"))
                    {
                        
ArrayPushString(eKnife[SELECT_MESSAGES], szValue)
                        
eKnife[SELECT_MESSAGES_NUM]++
                    }
                    else if(
equal(szKey"CATEGORY"))
                    {
                        if(!
TrieGetCell(g_tCategoriesszValueiCategory))
                        {
                            
TrieSetCell(g_tCategoriesszValueg_iCategories)
                            
TrieSetCell(g_tKnivesInCategoryszValue1)
                            
ArrayPushString(g_aCategoriesszValue)
                            
iCategory g_iCategories++
                        }
                        else
                        {
                            
TrieGetCell(g_tKnivesInCategoryszValueiNum)
                            
TrieSetCell(g_tKnivesInCategoryszValue, ++iNum)
                        }

                        
eKnife[CATEGORY] = iCategory
                    
}
                    else continue

                    static const 
szModelArg[] = "_MODEL"
                    
static const szSoundArg[] = "_SOUND"

                    
if(contain(szKeyszModelArg) != -1)
                    {
                        if(!
file_exists(szValue))
                        {
                            
log_amx("ERROR: model ^"%s^" not found!"szValue)
                        }
                        else
                        {
                            
precache_model(szValue)
                        }
                    }
                    else if(
contain(szKeyszSoundArg) != -1)
                    {
                        
formatex(szSoundcharsmax(szSound), "sound/%s"szValue)

                        if(!
file_exists(szSound))
                        {
                            
log_amx("ERROR: sound ^"%s^" not found!"szSound)
                        }
                        else
                        {
                            
precache_sound(szValue)
                        }

                        if(
bCustom)
                        {
                            
eKnife[HAS_CUSTOM_SOUND] = true
                        
}
                    }
                }
            }
        }

        if(
g_iKnivesNum)
        {
            
push_knife(eKnife)
        }

        
fclose(iFilePointer)
    }
}

public 
client_connect(id)
{
    
g_bFirstTime[id] = true
    ArrayGetArray
(g_aKnives0g_eKnife[id])
    
g_iKnife[id] = 0

    
new iReturn
    ExecuteForward
(g_fwdKnifeUpdatediReturnidg_iKnife[id], true)

    if(
g_eCvars[km_save_choice])
    {
        
get_user_authid(idg_szAuth[id], charsmax(g_szAuth[]))
        
set_task(DELAY_ON_CONNECT"load_data"id)
    }
}

public 
client_disconnected(id)
{
    if(
g_eCvars[km_save_choice])
    {
        
use_vault(idtrue)
    }
}

public 
OnEmitSound(idiChannel, const szSample[])
{
    if(!
is_user_connected(id) || !g_eKnife[id][HAS_CUSTOM_SOUND] || !is_knife_sound(szSample))
    {
        return 
FMRES_IGNORED
    
}

    switch(
detect_knife_sound(szSample))
    {
        case 
SOUND_DEPLOY:         if(g_eKnife[id][DEPLOY_SOUND][0])         { play_knife_sound(idg_eKnife[id][DEPLOY_SOUND][0]);      return FMRES_SUPERCEDE; }
        case 
SOUND_HIT:         if(g_eKnife[id][HIT_SOUND][0])             { play_knife_sound(idg_eKnife[id][HIT_SOUND][0]);         return FMRES_SUPERCEDE; }
        case 
SOUND_HITWALL:        if(g_eKnife[id][HITWALL_SOUND][0])         { play_knife_sound(idg_eKnife[id][HITWALL_SOUND][0]);     return FMRES_SUPERCEDE; }
        case 
SOUND_SLASH:         if(g_eKnife[id][SLASH_SOUND][0])         { play_knife_sound(idg_eKnife[id][SLASH_SOUND][0]);       return FMRES_SUPERCEDE; }
        case 
SOUND_STAB:         if(g_eKnife[id][STAB_SOUND][0])         { play_knife_sound(idg_eKnife[id][STAB_SOUND][0]);        return FMRES_SUPERCEDE; }
    }

    return 
FMRES_IGNORED
}

public 
Cmd_Knife(id)
{
    
ShowMainMenu(id)
    return 
PLUGIN_HANDLED
}

ShowMainMenu(idiCategory INVALID_CATEGORY)
{
    if(
g_eCvars[km_only_dead] && is_user_alive(id))
    {
        
CC_SendMessage(id"%L %L"id"KM_CHAT_PREFIX"id"KM_ONLY_DEAD")
        return 
PLUGIN_HANDLED
    
}

    new 
szTitle[128], szItem[128], szId[8], iMenu

    
if(g_eCvars[km_categories] && g_iCategories && iCategory == INVALID_CATEGORY)
    {
        
formatex(szTitlecharsmax(szTitle), "%L"id"KM_MENU_TITLE2")
        
iMenu menu_create(szTitle"CategoriesHandler")

        for(new 
iiNumg_iCategoriesi++)
        {
            
ArrayGetString(g_aCategoriesiszItemcharsmax(szItem))
            
TrieGetCell(g_tKnivesInCategoryszItemiNum)
            
format(szItemcharsmax(szItem), "%L"id"KM_MENU_CATEGORY"szItemiNum)
            
num_to_str(iszIdcharsmax(szId))
            
menu_additem(iMenuszItemszId)
        }

        
menu_display(idiMenu)
        return 
PLUGIN_HANDLED
    
}

    static 
eKnife[Knives]
    new 
iLeveliXP

    
if(g_bGetLevel)
    {
        
iLevel crxranks_get_user_level(id)
    }

    if(
g_bGetXP)
    {
        
iXP crxranks_get_user_xp(id)
    }

    
formatex(szTitlecharsmax(szTitle), "%L"id"KM_MENU_TITLE")
    
iMenu menu_create(szTitle"MenuHandler")

    for(new 
iFlags get_user_flags(id), ig_iKnivesNumi++)
    {
        
ArrayGetArray(g_aKnivesieKnife)

        if(
g_eCvars[km_categories] && iCategory != INVALID_CATEGORY && eKnife[CATEGORY] != iCategory)
        {
            continue
        }

        
copy(szItemcharsmax(szItem), eKnife[NAME])

        if(
g_bRankSystem)
        {
            if(
eKnife[LEVEL] && iLevel eKnife[LEVEL])
            {
                if(
eKnife[SHOW_RANK])
                {
                    static 
szRank[32]
                    
crxranks_get_rank_by_level(eKnife[LEVEL], szRankcharsmax(szRank))
                    
format(szItemcharsmax(szItem), "%s %L"szItemid"KM_MENU_RANK"szRank)
                }
                else
                {
                    
format(szItemcharsmax(szItem), "%s %L"szItemid"KM_MENU_LEVEL"eKnife[LEVEL])
                }
            }

            if(
eKnife[XP] && iXP eKnife[XP])
            {
                
format(szItemcharsmax(szItem), "%s %L"szItemid"KM_MENU_XP"eKnife[XP])
            }
        }

        if(
eKnife[FLAG] != ADMIN_ALL && !(iFlags eKnife[FLAG]))
        {
            
format(szItemcharsmax(szItem), "%s %L"szItemid"KM_MENU_VIP_ONLY")
        }

        if(
g_iKnife[id] == i)
        {
            
format(szItemcharsmax(szItem), "%s %L"szItemid"KM_MENU_SELECTED")
        }

        
num_to_str(iszIdcharsmax(szId))
        
menu_additem(iMenuszItemszIdeKnife[FLAG], g_iCallback)
    }

    if(
menu_pages(iMenu) > 1)
    {
        
formatex(szItemcharsmax(szItem), "%s%L"szTitleid"KM_MENU_TITLE_PAGE")
        
menu_setprop(iMenuMPROP_TITLEszItem)
    }

    
menu_display(idiMenu)
    return 
PLUGIN_HANDLED
}

public 
Cmd_Select(idiLeveliCid)
{
    if(!
cmd_access(idiLeveliCid2))
    {
        return 
PLUGIN_HANDLED
    
}

    if(
g_eCvars[km_only_dead] && is_user_alive(id))
    {
        
CC_SendMessage(id"%L %L"id"KM_CHAT_PREFIX"id"KM_ONLY_DEAD")
        return 
PLUGIN_HANDLED
    
}

    new 
szKnife[4]
    
read_argv(1szKnifecharsmax(szKnife))

    new 
iKnife str_to_num(szKnife)

    if(!
is_knife_valid(iKnife))
    {
        
console_print(id"%l""KM_INVALID_KNIFE"g_iKnivesNum 1)
        return 
PLUGIN_HANDLED
    
}

    if(!
has_knife_access(idiKnife))
    {
        
console_print(id"%l""KM_NO_ACCESS")
        return 
PLUGIN_HANDLED
    
}

    
select_knife(idiKnife)
    return 
PLUGIN_HANDLED
}

public 
CategoriesHandler(idiMenuiItem)
{
    new 
szCategoryId[8]
    
menu_item_getinfo(iMenuiItem_unused[0], szCategoryIdcharsmax(szCategoryId), _unusedcharsmax(_unused), _unused[0])

    
menu_destroy(iMenu)

    if(
iItem != MENU_EXIT)
    {
        
ShowMainMenu(idstr_to_num(szCategoryId))
    }

    return 
PLUGIN_HANDLED
}

public 
MenuHandler(idiMenuiItem)
{
    if(
g_eCvars[km_only_dead] && is_user_alive(id))
    {
        
CC_SendMessage(id"%L %L"id"KM_CHAT_PREFIX"id"KM_ONLY_DEAD")
        goto @
MENU_DESTROY
    
}

    if(!
is_user_connected(id))
    {
        goto @
MENU_DESTROY
    
}

    if(
iItem != MENU_EXIT)
    {
        new 
szKnifeId[8]
        
menu_item_getinfo(iMenuiItem_unused[0], szKnifeIdcharsmax(szKnifeId), _unusedcharsmax(_unused), _unused[0])
        
select_knife(idstr_to_num(szKnifeId))
    }

    @
MENU_DESTROY:
    
menu_destroy(iMenu)
    return 
PLUGIN_HANDLED
}

select_knife(idiKnife)
{
    new 
iReturn
    ExecuteForward
(g_fwdAttemptChangeiReturnidiKnife)

    if(
iReturn == PLUGIN_HANDLED)
    {
        return
    }

    
g_iKnife[id] = iKnife
    ArrayGetArray
(g_aKnivesiKnifeg_eKnife[id])
    
ExecuteForward(g_fwdKnifeUpdatediReturnidiKnifefalse)

    if(
is_user_alive(id) && get_user_weapon(id) == CSW_KNIFE)
    {
        
refresh_knife_model(id)
    }

    if(
g_eCvars[km_select_message])
    {
        new 
szMessage[160]
        
formatex(szMessagecharsmax(szMessage), "%L %L"id"KM_CHAT_PREFIX"id"KM_CHAT_SELECTED"g_eKnife[id][NAME])
        
CC_RemoveColors(szMessagecharsmax(szMessage), falsetrue)
        
CC_SendMessage(idszMessage)
    }

    if(
g_eKnife[id][SELECT_MESSAGES_NUM])
    {
        for(new 
ig_eKnife[id][SELECT_MESSAGES_NUM]; i++)
        {
            
CC_SendMessage(id"%a"ArrayGetStringHandle(g_eKnife[id][SELECT_MESSAGES], i))
        }
    }

    if(
g_eKnife[id][SELECT_SOUND][0])
    {
        
play_knife_sound(idg_eKnife[id][SELECT_SOUND])
    }
}

public 
load_data(id)
{
    if(
is_user_connected(id))
    {
        
use_vault(idfalse)
    }
}

public 
CheckKnifeAccess(idiMenuiItem)
{
    new 
szKnifeId[8]
    
menu_item_getinfo(iMenuiItem_unused[0], szKnifeIdcharsmax(szKnifeId), _unusedcharsmax(_unused), _unused[0])

    new 
iKnife str_to_num(szKnifeId)

    return ((
g_iKnife[id] == iKnife) || !has_knife_access(idiKnife)) ? ITEM_DISABLED ITEM_ENABLED
}

public 
OnPlayerSpawn(id)
{
    if(
is_user_alive(id) && g_eCvars[km_open_at_spawn] && !g_iKnife[id] && g_bFirstTime[id] && (g_iMenuFlags ADMIN_USER || get_user_flags(id) & g_iMenuFlags))
    {
        
g_bFirstTime[id] = false
        Cmd_Knife
(id)
    }
}

public 
OnSelectKnife(iEnt)
{
    new 
id get_pdata_cbase(iEntm_pPlayer4)

    if(
is_user_connected(id))
    {
        
refresh_knife_model(id)
    }
}

refresh_knife_model(const id)
{
    
set_pev(idpev_viewmodel2g_eKnife[id][V_MODEL])
    
set_pev(idpev_weaponmodel2g_eKnife[id][P_MODEL])
}

push_knife(eKnife[Knives])
{
    if(!
eKnife[V_MODEL][0])
    {
        
copy(eKnife[V_MODEL], charsmax(eKnife[V_MODEL]), CRXKNIVES_DEFAULT_V)
    }

    if(!
eKnife[P_MODEL][0])
    {
        
copy(eKnife[P_MODEL], charsmax(eKnife[P_MODEL]), CRXKNIVES_DEFAULT_P)
    }

    if(!
eKnife[FLAG])
    {
        
g_iMenuFlags |= ADMIN_USER
    
}

    if(
eKnife[CATEGORY] == INVALID_CATEGORY)
    {
        new 
iNum
        TrieGetCell
(g_tKnivesInCategoryINVALID_CATEGORY_STRiNum)
        
TrieSetCell(g_tKnivesInCategoryINVALID_CATEGORY_STR, ++iNum)
    }

    
ArrayPushArray(g_aKniveseKnife)
}

bool:has_knife_access(const id, const iKnife)
{
    static 
eKnife[Knives]
    
ArrayGetArray(g_aKnivesiKnifeeKnife)

    if(
eKnife[FLAG] != ADMIN_ALL)
    {
        if(
get_user_flags(id) & eKnife[FLAG])
        {
            if(
g_eCvars[km_admin_bypass])
            {
                return 
true
            
}
        }
        else
        {
            return 
false
        
}
    }

    if(
g_bRankSystem)
    {
        if(
eKnife[LEVEL] && crxranks_get_user_level(id) < eKnife[LEVEL])
        {
            return 
false
        
}

        if(
eKnife[XP] && crxranks_get_user_xp(id) < eKnife[XP])
        {
            return 
false
        
}
    }

    return 
true
}

bool:is_knife_sound(const szSample[])
{
    return 
bool:equal(szSample[8], "kni"3)
}

detect_knife_sound(const szSample[])
{
    static 
iSound
    iSound 
SOUND_NONE

    
if(equal(szSample"weapons/knife_deploy1.wav"))
    {
        
iSound SOUND_DEPLOY
    
}
    else if(
equal(szSample[14], "hit"3))
    {
        
iSound szSample[17] == 'w' SOUND_HITWALL SOUND_HIT
    
}
    else if(
equal(szSample[14], "sla"3))
    {
        
iSound SOUND_SLASH
    
}
    else if(
equal(szSample[14], "sta"3))
    {
        
iSound SOUND_STAB
    
}

    return 
iSound
}

use_vault(const id, const bool:bSave)
{
    if(
bSave)
    {
        new 
szData[4]
        
num_to_str(g_iKnife[id], szDatacharsmax(szData))
        
nvault_set(g_iVaultg_szAuth[id], szData)
    }
    else
    {
        new 
iKnife
        iKnife 
nvault_get(g_iVaultg_szAuth[id])

        if(!
is_knife_valid(iKnife))
        {
            
iKnife 0
        
}
        else if(
has_knife_access(idiKnife))
        {
            
g_iKnife[id] = iKnife

            
new iReturn
            ArrayGetArray
(g_aKnivesiKnifeg_eKnife[id])
            
ExecuteForward(g_fwdKnifeUpdatediReturnidiKnifefalse)

            if(
is_user_alive(id) && get_user_weapon(id) == CSW_KNIFE)
            {
                
refresh_knife_model(id)
            }
        }
    }
}

play_knife_sound(const id, const szSound[])
{
    
engfunc(EngFunc_EmitSoundidCHAN_AUTOszSound1.0ATTN_NORM0PITCH_NORM)
}

bool:is_knife_valid(const iKnife)
{
    return 
<= iKnife g_iKnivesNum
}

public 
plugin_natives()
{
    
register_library("crxknives")
    
register_native("crxknives_can_use_skill",       "_crxknives_can_use_skill")
    
register_native("crxknives_get_attribute_int",   "_crxknives_get_attribute_int")
    
register_native("crxknives_get_attribute_float""_crxknives_get_attribute_float")
    
register_native("crxknives_get_attribute_str",   "_crxknives_get_attribute_str")
    
register_native("crxknives_get_knives_num",      "_crxknives_get_knives_num")
    
register_native("crxknives_get_user_knife",      "_crxknives_get_user_knife")
    
register_native("crxknives_has_knife_access",    "_crxknives_has_knife_access")
    
register_native("crxknives_is_knife_valid",      "_crxknives_is_knife_valid")
    
set_native_filter("native_filter")
}

public 
native_filter(const szNative[], idiTrap)
{
    if(!
iTrap)
    {
        static 
i

        
for(0sizeof(g_szNatives); i++)
        {
            if(
equal(szNativeg_szNatives[i]))
            {
                return 
PLUGIN_HANDLED
            
}
        }
    }

    return 
PLUGIN_CONTINUE
}

public 
bool:_crxknives_can_use_skill(iPluginiParams)
{
    return !
g_eCvars[km_knife_only_skills] || (get_user_weapon(get_param(1)) == CSW_KNIFE)
}

public 
bool:_crxknives_get_attribute_int(iPluginiParams)
{
    static 
szAttribute[MAX_NAME_LENGTH], szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], id
    get_string
(2szAttributecharsmax(szAttribute))
    
id get_param(1)

    if(!
get_param(4))
    {
        if(!
is_knife_valid(id))
        {
            return 
false
        
}

        static 
eKnife[Knives]
        
ArrayGetArray(g_aKnivesideKnife)

        if(!
TrieKeyExists(eKnife[ATTRIBUTES], szAttribute))
        {
            return 
false
        
}

        
TrieGetString(eKnife[ATTRIBUTES], szAttributeszValuecharsmax(szValue))
        goto @
SET_ATTRIBUTE
    
}

    if(!
TrieKeyExists(g_eKnife[id][ATTRIBUTES], szAttribute))
    {
        return 
false
    
}

    
TrieGetString(g_eKnife[id][ATTRIBUTES], szAttributeszValuecharsmax(szValue))

    @
SET_ATTRIBUTE:
    
set_param_byref(3str_to_num(szValue))
    return 
true
}

public 
bool:_crxknives_get_attribute_float(iPluginiParams)
{
    static 
szAttribute[MAX_NAME_LENGTH], szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], id
    get_string
(2szAttributecharsmax(szAttribute))
    
id get_param(1)

    if(!
get_param(4))
    {
        if(!
is_knife_valid(id))
        {
            return 
false
        
}

        static 
eKnife[Knives]
        
ArrayGetArray(g_aKnivesideKnife)

        if(!
TrieKeyExists(eKnife[ATTRIBUTES], szAttribute))
        {
            return 
false
        
}

        
TrieGetString(eKnife[ATTRIBUTES], szAttributeszValuecharsmax(szValue))
        goto @
SET_ATTRIBUTE
    
}

    if(!
TrieKeyExists(g_eKnife[id][ATTRIBUTES], szAttribute))
    {
        return 
false
    
}

    
TrieGetString(g_eKnife[id][ATTRIBUTES], szAttributeszValuecharsmax(szValue))

    @
SET_ATTRIBUTE:
    
set_float_byref(3str_to_float(szValue))
    return 
true
}

public 
bool:_crxknives_get_attribute_str(iPluginiParams)
{
    static 
szAttribute[MAX_NAME_LENGTH], szValue[CRXKNIVES_MAX_ATTRIBUTE_LENGTH], id
    get_string
(2szAttributecharsmax(szAttribute))
    
id get_param(1)

    if(!
get_param(5))
    {
        if(!
is_knife_valid(id))
        {
            return 
false
        
}

        static 
eKnife[Knives]
        
ArrayGetArray(g_aKnivesideKnife)

        if(!
TrieKeyExists(eKnife[ATTRIBUTES], szAttribute))
        {
            return 
false
        
}

        
TrieGetString(eKnife[ATTRIBUTES], szAttributeszValuecharsmax(szValue))
        goto @
SET_ATTRIBUTE
    
}

    if(!
TrieKeyExists(g_eKnife[id][ATTRIBUTES], szAttribute))
    {
        return 
false
    
}

    
TrieGetString(g_eKnife[id][ATTRIBUTES], szAttributeszValuecharsmax(szValue))

    @
SET_ATTRIBUTE:
    
set_string(3szValueget_param(4))
    return 
true
}

public 
_crxknives_get_knives_num(iPluginiParams)
{
    return 
g_iKnivesNum
}

public 
_crxknives_get_user_knife(iPluginiParams)
{
    return 
g_iKnife[get_param(1)]
}

public 
bool:_crxknives_has_knife_access(iPluginiParams)
{
    return 
has_knife_access(get_param(1), get_param(2))
}

public 
bool:_crxknives_is_knife_valid(iPluginiParams)
{
    return 
is_knife_valid(get_param(1))

The category system works, but there is a problem with the menu names.
Attached Thumbnails
Click image for larger version

Name:	Screenshot_2.jpg
Views:	51
Size:	29.0 KB
ID:	195808  
Erra is offline
Taha_rajper
Member
Join Date: Jun 2021
Location: Under The Sea
Old 07-19-2022 , 07:35   Re: Knife Models [XP System & Skills Support]
Reply With Quote #345

Quote:
Originally Posted by Erra View Post
The category system works, but there is a problem with the menu names.
Do This
data/lang/KnifeModels.txt:
KM_MENU_CATEGORY = %s \y[%i Knives]
Taha_rajper is offline
ALonsoVIP4141
Senior Member
Join Date: May 2021
Location: Philippines
Old 07-19-2022 , 13:38   Re: Knife Models [XP System & Skills Support]
Reply With Quote #346

Does anyone here know how to add super knives with Natives. I just want to know how to add it I don't want to know Natives because I know how to use Natives
ALonsoVIP4141 is offline
Send a message via ICQ to ALonsoVIP4141 Send a message via AIM to ALonsoVIP4141 Send a message via Yahoo to ALonsoVIP4141 Send a message via Skype™ to ALonsoVIP4141
Napoleon_be
Veteran Member
Join Date: Jul 2011
Location: Belgium
Old 08-29-2022 , 12:07   Re: Knife Models [XP System & Skills Support]
Reply With Quote #347

dutch translation
Code:
[nl] -- LadderGoat
KM_CHAT_PREFIX = &x04[Mes Modellen]&x01
KM_CHAT_SELECTED = Je hebt het mes &x04%s&x01 geselecteerd.
KM_MENU_TITLE = \y< \rKies je mes model \y>
KM_MENU_TITLE_PAGE = ^n\r-- \yPagina:\r
KM_MENU_SELECTED = \y~ \rGESELECTEERD \y~
KM_MENU_VIP_ONLY = \y~ \rVIP \y~
KM_MENU_LEVEL = \r[LVL %i]
KM_MENU_RANK = \r[RANK: %s]
KM_MENU_XP = \r[XP: %i]
KM_ONLY_DEAD = Je kan je mes niet veranderen als je nog leeft.
KM_INVALID_KNIFE = * Dat mes bestaat niet. Waardebereik is van 0 tot %i.
KM_NO_ACCESS = * Je hebt geen toegang tot dat mes.
__________________
Napoleon_be is offline
Send a message via Skype™ to Napoleon_be
kiizu132
New Member
Join Date: Oct 2022
Old 10-05-2022 , 14:27   Re: Knife Models [XP System & Skills Support]
Reply With Quote #348

hello, i tried to install this plugin to my server but it does not have amxx fail?
kiizu132 is offline
menkisa
Junior Member
Join Date: Sep 2011
Old 10-09-2022 , 13:46   Re: Knife Models [XP System & Skills Support]
Reply With Quote #349

Quote:
Originally Posted by kiizu132 View Post
hello, i tried to install this plugin to my server but it does not have amxx fail?
https://wiki.alliedmods.net/Compilin...ns_(AMX_Mod_X)

Last edited by menkisa; 10-09-2022 at 13:46.
menkisa is offline
HundredEyes
Member
Join Date: Sep 2022
Old 12-06-2022 , 10:52   Re: Knife Models [XP System & Skills Support]
Reply With Quote #350

After restart or shut down, plugin doesn't save your selection. I choose to be saved by name
HundredEyes is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 01:37.


Powered by vBulletin®
Copyright ©2000 - 2023, vBulletin Solutions, Inc.
Theme made by Freecode