View Single Post
LithuanianJack
Senior Member
Join Date: Nov 2013
Location: Vilnius, Lithuania
Old 02-10-2019 , 12:08   Re: OciXCrom's Rank System [XP|Levels|Ranks]
Reply With Quote #193

Quote:
Originally Posted by OciXCrom View Post
@LithuanianJack - try this. I used the SQL_QuoteString function in all places where the player name is used, as well as the rank and next rank fields since they can contain problematic symbols as well.

PHP Code:
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <nvault>
#include <sqlx>

// Comment or remove this line in order to run the plugin on a mod different than Counter-Strike.
#define USE_CSTRIKE

#if defined USE_CSTRIKE
    #include <cromchat>
    #include <csx>
#else
new CC_PREFIX[64]
#endif

#if AMXX_VERSION_NUM < 183
    #include <dhudmessage>
#endif

#include <crxranks_const>

#if !defined client_disconnected
    #define client_disconnected client_disconnect
#endif

#if !defined replace_string
    #define replace_string replace_all
#endif

new const PLUGIN_VERSION[] = "3.1a"
const Float:DELAY_ON_CONNECT 5.0
const Float:HUD_REFRESH_FREQ 1.0
const Float:DELAY_ON_CHANGE 0.1
const MAX_SQL_LENGTH 512
const MAX_QUERY_LENGTH 256
const MAX_SOUND_LENGTH 128
const MAX_SQL_PLAYER_LENGTH 64
const MAX_SQL_RANK_LENGTH CRXRANKS_MAX_RANK_LENGTH 2
const TASK_HUD 304500

#if !defined MAX_NAME_LENGTH
const MAX_NAME_LENGTH 32
#endif

new const ARG_CURRENT_XP[]          = "$current_xp$"
new const ARG_NEXT_XP[]             = "$next_xp$"
new const ARG_XP_NEEDED[]           = "$xp_needed$"
new const ARG_LEVEL[]               = "$level$"
new const ARG_NEXT_LEVEL[]          = "$next_level$"
new const ARG_RANK[]                = "$rank$"
new const ARG_NEXT_RANK[]           = "$next_rank$"
new const ARG_MAX_LEVELS[]          = "$max_levels$"
new const ARG_LINE_BREAK[]          = "$br$"
new const ARG_NAME[]                = "$name$"

new const XPREWARD_KILL[]           = "kill"
new const XPREWARD_HEADSHOT[]       = "headshot"
new const XPREWARD_TEAMKILL[]       = "teamkill"
new const XPREWARD_SUICIDE[]        = "suicide"

#if defined USE_CSTRIKE
new const XPREWARD_BOMB_PLANTED[]   = "bomb_planted"
new const XPREWARD_BOMB_DEFUSED[]   = "bomb_defused"
new const XPREWARD_BOMB_EXPLODED[]  = "bomb_exploded"
#endif

#define clr(%1) %1 == -1 ? random(256) : %1

#define HUDINFO_PARAMS clr(g_eSettings[HUDINFO_COLOR][0]), clr(g_eSettings[HUDINFO_COLOR][1]), clr(g_eSettings[HUDINFO_COLOR][2]),\
g_eSettings[HUDINFO_POSITION][0], g_eSettings[HUDINFO_POSITION][1], 00.11.00.10.1

#define XP_NOTIFIER_PARAMS_GET clr(g_eSettings[XP_NOTIFIER_COLOR_GET][0]), clr(g_eSettings[XP_NOTIFIER_COLOR_GET][1]), clr(g_eSettings[XP_NOTIFIER_COLOR_GET][2]),\
g_eSettings[XP_NOTIFIER_POSITION][0], g_eSettings[XP_NOTIFIER_POSITION][1], .holdtime g_eSettings[XP_NOTIFIER_DURATION]

#define XP_NOTIFIER_PARAMS_LOSE clr(g_eSettings[XP_NOTIFIER_COLOR_LOSE][0]), clr(g_eSettings[XP_NOTIFIER_COLOR_LOSE][1]), clr(g_eSettings[XP_NOTIFIER_COLOR_LOSE][2]),\
g_eSettings[XP_NOTIFIER_POSITION][0], g_eSettings[XP_NOTIFIER_POSITION][1], .holdtime g_eSettings[XP_NOTIFIER_DURATION]

enum _:SaveLoad
{
    
SL_SAVE_DATA,
    
SL_LOAD_DATA
}

enum _:Objects
{
    
OBJ_HUDINFO,
    
OBJ_XP_NOTIFIER
}

enum _:SaveTypes
{
    
SAVE_NICKNAME,
    
SAVE_IP,
    
SAVE_STEAMID
}

enum _:SaveMethods
{
    
SAVE_NVAULT,
    
SAVE_MYSQL
}

enum _:Sections
{
    
SECTION_NONE,
    
SECTION_SETTINGS,
    
SECTION_RANKS,
    
SECTION_XP_REWARDS
}

enum _:PlayerData
{
    
XP,
    
Level,
    
NextXP,
    
Rank[CRXRANKS_MAX_RANK_LENGTH],
    
NextRank[CRXRANKS_MAX_RANK_LENGTH],
    
HUDInfo[CRXRANKS_MAX_HUDINFO_LENGTH],
    
bool:IsOnFinalLevel,
    
bool:IsVIP,
    
bool:IsBot
}

enum _:Settings
{
    
SAVE_TYPE,
    
bool:USE_MYSQL,
    
SQL_HOST[MAX_NAME_LENGTH],
    
SQL_USER[MAX_NAME_LENGTH],
    
SQL_PASSWORD[MAX_NAME_LENGTH],
    
SQL_DATABASE[MAX_NAME_LENGTH],
    
SQL_TABLE[MAX_NAME_LENGTH],
    
LEVELUP_MESSAGE_TYPE,
    
LEVELUP_SOUND[MAX_SOUND_LENGTH],
    
bool:LEVELUP_SCREEN_FADE_ENABLED,
    
LEVELUP_SCREEN_FADE_COLOR[4],
    
LEVELDN_SOUND[MAX_SOUND_LENGTH],
    
bool:LEVELDN_SCREEN_FADE_ENABLED,
    
LEVELDN_SCREEN_FADE_COLOR[4],
    
FINAL_LEVEL_FLAGS[32],
    
FINAL_LEVEL_FLAGS_BIT,
    
VIP_FLAGS[32],
    
VIP_FLAGS_BIT,
    
VAULT_NAME[32],
    
TEAM_LOCK,
    
MINIMUM_PLAYERS,
    
bool:IGNORE_BOTS,
    
bool:USE_COMBINED_EVENTS,
    
bool:NOTIFY_ON_KILL,
    
bool:HUDINFO_ENABLED,
    
bool:HUDINFO_ALIVE_ONLY,
    
bool:HUDINFO_TEAM_LOCK,
    
bool:HUDINFO_OTHER_PLAYERS,
    
HUDINFO_COLOR[3],
    
Float:HUDINFO_POSITION[2],
    
bool:HUDINFO_USE_DHUD,
    
HUDINFO_FORMAT[CRXRANKS_MAX_HUDINFO_LENGTH],
    
HUDINFO_FORMAT_FINAL[CRXRANKS_MAX_HUDINFO_LENGTH],
    
HUDINFO_INVALID_TEXT[32],
    
bool:XP_NOTIFIER_ENABLED,
    
XP_NOTIFIER_COLOR_GET[3],
    
XP_NOTIFIER_COLOR_LOSE[3],
    
Float:XP_NOTIFIER_POSITION[2],
    
Float:XP_NOTIFIER_DURATION,
    
bool:XP_NOTIFIER_USE_DHUD
}

new 
g_eSettings[Settings]
new 
g_ePlayerData[33][PlayerData]
new 
g_szMaxLevels[CRXRANKS_MAX_XP_LENGTH]
new 
g_szSqlError[MAX_SQL_LENGTH]
new 
Handle:g_iSqlTuple
new Array:g_aLevels
new Array:g_aRankNames
new Trie:g_tSettings
new Trie:g_tXPRewards
new Trie:g_tXPRewardsVIP

new g_iVault
new g_iMaxLevels
new g_iFlagZ
new g_iScreenFade
new g_iObject[2]

new 
g_fwdUserLevelUpdated
new g_fwdUserReceiveXP
new g_fwdUserXPUpdated

public plugin_init()
{
    
register_plugin("OciXCrom's Rank System"PLUGIN_VERSION"OciXCrom")
    
register_cvar("CRXRankSystem"PLUGIN_VERSIONFCVAR_SERVER|FCVAR_SPONLY|FCVAR_UNLOGGED)

    
#if defined USE_CSTRIKE
    
register_dictionary("RankSystem.txt")
    
#else
    
register_dictionary("RankSystemNoColors.txt")
    
#endif

    
register_event("DeathMsg""OnPlayerKilled""a")

    
register_clcmd("say /xplist",            "Cmd_XPList",      ADMIN_BAN)
    
register_clcmd("say_team /xplist",       "Cmd_XPList",      ADMIN_BAN)
    
register_concmd("crxranks_give_xp",      "Cmd_GiveXP",      ADMIN_RCON"<nick|#userid> <amount>")
    
register_concmd("crxranks_reset_xp",     "Cmd_ResetXP",     ADMIN_RCON"<nick|#userid>")
    
register_srvcmd("crxranks_update_mysql""Cmd_UpdateMySQL")

    if(
g_eSettings[LEVELUP_SCREEN_FADE_ENABLED] || g_eSettings[LEVELDN_SCREEN_FADE_ENABLED])
    {
        
g_iScreenFade get_user_msgid("ScreenFade")
    }

    
g_fwdUserLevelUpdated CreateMultiForward("crxranks_user_level_updated"ET_IGNOREFP_CELLFP_CELLFP_CELL)
    
g_fwdUserReceiveXP    CreateMultiForward("crxranks_user_receive_xp",    ET_STOP,   FP_CELLFP_CELLFP_CELL)
    
g_fwdUserXPUpdated    CreateMultiForward("crxranks_user_xp_updated",    ET_IGNOREFP_CELLFP_CELLFP_CELL)

    if(
g_eSettings[USE_MYSQL])
    {
        
g_iSqlTuple SQL_MakeDbTuple(g_eSettings[SQL_HOST], g_eSettings[SQL_USER], g_eSettings[SQL_PASSWORD], g_eSettings[SQL_DATABASE])

        new 
iErrorCodeHandle:iSqlConnection SQL_Connect(g_iSqlTupleiErrorCodeg_szSqlErrorcharsmax(g_szSqlError))

        if(
iSqlConnection == Empty_Handle)
        {
            
log_amx(g_szSqlError)
            
switch_to_nvault()
            goto @
AFTER_MYSQL
        
}

        new 
Handle:iQueries SQL_PrepareQuery(iSqlConnection,\
        
"CREATE TABLE IF NOT EXISTS `%s` (`Player` VARCHAR(%i) NOT NULL, `XP` INT(%i) NOT NULL, `Level` INT(%i) NOT NULL,\
        `Next XP` INT(%i) NOT NULL, `Rank` VARCHAR(%i) NOT NULL, `Next Rank` VARCHAR(%i) NOT NULL, PRIMARY KEY(Player));"
,\
        
g_eSettings[SQL_TABLE], MAX_SQL_PLAYER_LENGTHCRXRANKS_MAX_XP_LENGTHCRXRANKS_MAX_XP_LENGTHCRXRANKS_MAX_XP_LENGTH,\
        
MAX_SQL_RANK_LENGTHMAX_SQL_RANK_LENGTH)

        if(!
SQL_Execute(iQueries))
        {
            
SQL_QueryError(iQueriesg_szSqlErrorcharsmax(g_szSqlError))
            
log_amx(g_szSqlError)
            
switch_to_nvault()
            goto @
AFTER_MYSQL
        
}

        
SQL_FreeHandle(iQueries)
        
SQL_FreeHandle(iSqlConnection)
    }

    @
AFTER_MYSQL:

    if(!
g_eSettings[USE_MYSQL])
    {
        
g_iVault nvault_open(g_eSettings[VAULT_NAME])
    }
}

public 
plugin_precache()
{
    
g_aLevels ArrayCreate(16)
    
ArrayPushCell(g_aLevels0)

    
g_aRankNames ArrayCreate(32)
    
ArrayPushString(g_aRankNames"")

    
g_tSettings TrieCreate()
    
g_tXPRewards TrieCreate()
    
g_tXPRewardsVIP TrieCreate()

    
ReadFile()
}

public 
plugin_end()
{
    
ArrayDestroy(g_aLevels)
    
ArrayDestroy(g_aRankNames)
    
TrieDestroy(g_tSettings)
    
TrieDestroy(g_tXPRewards)
    
TrieDestroy(g_tXPRewardsVIP)
    
DestroyForward(g_fwdUserLevelUpdated)

    if(!
g_eSettings[USE_MYSQL])
    {
        
nvault_close(g_iVault)
    }
}

ReadFile()
{
    new 
szFilename[256]
    
get_configsdir(szFilenamecharsmax(szFilename))
    
add(szFilenamecharsmax(szFilename), "/RankSystem.ini")

    new 
iFilePointer fopen(szFilename"rt")

    if(
iFilePointer)
    {
        new 
szData[CRXRANKS_MAX_HUDINFO_LENGTH MAX_NAME_LENGTH], szValue[CRXRANKS_MAX_HUDINFO_LENGTH], szMap[MAX_NAME_LENGTH], szKey[MAX_NAME_LENGTH]
        new 
szTemp[4][5], bool:bRead trueiiSizeiSection SECTION_NONE
        get_mapname
(szMapcharsmax(szMap))

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

            switch(
szData[0])
            {
                case 
EOS'#'';': continue
                case 
'-':
                {
                    
iSize strlen(szData)

                    if(
szData[iSize 1] == '-')
                    {
                        
szData[0] = ' '
                        
szData[iSize 1] = ' '
                        
trim(szData)

                        if(
contain(szData"*") != -1)
                        {
                            
strtok(szDataszKeycharsmax(szKey), szValuecharsmax(szValue), '*')
                            
copy(szValuestrlen(szKey), szMap)
                            
bRead equal(szValueszKey) ? true false
                        
}
                        else
                        {
                            static const 
szAll[] = "#all"
                            
bRead equal(szDataszAll) || equali(szDataszMap)
                        }
                    }
                    else continue
                }
                case 
'[':
                {
                    
iSize strlen(szData)

                    if(
szData[iSize 1] == ']')
                    {
                        switch(
szData[1])
                        {
                            case 
'S''s'iSection SECTION_SETTINGS
                            
case 'R''r'iSection SECTION_RANKS
                            
case 'X''x'iSection SECTION_XP_REWARDS
                            
default: iSection SECTION_NONE
                        
}
                    }
                    else continue
                }
                default:
                {
                    if(!
bRead || iSection == SECTION_NONE)
                    {
                        continue
                    }

                    
strtok(szDataszKeycharsmax(szKey), szValuecharsmax(szValue), '=')
                    
trim(szKey); trim(szValue)

                    if(!
szValue[0])
                    {
                        continue
                    }

                    switch(
iSection)
                    {
                        case 
SECTION_SETTINGS:
                        {
                            
TrieSetString(g_tSettingsszKeyszValue)

                            if(
equal(szKey"CHAT_PREFIX"))
                            {
                                
#if defined USE_CSTRIKE
                                
CC_SetPrefix(szValue)
                                
#else
                                
copy(CC_PREFIXcharsmax(CC_PREFIX), szValue)
                                
#endif
                            
}
                            else if(
equal(szKey"SAVE_TYPE"))
                            {
                                
g_eSettings[SAVE_TYPE] = clamp(str_to_num(szValue), SAVE_NICKNAMESAVE_STEAMID)
                            }
                            else if(
equal(szKey"USE_MYSQL"))
                            {
                                
g_eSettings[USE_MYSQL] = _:clamp(str_to_num(szValue), falsetrue)
                            }
                            else if(
equal(szKey"SQL_HOST"))
                            {
                                
copy(g_eSettings[SQL_HOST], charsmax(g_eSettings[SQL_HOST]), szValue)
                            }
                            else if(
equal(szKey"SQL_USER"))
                            {
                                
copy(g_eSettings[SQL_USER], charsmax(g_eSettings[SQL_USER]), szValue)
                            }
                            else if(
equal(szKey"SQL_PASSWORD"))
                            {
                                
copy(g_eSettings[SQL_PASSWORD], charsmax(g_eSettings[SQL_PASSWORD]), szValue)
                            }
                            else if(
equal(szKey"SQL_DATABASE"))
                            {
                                
copy(g_eSettings[SQL_DATABASE], charsmax(g_eSettings[SQL_DATABASE]), szValue)
                            }
                            else if(
equal(szKey"SQL_TABLE"))
                            {
                                
copy(g_eSettings[SQL_TABLE], charsmax(g_eSettings[SQL_TABLE]), szValue)
                            }
                            else if(
equal(szKey"XP_COMMANDS"))
                            {
                                while(
szValue[0] != && strtok(szValueszKeycharsmax(szKey), szValuecharsmax(szValue), ','))
                                {
                                    
trim(szKey); trim(szValue)
                                    
register_clcmd(szKey"Cmd_XP")
                                }
                            }
                            else if(
equal(szKey"LEVELUP_MESSAGE_TYPE"))
                            {
                                
g_eSettings[LEVELUP_MESSAGE_TYPE] = clamp(str_to_num(szValue), 02)
                            }
                            else if(
equal(szKey"LEVELUP_SOUND"))
                            {
                                
copy(g_eSettings[LEVELUP_SOUND], charsmax(g_eSettings[LEVELUP_SOUND]), szValue)

                                if(
szValue[0])
                                {
                                    
precache_sound(szValue)
                                }
                            }
                            else if(
equal(szKey"LEVELUP_SCREEN_FADE_ENABLED"))
                            {
                                
g_eSettings[LEVELUP_SCREEN_FADE_ENABLED] = _:clamp(str_to_num(szValue), falsetrue)
                            }
                            else if(
equal(szKey"LEVELUP_SCREEN_FADE_COLOR"))
                            {
                                
parse(szValueszTemp[0], charsmax(szTemp[]), szTemp[1], charsmax(szTemp[]), szTemp[2], charsmax(szTemp[]), szTemp[3], charsmax(szTemp[]))

                                for(
04i++)
                                {
                                    
g_eSettings[LEVELUP_SCREEN_FADE_COLOR][i] = clamp(str_to_num(szTemp[i]), -1255)
                                }
                            }
                            else if(
equal(szKey"LEVELDN_SOUND"))
                            {
                                
copy(g_eSettings[LEVELDN_SOUND], charsmax(g_eSettings[LEVELDN_SOUND]), szValue)

                                if(
szValue[0])
                                {
                                    
precache_sound(szValue)
                                }
                            }
                            else if(
equal(szKey"LEVELDN_SCREEN_FADE_ENABLED"))
                            {
                                
g_eSettings[LEVELDN_SCREEN_FADE_ENABLED] = _:clamp(str_to_num(szValue), falsetrue)
                            }
                            else if(
equal(szKey"LEVELDN_SCREEN_FADE_COLOR"))
                            {
                                
parse(szValueszTemp[0], charsmax(szTemp[]), szTemp[1], charsmax(szTemp[]), szTemp[2], charsmax(szTemp[]), szTemp[3], charsmax(szTemp[]))

                                for(
04i++)
                                {
                                    
g_eSettings[LEVELDN_SCREEN_FADE_COLOR][i] = clamp(str_to_num(szTemp[i]), -1255)
                                }
                            }
                            else if(
equal(szKey"FINAL_LEVEL_FLAGS"))
                            {
                                
copy(g_eSettings[FINAL_LEVEL_FLAGS], charsmax(g_eSettings[FINAL_LEVEL_FLAGS]), szValue)
                                
g_eSettings[FINAL_LEVEL_FLAGS_BIT] = read_flags(szValue)
                                
g_iFlagZ read_flags("z")
                            }
                            else if(
equal(szKey"VIP_FLAGS"))
                            {
                                
copy(g_eSettings[VIP_FLAGS], charsmax(g_eSettings[VIP_FLAGS]), szValue)
                                
g_eSettings[VIP_FLAGS_BIT] = read_flags(szValue)
                            }
                            else if(
equal(szKey"VAULT_NAME"))
                            {
                                
copy(g_eSettings[VAULT_NAME], charsmax(g_eSettings[VAULT_NAME]), szValue)
                            }
                            else if(
equal(szKey"TEAM_LOCK"))
                            {
                                
g_eSettings[TEAM_LOCK] = str_to_num(szValue)
                            }
                            else if(
equal(szKey"MINIMUM_PLAYERS"))
                            {
                                
g_eSettings[MINIMUM_PLAYERS] = clamp(str_to_num(szValue), 032)
                            }
                            else if(
equal(szKey"IGNORE_BOTS"))
                            {
                                
g_eSettings[IGNORE_BOTS] = _:clamp(str_to_num(szValue), falsetrue)
                            }
                            else if(
equal(szKey"USE_COMBINED_EVENTS"))
                            {
                                
g_eSettings[USE_COMBINED_EVENTS] = _:clamp(str_to_num(szValue), falsetrue)
                            }
                            else if(
equal(szKey"NOTIFY_ON_KILL"))
                            {
                                
g_eSettings[NOTIFY_ON_KILL] = _:clamp(str_to_num(szValue), falsetrue)
                            }
                            else if(
equal(szKey"HUDINFO_ENABLED"))
                            {
                                
g_eSettings[HUDINFO_ENABLED] = _:clamp(str_to_num(szValue), falsetrue)
                            }
                            else if(
equal(szKey"HUDINFO_ALIVE_ONLY"))
                            {
                                
g_eSettings[HUDINFO_ALIVE_ONLY] = _:clamp(str_to_num(szValue), falsetrue)
                            }
                            else if(
equal(szKey"HUDINFO_TEAM_LOCK"))
                            {
                                
g_eSettings[HUDINFO_TEAM_LOCK] = _:clamp(str_to_num(szValue), falsetrue)
                            }
                            else if(
equal(szKey"HUDINFO_OTHER_PLAYERS"))
                            {
                                
g_eSettings[HUDINFO_OTHER_PLAYERS] = _:clamp(str_to_num(szValue), falsetrue)
                            }
                            else if(
equal(szKey"HUDINFO_COLOR"))
                            {
                                
parse(szValueszTemp[0], charsmax(szTemp[]), szTemp[1], charsmax(szTemp[]), szTemp[2], charsmax(szTemp[]))

                                for(
03i++)
                                {
                                    
g_eSettings[HUDINFO_COLOR][i] = clamp(str_to_num(szTemp[i]), -1255)
                                }
                            }
                            else if(
equal(szKey"HUDINFO_POSITION"))
                            {
                                
parse(szValueszTemp[0], charsmax(szTemp[]), szTemp[1], charsmax(szTemp[]))

                                for(
02i++)
                                {
                                    
g_eSettings[HUDINFO_POSITION][i] = _:floatclamp(str_to_float(szTemp[i]), -1.01.0)
                                }
                            }
                            else if(
equal(szKey"HUDINFO_USE_DHUD"))
                            {
                                
g_eSettings[HUDINFO_USE_DHUD] = _:clamp(str_to_num(szValue), falsetrue)

                                if(!
g_eSettings[HUDINFO_USE_DHUD])
                                {
                                    
g_iObject[OBJ_HUDINFO] = CreateHudSyncObj()
                                }
                            }
                            else if(
equal(szKey"HUDINFO_FORMAT"))
                            {
                                
copy(g_eSettings[HUDINFO_FORMAT], charsmax(g_eSettings[HUDINFO_FORMAT]), szValue)
                            }
                            else if(
equal(szKey"HUDINFO_FORMAT_FINAL"))
                            {
                                
copy(g_eSettings[HUDINFO_FORMAT_FINAL], charsmax(g_eSettings[HUDINFO_FORMAT_FINAL]), szValue)
                            }
                            else if(
equal(szKey"HUDINFO_INVALID_TEXT"))
                            {
                                
copy(g_eSettings[HUDINFO_INVALID_TEXT], charsmax(g_eSettings[HUDINFO_INVALID_TEXT]), szValue)
                            }
                            else if(
equal(szKey"XP_NOTIFIER_ENABLED"))
                            {
                                
g_eSettings[XP_NOTIFIER_ENABLED] = _:clamp(str_to_num(szValue), falsetrue)
                            }
                            else if(
equal(szKey"XP_NOTIFIER_COLOR_GET"))
                            {
                                
parse(szValueszTemp[0], charsmax(szTemp[]), szTemp[1], charsmax(szTemp[]), szTemp[2], charsmax(szTemp[]))

                                for(
03i++)
                                {
                                    
g_eSettings[XP_NOTIFIER_COLOR_GET][i] = clamp(str_to_num(szTemp[i]), -1255)
                                }
                            }
                            else if(
equal(szKey"XP_NOTIFIER_COLOR_LOSE"))
                            {
                                
parse(szValueszTemp[0], charsmax(szTemp[]), szTemp[1], charsmax(szTemp[]), szTemp[2], charsmax(szTemp[]))

                                for(
03i++)
                                {
                                    
g_eSettings[XP_NOTIFIER_COLOR_LOSE][i] = clamp(str_to_num(szTemp[i]), -1255)
                                }
                            }
                            else if(
equal(szKey"XP_NOTIFIER_POSITION"))
                            {
                                
parse(szValueszTemp[0], charsmax(szTemp[]), szTemp[1], charsmax(szTemp[]))

                                for(
02i++)
                                {
                                    
g_eSettings[XP_NOTIFIER_POSITION][i] = _:floatclamp(str_to_float(szTemp[i]), -1.01.0)
                                }
                            }
                            else if(
equal(szKey"XP_NOTIFIER_DURATION"))
                            {
                                
g_eSettings[XP_NOTIFIER_DURATION] = _:floatclamp(str_to_float(szValue), 0.0float(cellmax))
                            }
                            else if(
equal(szKey"XP_NOTIFIER_USE_DHUD"))
                            {
                                
g_eSettings[XP_NOTIFIER_USE_DHUD] = _:clamp(str_to_num(szValue), falsetrue)

                                if(!
g_eSettings[XP_NOTIFIER_USE_DHUD])
                                {
                                    
g_iObject[OBJ_XP_NOTIFIER] = CreateHudSyncObj()
                                }
                            }
                        }
                        case 
SECTION_RANKS:
                        {
                            
ArrayPushCell(g_aLevelsclamp(str_to_num(szValue), 0))
                            
ArrayPushString(g_aRankNamesszKey)
                            
g_iMaxLevels++
                        }
                        case 
SECTION_XP_REWARDS:
                        {
                            static 
szReward[2][16]
                            
szReward[1][0] = EOS

                            parse
(szValueszReward[0], charsmax(szReward[]), szReward[1], charsmax(szReward[]))
                            
TrieSetCell(g_tXPRewardsszKeystr_to_num(szReward[0]))

                            if(
szReward[1][0])
                            {
                                
TrieSetCell(g_tXPRewardsVIPszKeystr_to_num(szReward[1]))
                            }
                        }
                    }
                }
            }
        }

        
num_to_str(g_iMaxLevelsg_szMaxLevelscharsmax(g_szMaxLevels))
        
fclose(iFilePointer)
    }
}

public 
client_connect(id)
{
    
reset_player_stats(id)

    new 
szInfo[CRXRANKS_MAX_PLAYER_INFO_LENGTH]
    
get_user_saveinfo(idszInfocharsmax(szInfo))
    
save_or_load(idszInfoSL_LOAD_DATA)

    
g_ePlayerData[id][IsBot] = is_user_bot(id) != 0
    set_task
(DELAY_ON_CONNECT"update_vip_status"id)

    if(
g_eSettings[HUDINFO_ENABLED])
    {
        
set_task(HUD_REFRESH_FREQ"DisplayHUD"id TASK_HUD, .flags "b")
    }
}

public 
client_disconnected(id)
{
    new 
szInfo[CRXRANKS_MAX_PLAYER_INFO_LENGTH]
    
get_user_saveinfo(idszInfocharsmax(szInfo))
    
save_or_load(idszInfoSL_SAVE_DATA)
    
remove_task(id TASK_HUD)
}

public 
client_infochanged(id)
{
    if(!
is_user_connected(id))
    {
        return
    }

    static const 
szKey[] = "name"
    
static szNewName[MAX_NAME_LENGTH], szOldName[MAX_NAME_LENGTH]
    
get_user_info(idszKeyszNewNamecharsmax(szNewName))
    
get_user_name(idszOldNamecharsmax(szOldName))

    if(!
equal(szNewNameszOldName))
    {
        if(
g_eSettings[SAVE_TYPE] == SAVE_NICKNAME)
        {
            
save_or_load(idszOldNameSL_SAVE_DATA)

            if(
g_eSettings[USE_MYSQL])
            {
                
reset_player_stats(id)
                
set_task(DELAY_ON_CHANGE"load_after_change"id)
            }
            else
            {
                
save_or_load(idszNewNameSL_LOAD_DATA)
                
update_hudinfo(id)
            }
        }

        
set_task(DELAY_ON_CHANGE"update_vip_status"id)
    }
}

public 
load_after_change(id)
{
    static 
szName[MAX_NAME_LENGTH]
    
get_user_name(idszNamecharsmax(szName))
    
save_or_load(idszNameSL_LOAD_DATA)
    
update_hudinfo(id)
}

public 
DisplayHUD(id)
{
    
id -= TASK_HUD

    
static iTarget
    iTarget 
id

    
if(!is_user_alive(id))
    {
        if(
g_eSettings[HUDINFO_ALIVE_ONLY])
        {
            return
        }

        if(
g_eSettings[HUDINFO_OTHER_PLAYERS])
        {
            
iTarget pev(idpev_iuser2)
        }
    }

    if(!
iTarget)
    {
        return
    }

    if(
g_eSettings[TEAM_LOCK] && g_eSettings[HUDINFO_TEAM_LOCK] && get_user_team(iTarget) != g_eSettings[TEAM_LOCK])
    {
        return
    }

    if(
g_eSettings[HUDINFO_USE_DHUD])
    {
        
set_dhudmessage(HUDINFO_PARAMS)
        
show_dhudmessage(idg_ePlayerData[iTarget][HUDInfo])
    }
    else
    {
        
set_hudmessage(HUDINFO_PARAMS)
        
ShowSyncHudMsg(idg_iObject[OBJ_HUDINFO], g_ePlayerData[iTarget][HUDInfo])
    }
}

#if defined USE_CSTRIKE
public bomb_planted(id)
{
    
give_user_xp(idget_xp_reward(idXPREWARD_BOMB_PLANTED), CRXRANKS_XPS_REWARD)
}

public 
bomb_defused(id)
{
    
give_user_xp(idget_xp_reward(idXPREWARD_BOMB_DEFUSED), CRXRANKS_XPS_REWARD)
}

public 
bomb_explode(id)
{
    
give_user_xp(idget_xp_reward(idXPREWARD_BOMB_EXPLODED), CRXRANKS_XPS_REWARD)
}
#endif

public Cmd_XP(id)
{
    if(
g_ePlayerData[id][Level] == g_iMaxLevels)
    {
        
send_chat_message(idfalse"%L"id"CRXRANKS_RANKINFO_FINAL"g_ePlayerData[id][XP], g_ePlayerData[id][Level], g_ePlayerData[id][Rank])
    }
    else
    {
        
send_chat_message(idfalse"%L"id"CRXRANKS_RANKINFO_NORMAL"g_ePlayerData[id][XP], g_ePlayerData[id][NextXP],\
        
g_ePlayerData[id][Level], g_ePlayerData[id][Rank], g_ePlayerData[id][NextRank])
    }

    return 
PLUGIN_HANDLED
}

public 
Cmd_XPList(idiLeveliCid)
{
    if(!
cmd_access(idiLeveliCid1))
    {
        return 
PLUGIN_HANDLED
    
}

    new 
szTitle[128]
    
formatex(szTitlecharsmax(szTitle), "%L"id"CRXRANKS_MENU_TITLE")

    new 
iPlayers[32], iPnumiMenu menu_create(szTitle"XPList_Handler")
    
get_players(iPlayersiPnum); SortCustom1D(iPlayersiPnum"sort_players_by_xp")

    for(new 
szItem[128], szName[32], iPlayeriiPnumi++)
    {
        
iPlayer iPlayers[i]
        
get_user_name(iPlayerszNamecharsmax(szName))
        
formatex(szItemcharsmax(szItem), "%L"id"CRXRANKS_ITEM_FORMAT"g_ePlayerData[iPlayer][XP], szNameg_ePlayerData[iPlayer][Level], g_ePlayerData[iPlayer][Rank])
        
menu_additem(iMenuszItem)
    }

    
menu_display(idiMenu)
    return 
PLUGIN_HANDLED
}

public 
XPList_Handler(idiMenuiItem)
{
    
menu_destroy(iMenu)
    return 
PLUGIN_HANDLED
}

public 
Cmd_GiveXP(idiLeveliCid)
{
    if(!
cmd_access(idiLeveliCid3))
    {
        return 
PLUGIN_HANDLED
    
}

    new 
szPlayer[MAX_NAME_LENGTH]
    
read_argv(1szPlayercharsmax(szPlayer))

    new 
iPlayer cmd_target(idszPlayer0)

    if(!
iPlayer)
    {
        return 
PLUGIN_HANDLED
    
}

    new 
szName[2][MAX_NAME_LENGTH], szAmount[CRXRANKS_MAX_XP_LENGTH]
    
read_argv(2szAmountcharsmax(szAmount))
    
get_user_name(idszName[0], charsmax(szName[]))
    
get_user_name(iPlayerszName[1], charsmax(szName[]))

    new 
szKey[32], iXP str_to_num(szAmount)
    
give_user_xp(iPlayeriXPCRXRANKS_XPS_ADMIN)

    if(
iXP >= 0)
    {
        
copy(szKeycharsmax(szKey), "CRXRANKS_GIVE_XP")
    }
    else
    {
        
copy(szKeycharsmax(szKey), "CRXRANKS_TAKE_XP")
        
iXP *= -1
    
}

    
send_chat_message(0true"%L"idszKeyszName[0], iXPszName[1])
    return 
PLUGIN_HANDLED
}

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

    new 
szPlayer[MAX_NAME_LENGTH]
    
read_argv(1szPlayercharsmax(szPlayer))

    new 
iPlayer cmd_target(idszPlayerCMDTARGET_OBEY_IMMUNITY|CMDTARGET_ALLOW_SELF)

    if(!
iPlayer)
    {
        return 
PLUGIN_HANDLED
    
}

    new 
szName[2][MAX_NAME_LENGTH]
    
get_user_name(idszName[0], charsmax(szName[]))
    
get_user_name(iPlayerszName[1], charsmax(szName[]))

    
g_ePlayerData[iPlayer][XP] = 0
    check_level
(iPlayertrue)
    
send_chat_message(0true"%L"id"CRXRANKS_RESET_XP"szName[0], szName[1])

    return 
PLUGIN_HANDLED
}

// This command is here because the update from v3.0 to v3.1 changed the way data is stored in MySQL.
// Because of that, a new table is required and this command is here to transfer the data from the old one.
// The command will be removed in future versions, so I decided not to translate the strings used in it.
public Cmd_UpdateMySQL()
{
    static 
bUsed

    
if(bUsed)
    {
        
server_print("The MySQL table has already been updated to version v3.1. There's no point in doing this again.")
        return 
PLUGIN_HANDLED
    
}

    if(!
g_eSettings[USE_MYSQL])
    {
        
server_print("The plugin isn't using MySQL at the moment. Please enable the feature before using this command.")
        return 
PLUGIN_HANDLED
    
}

    new 
szTable[MAX_NAME_LENGTH]
    
read_argv(1szTablecharsmax(szTable))

    if(!
szTable[0])
    {
        
server_print("Plese provide the name of the previous table in order to transfer data to the current one.")
        return 
PLUGIN_HANDLED
    
}

    new 
szQuery[MAX_NAME_LENGTH 2]
    
formatex(szQuerycharsmax(szQuery), "SELECT * FROM `%s`;"szTable)
    
SQL_ThreadQuery(g_iSqlTuple"QueryUpdateMySQL"szQuery)

    
bUsed true
    
return PLUGIN_HANDLED
}

public 
QueryUpdateMySQL(iFailStateHandle:iQueryszError[], iErrorCode)
{
    if(
iFailState == TQUERY_CONNECT_FAILED || iFailState == TQUERY_QUERY_FAILED)
    {
        
server_print(szError)
        return
    }

    new 
iErrorCodeHandle:iSqlConnection SQL_Connect(g_iSqlTupleiErrorCodeg_szSqlErrorcharsmax(g_szSqlError))

    if(
iSqlConnection == Empty_Handle)
    {
        
server_print(g_szSqlError)
        return
    }

    new 
Handle:iQuery2szQuery[MAX_QUERY_LENGTH], szPlayer[MAX_SQL_PLAYER_LENGTH], szInfo[MAX_SQL_PLAYER_LENGTH], iCounteriPlayeriXP
    
new szColumnPlayer SQL_FieldNameToNum(iQuery"User")
    new 
szColumnXP SQL_FieldNameToNum(iQuery"XP")

    while(
SQL_MoreResults(iQuery))
    {
        
SQL_ReadResult(iQueryszColumnPlayerszInfocharsmax(szInfo))
        
SQL_QuoteString(iSqlConnectionszPlayercharsmax(szPlayer), szInfo)
        
iQuery2 SQL_PrepareQuery(iSqlConnection"SELECT * FROM %s WHERE Player = '%s';"g_eSettings[SQL_TABLE], szPlayer)

        if(!
SQL_Execute(iQuery2))
        {
            
SQL_QueryError(iQuery2g_szSqlErrorcharsmax(g_szSqlError))
            
server_print(g_szSqlError)
            return
        }

        
iXP SQL_ReadResult(iQueryszColumnXP)

        if(
SQL_NumResults(iQuery2) > 0)
        {
            
formatex(szQuerycharsmax(szQuery), "UPDATE `%s` SET `XP`='%i' WHERE `Player`='%s';"g_eSettings[SQL_TABLE], iXPszPlayer)
        }
        else
        {
            
formatex(szQuerycharsmax(szQuery), "INSERT INTO %s (`Player`,`XP`,`Level`,`Next XP`,`Rank`,`Next Rank`) VALUES ('%s','%i','1','0','n/a','n/a');"g_eSettings[SQL_TABLE], szPlayeriXP)
        }

        switch(
g_eSettings[SAVE_TYPE])
        {
            case 
CRXRANKS_ST_NICKNAMEiPlayer find_player("a"szInfo)
            case 
CRXRANKS_ST_STEAMID:  iPlayer find_player("c"szInfo)
            case 
CRXRANKS_ST_IP:       iPlayer find_player("d"szInfo)
        }

        if(
iPlayer)
        {
            
g_ePlayerData[iPlayer][XP] = iXP
            check_level
(iPlayertrue)
        }

        
SQL_ThreadQuery(g_iSqlTuple"QueryHandler"szQuery)
        
SQL_NextRow(iQuery)
        
iCounter++
    }

    
SQL_FreeHandle(iQuery2)
    
SQL_FreeHandle(iSqlConnection)
}

public 
OnPlayerKilled()
{
    new 
iAttacker read_data(1), iVictim read_data(2)

    if(!
is_user_connected(iAttacker) || !is_user_connected(iVictim))
    {
        return
    }

    new 
iRewardiTemp

    
if(iAttacker == iVictim)
    {
        
iTemp get_xp_reward(iAttackerXPREWARD_SUICIDE)
        
iReward += iTemp

        
if(should_skip(iTemp))
        {
            goto @
GIVE_REWARD
        
}
    }
    else if(
get_user_team(iAttacker) == get_user_team(iVictim))
    {
        
iTemp get_xp_reward(iAttackerXPREWARD_TEAMKILL)
        
iReward += iTemp

        
if(should_skip(iTemp))
        {
            goto @
GIVE_REWARD
        
}
    }
    else
    {
        new 
szWeapon[16]
        
read_data(4szWeaponcharsmax(szWeapon))

        
iTemp get_xp_reward(iAttackerszWeapon)
        
iReward += iTemp

        
if(should_skip(iTemp))
        {
            goto @
GIVE_REWARD
        
}

        if(
read_data(3))
        {
            
iTemp get_xp_reward(iAttackerXPREWARD_HEADSHOT)
            
iReward += iTemp

            
if(should_skip(iTemp))
            {
                goto @
GIVE_REWARD
            
}
        }

        
iReward += get_xp_reward(iAttackerXPREWARD_KILL)
    }

    @
GIVE_REWARD:
    new 
iXP give_user_xp(iAttackeriRewardCRXRANKS_XPS_REWARD)

    if(
g_eSettings[NOTIFY_ON_KILL] && iXP != 0)
    {
        if(
iAttacker == iVictim)
        {
            
CC_SendMessage(iAttacker"%L"iAttacker"CRXRANKS_NOTIFY_SUICIDE"abs(iXP))
        }
        else
        {
            new 
szName[MAX_NAME_LENGTH]
            
get_user_name(iVictimszNamecharsmax(szName))
            
CC_SendMessage(iAttacker"%L"iAttackeriXP >= "CRXRANKS_NOTIFY_KILL_GET" "CRXRANKS_NOTIFY_KILL_LOSE"abs(iXP), szName)
        }
    }
}

public 
sort_players_by_xp(id1id2)
{
    if(
g_ePlayerData[id1][XP] > g_ePlayerData[id2][XP])
    {
        return -
1
    
}
    else if(
g_ePlayerData[id1][XP] < g_ePlayerData[id2][XP])
    {
        return 
1
    
}

    return 
0
}

public 
QueryHandler(iFailStateHandle:iQueryszError[], iErrorCode)
{
    switch(
iFailState)
    {
        case 
TQUERY_CONNECT_FAILEDlog_amx("[SQL Error] Connection failed (%i): %s"iErrorCodeszError)
        case 
TQUERY_QUERY_FAILED:   log_amx("[SQL Error] Query failed (%i): %s"iErrorCodeszError)
    }
}

save_or_load(const id, const szInfo[], const iType)
{
    if(!
szInfo[0])
    {
        return
    }

    switch(
iType)
    {
        case 
SL_SAVE_DATA:
        {
            if(
g_eSettings[USE_MYSQL])
            {
                static 
szQuery[MAX_QUERY_LENGTH], szPlayer[MAX_SQL_PLAYER_LENGTH], szRank[MAX_SQL_RANK_LENGTH], szNextRank[MAX_SQL_RANK_LENGTH]
                new 
iErrorCodeHandle:iSqlConnection SQL_Connect(g_iSqlTupleiErrorCodeg_szSqlErrorcharsmax(g_szSqlError))

                
SQL_QuoteString(iSqlConnectionszPlayercharsmax(szPlayer), szInfo)
                
SQL_QuoteString(iSqlConnectionszRankcharsmax(szRank), g_ePlayerData[id][Rank])
                
SQL_QuoteString(iSqlConnectionszNextRankcharsmax(szNextRank), g_ePlayerData[id][NextRank])

                
formatex(szQuerycharsmax(szQuery), "UPDATE `%s` SET `XP`='%i',`Level`='%i',`Next XP`='%i',`Rank`='%s',`Next Rank`='%s' WHERE `Player`='%s';",\
                
g_eSettings[SQL_TABLE], g_ePlayerData[id][XP], g_ePlayerData[id][Level], g_ePlayerData[id][NextXP], szRankszNextRankszPlayer)
                
SQL_ThreadQuery(g_iSqlTuple"QueryHandler"szQuery)
            }
            else
            {
                static 
szData[CRXRANKS_MAX_XP_LENGTH]
                
num_to_str(g_ePlayerData[id][XP], szDatacharsmax(szData))
                
nvault_set(g_iVaultszInfoszData)
            }
        }
        case 
SL_LOAD_DATA:
        {
            if(
g_eSettings[USE_MYSQL])
            {
                static 
szPlayer[MAX_SQL_PLAYER_LENGTH]
                new 
iErrorCodeHandle:iSqlConnection SQL_Connect(g_iSqlTupleiErrorCodeg_szSqlErrorcharsmax(g_szSqlError))
                
SQL_QuoteString(iSqlConnectionszPlayercharsmax(szPlayer), szInfo)

                if(
iSqlConnection == Empty_Handle)
                {
                    
log_amx(g_szSqlError)
                    return
                }

                new 
Handle:iQuery SQL_PrepareQuery(iSqlConnection"SELECT * FROM %s WHERE Player = '%s';"g_eSettings[SQL_TABLE], szPlayer)

                if(!
SQL_Execute(iQuery))
                {
                    
SQL_QueryError(iQueryg_szSqlErrorcharsmax(g_szSqlError))
                    
log_amx(g_szSqlError)
                    return
                }

                
prepare_player(idszPlayerSQL_NumResults(iQuery) > false true)
                
SQL_FreeHandle(iQuery)
                
SQL_FreeHandle(iSqlConnection)
            }
            else
            {
                static 
iData
                iData 
nvault_get(g_iVaultszInfo)
                
g_ePlayerData[id][XP] = iData clamp(iData0) : 0
                check_level
(idfalse)
            }
        }
    }
}

prepare_player(id, const szPlayer[], bool:bNewPlayer)
{
    new 
iErrorCodeHandle:iSqlConnection SQL_Connect(g_iSqlTupleiErrorCodeg_szSqlErrorcharsmax(g_szSqlError))

    if(
iSqlConnection == Empty_Handle)
    {
        
log_amx(g_szSqlError)
        return
    }

    static 
szQuery[MAX_QUERY_LENGTH]

    if(
bNewPlayer)
    {
        
formatex(szQuerycharsmax(szQuery), "INSERT INTO %s (`Player`,`XP`,`Level`,`Next XP`,`Rank`,`Next Rank`) VALUES ('%s','0','1','0','n/a','n/a');"g_eSettings[SQL_TABLE], szPlayer)
    }
    else
    {
        
formatex(szQuerycharsmax(szQuery), "SELECT XP FROM %s WHERE Player = '%s';"g_eSettings[SQL_TABLE], szPlayer)
    }

    new 
Handle:iQuery SQL_PrepareQuery(iSqlConnectionszQuery)

    if(!
SQL_Execute(iQuery))
    {
        
SQL_QueryError(iQueryg_szSqlErrorcharsmax(g_szSqlError))
        
log_amx(g_szSqlError)
    }

    if(!
bNewPlayer)
    {
        if(
SQL_NumResults(iQuery) > 0)
        {
            
g_ePlayerData[id][XP] = SQL_ReadResult(iQuery0)
        }
    }

    
check_level(idfalse)

    
SQL_FreeHandle(iQuery)
    
SQL_FreeHandle(iSqlConnection)
}

get_xp_reward(const id, const szKey[])
{
    static 
iReward

    
if(g_ePlayerData[id][IsVIP])
    {
        if(
TrieKeyExists(g_tXPRewardsVIPszKey))
        {
            
TrieGetCell(g_tXPRewardsVIPszKeyiReward)
            return 
iReward
        
}
    }

    if(
TrieKeyExists(g_tXPRewardsszKey))
    {
        
TrieGetCell(g_tXPRewardsszKeyiReward)
        return 
iReward
    
}

    return 
0
}

give_user_xp(const idiXPCRXRanks_XPSources:iSource CRXRANKS_XPS_PLUGIN)
{
    if(!
iXP)
    {
        return 
0
    
}

    if(
g_eSettings[IGNORE_BOTS] && g_ePlayerData[id][IsBot])
    {
        return 
0
    
}

    if(
iSource == CRXRANKS_XPS_REWARD)
    {
        if(
g_eSettings[MINIMUM_PLAYERS] && get_playersnum() < g_eSettings[MINIMUM_PLAYERS])
        {
            return 
0
        
}

        if(
g_eSettings[TEAM_LOCK] && get_user_team(id) != g_eSettings[TEAM_LOCK])
        {
            return 
0
        
}
    }

    static 
iReturn
    ExecuteForward
(g_fwdUserReceiveXPiReturnidiXPiSource)

    switch(
iReturn)
    {
        case 
CRXRANKS_HANDLED: return 0
        
case CRXRANKS_CONTINUE: { }
        default:
        {
            if(
iReturn != 0)
            {
                
iXP iReturn
            
}
        }
    }

    
g_ePlayerData[id][XP] += iXP

    
if(g_ePlayerData[id][XP] < 0)
    {
        
g_ePlayerData[id][XP] = 0
    
}

    
check_level(idtrue)
    
ExecuteForward(g_fwdUserXPUpdatediReturnidg_ePlayerData[id][XP], iSource)

    if(
g_eSettings[XP_NOTIFIER_ENABLED])
    {
        static 
szKey[32], bool:bPositive
        bPositive 
iXP >= 0

        copy
(szKeycharsmax(szKey), bPositive "CRXRANKS_XP_NOTIFIER_GET" "CRXRANKS_XP_NOTIFIER_LOSE")

        if(
g_eSettings[XP_NOTIFIER_USE_DHUD])
        {
            if(
bPositive)
            {
                
set_dhudmessage(XP_NOTIFIER_PARAMS_GET)
            }
            else
            {
                
set_dhudmessage(XP_NOTIFIER_PARAMS_LOSE)
            }

            
show_dhudmessage(id"%L"idszKeyabs(iXP))
        }
        else
        {
            if(
bPositive)
            {
                
set_hudmessage(XP_NOTIFIER_PARAMS_GET)
            }
            else
            {
                
set_hudmessage(XP_NOTIFIER_PARAMS_LOSE)
            }

            
ShowSyncHudMsg(idg_iObject[OBJ_XP_NOTIFIER], "%L"idszKeyabs(iXP))
        }
    }

    return 
iXP
}

get_user_saveinfo(const idszInfo[CRXRANKS_MAX_PLAYER_INFO_LENGTH], const iLen)
{
    switch(
g_eSettings[SAVE_TYPE])
    {
        case 
SAVE_NICKNAME:    get_user_name(idszInfoiLen)
        case 
SAVE_IPget_user_ip(idszInfoiLen1)
        case 
SAVE_STEAMIDget_user_authid(idszInfoiLen)
    }
}

reset_player_stats(const id)
{
    
g_ePlayerData[id][XP] = 0
    g_ePlayerData
[id][Level] = 0
    g_ePlayerData
[id][NextXP] = 0
    g_ePlayerData
[id][Rank][0] = EOS
    g_ePlayerData
[id][NextRank][0] = EOS
    g_ePlayerData
[id][HUDInfo][0] = EOS
    g_ePlayerData
[id][IsOnFinalLevel] = false
    g_ePlayerData
[id][IsVIP] = false
    g_ePlayerData
[id][IsBot] = false
}

switch_to_nvault()
{
    if(
g_eSettings[USE_MYSQL])
    {
        
g_eSettings[USE_MYSQL] = false
        log_amx
("%L"LANG_SERVER"CRXRANKS_MYSQL_FAILED")
    }
}

bool:has_argument(const szMessage[], const szArg[])
{
    return 
contain(szMessageszArg) != -1
}

bool:should_skip(const iNum)
{
    return (
iNum != && !g_eSettings[USE_COMBINED_EVENTS])
}

send_chat_message(const id, const bool:bLog, const szInput[], any:...)
{
    static 
szMessage[192]
    
vformat(szMessagecharsmax(szMessage), szInput4)

    
#if defined USE_CSTRIKE
    
bLog CC_LogMessage(id_szMessage) : CC_SendMessage(idszMessage)
    
#else
    
format(szMessagecharsmax(szMessage), "%s %s"CC_PREFIXszMessage)
    
client_print(idprint_chatszMessage)

    if(
bLog)
    {
        
log_amx(szMessage)
    }
    
#endif
}

update_hudinfo(const id)
{
    if(!
g_eSettings[HUDINFO_ENABLED])
    {
        return
    }

    static 
szMessage[CRXRANKS_MAX_HUDINFO_LENGTH], szPlaceHolder[32], bool:bIsOnFinal

    bIsOnFinal 
g_ePlayerData[id][IsOnFinalLevel]
    
copy(szMessagecharsmax(szMessage), g_eSettings[bIsOnFinal HUDINFO_FORMAT_FINAL HUDINFO_FORMAT])

    if(
has_argument(szMessageARG_CURRENT_XP))
    {
        
num_to_str(g_ePlayerData[id][XP], szPlaceHoldercharsmax(szPlaceHolder))
        
replace_string(szMessagecharsmax(szMessage), ARG_CURRENT_XPszPlaceHolder)
    }

    if(
has_argument(szMessageARG_NEXT_XP))
    {
        
num_to_str(g_ePlayerData[id][NextXP], szPlaceHoldercharsmax(szPlaceHolder))
        
replace_string(szMessagecharsmax(szMessage), ARG_NEXT_XPszPlaceHolder)
    }

    if(
has_argument(szMessageARG_XP_NEEDED))
    {
        
num_to_str(g_ePlayerData[id][NextXP] - g_ePlayerData[id][XP], szPlaceHoldercharsmax(szPlaceHolder))
        
replace_string(szMessagecharsmax(szMessage), ARG_XP_NEEDEDszPlaceHolder)
    }

    if(
has_argument(szMessageARG_LEVEL))
    {
        
num_to_str(g_ePlayerData[id][Level], szPlaceHoldercharsmax(szPlaceHolder))
        
replace_string(szMessagecharsmax(szMessage), ARG_LEVELszPlaceHolder)
    }

    if(
has_argument(szMessageARG_NEXT_LEVEL))
    {
        
num_to_str(g_ePlayerData[id][bIsOnFinal Level Level 1], szPlaceHoldercharsmax(szPlaceHolder))
        
replace_string(szMessagecharsmax(szMessage), ARG_NEXT_LEVELszPlaceHolder)
    }

    
replace_string(szMessagecharsmax(szMessage), ARG_MAX_LEVELSg_szMaxLevels)

    if(
has_argument(szMessageARG_NAME))
    {
        
get_user_name(idszPlaceHoldercharsmax(szPlaceHolder))
        
replace_string(szMessagecharsmax(szMessage), ARG_NAMEszPlaceHolder)
    }

    
replace_string(szMessagecharsmax(szMessage), ARG_RANKg_ePlayerData[id][Rank])
    
replace_string(szMessagecharsmax(szMessage), ARG_NEXT_RANKg_ePlayerData[id][NextRank])
    
replace_string(szMessagecharsmax(szMessage), ARG_LINE_BREAK"^n")
    
copy(g_ePlayerData[id][HUDInfo], charsmax(g_ePlayerData[][HUDInfo]), szMessage)
}

check_level(const id, const bool:bNotify)
{
    static 
iLeveli
    iLevel 
0

    
for(1g_iMaxLevels 1i++)
    {
        if(
g_ePlayerData[id][XP] >= ArrayGetCell(g_aLevelsi))
        {
            
iLevel++
        }
    }

    if(
iLevel != g_ePlayerData[id][Level])
    {
        static 
bool:bLevelUpiReturn
        bLevelUp 
iLevel g_ePlayerData[id][Level]
        
g_ePlayerData[id][Level] = iLevel
        ArrayGetString
(g_aRankNamesiLevelg_ePlayerData[id][Rank], charsmax(g_ePlayerData[][Rank]))

        if(
iLevel g_iMaxLevels)
        {
            
g_ePlayerData[id][IsOnFinalLevel] = false
            g_ePlayerData
[id][NextXP] = ArrayGetCell(g_aLevelsiLevel 1)
            
ArrayGetString(g_aRankNamesiLevel 1g_ePlayerData[id][NextRank], charsmax(g_ePlayerData[][NextRank]))
        }
        else
        {
            
g_ePlayerData[id][IsOnFinalLevel] = true
            g_ePlayerData
[id][NextXP] = ArrayGetCell(g_aLevelsiLevel)
            
copy(g_ePlayerData[id][NextRank], charsmax(g_ePlayerData[][NextRank]), g_eSettings[HUDINFO_INVALID_TEXT])

            if(
g_eSettings[FINAL_LEVEL_FLAGS])
            {
                
set_user_flags(idg_eSettings[FINAL_LEVEL_FLAGS_BIT])
                
remove_user_flags(idg_iFlagZ)
            }
        }

        
ExecuteForward(g_fwdUserLevelUpdatediReturnidiLevelbLevelUp)

        if(
bNotify && g_eSettings[LEVELUP_MESSAGE_TYPE])
        {
            static 
szMessage[128], szName[32], bool:bGlobalMsg
            get_user_name
(idszNamecharsmax(szName))
            
bGlobalMsg g_eSettings[LEVELUP_MESSAGE_TYPE] == 2

            formatex
(szMessagecharsmax(szMessage), "%L"bGlobalMsg LANG_PLAYER id,\
            
bLevelUp "CRXRANKS_LEVEL_REACHED" "CRXRANKS_LEVEL_LOST"szNameg_ePlayerData[id][Level], g_ePlayerData[id][Rank])
            
send_chat_message(bGlobalMsg idfalseszMessage)

            if(
bLevelUp && g_eSettings[LEVELUP_SOUND][0])
            {
                
emit_sound(idCHAN_AUTOg_eSettings[LEVELUP_SOUND], 1.0ATTN_NORM0PITCH_NORM)
            }
            else if(!
bLevelUp && g_eSettings[LEVELDN_SOUND][0])
            {
                
emit_sound(idCHAN_AUTOg_eSettings[LEVELDN_SOUND], 1.0ATTN_NORM0PITCH_NORM)
            }

            if(
g_eSettings[bLevelUp LEVELUP_SCREEN_FADE_ENABLED LEVELDN_SCREEN_FADE_ENABLED])
            {
                
message_begin(MSG_ONEg_iScreenFade, {000}, id)
                
write_short(1<<10)
                
write_short(1<<10)
                
write_short(0x0000)

                if(
bLevelUp)
                {
                    
write_byte(clr(g_eSettings[LEVELUP_SCREEN_FADE_COLOR][0]))
                    
write_byte(clr(g_eSettings[LEVELUP_SCREEN_FADE_COLOR][1]))
                    
write_byte(clr(g_eSettings[LEVELUP_SCREEN_FADE_COLOR][2]))
                    
write_byte(clr(g_eSettings[LEVELUP_SCREEN_FADE_COLOR][3]))
                }
                else
                {
                    
write_byte(clr(g_eSettings[LEVELDN_SCREEN_FADE_COLOR][0]))
                    
write_byte(clr(g_eSettings[LEVELDN_SCREEN_FADE_COLOR][1]))
                    
write_byte(clr(g_eSettings[LEVELDN_SCREEN_FADE_COLOR][2]))
                    
write_byte(clr(g_eSettings[LEVELDN_SCREEN_FADE_COLOR][3]))
                }

                
message_end()
            }
        }
    }

    
update_hudinfo(id)
}

public 
update_vip_status(id)
{
    if(
is_user_connected(id) && g_eSettings[VIP_FLAGS_BIT] != ADMIN_ALL)
    {
        
g_ePlayerData[id][IsVIP] = bool:((get_user_flags(id) & g_eSettings[VIP_FLAGS_BIT]) == g_eSettings[VIP_FLAGS_BIT])
    }
}

public 
plugin_natives()
{
    
register_library("crxranks")
    
register_native("crxranks_get_chat_prefix",         "_crxranks_get_chat_prefix")
    
register_native("crxranks_get_final_flags",         "_crxranks_get_final_flags")
    
register_native("crxranks_get_hudinfo_format",      "_crxranks_get_hudinfo_format")
    
register_native("crxranks_get_max_levels",          "_crxranks_get_max_levels")
    
register_native("crxranks_get_rank_by_level",       "_crxranks_get_rank_by_level")
    
register_native("crxranks_get_save_type",           "_crxranks_get_save_type")
    
register_native("crxranks_get_setting",             "_crxranks_get_setting")
    
register_native("crxranks_get_user_hudinfo",        "_crxranks_get_user_hudinfo")
    
register_native("crxranks_get_user_level",          "_crxranks_get_user_level")
    
register_native("crxranks_get_user_next_rank",      "_crxranks_get_user_next_rank")
    
register_native("crxranks_get_user_next_xp",        "_crxranks_get_user_next_xp")
    
register_native("crxranks_get_user_rank",           "_crxranks_get_user_rank")
    
register_native("crxranks_get_user_xp",             "_crxranks_get_user_xp")
    
register_native("crxranks_get_vault_name",          "_crxranks_get_vault_name")
    
register_native("crxranks_get_vip_flags",           "_crxranks_get_vip_flags")
    
register_native("crxranks_get_xp_for_level",        "_crxranks_get_xp_for_level")
    
register_native("crxranks_get_xp_reward",           "_crxranks_get_xp_reward")
    
register_native("crxranks_give_user_xp",            "_crxranks_give_user_xp")
    
register_native("crxranks_is_hi_using_dhud",        "_crxranks_is_hi_using_dhud")
    
register_native("crxranks_is_hud_enabled",          "_crxranks_is_hud_enabled")
    
register_native("crxranks_is_sfdn_enabled",         "_crxranks_is_sfdn_enabled")
    
register_native("crxranks_is_sfup_enabled",         "_crxranks_is_sfup_enabled")
    
register_native("crxranks_is_user_on_final",        "_crxranks_is_user_on_final")
    
register_native("crxranks_is_user_vip",             "_crxranks_is_user_vip")
    
register_native("crxranks_is_using_mysql",          "_crxranks_is_using_mysql")
    
register_native("crxranks_is_xpn_enabled",          "_crxranks_is_xpn_enabled")
    
register_native("crxranks_is_xpn_using_dhud",       "_crxranks_is_xpn_using_dhud")
    
register_native("crxranks_set_user_xp",             "_crxranks_set_user_xp")
    
register_native("crxranks_using_comb_events",       "_crxranks_using_comb_events")
}

public 
_crxranks_get_chat_prefix(iPluginiParams)
{
    
set_string(1CC_PREFIXget_param(2))
}

public 
_crxranks_get_final_flags(iPluginiParams)
{
    
set_string(1g_eSettings[FINAL_LEVEL_FLAGS], get_param(2))
    return 
g_eSettings[FINAL_LEVEL_FLAGS_BIT]
}

public 
_crxranks_get_hudinfo_format(iPluginiParams)
{
    
set_string(2g_eSettings[get_param(1) ? HUDINFO_FORMAT_FINAL HUDINFO_FORMAT], get_param(3))
}

public 
_crxranks_get_max_levels(iPluginiParams)
{
    return 
g_iMaxLevels
}

public 
_crxranks_get_rank_by_level(iPluginiParams)
{
    static 
iLevel
    iLevel 
get_param(1)

    if(
iLevel || iLevel g_iMaxLevels)
    {
        return 
0
    
}

    static 
szRank[CRXRANKS_MAX_RANK_LENGTH]
    
ArrayGetString(g_aRankNamesiLevelszRankcharsmax(szRank))
    
set_string(2szRankget_param(3))
    return 
1
}

public 
_crxranks_get_save_type(iPluginiParams)
{
    return 
g_eSettings[SAVE_TYPE]
}

public 
bool:_crxranks_get_setting(iPluginiParams)
{
    static 
szKey[MAX_NAME_LENGTH], szValue[CRXRANKS_MAX_HUDINFO_LENGTH], bool:bReturn
    get_string
(1szKeycharsmax(szKey))

    
bReturn TrieGetString(g_tSettingsszKeyszValuecharsmax(szValue))
    
set_string(2szValueget_param(3))
    return 
bReturn
}

public 
_crxranks_get_user_hudinfo(iPluginiParams)
{
    
set_string(2g_ePlayerData[get_param(1)][HUDInfo], get_param(3))
}

public 
_crxranks_get_user_level(iPluginiParams)
{
    return 
g_ePlayerData[get_param(1)][Level]
}

public 
_crxranks_get_user_next_rank(iPluginiParams)
{
    
set_string(2g_ePlayerData[get_param(1)][NextRank], get_param(3))
}

public 
_crxranks_get_user_next_xp(iPluginiParams)
{
    return 
g_ePlayerData[get_param(1)][NextXP]
}

public 
_crxranks_get_user_rank(iPluginiParams)
{
    
set_string(2g_ePlayerData[get_param(1)][Rank], get_param(3))
}

public 
_crxranks_get_user_xp(iPluginiParams)
{
    return 
g_ePlayerData[get_param(1)][XP]
}

public 
_crxranks_get_vault_name(iPluginiParams)
{
    
set_string(1g_eSettings[VAULT_NAME], get_param(2))
}

public 
_crxranks_get_vip_flags(iPluginiParams)
{
    
set_string(1g_eSettings[VIP_FLAGS], get_param(2))
    return 
g_eSettings[VIP_FLAGS_BIT]
}

public 
_crxranks_get_xp_for_level(iPluginiParams)
{
    static 
iLevel
    iLevel 
get_param(1)

    if(
iLevel || iLevel g_iMaxLevels)
    {
        return -
1
    
}

    return 
ArrayGetCell(g_aLevelsiLevel)
}

public 
_crxranks_get_xp_reward(iPluginiParams)
{
    static 
szReward[CRXRANKS_MAX_XP_REWARD_LENGTH]
    
get_string(2szRewardcharsmax(szReward))
    return 
get_xp_reward(get_param(1), szReward)
}

public 
_crxranks_give_user_xp(iPluginiParams)
{
    static 
szReward[CRXRANKS_MAX_XP_REWARD_LENGTH], iRewardid

    szReward
[0] = EOS
    id 
get_param(1)
    
get_string(3szRewardcharsmax(szReward))

    if(
szReward[0])
    {
        
iReward get_xp_reward(idszReward)

        if(
iReward)
        {
            
give_user_xp(idiRewardCRXRanks_XPSources:get_param(3))
        }

        return 
iReward
    
}

    
iReward get_param(2)
    
give_user_xp(idiRewardCRXRanks_XPSources:get_param(3))
    return 
iReward
}

public 
bool:_crxranks_is_hi_using_dhud(iPluginiParams)
{
    return 
g_eSettings[HUDINFO_USE_DHUD]
}

public 
bool:_crxranks_is_hud_enabled(iPluginiParams)
{
    return 
g_eSettings[HUDINFO_ENABLED]
}

public 
bool:_crxranks_is_sfdn_enabled(iPluginiParams)
{
    return 
g_eSettings[LEVELDN_SCREEN_FADE_ENABLED]
}

public 
bool:_crxranks_is_sfup_enabled(iPluginiParams)
{
    return 
g_eSettings[LEVELUP_SCREEN_FADE_ENABLED]
}

public 
bool:_crxranks_is_user_on_final(iPluginiParams)
{
    return 
g_ePlayerData[get_param(1)][IsOnFinalLevel]
}

public 
bool:_crxranks_is_user_vip(iPluginiParams)
{
    return 
g_ePlayerData[get_param(1)][IsVIP]
}

public 
bool:_crxranks_is_using_mysql(iPluginiParams)
{
    return 
g_eSettings[USE_MYSQL]
}

public 
bool:_crxranks_is_xpn_enabled(iPluginiParams)
{
    return 
g_eSettings[XP_NOTIFIER_ENABLED]
}

public 
bool:_crxranks_set_user_xp(iPluginiParams)
{
    static 
idiReturnCRXRanks_XPSources:iSource
    id 
get_param(1)
    
iSource CRXRanks_XPSources:get_param(3)
    
g_ePlayerData[id][XP] = clamp(get_param(2), 0)

    
check_level(idtrue)
    
ExecuteForward(g_fwdUserXPUpdatediReturnidg_ePlayerData[id][XP], iSource)
}

public 
bool:_crxranks_using_comb_events(iPluginiParams)
{
    return 
g_eSettings[USE_COMBINED_EVENTS]
}

public 
bool:_crxranks_is_xpn_using_dhud(iPluginiParams)
{
    return 
g_eSettings[XP_NOTIFIER_USE_DHUD]

@Supergirl - I'm not very sure how exactly that's going to work. Pretty sure a huge portion of the code needs to be completely changed in order to implement such a thing so I don't think it's a good idea from coding perspective.
Fine now. Thanks
LithuanianJack is offline